Jump to content

Photo

Optimal way to Direct/Indirect Address from another bank?


7 replies to this topic

#1 Jinroh OFFLINE  

Jinroh

    Dragonstomper

  • 670 posts
  • Catgirl Maid Lover

Posted Mon Aug 6, 2018 8:13 PM

Since I am re-writing the bankswitching for Carrot Kingdom™, I am curious if there is an optimal generic way in the past 30 years to use direct/indirect addressing of data from another bank within my display kernel. This would really help speed up development being more well organized and generic maintainable code. :)

 

I would like to keep all the graphics data in one bank (right now it is mirrored in each bank) like I do with the level data currently. The level data only needs to be used in one section of code so it is easy to have one hot spot to jump back and forth between the banks as it executes.

 

For the graphics data it needs to be more generic since it is used in many more places, and the best I can think is to have multiple hot spot points to jump back and forth but this seems irritating as it would add more to keep track of and more overhead.

 

Any suggestions for this? Thanks my friends! :D But time to get back to homework. =.=

 

For reference something like this. 
 |
 |

V

 

Bank 1 Kernel:

              DrawStuff:

                    lda GraphicCarrot,x or (GraphicCarrot),y ;Load from Bank Graphics

                    sta GRPx

 

 

Bank 2 Graphics:

               GraphicCarrot:

                     blah,

                     blah,

                     blah,

                     blah,

                     blah

 



#2 Mr SQL OFFLINE  

Mr SQL

    Stargunner

  • 1,984 posts

Posted Tue Aug 7, 2018 12:57 AM

Yes, the 2k bank size memory schemes are ideal for this because once switched in all the data is visible from the other bank with no additional hot-spotting overhead.  

 

With 4K bank sizes I use an identical switchboard at the top of each bank so I don't have to calculate anything.



#3 Jinroh OFFLINE  

Jinroh

    Dragonstomper

  • Topic Starter
  • 670 posts
  • Catgirl Maid Lover

Posted Tue Aug 7, 2018 8:23 PM

Thanks Mr SQL. :)

 

Well I do know how to Bankswitch so maybe I misspeak in my post. I am trying to figure out a good way that is low overhead as possible to switch banks mid-kernel to draw graphics stored in.

 

I have been doing similarly things to this with a Jump Table I use to jump into various places in various banks and jump back. This works well for some special cases, but not so much in this case. The jump table would become crazy annoying and a pain to maintain all the hot spot points.

 

I do like your idea of having a Subroutine in the same spot in the two banks to jump between them. This lends itself very well to making it generic so it can jump mid-kernel with a JSR and then RTS back to that spot.

 

It made me the idea for something like this (Excuse the Messy Pseudo-Code), still doesn't feel super optimal as it wastes some cycles in a kernel (and some bytes of overhead in the Graphics Bank though that may be unavoidable.), but it is a reusable way to do what I am thinking at least in my head I haven't tested it yet. Unless someone has a better idea I am not thinking. ^^ What do you guys think?

Variables:
    GraphicsPtr - 2 bytes

Bank 1 (Kernels):
     ;Top of bank Put SetGraphicPointer and DrawGraphicFromPointer
     SetGraphicPointer:
         sta SwitchToBank2
         rts

     DrawGraphicFromPointer:
         sta SwitchToBank2
         rts

     PreKernel:
         ldx NumberOfGraphicYouWant
         jsr SetGraphicPointer

     Kernel:
         ;Do Some Stuff
         ....
         ;Time To Draw Graphic
         ;y contains index to graphic data for P0
         jsr DrawGraphicFromPointer

Bank 2 (Graphics Data):
     ;Top of bank 2 Put SetGraphicPointer and DrawGraphicFromPointer 2nd versions
     SetGraphicPointer:
         lda GraphicsPtrHi,x
         sta GraphicsPtr
         lda GraphicsPtrLow,x
         sta GraphicsPtr+1
         sta Bank1 ;Return to bank 1
         rts

     DrawGraphicFromPointer:
         lda (GraphicsPtr),y
         sta GRP0 ;Draw P0
         sta Bank1 ;Return to Bank1
         rts

     ;Following Data
     ;GraphicsPtrHi/Low Tables.
     ;Tons of Data for graphics.

Edited by Jinroh, Tue Aug 7, 2018 8:26 PM.


#4 Mr SQL OFFLINE  

Mr SQL

    Stargunner

  • 1,984 posts

Posted Wed Aug 8, 2018 9:44 PM

You're welcome Jinroh! :)

 

Yes having the subroutine in the same spot in all banks is great for universal access from any bank with a single JSR and RTS which is also good for saving code, but there is a second JSR and RTS taking place once it reaches the subroutine at the top of the bank to reach the actual code. SvOlli and I did an interesting analysis somewhere of the method as being more or less efficient than other optimized methods depending upon how large the switchboard grows.

 

Looking at your pseudocode two things I would add to implement it are adding the second hop so the actual routines are not in the switchboard, and appending a suffix to the labels in the second banks switchboard so the Assembler doesn't get confused unless the : allows duplicate labels which would be fine since they point to the same spots.

 



#5 Jinroh OFFLINE  

Jinroh

    Dragonstomper

  • Topic Starter
  • 670 posts
  • Catgirl Maid Lover

Posted Wed Aug 8, 2018 9:54 PM

Oh very interesting Mr. SQL and thanks. :D I wrote up the pseudo-code right before bed so I was leaving things out just to get the general idea across, but those are definitely things I missed. :D

 

Since you and SvOllie looked at the efficiencies of these routines do you think this particular one is the best way to go about fetching this data in a kernel?

 

Or is there an alternative that might give me less cycles to fetch it?

 

After my re-organization I have ~800 bytes left in the graphics bank (which would be nice to add some more code graphics but we'll see) so I could put the time sensitive base kernel code that just processes the graphics data in there. Since it is not so many bytes. That may be a better alternative. Though if I could I would like to keep them separate if I needed to have as much graphics data in a bank as possible.

 

Still kicking around ideas, but the code will be more organized and have less redundancy in the long run. :) So I appreciate bouncing ideas off of you.


Edited by Jinroh, Wed Aug 8, 2018 9:55 PM.


#6 Mr SQL OFFLINE  

Mr SQL

    Stargunner

  • 1,984 posts

Posted Wed Aug 8, 2018 10:54 PM

Oh very interesting Mr. SQL and thanks. :D I wrote up the pseudo-code right before bed so I was leaving things out just to get the general idea across, but those are definitely things I missed. :D

 

Since you and SvOllie looked at the efficiencies of these routines do you think this particular one is the best way to go about fetching this data in a kernel?

 

Or is there an alternative that might give me less cycles to fetch it?

 

After my re-organization I have ~800 bytes left in the graphics bank (which would be nice to add some more code graphics but we'll see) so I could put the time sensitive base kernel code that just processes the graphics data in there. Since it is not so many bytes. That may be a better alternative. Though if I could I would like to keep them separate if I needed to have as much graphics data in a bank as possible.

 

Still kicking around ideas, but the code will be more organized and have less redundancy in the long run. :) So I appreciate bouncing ideas off of you.

 

Sure bounce some ideas and I'll help if I can - Carrot Kingdom is an awesome game! :)

 

Here's the thread, it's a pretty interesting discussion. Turns out spacewise the switchboard method starts to become less space efficient after 4 routines, but I think speed wise it still saves a cycle.

 

There's also an interesting programmer perspective article on using macro based bank switching routines that are slow and large. I generally avoid macro's for that tendency. 

 

You are pushing the 6502 pretty hard with the scrolling in Carrot Kingdom - I think for this game the fastest bankswitching method is the best, space efficient not as important.  



#7 Jinroh OFFLINE  

Jinroh

    Dragonstomper

  • Topic Starter
  • 670 posts
  • Catgirl Maid Lover

Posted Thu Aug 9, 2018 9:51 PM

Awesome! I appreciate the support MrSQL I am going to code up a small test with my idea and see if I get my title and scrolling kernels working with the method I psuedo-coded above since it will be nice and re-usable.

 

Not sure if I have any more cycle time in the Kernel, but I'm sure it can be optimized a bit. If not I could remove 'PF5' which might free some up. Not ideal, but a lot of similar scrolling games do the same.



#8 Jinroh OFFLINE  

Jinroh

    Dragonstomper

  • Topic Starter
  • 670 posts
  • Catgirl Maid Lover

Posted Thu Aug 23, 2018 9:03 PM

So I got a good base setup for Carrot Kingdom with some macros and things to help out the more complicated bits.

 

However, so we can have a very simple (stupidly simple) bit of code on the books that is easy to follow. I took one of SpiceWare's template files and coded up a really simple example of loading and using graphics data during a kernel to draw a sprite.

Attached Files






0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users