Can you store a scope/proc reference in a table?
Moderator: Moderators
Can you store a scope/proc reference in a table?
So I’m trying to do some code optimizing.
I know I can store an address to a code jmp in a table but I do not see anything about scope/proc references.
But seeing as you can pass a scope reference through a macro I thought I’d ask if it was possible to store them in a table to cut down on having long lists of cmps?
I know I can store an address to a code jmp in a table but I do not see anything about scope/proc references.
But seeing as you can pass a scope reference through a macro I thought I’d ask if it was possible to store them in a table to cut down on having long lists of cmps?
Re: Can you store a scope/proc reference in a table?
Scopes have nothing to do with the CPU itself, they're constructs used during assembly time for the purpose of keeping code organized. The 6502 itself doesn't have any concept of scopes - all symbols/labels, regardless of their scopes, are simply converted to numbers when the code is assembled.
What exactly is it that you're trying to do? How would a table of scopes help reduce long lists of CMPs?
What exactly is it that you're trying to do? How would a table of scopes help reduce long lists of CMPs?
Re: Can you store a scope/proc reference in a table?
It’s all to do with organization.
You could have your enemy updates all set to their own scopes/proc with each having a scope::update.
Instead of writing out multiple compares for an enemy type then branching to the correct subroutine you could just write a much smaller pull the reference for the scope based on a type and then a single enemyscope::update.
You could have your enemy updates all set to their own scopes/proc with each having a scope::update.
Instead of writing out multiple compares for an enemy type then branching to the correct subroutine you could just write a much smaller pull the reference for the scope based on a type and then a single enemyscope::update.
Re: Can you store a scope/proc reference in a table?
If I'm understanding you correctly, it sounds like you're trying specify pointers in a jump table where those pointers all exist within specific namespaces.
It would help to know which assembler you're using, since the answer will probably vary quite a lot.
It would help to know which assembler you're using, since the answer will probably vary quite a lot.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
P.S. If you don't get this note, let me know and I'll write you another.
Re: Can you store a scope/proc reference in a table?
Looks like ca65 syntax. All labels are simply converted into addresses at assembly time, so there's nothing stopping you from doing this:
It's exactly the same as if you weren't using scopes at all.
Code: Select all
ObjectUpdateTable:
.word object0scope::update
.word object1scope::update
.word object2scope::update
;(...)
.word object126scope::update
.word object127scope::update
Re: Can you store a scope/proc reference in a table?
Another thing I sometimes do when I want to define the values that go in a table away from the table itself is something like this:
Then, inside the object's own scope I can do:
This way I get to decide each object's number inside the object's own file, instead of having to make sure that a table defined elsewhere has the object in the position I want.
The downside is that the assembler will throw errors if you try to assign multiple values to the same placeholder, or if you leave any placeholder uninitialized. You can write macros to help automate this task, though - a macro (e.g. "RegisterObject") could take INIT, UPDATE, DRAW, etc. addresses and the desired number for the object and automatically assign them to the respective placeholders, and another macro called at the end would verify which placeholders were left unused and assign some bogus value to them.
Code: Select all
ObjectUpdateTable:
.word UpdatePlaceholder0
.word UpdatePlaceholder1
.word UpdatePlaceholder2
;(...)
Code: Select all
.scope EvilEnemy
::UpdatePlaceholder5 := Update
Update:
;(...)
The downside is that the assembler will throw errors if you try to assign multiple values to the same placeholder, or if you leave any placeholder uninitialized. You can write macros to help automate this task, though - a macro (e.g. "RegisterObject") could take INIT, UPDATE, DRAW, etc. addresses and the desired number for the object and automatically assign them to the respective placeholders, and another macro called at the end would verify which placeholders were left unused and assign some bogus value to them.
Re: Can you store a scope/proc reference in a table?
I think I have found a solution.
instead of pulling a scope reference I can create 1 macro that takes a type ID and a sub routine name. Then just reuse that macro everytime I need to get a scope for a sub routine. The subroutine can be anything as long as the enemy scopes each have one named the same. So now if I need to add a new enemy type all i need to do is add the new scope and the cmp in the one macro.
example:
update: This works beautifully! in just a few short mins i have already knocked down all the enemy updates and sprite draws to a few lines of code instead of the long compare lists as before.
instead of pulling a scope reference I can create 1 macro that takes a type ID and a sub routine name. Then just reuse that macro everytime I need to get a scope for a sub routine. The subroutine can be anything as long as the enemy scopes each have one named the same. So now if I need to add a new enemy type all i need to do is add the new scope and the cmp in the one macro.
example:
Code: Select all
.macro scopeCall typeid, sbr
lda typeid
cmp #01
bne:+
jsr ena::sbr
:
cmp #02
bne:+
jsr enb::sbr
:
.endmacro
update: This works beautifully! in just a few short mins i have already knocked down all the enemy updates and sprite draws to a few lines of code instead of the long compare lists as before.
-
- Posts: 1565
- Joined: Tue Feb 07, 2017 2:03 am
Re: Can you store a scope/proc reference in a table?
if optimization is the aim
less code, const dispatch time
Code: Select all
ldx typeid
lda CallTableSBR_hi,x
pha
lda CallTableSBR_lo,x
pha
rts
CallTableSBR_lo .byte <(ena::sbr-1),<(enb::sbr-1)
CallTableSBR_hi .byte >(ena::sbr-1),>(enb::sbr-1)
Re: Can you store a scope/proc reference in a table?
This is gonna get reaaaally slow after you've implemented dozens of objects... I though your goal was precisely to avoid large CMP chains. Jump tables are indeed much better in these situations.bjones wrote: ↑Sun Mar 19, 2023 3:58 pmCode: Select all
.macro scopeCall typeid, sbr lda typeid cmp #01 bne:+ jsr ena::sbr : cmp #02 bne:+ jsr enb::sbr : .endmacro
Re: Can you store a scope/proc reference in a table?
its actually not in many places and a total of 6 different eneamy types right now.tokumaru wrote: ↑Mon Mar 20, 2023 5:40 amThis is gonna get reaaaally slow after you've implemented dozens of objects... I though your goal was precisely to avoid large CMP chains. Jump tables are indeed much better in these situations.bjones wrote: ↑Sun Mar 19, 2023 3:58 pmCode: Select all
.macro scopeCall typeid, sbr lda typeid cmp #01 bne:+ jsr ena::sbr : cmp #02 bne:+ jsr enb::sbr : .endmacro
The main goal was to stream line having to manually add or take away enemies from multiple call lists. Human error and all that..
, but also I thought jump tables did not act as JSR just JMP? How would you retun to the loop?
Re: Can you store a scope/proc reference in a table?
You JSR from where you want the return point to be to the code that will use the jump table (the code that Oziphantom posted).
You're not required to use the RTS trick for jump tables though... If you prefer, you can copy the address from the table to a temporary variable in RAM and do an indirect JMP (do use the exact addresses in the table if you do this - subtracting 1 is only for the RTS method). It's 1 cycle faster than the RTS way if you use zero page RAM.