Jump to content
IGNORED

My assembly questions thread


Recommended Posts

  • 2 weeks later...

Once you reach the end of the table, if you are reading from a pointer, you could incremens the high bit of the pointer to be able to read from the next page of data.

 

Pointers is the last thing I need to learn, and I'm really having trouble with it!

 

 

Is this how it works?..

 

you point one byte to the beginning of the data

and another byte to the end (256 bytes further down)

and put them together to a 16 bit variable (called table in this example)

 

and then

CLC

LDA #<table

ADC #1 ; if result is > 255 then carry gets set (and the pointer ends up on the next page)

STA ; to what??

LDA #>table

ADC #0 ; if carry is set, then the high byte somehow ends up 256 bytes further down the table so the pointers are on the same page??

AND #$0F ; doesn't this turn off the last four bits? why???

STA ; to what??

 

 

do I store the result to another 16 bit variable? so I need to use four bytes to do this?

or can #<table and #>table just be constant values of where the table is? and I'm suppose to store that to my 16 bit variable which I then use as the pointer?

how do I use a 16 bit pointer???

Please someone help me get this.

 

 

With a more complicated banking scheme, you don't need to alter the pointers. Just switch banks. That's also the easiest way to animate.

That doesn't sound easy at all!!!!

Edited by Lillapojkenpåön
Link to comment
Share on other sites

Pointers are easier than you think they are. Memory addresses are 16-bit, and a pointer is two consecutive bytes that hold a memory address. The pointer may be used to access the data at the address stored in the pointer. An advantage of using a pointer vs using the address directly is that the address pointed to can be changed, and the same pointer can still be used to access the data. So, here's an example for data for player graphics:

Player0GfxPtr     ds 2 ; two bytes

player0frame0
    .byte %0001000
    .byte %0001000
    .byte %0111110
    .byte %0001000
    .byte %0001000


player0frame1
    .byte %0100010
    .byte %0010100
    .byte %0001000
    .byte %0010100
    .byte %0100010


    lda #<player0frame0  ; low byte of player0frame0
    sta Player0GfxPtr    ; store in first byte of pointer
    lda #>player0frame0    ; high byte of player0frame0
    sta Player0GfxPtr+1  ; store in second byte of pointer

    ldy #4

playergfxloop
    sta WSYNC
    lda (Player0GfxPtr),y ; load from address stored in pointer (player0frame0) with offset
    sta GRP0
    dey
    bpl playergfxloop

    lda #<player0frame1  ; low byte of player0frame1
    sta Player0GfxPtr    ; store in first byte of pointer
    lda #>player0frame1  ; high byte of player0frame0
    sta Player0GfxPtr+1  ; store in second byte of pointer

playergfxloop2
    sta WSYNC
    lda (Player0GfxPtr),y ; load from address stored in pointer (player0frame1) with offset
    sta GRP0
    dey
    bpl playergfxloop2

In this case, you would read data from Player0GfxPtr, and if you wanted to switch frames of animation, you would update the pointer to point to the table with the appropriate graphics.

  • Like 1
Link to comment
Share on other sites

Now in the case of a table with more than 256 bytes of data, you could set the pointer to the address of the table as normal:

    lda #<reallybigtable ; low byte of reallybigtable
    sta DataPtr          ; store in first byte of pointer
    lda #>reallybigtable ; high byte of reallybigtable
    sta DataPtr+1        ; store in second byte of pointer

You can access the first 256 bytes in the table with (DataPtr),y

 

If you needed to access the next 256 bytes, you could add 1 to the high byte of DataPtr, and then read from it in the same way.

    inc DataPtr+1  ; Increment high byte of DataPtr
    ldy #0
    lda (DataPtr),y  ; load byte 256 bytes from start of table

I hope that makes a little more sense.

Link to comment
Share on other sites

That doesn't sound easy at all!!!!

 

Actually, it is. In order to animate -everything- in a game, you really only need to know which Ram location holds the frame counter and 9 bytes of Rom space.

 

Take a game like Venture. Pretty boring gfx, right?

 

 

  lda $DD ; the frame counter in Venture
   and #$07 ; only keep the 3 low bits
   bne NoSwitch ; do not branch every 8th frame only
   sta $FFF8 ; F8 bankswitch hotspot
NoSwitch

 

Insert this code at some point in the program which is executed on every frame...such as to lead in to the display kernel where the INTIM timer is checked. Then turn the game into an 8k F8 version by doubling it (2 copies of the Rom pasted back-to-back). Use a bithacker to alter the sta $FFF8 instruction in the first copy to be $FFF9 instead (the other F8 hotspot).

 

Now you can alter anything in the Rom to look different in each of the 2 banks.

Link to comment
Share on other sites

Thanks alot everybody!!! I get it now finally!!

 

Now in the case of a table with more than 256 bytes of data, you could set the pointer to the address of the table as normal:

    lda #<reallybigtable ; low byte of reallybigtable
    sta DataPtr          ; store in first byte of pointer
    lda #>reallybigtable ; high byte of reallybigtable
    sta DataPtr+1        ; store in second byte of pointer

You can access the first 256 bytes in the table with (DataPtr),y

 

If you needed to access the next 256 bytes, you could add 1 to the high byte of DataPtr, and then read from it in the same way.

    inc DataPtr+1  ; Increment high byte of DataPtr
    ldy #0
    lda (DataPtr),y  ; load byte 256 bytes from start of table

I hope that makes a little more sense.

I'm having a little bit of trouble figuring out when to inc and dec the high byte when reading two bytes at a time from the table?? I've tried everything but when scrolling quickly back and forth over the 256 edge the playfield gets a little messed up sometimes. I tried to dec the high byte when index was zero and set the index to 254,

and inc at 254 and set index to zero, that didn't work, I guess going back and forth can result in the index being 255? Tried a thousand ways to solve that without success.

 

so I tried incrementing the pointer between the two table reads so the first byte could be 255 and second byte 0 of the next 256 bytes, but didn't get that working correctly either..

 

.scrollleft

ldy Index
lda (DataPtr),y
sta temp2
iny
lda (DataPtr),y
sta temp3
inc Index
rts
.scrollright
ldy Index
lda (DataPtr),y
sta temp2
iny
lda (DataPtr),y
sta temp3
dec Index

rts

 

 

Any tips on where to put the index check, what to check for, and what to set it to?

Link to comment
Share on other sites

  • 2 months later...
  • 1 month later...

Hmm how do I ask this.. Let's say you could shoot enemies all over the screen, and that when an enemy is shot something travels from it's location down to the score, but I want it to allways take one second to travel there even if it's far away or close to the score, you would have to calculate a 8.8 speed that makes the thing reach it's destination within said time, possible? anybody know of some similar code?

Link to comment
Share on other sites

you're asking for a divide by 60 for a NTSC or PAL60 game.

 

6507 doesn't have a divide feature, but it does have a shift feature which is the same as divide by 2.  If you do that 6 times that's a divide by 64, which is close enough.

 

So I would start with something like this:

;RAM usage
stephigh ds 1
steplow ds 1


; call with Y holding the distance to move to get to the score
DivBy64:
	sty stephigh
	ldy #0
	sty steplow
	ldy #6
Div64Loop:
	lsr stephigh
	ror steplow
	dey
	bne Div64Loop

 

 

 

  • Like 1
Link to comment
Share on other sites

Yep - since this is a newbies forum it's helpful to start with the straightforward answer, then follow up with the optimization.

 

;RAM usage
stephigh ds 1
steplow ds 1


; call with Y holding the distance to move to get to the score
; (# / 256) * 2 * 2 = # / 64
DivBy64:
	sty steplow ; these 3 instructions are a divide by 256
	ldy #0
	sty stephigh

	asl steplow ; these 2 instructions are times 2
	rol stephigh
    
	asl steplow ; these 2 instructions are times 2
	rol stephigh

 

 

  • Like 1
Link to comment
Share on other sites

  • 3 months later...

I forgot to say THANKS! that worked great!

 

I'm working on a bB kernel, but the code (level data, logic etc.) in bB needs to end up in different places in the kernel, are there any preprcessor commands that can change where code ends up? or a way to split up the generated assembly from bB to different parts?

The DPCplus include file has this

bB.asm

; DPC frequencies
DPC_waveforms.asm

; rest of bB stuff, ending with graphics
bB2.asm

 

but I can't find how it's split into two parts?

 

Link to comment
Share on other sites

  • 6 months later...

I have a problem that's driving me nuts, 

I have a table that looks like this

 

 255,255,63,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,34,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,34,0,4,32,0,4,32,0

 4,32,0,4,32,0,4,32,0,4,32,0,4,33,0,4,33,0,4,33,0,4,33,0,4,32,0,4,32,0,4,32,0,4,32,0,4,48,0,4,56,0,4,60,0,4,60,0,4,0,0,4,0,0,0,0,0,128,0,0,128,0,0,128

 0,0,128,0,0,0,0,0,0,60,0,0,60,0,16,60,0,16,60,0,16,32,0,16,32,0,0,32,0,4,32,0,4,32,16,132,32,16,132,32,16,132,32,16,132,0,16,132,0,16,132,0,16,132,32,16,132,32,0,4,32,0,4,32

 0,4,32,0,4,32,0,4,32,0,4,32,0,4,33,0,4,33,0,4,33,0,4,33,0,4,33,0,4,33,0,4,33,0,4,33,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32

 0,0,0,0

 0,4,32,0,0,32,0,0,32,128,1,56,128,1,56,128,1,56,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,32,4,32,32,4,32,32,4,32,32,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0

 4,32,0,4,32,0,4,32,0,4,48,0,4,32,0,4,36,0,0,32,0,0,33,0,0,32,0,64,32,0,0,32,0,0,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4

 32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32

 0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,0,0,4,0,0,4,0,0,4,32,0,4,32

 0,0,0,0

 0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,0,32,0,0,32,0,0,32,0,0,0,0,0,0,0,1,0,0,1,32,0,1,32,0,1,32,0

 1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,0,32,0,0,0,0,0,0,64,0,0,64,0,32,0,0,32,0,0,32,0,0,32,0,1,32,0,1,32,0,1

 32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,0,32,0,0,32,0,0,32,0,0,32,0,0,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32

 0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8

 0,0,0,0

 0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0

 4,32,0,4,32,0,4,32,0,4,32,0,4,0,0,4,0,0,4,0,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,0

 32,0,0,32,0,0,32,0,0,0,0,0,0,0,1,0,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,0,32,0,0,0

 0,0,0,64,0,0,64,0,32,0,0,32,0,0,32,0,0,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32

 0,0,0,0

 0,0,32,0,0,32,0,0,32,0,0,32,0,0,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,8,0,4,8,0,4,8,0

 4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4

 32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32

 0,4,32,0,4,0,0,4,0,0,4,0,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,0,32,0,0,32

 0,0,0,0

 0,0,32,0,0,0,0,0,0,0,1,0,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,0,32,0,0,0,0,0,0,64

 0,0,64,0,32,0,0,32,0,0,32,0,0,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,1,32,0,0,32,0,0,32,0,0

 32,0,0,32,0,0,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,32,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8

 0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,0,4,8,255,255,15

 0,0,0,0

 

It's playfield data, and the last four bytes on each page is just padding to keep it aligned, 63 values on each line plus four padding bytes = 256

I had to do it like that because I read three values at a time, so when the index is 251 I increment the page and set Index to 0

I can scroll perfectly to the left like that, but the problem is when scrolling back, the data is for the pixels to be turned on after scrolling the screen, so every three values is a playfield column, so ofcourse when scrolling the other way, I now need to read the data that's 99 (width 32 x height 3 + one column 3) 

positions before Index, pretty easy

 

 lda Index

 sbc #distance

 tay

 

but when Index is less than 99 and the left column is on the previous page you need to also skip the padding bytes right? I tried it like this

 

 

 lda Index

 cmp #distance 

 bcs .skip    ; skip if Index is bigger or equal to distance

 

 dec Page    ; decrement Page if Index is smaller than distance

 sec

 sbc #distance + 4

 jmp .123

 

.skip

 sec

 sbc #distance

.123

 

 tay

 

Anything wrong with that code? or else I'll post more of it

The problem I'm seeing is that sometimes the playfield moves up, then back down again, so seems to have to do with the distance.

Link to comment
Share on other sites

2 hours ago, Andrew Davie said:

Useful tip:

You can align to a page boundary in DASM by just using " align 256" in the source code.

No need to add padding bytes manually.

 ldx #2

 jmp .bs5

 

 ;there's a couple free bytes between here

 align 133 

 

bs5

 

  lda bankswitch_hotspot-1,x

  rts

 

If I remove the jmp to .bs5 will the program counter jump to .bs5 by itself or will it take time doing a couple nop's first?

Link to comment
Share on other sites

"align 133" is bizarre.  Normally "align" is used to align to a 256 byte boundary. A 133 byte boundary is... weird.

"align x" does not put in "x" bytes.  Instead, it puts in as many bytes as needed to get to a multiple of "x" in the ROM.

So, "align 256" will put in as many padding bytes as needed to finish the current page, and get to the start of the next one.

 

In answer to your actual question - no, you cannot to this. The area skipped by the align should be considered "garbage" and you don't execute it as code. You will need to jump over it.

  • Thanks 1
Link to comment
Share on other sites

Ok thanks.

I'm a bizarre dude ?

It's for a bB thing, and 133 bytes are allready used in bank 2 by the kernel, so that's where the bankswitch code ends up if you put it first thing in that bank,

it just so happens the code I'm bankswitching to fits allmost perfectly above it in the other banks,

 

 ldx #2

 jmp .bs5

 

is the end of that code where I return, I just realised I can put the align before that codeblock to just fall into the return. 

Link to comment
Share on other sites

On 5/20/2020 at 2:18 AM, Lillapojkenpåön said:

 ldx #2

 jmp .bs5

 

 ;there's a couple free bytes between here

 align 133 

 

bs5

 

  lda bankswitch_hotspot-1,x

  rts

 

If I remove the jmp to .bs5 will the program counter jump to .bs5 by itself or will it take time doing a couple nop's first?

Actually #<bs5 is 164, so why am I not aligning 164? I must have understood why when I did it, but now I don't???

Or I checked the wrong address and it was a lucky accident it worked? But why is it working?

 

_bank6data  ; #< = 133

 

 lda (DataPtr),y

 sta DF0PUSH ;210

 

 iny

 lda (DataPtr),y

 sta DF0PUSH ;209

 

 if PFRESOLUTION == 22

 iny

 lda (DataPtr),y

 sta DF0PUSH

 endif

 

 ;ldx #2

 jmp .bs6

 

 align 133

 

.bs6 ; #< = 164

 

  lda $1FF7

  rts

 

Link to comment
Share on other sites

2 hours ago, Lillapojkenpåön said:

Actually #<bs5 is 164, so why am I not aligning 164? I must have understood why when I did it, but now I don't???

Or I checked the wrong address and it was a lucky accident it worked? But why is it working?

 

_bank6data  ; #< = 133

 

 lda (DataPtr),y

 sta DF0PUSH ;210

 

 iny

 lda (DataPtr),y

 sta DF0PUSH ;209

 

 if PFRESOLUTION == 22

 iny

 lda (DataPtr),y

 sta DF0PUSH

 endif

 

 ;ldx #2

 jmp .bs6

 

 align 133

 

.bs6 ; #< = 164

 

  lda $1FF7

  rts

 

 

I totally don't understand your usage of "align" or what you're trying to do here.

If it's to get bankswitching code in the right place, then I've not seen it done using aligns. It might work.

Generate a listing file, and have a look at the assembly. That will clearly show you what is where.

I have only ever used "align" to get to page boundaries.  The "align 133" would, I assume, align to the 133rd byte in the current page, except where you're already past that, in which case it will be the 133rd byte in the NEXT page. It's still bizarre usage to me, tough.

You code, as shown, does not seem to have much of any idea where it is related to page boundaries.

Not saying it's wrong - it's just very foreign to me, this usage.

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