Jump to content

Photo

Can the DPC+ Stack Be Hacked and Turned Into Variables?


32 replies to this topic

#26 SpiceWare ONLINE  

SpiceWare

    Draconian

  • 11,662 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Wed Sep 14, 2016 8:07 AM

...convert the DPC+ 256 stack locations into 256 variables?...

I'll take what I can get.


One more update!
 
If you do not want to use the DPC+ Stack then:

  • If the value is >= 0 then you can use Set/GetValue1 to save 256 values
  • If the value is >= 256 then you can also use Set/GetValue2 for a total of 512 values
  • If the value is >= 512 then you can also use Set/GetValue3 for a total of 768 values
SetValue3
    ; A = location 0-255
    ; Y = value
    sta DF0LOW
    lda #$0d
    sta DF0HI
    sty DF0WRITE
    RETURN
    
GetValue3
    ; A = location 0-255
    sta DF0LOW
    lda #$0d
    sta DF0HI
    lda DF0DATA
    ; A is the return value
    RETURN

 
You can view those in Stella's debugger on page $0D of the Cartridge RAM tab.



#27 SpiceWare ONLINE  

SpiceWare

    Draconian

  • 11,662 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Wed Sep 14, 2016 5:10 PM

Thanks. I don't understand any of it, but I can link to it from the bB page for other people who might be able to use it.


Think of the values as files on your disk - if you want to edit your shopping list you must load it into memory, make changes, then save it back to disk. For these values you just load them into a variable (a-z, var0-var8), make changes, then save them back.


Imagine a game where you're a wizard and are wandering around collecting items for your spells and potions. Use these new values to hold counts of how many of each item you've collected. First define the values you want to keep track of:
 
const V1_Amber       = 0
const V1_BayLaurel   = 1
const V1_Coriander   = 2
const V1_GarlicClove = 3
const V1_Lavender    = 4
const V1_Oil         = 5
const V1_Quartz      = 6
const V1_Rosemary    = 7
const V1_Thyme       = 8
const V1_Toadstool   = 9
 
When a new game starts you want all the counts to be zero. You can do it like this:
 temp1 = SetValue1(#V1_Amber,       0)
 temp1 = SetValue1(#V1_BayLaurel,   0)
 temp1 = SetValue1(#V1_Coriander,   0)
 temp1 = SetValue1(#V1_GarlicClove, 0)
 temp1 = SetValue1(#V1_Lavender,    0)
 temp1 = SetValue1(#V1_Oil,         0)
 temp1 = SetValue1(#V1_Quartz,      0)
 temp1 = SetValue1(#V1_Rosemary,    0)
 temp1 = SetValue1(#V1_Thyme,       0)
 temp1 = SetValue1(#V1_ToadStool,   0)
 
An alternative way, which would be a little slower but use less ROM, would be to use a for-next loop. The item #s are 0 thru 9 so:
 for x = 0 to 9 : temp1 = SetValue1(x, 0) : next
 
this might work too, and would make the intent a bit clearer:
 for x = #V1_Amber to #V1_ToadStool : temp1 = SetValue1(x, 0) : next
 
As your wizard goes around collecting things you need to update your inventory.
FoundToadstool
 rem for this function:
 rem var0 is used for toadstool count
 var0 = GetValue1(#V1_ToadStool) : rem get the current count for toadstools
 if var0 < 255 then var0 = var0 + 1 : rem max toadstools we can have are 255
 temp1 = SetValue1(#V1_ToadStool, var0) : rem we are done changing count, so need to save it
 return

FoundGarlicBulb
 rem for this function:
 rem var0 is used for starting clove count
 rem var1 is used for # of found cloves
 rem var2 is used for ending clove count
 var0 = GetValue1(#V1_GarlicClove) : rem get the current count for garlic cloves
 var1 = (rand & 3) + 4 : rem garlic bulbs have a variable number of garlic cloves, for this demo we are using a random number 4-7
 var2 = var0 + var1 : add the number of just found cloves to our current balance
 if var2 < var0 then var2 = 255 : rem if var2 < var0 then the count exceeded the max of 255 that can be held in a byte
 temp1 = SetValue1(#V1_GarlicClove, var2): rem we are done changing count, so save it
 return

etc.
 
Now that we have items, we want to brew up a healing potion. Let's say that needs a bay laurel, 3 garlic cloves, oil and 2 thyme:
 function HealingPotion
   rem for this function:
   rem var0 is used for bay laurel count
   rem var1 is used for garlic clove count
   rem var2 is used for oil count
   rem var3 is used for thyme count

   rem get our ingredients
   var0 = GetValue1(#V1_Baylaurel)
   var1 = GetValue1(#V1_GarlicClove)
   var2 = GetValue1(#V1_Oil)
   var3 = GetValue1(#V1_Thyme)

   rem make sure we have enough
   if var0 < 1 then return 0 : rem do we have enough bay laurel?  A return value of 0 means no potion made
   if var1 < 3 then return 0 : rem do we have enough garlic clove?
   if var2 < 1 then return 0 : rem do we have enough oil?
   if var3 < 2 then return 0 : rem do we have enough thyme?

   rem subtract them from inventory
   var0 = var0 - 1 : rem bay laurel
   var1 = var1 - 3 : rem garlic clove
   var2 = var2 - 1 : rem oil
   var3 = var3 - 2 : rem thyme

   rem update(save) our inventory
   temp1 = GetValue1(#V1_Baylaurel, var0)
   temp1 = GetValue1(#V1_GarlicClove, var1)
   temp1 = GetValue1(#V1_Oil, var2)
   temp1 = GetValue1(#V1_Thyme, var3)

   return 1 : rem return value of 1 means potion was made
 

Any help?

#28 wallaby OFFLINE  

wallaby

    Chopper Commander

  • 100 posts

Posted Wed Sep 14, 2016 7:25 PM

This really solves the variable problem. And in good time too. I just ran out. I was going to use the stack but this is much easier to use.



#29 Random Terrain ONLINE  

Random Terrain

    Visual batari Basic User

  • Topic Starter
  • 28,330 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Wed Sep 14, 2016 7:57 PM

Any help?


I'm sure that will help after I get more sleep. I'll read it in detail tomorrow. Thanks.

#30 SpiceWare ONLINE  

SpiceWare

    Draconian

  • 11,662 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Fri Sep 16, 2016 9:26 AM

When a new game starts you want all the counts to be zero. You can do it like this:

temp1 = SetValue1(#V1_Amber, 0)
temp1 = SetValue1(#V1_BayLaurel, 0)
temp1 = SetValue1(#V1_Coriander, 0)
temp1 = SetValue1(#V1_GarlicClove, 0)
temp1 = SetValue1(#V1_Lavender, 0)
temp1 = SetValue1(#V1_Oil, 0)
temp1 = SetValue1(#V1_Quartz, 0)
temp1 = SetValue1(#V1_Rosemary, 0)
temp1 = SetValue1(#V1_Thyme, 0)
temp1 = SetValue1(#V1_ToadStool, 0)
 
An alternative way, which would be a little slower but use less ROM, would be to use a for-next loop. The item #s are 0 thru 9 so:
for x = 0 to 9 : temp1 = SetValue1(x, 0) : next
 
this might work too, and would make the intent a bit clearer:
for x = #V1_Amber to #V1_ToadStool : temp1 = SetValue1(x, 0) : next

 
There's a way to have DPC+ fill memory that would be super fast. I've never used it myself as it wouldn't make sense to drop out of the fast C code, have the slow 6507 request DPC+ to fill memory, then return to the fast C code.
 
; prep the datafetcher
    ; set the starting location
    lda #V1_Amber 
    sta DF0LOW

    ; set the page.  Use $0f for V1_, $0e for V2_, or $0d for V3_ values
    lda #$0f 
    sta DF0HI


 ; set the parameters
    ; fill value (can fill any value 0-255 that you wish).  stored twice, probably so the "data fetcher" and "bytes to fill" match the copy function
    lda #0 
    sta PARAMETER
    sta PARAMETER

    ; data fetcher (the one used above in "prep the datafetcher")
    lda #0 
    sta PARAMETER

    ; how many bytes to fill
    lda #(V1_ToadStool - V1_Amber) + 1 ; same as lda #10, but makes meaning clearer on the range to be filled
    sta PARAMETER


 ; trigger the fill process
    ; 2 selects the "Fill function"
    lda #2 
    sta CALLFUNCTION
 
Note: code is untested

#31 Mr SQL OFFLINE  

Mr SQL

    Stargunner

  • 1,754 posts

Posted Fri Sep 16, 2016 10:12 AM

imo it would be more intuitive for BASIC programming to expose the DPC stack transparently as a variable array that could be used interchangably with other variables instead of requiring compound functions:

 

 g = f  + DPC(0) + DPC(30)*r

 

It would take a lot of compiler code revision to make array variables work with regular vars like that, but not so much if they are just being exposed as an array and shuttled back and forth into low ram vars before participating in expression calcs:

 

 g=DPC(50):DPC(51)=r

 

One thing to keep in mind is that BASIC has the concept of = being intuitive (there is no == or ===) so to even integrate "g=DPC(#myvar):DPC(5)=37" requires that a c programmer forget about ==. If you dig into the source code you will doubtless find batari's hooks to handle when = means equals and when = means ==; but it only means that to the c programmer, to the BASIC programmer c style functions can be confusing.



#32 Random Terrain ONLINE  

Random Terrain

    Visual batari Basic User

  • Topic Starter
  • 28,330 posts
  • Controlled Randomness
    Replay Value
    Nonlinear
  • Location:North Carolina (USA)

Posted Sun Sep 18, 2016 8:21 PM

I'm sure that will help after I get more sleep. I'll read it in detail tomorrow. Thanks.


It took longer before I could get to it. Thanks for trying to make it clearer. I don't use functions since they are too complicated for me to use. Speaking of complicated, I also quit using Nybble Variables because the code for one of my programs became so confusing that I quit working on it for several years. When I eventually yanked out the Nybble Variables, I could finally work on the program again. As long as I keep it simple and avoid things that are too hard to remember, I can get things done.



#33 Lillapojkenpćön OFFLINE  

Lillapojkenpćön

    Space Invader

  • 41 posts

Posted Fri Dec 1, 2017 3:17 PM

Is this faster than the regular way of using the stack?

 

I pull and push values to temp2 and temp3 every frame of the main loop the normal way..

 stack 70
 pull temp2 temp3

 (increase or decrease temp2 and temp3 values)

and then

 stack 72
 push temp2 temp3

 

 I tried to pull like this instead

 asm
    ; A = location 0-255
    LDA #<(STACKbegin+72)

    sta DF0LOW

    lda #$0f

    sta DF0HI

    lda DF0DATA

    ; A is the return value
    STA temp2
end

 

..and push like this

 asm

  ; Y = value
    LDY temp2

  ; A = location 0-255
    LDA #<(STACKbegin+72)

  sta DF0LOW

  lda #$0f

  sta DF0HI

  sty DF0WRITE
end

 

That seems to push and pull correct for temp2 but alot of other thing start to glitch, the players will teleport a couple pixels to the right, then back again etc.

If this isn't faster I will keep the regular way, but it would still be nice to know what's wrong with it?






0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users