Jump to content
IGNORED

Maxximum Confusion


The Maxx

Recommended Posts

Aha! Now, this is something that I'm pretty sure I understand. I've been wondering how to use tables and it appears that it is easier than I thought... kind of like a 1d (read only?) array... that can be used with multiple objects.

 

Thanks!!! Now, I just need to put it to use. :D

 

Yes but it's read only only because it's in ROM

the variables are in sequence in memory so

 

a[0] = 3

a[1] = 4

 

sets a to 3 and b to 4

Link to comment
Share on other sites

I'm not all that familiar with the DPC+ kernel

 

It looks to me like it just passes a pointer to the color table to the ARM code.

so short of modifying the kernel

you could have a routine that passed a pointer from a variable, but the colors themselves would

have to be in a ROM table and they'd have to be in the graphics bank and I think the only

way to get them there is with a player color statement

 

it might be possible to have all the colors in one big playercolor statement though

 

Remember in our DK Arcade 2600 I could only have 2 max resolution playfield screens in the graphics.bank?

I needed a way to add the other 2 playfield levels.

You helped with a routine to set pfpixel on/off from a data table that draws the entire new playfield level.

Advantage: 2 more single line max resolution playfield levels.

------------- Doesn't use DPC+ "graphics bank" space.

Disadvantage: Uses game ROM space for data tables. (A compression/decompression routine will massively reduce the 1,000+ bytes of a max res PF screen)0

---------------- pfpixel statement uses 100+ game ROM bytes (in a loop or subroutine it only costs 100+ bytes once even though you loop over it hundreds of times).

 

You can bypass pfpixel by doing what the compiled pfpixel statement does: setting the hi/low address of the graphics data bank in bB and ARM calls to change Playfield data: DF0PUSH (variables).

 

It it has not been figured out yet, but directly changing other data in DPC+'s "graphics bank" (which is in RAM) such as player colors, playfield colors, player shape data, etc. I think should also be possible because it works for "playfield:"

 

bogax, I hope That the above makes some sense.

Link to comment
Share on other sites

I sent SeaGtGruff a message already, but I'll repost it here to see if you guys can help.

 

http://atariage.com/forums/topic/171024-quick-yes-or-no-question-on-variable-arrays/?p=2116346

 

I think a read/write array would be beneficial to keep track of collectibles in my platformer.

My problem is, I don't really understand the read/write part.

So, I dimmed the array in bank1:

 dim arrayW=$F000
 dim arrayR=$F080

then within the game loop (bank3), i have the player pick up an item:

 if player0x>player1x-4 && player0x<player1x+12 && player0y>player1y-4 && player0y<player1y+12 then player1x=227 : player1y=227 : arrayW[0]=1

To change screens, I jump to another bank to load the stage data:

 player1x=240 : player1y=240
 arrayR[0]=arrayW[0]

 if stage<>0 then goto skip0

 if arrayR[0]=0 then player1x=32 : player1y=128

skip0

 goto stageLoaded bank3

So if it isn't obvious, I only want to place player1 on the screen if it hasn't yet been collected.

 

I am (obviously) doing something wrong. I don't understand how you write to one address, and read that value from another... if you cannot write to the address you are reading from... am I making sense?

Edited by The Maxx
  • Like 1
Link to comment
Share on other sites

Again I'm no expert but I think that's not going to work with DPC+

 

Thats for a different sort of RAM expansion

 

I think what you want is here

 

 

I think iesposta is correct

I think it should be possible to poke the player colors

 

edit OK maybe not

at least I haven't been able to get it to work

 

(I thought maybe you could point the player color pointers at the stack)

Edited by bogax
  • Like 1
Link to comment
Share on other sites

Mmmkay.

 

So, I have some code that works in an emulator, but crashes on real hardware. It is a simple calculation to decide which stage to load when the player passes specific coordinates in the play area:

 ; scroll | change screen

 if player0x<16 then player0x=136 : xPos=136 : scrollFlag{0}=1
 if player0x>136 then player0x=16 : xPos=16 : scrollFlag{1}=1
 if player0y>200 then player0y=160 : scrollFlag{2}=1
 if player0y>160 && player0y<200 then player0y=0 : scrollFlag{3}=1


 ; scrollFlag{0} left, {1} right, {2} up, {3} down

 temp1=stage/4 : temp2=temp1*4 : temp3=stage-temp2  

 if !scrollFlag{0} then goto skipLeft 
 if temp3>0 then stage=stage-1 else stage=stage+3
skipLeft

 if !scrollFlag{1} then goto skipRight
 if temp3<3 then stage=stage+1 else stage=stage-3
skipRight

 if !scrollFlag{2} then goto skipUp
 if stage>3 then stage=stage-4 else stage=stage+12
skipUp

 if !scrollFlag{3} then goto skipDown
 if stage<12 then stage=stage+4 else stage=stage-12
skipDown


 if scrollFlag{0} || scrollFlag{1} then goto loadStage bank4
 if scrollFlag{2} || scrollFlag{3} then goto loadStage bank4

stageLoaded

the "loadStage" routine simply directs the program to load a new playfield and then jumps back. (I'll only include one pf here to conserve space...

 if stage<>0 then goto skip0

 playfield:
 ................................
 ................................
 .............XXX................
 .............X.X................
 .............X.X................
 .............X.X................
 .............X.X................
 .............X.X................
 .............XXX................
 ................................
 ................................
end

 ;  Other playfield data with nearly identical event code here.

 ;  Now that the stage is loaded, turn the stageLoaded scrollFlag on and jump back to the game
 
 scrollFlag{0}=0 : scrollFlag{1}=0 : scrollFlag{2}=0 : scrollFlag{3}=0 : goto stageLoaded bank3

K, so (queso?) loading a new playfield works fine when the player moves up, right, or down. If the player moves to the left, the program crashes. Any ideas?

Link to comment
Share on other sites

  • 2 weeks later...

Three more newbie questions: (DPC+)

 

1. What's up with missile0? Every time I try to change the height, it draws weird diagonal lines. Is there a way to get it to behave more like missile1?

 

2. Can I get missile1 to be any wider than 8 pixels?

 

3. If I understand correctly (which is unlikely), all of the graphics are crammed into one bank. I am running out of room in that bank - is there a way to store more in another bank? Ha.

 

Thanks in advance. :D

Link to comment
Share on other sites

Not a problem.

 

About #2 - Quad width missiles is all you can do. (which is what I think you mean by 8 pixels, since in DPC+ the regular missile is about 2:1 at height=1.)

 

About #3 - It looks like you can with bB DPC+, though I'm not sure anyone has played with this, so I'm not sure if there are limitations.

 

I took a look at the assembly code produced by player2: and player2colors: and modified it to use data in the current bank. That seems to have worked well enough.

 

Here's an example for player2. IIRC the "playerpointers" values used need to increase by +2 to set data for player3, +4 for player4, etc.

 

 asm
 lda #<(playerpointers+20)
 sta DF0LOW
         lda #(>(playerpointers+20)) & $0F
 sta DF0HI
        LDX #<ourplayer_colors
 STX DF0WRITE
 LDA #((>ourplayer_colors) & $0f) | (((>ourplayer_colors) / 2) & $70)
 STA DF0WRITE

 lda #<(playerpointers+2)
 sta DF0LOW
         lda #(>(playerpointers+2)) & $0F
 sta DF0HI
        LDX #<ourplayer_gfx
 STX DF0WRITE
 LDA #((>ourplayer_gfx) & $0f) | (((>ourplayer_gfx) / 2) & $70)
 STA DF0WRITE
         LDA #12
 STA player2height
end

 data ourplayer_gfx
 %11111111
 %11011011
 %11011011
 %11111111
 %11111111
 %11111111
 %11111111
 %11111111
 %10000001
 %11000011
 %11111111
 %11111111
end

 data ourplayer_colors
 $22
 $22
 $24
 $24
 $26
 $26
 $28
 $28
 $2A
 $2A
 $2B
 $2B
end

Before using that, you might want to test it out on real hardware.

Link to comment
Share on other sites

My second game was received with less enthusiasm than my first and I was thinking about throwing it in the same cart as my first - as an easter egg or something. If my third game doesn't grab much attention I might want to do the same.

 

So, my third game is already out of graphics ROM. However, I think there is likely enough space on a DPC cart to contain all three. Would the graphics bankswitching method above still be necessary if it is a game running from a completely different bank? I am assuming the answer is yes, but assuming gets me in trouble. Maybe there is an easier way?

Edited by The Maxx
Link to comment
Share on other sites

  • 3 weeks later...
  • 2 weeks later...

Hello again! :)

 

I have run out of graphics ROM in my game. Luckily, I have most everything I need. I would, however, like to have an arrow cutscene of sorts. I started messing around with a script to draw the arrow this morning. However, I have a few problems.

 

1. The framerate is all over the place. I have tried adding an extra drawscreen here and there, but I can't seem to get it right.

2. Stella detects the ROM as PAL

3. The background color changes - probably due to #2

 

Thanks in advance!

 

//edit//

 

I found some graphics ROM and ended up ditching this bit of code.

Edited by The Maxx
Link to comment
Share on other sites

Mmmkay. I have a problem.

 

My game is in a playable state and I am at the point where I would like to add multiple stages. I wrote the code to read a data table to load a map. I was shortsighted and didn't test to see if the method I had in mind would work. Now I am unsure how to proceed.

 

I have a variable "stage" and thought I might be able to load each stage like this:

 if stage<>0 then goto skipStage0

 data stageData
 0,	16,	22,	12,	5,	4,	44,
 36,	42,	12,	20,	13,	8,	0,
end

skipStage0

 if stage<>1 then goto skipStage1

 data stageData
 40,	0,	46,	8,	17,	20,	40,
 4,	20,	28,	1,	33,	4,	4,
end

skipStage1

etc...

 

Then I have six events that change variables based on the data. ie.

 temp2=stageData[9] : temp3=temp2/7 : temp4=temp3*7 : temp5=temp2-temp4

 xPos=26+temp5*16 : yPos=24+temp3*32
 player0x=xPos : player0y=yPos

 roomNumber=stageData[roomIndex]
 monsterRoom=stageData[10]
 monster2Room=stageData[11]
 monster3Room=stageData[12]
 monster4Room=stageData[13]



(It's not especially necessary to understand what the code above is for... I just posted it to illustrate how the data is being used and why I wouldn't have to duplicate the events for each data set.)

 

However, as more advanced bB users probably saw straight away, you cannot have multiple arrays with the same name - even if you skip the events that load each array. I was shortsighted and didn't think this was going to be a problem while developing the rest of the game. D'oh!

 

So, I am wondering if anyone has a solution to load a data set based on a variable... and use that data set in a bunch of events without having to duplicate the event code for each data set?

 

I hope this makes sense. :?

 

...

 

I did some calculations (and they are probably wrong) by commenting out stage data and load event code. If I could load an array similar to the way I thought i could, I might be able to get around 50 different maps. If I have to duplicate the events per map, I might get 8. :_(

Edited by The Maxx
Link to comment
Share on other sites

Instead of bundling all level data up into 1 array, split everything into different arrays.

 

Something like...

 

 temp2=PlayerPositionData[level] : temp3=temp2/7 : temp4=temp3*7 : temp5=temp2-temp4
 xPos=26+temp5*16 : yPos=24+temp3*32
 player0x=xPos : player0y=yPos
 monster1Room=Monster1Data[level]
 monster2Room=Monster2Data[level]
 monster3Room=Monster3Data[level]
 monster4Room=Monster4Data[level]
 if roomIndex=0 then roomNumber=room0Data[level]
 if roomIndex=1 then roomNumber=room1Data[level]
 if roomIndex=2 then roomNumber=room2Data[level]
 ...

The last roomIndex bit of code could be made to be a bit more space-efficient with on...gosub, but it's not too bad for a single case of 9 elements.

  • Like 1
Link to comment
Share on other sites

Interesting! Thank you! :)

 

I actually shortened the stageData for this post. It's more like 39 elements. Building the room data arrays would be a challenge (I wrote a program that helps me build the stages), but the method you've shown here makes some sense to me... I will have to do some testing. :)

 

...

 

Hmm, actually, I think I have an idea for how I could write another program to gather elements from the multiple stages built in the editor and combine them to correctly form the data arrays that work with your method.

 

Still, tedious. HAHAHHA. I may need to take a break from the project.

Edited by The Maxx
  • Like 1
Link to comment
Share on other sites


indexes are limited to 8 bits so it's definetely best to limit your tables to 256 bytes

when possible


to that end I wrote a bit of javascript that transposes data so that each column goes into

it's own table


for those instances where you need two levels of indirection and still need to compute an index into a

table of tables so to speak I wouldn't use if statements


it's probably smaller and faster to use a lookup table

if you can't fit your table of tables in to 256 bytes you can still do it with microscopic amounts

of asm


using RevEng's example



if roomIndex=0 then roomNumber=room0Data[level]
if roomIndex=1 then roomNumber=room1Data[level]
if roomIndex=2 then roomNumber=room2Data[level]




I'd do it like this (there may be pathological cases where it would be better to use if statments though)




index = roomOffset[roomIndex] ; room_offset is an LUT for number of rooms x number of levels, zero based
roomNumber = roomData[level]

; so if your room index ranges to 0..14 and there are 10 levels your roomOffset table is

data roomOffset
0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140
end

; and your roomData table will be 150 bytes





if the table is more than 256 bytes it'd be something like this




dim indexLo = temp3
dim indexHi = temp4

def load_indirect = callmcro ldin


; looks up a byte from a 16 bit address, lo byte in temp3 hi byte in temp4
; indexed by the value in the variable specified by the first parameter
; and puts it in to the second parameter variable
macro ldin
asm
ldy {1}
lda (temp3),y
sta {2}
end
end




indexLo = roomOffsetLo[roomIndex] ; roomOffsetLo is a table of the lo bytes of the offset
indexHi = roomOffsetHi[roomIndex] ; roomOffsetHi is a table of the hi bytes of the offset

load_indirect level roomNumber



; "<" signifies the lo byte ">" is the hi byte
; these values/expressions are asm not bB
data roomOffsetLo
<(roomData + 0), <(roomData + 10), <(roomData + 20), <(roomData + 30), <(roomData + 40), <(roomData + 50), <(roomData + 60), <(roomData + 70)
<(roomData + 80), <(roomData + 90), <(roomData + 100), <(roomData + 110), <(roomData + 120), <(roomData + 130), <(roomData + 140)
end

data roomOffsetHi
>(roomData + 0), >(roomData + 10), >(roomData + 20), >(roomData + 30), >(roomData + 40), >(roomData + 50), >(roomData + 60), >(roomData + 70)
>(roomData + 80), >(roomData + 90), >(roomData + 100), >(roomData + 110), >(roomData + 120), >(roomData + 130), >(roomData + 140)
end





you break even somwhere around three or four if statements



it would also be possible to calculate the offsets at run time

and if your offsets are a power of 2 that could be fairly fast

(eg in this case, if the number of levels were a power of 2)


you could also do something in between like group them into

tables <= 256 bytes and use if statements to choose a table
Edited by bogax
  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Thanks for all the information above. Admittedly, much of it is over my head... maybe as I get smarter/more acquainted with this stuff, things will start to sink in. I went ahead with my idiotic code duplication method and used bankswitching to get 32 maps. I realized while creating the maps that 32 should be more than enough... at least more than I was really interested in making. Haha, tedium! Anyway, here is another oddity I ran into: I had some event code that looked like this: if !fireLimit && joy0fire then arrowRoomNumber=roomNumber : fireLimit=1 : readyBow=!readyBow : sound=2 if !joy0fire then fireLimit=0 The above works in Stella, but crashes the game on real hardware. I was able to eliminate the issue by adding another line: if !fireLimit && joy0fire then sound=2 if !fireLimit && joy0fire then arrowRoomNumber=roomNumber : fireLimit=1 : readyBow=!readyBow if !joy0fire then fireLimit=0 This works on real hardware, but I can't figure out why the difference would matter at all. Any insight?

 

/edit

 

WHOAH, WTF HAPPENED THERE?

 

... AA forum is being strange. I'll try again

 

Thanks for all the information above. Admittedly, much of it is over my head... maybe as I get smarter/more acquainted with this stuff, things will start to sink in.

 

I went ahead with my idiotic code duplication method and used bankswitching to get 32 maps. I realized while creating the maps that 32 should be more than enough... at least it was more than I was really interested in making. Haha, tedium!

 

Anyway, here is another oddity I ran into: I had some event code that looked like this:

 

if !fireLimit && joy0fire then arrowRoomNumber=roomNumber : fireLimit=1 : readyBow=!readyBow : sound=2

if !joy0fire then fireLimit=0

 

The above works in Stella, but crashes the game on real hardware. I was able to eliminate the issue by adding another line:

 

if !fireLimit && joy0fire then sound=2

if !fireLimit && joy0fire then arrowRoomNumber=roomNumber : fireLimit=1 : readyBow=!readyBow

if !joy0fire then fireLimit=0

 

This works on real hardware, but I can't figure out why the difference would matter at all. Any insight?

Edited by The Maxx
Link to comment
Share on other sites

  • 2 weeks later...

Thanks for all the information above. Admittedly, much of it is over my head... maybe as I get smarter/more acquainted with this stuff, things will start to sink in. I went ahead with my idiotic code duplication method and used bankswitching to get 32 maps. I realized while creating the maps that 32 should be more than enough... at least more than I was really interested in making. Haha, tedium! Anyway, here is another oddity I ran into: I had some event code that looked like this: if !fireLimit && joy0fire then arrowRoomNumber=roomNumber : fireLimit=1 : readyBow=!readyBow : sound=2 if !joy0fire then fireLimit=0 The above works in Stella, but crashes the game on real hardware. I was able to eliminate the issue by adding another line: if !fireLimit && joy0fire then sound=2 if !fireLimit && joy0fire then arrowRoomNumber=roomNumber : fireLimit=1 : readyBow=!readyBow if !joy0fire then fireLimit=0 This works on real hardware, but I can't figure out why the difference would matter at all. Any insight?

 

/edit

 

WHOAH, WTF HAPPENED THERE?

 

... AA forum is being strange. I'll try again

 

Thanks for all the information above. Admittedly, much of it is over my head... maybe as I get smarter/more acquainted with this stuff, things will start to sink in.

 

I went ahead with my idiotic code duplication method and used bankswitching to get 32 maps. I realized while creating the maps that 32 should be more than enough... at least it was more than I was really interested in making. Haha, tedium!

 

Anyway, here is another oddity I ran into: I had some event code that looked like this:

 

if !fireLimit && joy0fire then arrowRoomNumber=roomNumber : fireLimit=1 : readyBow=!readyBow : sound=2

if !joy0fire then fireLimit=0

 

The above works in Stella, but crashes the game on real hardware. I was able to eliminate the issue by adding another line:

 

if !fireLimit && joy0fire then sound=2

if !fireLimit && joy0fire then arrowRoomNumber=roomNumber : fireLimit=1 : readyBow=!readyBow

if !joy0fire then fireLimit=0

 

This works on real hardware, but I can't figure out why the difference would matter at all. Any insight?

 

Is readyBow a bit that you are flipping?

 

Have you tried doing this:


   if !joy0fire then fireLimit = 0 : goto __Skip_Fire_Limit

   if !fireLimit then arrowRoomNumber = roomNumber : fireLimit = 1 : readyBow = !readyBow : sound=2

__Skip_Fire_Limit
Link to comment
Share on other sites

  • 4 months later...

In DPC+, is compiling for PAL systems as simple as changing "set tv ntsc" to "set tv pal"? Both versions of my game seem to run fine in Stella, but I cannot test on a PAL system. Are there any PAL users with a Harmony cartridge that might be interested in testing a ROM for me?

 

Also, I have an explosion sound effect on channel 0 that seems to be affecting the volume level of channel 1. I don't know if it is just my hardware... or? It's probably my code, but I have been through it a few times and cannot see what I have done. It works as expected in Stella.

Edited by mojofltr
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...