Jump to content
IGNORED

What's the Point(er)?


Recommended Posts

I'm attempting to mix bB code and Assembly to do some more advanced things, such as having a single bank of colors/sprites that are assigned to players based on a variable. Note that this is using the DPC+ bB kernel.

 

The issue here is in regards to pointers and how flexible they are in Assembly, because I don't know.

 

For instance, I have a set of colors for a sprite:

 


asm
milCol
.byte  $D6
.byte  $D6
.byte  $D6
.byte  $D6
.byte  $D6
.byte  $D6
.byte  $D6
end

 

I want to call this bank of color values and assign them to every player in a loop, in case I want to assign a specific color to individual players later.

 

 

I noticed when looking at the game's assembly that colors are assigned like so:

 


.L0241 ;  player2color:

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

.L0242 ;  player3color:

lda #<(playerpointers+22)
sta DF0LOW
lda #(>(playerpointers+22)) & $0F
sta DF0HI
LDX #<playercolorL0242_3
STX DF0WRITE
LDA #((>playercolorL0242_3) & $0f) | (((>playercolorL0242_3) / 2) & $70)
STA DF0WRITE
.
; 

 

There's a pattern--players 1-9 are assigned their low and high points using the (playerpointers+x) phrase where x = 20 + (sprite# * 2)

 

I'm attempting the following:

 


for temp1 = 0 to 3

temp2 = 20 + temp1 + temp1

asm
.enemycolor

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

next

 

This should calculate where the high and low points for the player pointer will be and add it to playerpointers in order to point to the right location. It compiles, but doesn't work. Is there some special way I need to address the temp2 variable in order to allow it to be added to playerpointers?

 

This also applies to sprites. I would like the sprite for any player to be chosen based on a certain variable (in my case it's enemy0, enemy1, enemy2, etc.) so, if enemy0 is 1, it will grab a certain sprite for that player and set it to a certain color, without the redundancy of repeating sprite and color tables for each possible combination for each player.

 

There are two ways to do it. Either I could have a series of statements like the above .enemycolor for each possible color/sprite and then adjust the player's pointer based on a variable to point to the sprite/colors that are applicable, or (preferably) I need some way to change which data set is being loaded on the fly, such as the following mock-up:

 


for temp1 = 0 to 3

temp2 = 20 + temp1 + temp1

data playerColors
milCol, milCol, milCol, drkCol
end

temp3 = enemy0[temp1]
temp4 = playerColors[temp3]

asm
.enemycolor

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

next

 

...

 


asm
milCol
.byte  $D6
.byte  $D6
.byte  $D6
.byte  $D6
.byte  $D6
.byte  $D6
.byte  $D6


drkCol
.byte  $00
.byte  $00
.byte  $00
.byte  $00
.byte  $00
.byte  $00
.byte  $00
end

 

So, two questions:

 

1. Is there any way to dynamically adjust the value being used for the player's pointer?

 

2. Is there any way to dynamically adjust which data set is being pointed to?

Link to comment
Share on other sites

I know nothing of DPC+

 

one thing,

 

temp2 is a constant

in the standard kenel its = $9D

where you have

lda #<(playerpointers+temp2)

I think you want something like

lda temp2
clc
adc #<playerpointers

so something like eg

for temp1 = 20 to 26 step 2

enemycolor
asm
lda #<playerpointers
clc
adc temp1
sta DF0LOW
lda #>playerpointers
clc
adc temp1
and #$0F
sta DF0HI
lda #<milCol
sta DF0WRITE
lda #((>milCol) & $0F) | (((>milCol) / 2) & $70)
sta DF0WRITE
end

next

Link to comment
Share on other sites

I have been able to change the playfield pixel on/off, and the playfield colors.

Just by trial and error by the way and without assembly.

I haven't found where to point to the players or their colors yet.

I think I posted code in my pointers thread, but it is like this:

DF7LO = 96

DF7HI = 40

DF7PUSH = rand

DF7PUSH = rand

DF7PUSH = rand

DF7PUSH = rand

DF7PUSH = rand

 

drawscreen

 

That will change the bottom of PF2R (the 8 bits of the right side playfield) in my 128 value playfield.

If playfield data is in this drawscreen loop before this it will keep setting it back and changing it.

 

Link to comment
Share on other sites

There's a pattern--players 1-9 are assigned their low and high points using the (playerpointers+x) phrase where x = 20 + (sprite# * 2)

 

.

.

.

This also applies to sprites. I would like the sprite for any player to be chosen based on a certain variable (in my case it's enemy0, enemy1, enemy2, etc.) so, if enemy0 is 1, it will grab a certain sprite for that player and set it to a certain color, without the redundancy of repeating sprite and color tables for each possible combination for each player.

 

There are two ways to do it. Either I could have a series of statements like the above .enemycolor for each possible color/sprite and then adjust the player's pointer based on a variable to point to the sprite/colors that are applicable, or (preferably) I need some way to change which data set is being loaded on the fly, such as the following mock-up:

 


for temp1 = 0 to 3

temp2 = 20 + temp1 + temp1

data playerColors
milCol, milCol, milCol, drkCol
end

temp3 = enemy0[temp1]
temp4 = playerColors[temp3]

asm
.enemycolor

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

next

 

...

 


asm
milCol
.byte $D6
.byte $D6
.byte $D6
.byte $D6
.byte $D6
.byte $D6
.byte $D6


drkCol
.byte $00
.byte $00
.byte $00
.byte $00
.byte $00
.byte $00
.byte $00
end

 

 

I know nothing of DPC+

 

Your code is kind of goofy sometimes and I

didn't try to figure out if it will do what

you want it to do.

 

Here's that code in bB

 

const pptrs_lo = <playerpointers
const pptrs_hi = >playerpointers

data playerColorslo
<milCol, <milCol, <milCol, <drkCol
end

data playerColorshi
>milCol, >milCol, >milCol, >drkCol
end

temp1 = 0
for temp2 = 20 to 26 step 2

temp3 = enemy0[temp1]

DF0LOW = pptrs_lo + temp2
DF0HI = (pptrs_hi + temp2) & $0F
DF0WRITE = playerColorslo[temp3]
temp3 = playerColorshi[temp3]
temp4 = temp3 & $0F
DF0WRITE = ((temp3 / 2) & $70) | temp4

temp1 = temp1 + 1
next

 

It looks like DF0LOW, DF0HI, DF0WRITE

are just regular variables in the DPC+

kernel (that is, they're zero page locations

that can be written to) but I can never

get DPC+ to work.

If they're dimmed to variables in the

standard kernel that code will compile.

Link to comment
Share on other sites

The code in bogax's second reply looks like the way to go-- although I haven't tried it.

 

I don't think anyone really explained why your code didn't work right. You can include math in an assembly instruction like you did-- LDA #<(playerpointers+temp2)-- but that doesn't mean the math will be done at runtime. What happens is the math is done by the assembler while it's assembling the code, so what you actually end up with is something quite different than what you were expecting. The assembler can't treat temp2 like a variable, because it has no way to know ahead of time what value will be stored in temp2 when the instruction is being executed. So what is has to do is treat temp2 like a label and use the value of the label-- i.e., its address-- while boiling the math down into a single value that can be written to the ROM file in the second half of that instruction (i.e., the byte that follows the opcode).

Link to comment
Share on other sites

By the way, it's hard to tell what's indented and what's not, because the forum software likes to eat leading spaces-- but it looks like the "asm" keyword is definitely indented but I can't see that the actual assembly code is. You need to indent assembly code the same way you do batari Basic code:

 

  asm

this_is_a_label ; labels aren't indented

  lda #1 ; this is assembly code, it needs to be indented at least 1 space

end ; the end keyword is typed as though it were a label-- do not indent it

 

That goes for things like BYTE, WORD, and HEX, too:

 

My_Data ; do not indent the label

  HEX DE AD BE EF DE AD BE EF DE AD BE EF ; but do indent HEX, BYTE, WORD, etc.

Link to comment
Share on other sites

It does something. But I'm lost here:

 

temp3 = enemy0[temp1]

 

What is enemy0 ?

How do I replace it with player8 so I can change its bits? Or player8's colors ?

 

enemy0 is a variable set aside to hold that enemy's "status" value.

 


dim enemy0 = j
dim enemy1 = k
dim enemy2 = l
dim enemy3 = m
dim enemy4 = n

 

Basically, it allows me to randomize what the enemy will be (which will determine sprite, color, spawn location, etc.) and, when set to 0, will denote that the enemy is destroyed.

 

Sorry--should have mentioned that.

 

Haven't had a chance to try the above code yet, but I hope to do so first thing tomorrow! I've been taking today off for a bit of R&R from non-stop 2600 stuff.

 

By the way, it's hard to tell what's indented and what's not, because the forum software likes to eat leading spaces-- but it looks like the "asm" keyword is definitely indented but I can't see that the actual assembly code is. You need to indent assembly code the same way you do batari Basic code:

Yes, it's indented. I think that the assembling would fail if it wasn't indented correctly, right? Or maybe that's only bB.

Edited by Cybearg
Link to comment
Share on other sites

Yes, it's indented. I think that the assembling would fail if it wasn't indented correctly, right? Or maybe that's only bB.

Yes, the assembly should fail if the lines aren't indented. I don't know why the forum software has such an appetite for leading spaces-- it's rather frustrating. It also seems to like to convert multiple spaces into tabs.

Link to comment
Share on other sites

a little shorter, a little faster, uses one less temp variable.

 

const pptrs_lo = <playerptrs
const pptrs_hi = >playerptrs

data playerColorslo
<milCol, <milCol, <milCol, <drkCol
end

data playerColorshi
>milCol, >milCol, >milCol, >drkCol
end

temp1 = 0
for temp2 = 20 to 26 step 2

temp3 = enemy0[temp1]

DF0LOW = pptrs_lo + temp2
DF0HI = (pptrs_hi + temp2) & $0F
DF0WRITE = playerColorslo[temp3]
temp3 = playerColorshi[temp3]
DF0WRITE = (((temp3 / 2) ^ temp3) & $F0) ^ temp3

temp1 = temp1 + 1
next

Link to comment
Share on other sites

Finally got a chance to try it. Sadly, it seems to do pretty much exactly what the other code did: i.e. it compiles, but it doesn't assign the colors. The sprites have a jumbled collection of colors instead of the solid colors they're supposed to have.

 

EDIT: And unfortunately, this doesn't work, either:

 

I know nothing of DPC+

 

one thing,

 

temp2 is a constant

in the standard kenel its = $9D

where you have

lda #<(playerpointers+temp2)

I think you want something like

lda temp2
clc
adc #<playerpointers

so something like eg

for temp1 = 20 to 26 step 2

enemycolor
asm
lda #<playerpointers
clc
adc temp1
sta DF0LOW
lda #>playerpointers
clc
adc temp1
and #$0F
sta DF0HI
lda #<milCol
sta DF0WRITE
lda #((>milCol) & $0F) | (((>milCol) / 2) & $70)
sta DF0WRITE
end

next

omega.bas.bin

omega.bas

omega.bas.asm

Edited by Cybearg
Link to comment
Share on other sites

This is about the highest level of abstraction I can manage with the result being functional (thanks to this for letting me even get this far).

 

It's close, but I need some way to break down that final piece of the color writing.

 


temp1 = 0
temp2 = 0

asm
ldy temp1

lda eclo, y
sta DF0LOW
lda echi, y
sta DF0HI

ldy temp2

LDX collo, y
STX DF0WRITE
LDA #((>milCol) & $0f) | (((>milCol) / 2) & $70)
STA DF0WRITE

eclo
BYTE #<(playerpointers+20)

echi
BYTE #(>(playerpointers+20)) & $0F

collo
BYTE #<milCol

end

Link to comment
Share on other sites

Still needing this.

 

Maybe I can start the thinking with some questions, such as:

 

This is fine:

 

eclo
BYTE <(playerpointers+20)

 

And this is fine:

 

echi
BYTE (>(playerpointers+20)) & $0F

 

and this is fine:

 

collo
BYTE <milCol

 

That is, the code compiles and everything works, but if I do this:

 

colhi
BYTE >milCol

 

or this:

 

colhi
BYTE (>(milCol)) & $0F

 

or this:

 

colhi
BYTE ((>milCol) & $0f) | (((>milCol) / 2) & $70)

 

The code technically compiles, but I just get a flickering black screen with a huge scanline report, so clearly it breaks something.

 

Why? What is this doing:

LDA #((>milCol) & $0f) | (((>milCol) / 2) & $70)

 

And how does that differ from what the playerpointer is doing?

 

Just to make it clear on why this is important: if there is a way to reference colors (and sprites) from an array, that means that any sprite could be quickly and easily assigned for any player without the need for redundancy of multiple identical sprites for each player. It's a pretty big deal, and there are a number of game ideas I have that are rendered impractical to the point of mostly impossible without the ability to reference colors and sprites on the fly.

 

There isn't any magic going on here--I just don't know how these pointers work or what Assembly wants in order to do what I'm trying to do. Does anyone else know?

Edited by Cybearg
Link to comment
Share on other sites

So what does it compile to? I.e. we need to see the list file.

 

 

Also, you should differentiate data tables from ram addresses in your punctuation. It'll make your code much more readable to others, and save you from mistakes as well. I looked at your label "milCol" and thought it was a ram location since it began with a lowercase letter.

 

I follow this:

 

; ram location

milCol ds 1

 

; data label

MilCol:

.byte $23

.byte $a1

 

; constant

MIL_COL = 10

 

That way when I read the code, I immediately know what everything is. By far the worse thing a person could do to themselves is mix spellings on the fly, deciding to do it a particular way one day, and vice-versa the next. Standards vary from person to person, company to company. There is no absolute right way to do it, but the important thing is to at least have a standard, and preferably something most other people do.

Link to comment
Share on other sites

1. Here is how things look with the following code (which works, but it's not enough).

omega_first.zip

 

enemygfx

temp1 = 0
temp2 = 0

asm
ldy temp1

lda eclo, y
sta DF0LOW
lda echi, y
sta DF0HI

ldy temp2

LDX collo, y
STX DF0WRITE
LDA #((>MilCol) & $0f) | (((>MilCol) / 2) & $70)
STA DF0WRITE

eclo
BYTE <(playerpointers+20)

echi
BYTE (>(playerpointers+20)) & $0F

collo
BYTE <MilCol

 

temp1 and temp2 are placeholders for now that would eventually be a for loop index and an indexed memory location, respectively, such as:

 

dim enemyType = a

for temp1 = 0 to 3
  temp2 = enemyType[temp1]
  *assembly here*
next

 

The following compile but don't give anything more than a blank screen in Stella:

 

2.

colhi
BYTE >milCol

omega_second.zip

 

3.

colhi
BYTE (>(milCol)) & $0F

omega_third.zip

 

4.

colhi
BYTE ((>milCol) & $0f) | (((>milCol) / 2) & $70)

omega_fourth.zip

 

EDIT: Sorry, but apparently my bB doesn't compile any .lst files. It used to, but doesn't anymore. It may be connected to all the troubles I've been having with DPC+ not reporting correct bytes remaining, not working on my main system (and only through a VMWare Windows XP), or something along those lines, but each of the attached directories have the .bas, .asm, and .bin files. Hopefully that's enough.

Edited by Cybearg
Link to comment
Share on other sites

I'm attempting to mix bB code and Assembly to do some more advanced things, such as having a single bank of colors/sprites that are assigned to players based on a variable. Note that this is using the DPC+ bB kernel.

 

The issue here is in regards to pointers and how flexible they are in Assembly, because I don't know.

Cybearg,

I found my way here from your other thread on Assembly, lots of complex code here! :)

There are some simple examples of using Assembly or bB to assign sprites to players from a single sprite bank using an offset variable on my thread on learning Assembly.

Link to comment
Share on other sites

 

Cybearg,

I found my way here from your other thread on Assembly, lots of complex code here! :)

There are some simple examples of using Assembly or bB to assign sprites to players from a single sprite bank using an offset variable on my thread on learning Assembly.

Thanks for the suggestion! I had been kind of feeling mixed about whether I wanted to try learning deeper or just finish my ideas with DPC+ (hopefully fairly quickly) and leave it at that, but I think I've decided to stick with homebrews longer than I had been oriignally, so I'll definitely be checking out your awesome set-up, as promised.

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...