+Random Terrain Posted September 12, 2016 Share Posted September 12, 2016 Back when RevEng had more time, he made improvements to batari Basic. Would it be possible for another person who is good at assembly language programming to dive in and convert the DPC+ 256 stack locations into 256 variables? If all 256 spots couldn't be used as variables, how about 200 variables? If 200 would still be too many, how about 100 variables? I'll take what I can get. Thanks. Quote Link to comment Share on other sites More sharing options...
Mr SQL Posted September 12, 2016 Share Posted September 12, 2016 http://atariage.com/forums/topic/255271-basic-programming-example-with-800-variables/ Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted September 12, 2016 Author Share Posted September 12, 2016 http://atariage.com/forums/topic/255271-basic-programming-example-with-800-variables/ Thanks, but that's not batari Basic's DPC+. Quote Link to comment Share on other sites More sharing options...
Mr SQL Posted September 12, 2016 Share Posted September 12, 2016 It's 800 variables RT - what happened to I'll take what I can get? It would be cool to see more variables in DPC+ but you can declare thousands of variables with virtual world BASIC's RAM arrays if you have a project that needs a lot of variables right now. Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted September 12, 2016 Share Posted September 12, 2016 It's 800 variables RT - what happened to I'll take what I can get? It would be cool to see more variables in DPC+ but you can declare thousands of variables with virtual world BASIC's RAM arrays if you have a project that needs a lot of variables right now. R.T. sometimes has his games physically published like Seaweed Assault. SuperCharger users are rare and CBS RAM donor carts are sometimes hard to find. He was thinking some of the RAM or EEPROM storage available to DPC+ carts could be re-purposed for batari BASIC. Kind of a hard position DPC+ or not. 1 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted September 12, 2016 Author Share Posted September 12, 2016 It's 800 variables RT - what happened to I'll take what I can get? It would be cool to see more variables in DPC+ but you can declare thousands of variables with virtual world BASIC's RAM arrays if you have a project that needs a lot of variables right now. I'll take what I can get with the 10 multicolored single-height sprites and high resolution playfield with simultaneous multicolored foreground and background. 2 Quote Link to comment Share on other sites More sharing options...
wallaby Posted September 12, 2016 Share Posted September 12, 2016 I'm using the stack as extra variables but it depends on how you use it. I use the stack command to position the location manually and store information there sort of like RAM. This range is for this thing, this range is for this thing, and so on. Where it gets tricky is manipulating the stack. The key is you need to first pull the data out in a variable. So while you can store more information, you can't use it all at once. I go to the stack location and pull the data out using temp variables. Manipulate it as I need, then push it back. This is more cycle intensive than just changing a normal variable. Thinking about it now though, maybe you can just manipulate the stack memory locations directly. I mean, we have the "stack" command, but maybe you don't have to use it that way and can use it like any other memory location. Hmm. Maybe the whole stack interface is unnecessary? 1 Quote Link to comment Share on other sites More sharing options...
Mr SQL Posted September 12, 2016 Share Posted September 12, 2016 I'll take what I can get with the 10 multicolored single-height sprites and high resolution playfield with simultaneous multicolored foreground and background. That's pretty cool! R.T. sometimes has his games physically published like Seaweed Assault. SuperCharger users are rare and CBS RAM donor carts are sometimes hard to find. He was thinking some of the RAM or EEPROM storage available to DPC+ carts could be re-purposed for batari BASIC. Kind of a hard position DPC+ or not. To boot it looks like none of these technologies work on the new Atari portable - DPC+ or vwB, but plain batari BASIC does. Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted September 12, 2016 Share Posted September 12, 2016 In the end I hope an AtariAge 2600 clone comes along with DPC+, extra RAM, AtariVox and SaveKey support built in. Pending that I wonder why a stack instead of directly accessible RAM was used. Maybe to maintain compatibility with the Activision DPC? 1 Quote Link to comment Share on other sites More sharing options...
RevEng Posted September 12, 2016 Share Posted September 12, 2016 The stack memory in question is locked up inside the ARM chip, and it's not normally accessible to the 6502 - except when the 6502 uses DPC+ functions to fetch it and put it back. The closest you can get to random access with this memory is exactly what wallaby is doing, and yes, it's cumbersome and cycle-intensive. There's no reason why a new standard - lets call it DPC++ - couldn't have RAM mapped into 6502 address space like the SARA chip. Just bear in mind you'll lose twice as much ROM as the RAM you get, and someone "just" needs to rewrite the ARM code and go through all of the testing. 2 Quote Link to comment Share on other sites More sharing options...
bogax Posted September 12, 2016 Share Posted September 12, 2016 (edited) The stack memory in question is locked up inside the ARM chip, and it's not normally accessible to the 6502 - except when the 6502 uses DPC+ functions to fetch it and put it back. So with the current DPC+ standard you won't be able The closest you can get to random access with this memory is exactly what wallaby is doing, and yes, it's cumbersome and cycle-intensive. There's other way DPC+. There's no reason why a new standard - lets call it DPC++ - couldn't have RAM mapped into 6502 address space like the SARA chip. Just bear in mind you'll lose twice as much ROM as the RAM you get, and someone "just" needs to rewrite the ARM code and go through all of the testing. how does RAM on the cartridge port(?) know if you're reading or writing? edit: you mention losing twice as much ROM so are you talking about using an address line for R/W ie read a location at one address and write that location at another address? Edited September 12, 2016 by bogax Quote Link to comment Share on other sites More sharing options...
wallaby Posted September 12, 2016 Share Posted September 12, 2016 Regarding the current stack, I feel it's great for storing information that doesn't change every frame. You can use it like 256 extra variables this way. It's funny, before I starting writing an Atari 2600 game, 256 bytes would have been completely inconsequential to me. 1 Quote Link to comment Share on other sites More sharing options...
RevEng Posted September 12, 2016 Share Posted September 12, 2016 how does RAM on the cartridge port(?) know if you're reading or writing? edit: you mention losing twice as much ROM so are you talking about using an address line for R/W ie read a location at one address and write that location at another address? Yeah, just like SARA. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 12, 2016 Share Posted September 12, 2016 Back when RevEng had more time, he made improvements to batari Basic. Would it be possible for another person who is good at assembly language programming to dive in and convert the DPC+ 256 stack locations into 256 variables? If all 256 spots couldn't be used as variables, how about 200 variables? If 200 would still be too many, how about 100 variables? I'll take what I can get. Thanks. A couple assembly functions would probably do it for you. These are untested: SetValue ; A = location 0-255 ; Y = value clc adc #<STACKbegin sta DF7LOW lda #0 adc #>STACKbegin sta DF7HI sty DF7WRITE RETURN GetValue ; A = location 0-255 clc adc #<STACKbegin sta DF7LOW lda #0 adc #>STACKbegin sta DF7HI lda DF7DATA ; A is the return value RETURN To use you'd do something like this: rem constants for locations the values are stored in the Stack RAM. Use values from 0 to 255 const SR_HitPoints = 0 const SR_Strength = 1 rem temp1 is the dummy return value for SetValue temp1 = SetValue(#SR_HitPoints, #10) : rem init hit points to 10 temp1 = SetValue(#SR_Strength, #20) : rem init strength to 20 REM take damage b = GetValue(#SR_HitPoints) b = b - 1 temp1 = SetValue(#SR_HitPoints, b) REM workout successful b = GetValue(#SR_Strength) b = b + 4 temp1 = SetValue(#SR_Strength, b) REM poisoned! b = GetValue(#SR_HitPoints) b = b - 5 temp1 = SetValue(#SR_HitPoints, b) b = GetValue(#SR_Strength) b = b - 2 temp1 = SetValue(#SR_Strength,b) If you start at the bottom of the stack (location 0) for your values, you can still use the stack like normal. Just make sure you don't collide - if you push 100 values on the stack without pulling any off, it'd overwrite data you stored at location 156. There's a bit of overhead for accessing these values, so save the most frequently used values in normal RAM and use these functions for things that aren't used as often. 1 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 12, 2016 Share Posted September 12, 2016 If you start at the bottom of the stack (location 0) for your values, you can still use the stack like normal. Just make sure you don't collide - if you push 100 values on the stack without pulling any off, it'd overwrite data you stored at location 156. On second thought that won't work. Data Fetcher 7 is what keeps track of where the stack is pointing at. Those functions would change that pointer. Looks like when you call the DPC+ version of drawscreen it initializes the other datafetchers, so if you change those functions to use data fetcher 0 (or DF1, DF2, ..., DF6) then you can also use the stack as normal: SetValue ; A = location 0-255 ; Y = value clc adc #<STACKbegin sta DF0LOW lda #0 adc #>STACKbegin sta DF0HI sty DF0WRITE RETURN GetValue ; A = location 0-255 clc adc #<STACKbegin sta DF0LOW lda #0 adc #>STACKbegin sta DF0HI lda DF0DATA ; A is the return value RETURN 1 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 12, 2016 Share Posted September 12, 2016 I see this in DPCplusbB.h: echo "DPC free RAM=",($1000-(USERSTACK&$0FFF))d What value does that output when you compile your various bB DPC+ projects? Is it consistent? If not, is it always greater than 256?What I'm looking at is if the last page ($0F00 - $0FFF) of DPC+ RAM is always free then you could use that RAM for variable storage and the functions would be shorter/faster: SetValue ; A = location 0-255 ; Y = value sta DF0LOW lda #$0f sta DF0HI sty DF0WRITE RETURN GetValue ; A = location 0-255 sta DF0LOW lda #$0f sta DF0HI lda DF0DATA ; A is the return value RETURN If that value is greater than 256 then you can safely use these new functions, as well as use the stack like normal.If the value is less than 256 you could just ignore the stack and use the new functions, or you could shrink the stack and use the new functions. If the value reported was 243 then you'd need to adjust the stack by 13 (256-243) and thus set the STACK to either 13 (0+13) or 242 (255-13). I'm not sure how the STACK command is implemented so don't know which of those 2 values would be correct. 2 Quote Link to comment Share on other sites More sharing options...
wallaby Posted September 13, 2016 Share Posted September 13, 2016 If that value is greater than 256 then you can safely use these new functions, as well as use the stack like normal. I only have one current project, but it reports DPC Ram = 603. I'll see if it changes as I add more code and stack manipulation. 1 Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted September 13, 2016 Share Posted September 13, 2016 On second thought that won't work. Data Fetcher 7 is what keeps track of where the stack is pointing at. Those functions would change that pointer. Looks like when you call the DPC+ version of drawscreen it initializes the other datafetchers, so if you change those functions to use data fetcher 0 (or DF1, DF2, ..., DF6) then you can also use the stack as normal: SetValue ; A = location 0-255 ; Y = value clc adc #<STACKbegin sta DF0LOW lda #0 adc #>STACKbegin sta DF0HI sty DF0WRITE RETURN GetValue ; A = location 0-255 clc adc #<STACKbegin sta DF0LOW lda #0 adc #>STACKbegin sta DF0HI lda DF0DATA ; A is the return value RETURN FastFetch Mode is off at this point, no? If not you can still safely use AND #0 instead of LDA #0 to get around this. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 13, 2016 Share Posted September 13, 2016 FastFetch Mode is off at this point, no? If not you can still safely use AND #0 instead of LDA #0 to get around this. Yep, it's off. The bB DPC+ kernel turns fast fetch on before it starts drawing the display, then back off when it's done. I suspect that's because it'd be too difficult to rewrite the existing bB framework to not use LDA #. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 13, 2016 Share Posted September 13, 2016 I only have one current project, but it reports DPC Ram = 603. I'll see if it changes as I add more code and stack manipulation. Wow, way more than I was expecting. Time for a revision! The following in DPCplusbB.h will output a value when you compile your bB program: echo "DPC free RAM=",($1000-(USERSTACK&$0FFF))d Considering the value reported by that - if you want to use the DPC+ Stack then: If the value is >= 256 then you can use Set/GetValue1 to save 256 values If the value is >= 512 then you can also use Set/GetValue2 for a total of 512 values 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 SetValue1 ; A = location 0-255 ; Y = value sta DF0LOW lda #$0f sta DF0HI sty DF0WRITE RETURN GetValue1 ; A = location 0-255 sta DF0LOW lda #$0f sta DF0HI lda DF0DATA ; A is the return value RETURN SetValue2 ; A = location 0-255 ; Y = value sta DF0LOW lda #$0e sta DF0HI sty DF0WRITE RETURN GetValue2 ; A = location 0-255 sta DF0LOW lda #$0e sta DF0HI lda DF0DATA ; A is the return value RETURN Example of using both sets of functions: rem constants for locations of values stored in last page of DPC+ RAM rem assign constants to unique values from 0 to 255 rem V1_ helps to reinforce the use of GetValue1() and SetValue1() const V1_HitPoints = 0 rem constants for locations of values stored in second-to-last page of DPC+ RAM rem assign constants to unique values from 0 to 255 rem V2_ helps to reinforce the use of GetValue2() and SetValue2() const V2_Strength = 0 rem temp1 is the dummy return value for SetValue temp1 = SetValue1(#V1_HitPoints, #10) : rem init hit points to 10 temp1 = SetValue2(#V2_Strength, #20) : rem init strength to 20 REM take damage b = GetValue1(#V1_HitPoints) b = b - 1 temp1 = SetValue1(#V1_HitPoints, b) REM workout successful b = GetValue2(#V2_Strength) b = b + 4 temp1 = SetValue2(#V2_Strength, b) REM poisoned! b = GetValue1(#V1_HitPoints) b = b - 5 temp1 = SetValue1(#V1_HitPoints, b) b = GetValue2(#V2_Strength) b = b - 2 temp1 = SetValue2(#V2_Strength,b) Get/SetValue1 uses the last page, $0F, of DPC+ RAM. Get/SetValue2 uses the second-to-the-last page, $0E, of DPC+ RAM. Items are on the same page when the high-byte of their addresses have the same value, so addresses $0F00 and $0FFF are both on the same page (page $0F) while $0EFF and $0F00 are on different pages (page $0E and $0F respectively). 1 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 13, 2016 Share Posted September 13, 2016 I made some minor revisions to the above example - namely changed the constants from SR# (from the original "Stack RAM") to V# to denote Value. 1 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 13, 2016 Share Posted September 13, 2016 When you get around to testing these functions you can use Stella to make sure the values are being set like you expect. The values saved with SetValue1() should be found on page $0F of Cartridge RAM: Those saved with SetValue2() should be on page $0E: 1 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted September 13, 2016 Author Share Posted September 13, 2016 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. Quote Link to comment Share on other sites More sharing options...
wallaby Posted September 14, 2016 Share Posted September 14, 2016 (edited) EDIT Fixed it. Here is the code adapted to bB function SetValue1 asm ; A = location 0-255 ; Y = value sta DF0LOW lda #$0f sta DF0HI sty DF0WRITE end return function GetValue1 asm ; A = location 0-255 sta DF0LOW lda #$0f sta DF0HI ;lda DF0DATA ; A is the return value end return DF0DATA function SetValue2 asm ; A = location 0-255 ; Y = value sta DF0LOW lda #$0e sta DF0HI sty DF0WRITE end return function GetValue2 asm ; A = location 0-255 sta DF0LOW lda #$0e sta DF0HI ;lda DF0DATA ; A is the return value end return DF0DATA I commented out the last LDA on the Get functions because of how I return from the functions. If I leave the LDA in, the return value is 1 off. If I comment it out, it works as expected in bB. Edited September 14, 2016 by wallaby Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 14, 2016 Share Posted September 14, 2016 Yep - doing LDA DF0DATA followed by RETURN DF0DATA would result in the next value being returned instead of the value you wanted as the Data Fetcher's pointer would have advanced to the next memory location after the first DF0DATA. When I wrote the Sound Effect Driver a few years back I put the functions such as sfxtrigger in a file called sfx.asm: sfxtrigger tay ; sound effect is passed in accumulator, move to Y ldx SFX_LEFT ; test left channel lda sfxCV,x ; CV value will be 0 if channel is idle bne .leftnotfree ; if not 0 then skip ahead sty SFX_LEFT ; channel is idle, use it RETURN ; all done .leftnotfree ldx SFX_RIGHT ; test right channel lda sfxCV,x ; CV value will be 0 if channel is idle bne .rightnotfree ; if not 0 then skip ahead sty SFX_RIGHT ; channel is idle, use it RETURN ; all done .rightnotfree cpy SFX_LEFT ; test sfx priority with left channel bcc .leftnotlower ; skip ahead if new sfx has lower priority than active sfx sty SFX_LEFT ; new sfx has higher priority so use left channel RETURN .leftnotlower cpy SFX_RIGHT ; test sfx with right channel bcc .rightnotlower ; skip ahead if new sfx has lower priority than active sfx sty SFX_RIGHT ; new sfx has higher priority so use right channel .rightnotlower RETURN then included that file in a bB demo program via the inline statement. Doing it that way I didn't need to use function, asm, or end. My understanding, based on the documentation for function, is whatever was in the accumulator (A) would be the return value; though, the driver didn't have values to return so I never confirmed that was true. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.