6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Oct 05, 2024 9:55 pm

All times are UTC




Post new topic Reply to topic  [ 56 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
PostPosted: Sun Mar 04, 2007 2:00 am 
Offline

Joined: Sun Mar 04, 2007 1:47 am
Posts: 19
I have a two byte variable in zero page memory which contains the 16-bit address of a ROM table.
I need to access that memory location, but I'm confused on how to do it.
I can LDA , but how do I 'concatenate' the low and hi bytes of the address? Or is there a better way?
Thanks, here's my code:

PF0_addr .word ;zero page variable
...

SET_POINTER PF0_addr, TitleScreen_PF0 ;Macro storing addr of TitleScreen into PFO_addr
...

lda PF0_addr-1,x ;???????
sta PF0
...

TitleScreen_PF0
.byte #%00001100 ; ROM table
.byte #%00010010
...

MAC SET_POINTER
.POINTER SET {1}
.ADDRESS SET {2}

LDA #<.ADDRESS ; Get Lowbyte of Address
STA .POINTER ; Store in pointer
LDA #>.ADDRESS ; Get Hibyte of Address
STA .POINTER+1 ; Store in pointer+1

ENDM


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Mar 04, 2007 2:43 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
I'm not sure exactly what you're trying to do, but if you don't need indexing and all you want to do is load the accumulator with the contents of the address pointed to by a pair of bytes in ZP, all you need is the one instruction LDA (ZP). It's a two-byte instruction, op code B2, with one byte of operand, and it takes 5 clocks to execute.

If you need indexing into the table and the table is no more than 256 bytes, put the index value in Y and use LDA (ZP),Y, again a 2-byte instruction, with op code B1. Then to step through the table, just increment or decrement Y with the single-byte, two-clock instructions INY or DEY, instead of having to modify the address in ZP.

If you know where the table is at compilation time so you don't even need to refer to the table's address in ZP, just use LDA abs,X, a 3-byte, 4-clock instruction with op code BD.


Top
 Profile  
Reply with quote  
 Post subject: Still not working...
PostPosted: Mon Mar 05, 2007 12:18 am 
Offline

Joined: Sun Mar 04, 2007 1:47 am
Posts: 19
Thanks for your help. This is what I tried...
I have a 2 byte pointer in ZP memory, and another var (ScreenFake) in ZP with an arbitrary value.
I also have a byte past ZP memory (Screen_PF1) with different data. In this example I explicitly set the address for testing purposes. In the real program I wont know it at compile time.
Anyway, the code runs, but only seems to get the LSB of the address, thus loading the data in ScreenFake, not Screen_PF1...
What am I doing wrong?
Thanks again.

Code:
;------------------------------------------------
; Addressing Test
;------------------------------------------------
processor 6502
include vcs.h
include macro.h
;------------------------------------------------
; Constants and Variables
;------------------------------------------------
SEG.U variables
ORG $80
PF1_pointer .word
ScreenFake = $AA
Screen_PF1 = $01AA

;------------------------------------------------
; START OF ROM
;------------------------------------------------
SEG Bank0
ORG $F000 ; 4k ROM start point
;-------------------------------------------------------------------------
; Game
;------------------------------------------------
Start
CLEAN_START ; Clear RAM and Registers

lda #%10001000
sta Screen_PF1
lda #%11111111
sta ScreenFake

SET_POINTER PF1_pointer, Screen_PF1
ldy #0
lda (PF1_pointer),Y
sta PF1

lda #$94
sta COLUPF

.mainLoop
jsr VERTICAL_BLANK
jsr DRAW
jsr WAIT_V_BLANK
jsr OVERSCAN
jmp .mainLoop

;-------------------------------------------------------------------------
; SUBROUTINES
;------------------------------------------------
;***** VERTICAL_BLANK *****
VERTICAL_BLANK
lda #0
sta VBLANK
VERTICAL_SYNC
lda #41 ;41 64-cycle ticks
sta TIM64T
RTS

;***** WAIT_V_BLANK *****
WAIT_V_BLANK
.waitForVBlank
lda INTIM
bne .waitForVBlank
RTS

;***** DRAW *****
DRAW
ldx #220
.drawLine
sta WSYNC
dex
bne .drawLine
RTS

;***** OVERSCAN *****
OVERSCAN
lda #%01000010
sta VBLANK
lda #35
sta TIM64T
.waitForOverscan
lda INTIM
bne .waitForOverscan
RTS

;------------------------------------------------
; Interrupt Vectors
;------------------------------------------------
echo [*-$F000]d, " ROM bytes used"
ORG $FFFA
.word Start ; NMI
.word Start ; RESET
.word Start ; IRQ
END


Top
 Profile  
Reply with quote  
 Post subject: PS
PostPosted: Mon Mar 05, 2007 12:23 am 
Offline

Joined: Sun Mar 04, 2007 1:47 am
Posts: 19
PS - I don't need indexing and all I want to do is load the accumulator with the contents of the address pointed to by a pair of bytes in ZP,
but this didnt work:

lda (PF1_pointer)

it told me it was an illegal addressing mode...


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 05, 2007 5:54 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
Quote:
Anyway, the code runs, but only seems to get the LSB of the address, thus loading the data in ScreenFake, not Screen_PF1...
What am I doing wrong?

You don't show your macro definitions, but it sounds like SET_POINTER is only taking care of one byte, and not putting the 1 (high byte of Screen_PF1's 1FF) at the next byte after the FF at PF1_pointer.

Quote:
it told me it was an illegal addressing mode...

It's standard for all CMOS 6502's. AFAIK, the NMOS one have not been made in two decades, but Western Design Center is making CMOS ones with no end in sight, with more instructions and addressing modes than the NMOS ones had. You might need to tell your assembler you're using CMOS by using the line "processor 65c02", if indeed you are. The only reason not to use CMOS is if you're using old hardware like the Commodore 64 which used the 6510 which was never avaialble in a CMOS version. With an NMOS 6502, your putting 0 in Y and using LDA (ZP),Y is the best way to do it.

Depending on whether the stack is getting initialized at 1FF at reset and whether there's a system running in the background that might eat up a lot of stack space, it might be a little dangerous to put Screen_PF1 in $01AA where it could get stepped on by the stack. Page 1, especially high in the page, is generally not a good place to put variables.

When you list code on this forum, in order to keep the spaces from getting gobbled up and everything shoved against the left margin, bracket the code with left-square-bracket CODE right-square-bracket (or just mark the block and then click "Code"), and uncheck the "disable BB code" box at the bottom.


Top
 Profile  
Reply with quote  
 Post subject: SET_POINTER macro
PostPosted: Mon Mar 05, 2007 2:30 pm 
Offline

Joined: Sun Mar 04, 2007 1:47 am
Posts: 19
Garth, thanks for the replies. I'm just getting started and this is clearing a lot of things up.
I am coding for the Atari VCS, so I guess I will just use a zero offset when addressing like this.
Here is the SET_POINTER macro. I didn't write it, but it looks like it should write the low and high bytes...

Code:
;-------------------------------------------------------
; SET_POINTER
; Original author: Manuel Rotschkar
;
; Sets a 2 byte RAM pointer to an absolute address.
;
; Usage: SET_POINTER pointer, address
; Example: SET_POINTER SpritePTR, SpriteData
;
; Note: Alters the accumulator, NZ flags
; IN 1: 2 byte RAM location reserved for pointer
; IN 2: absolute address

            MAC SET_POINTER
.POINTER    SET {1}
.ADDRESS    SET {2}

                LDA #<.ADDRESS  ; Get Lowbyte of Address
                STA .POINTER    ; Store in pointer
                LDA #>.ADDRESS  ; Get Hibyte of Address
                STA .POINTER+1  ; Store in pointer+1

            ENDM


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 05, 2007 3:18 pm 
Offline

Joined: Sun Mar 04, 2007 1:47 am
Posts: 19
OK, I changed the address to $0AAA.
I did some tests and it looks like both the low and high bytes are getting set,
but LDA (PF1_pointer),#0 only goes to the low byte $0A and
LDA (PF1_pointer+1),#0 only goes to the high byte $AA.
So I still cant get the data from $0AAA...


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 05, 2007 8:03 pm 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
wstjohn wrote:
LDA (PF1_pointer),#0
LDA (PF1_pointer+1),#0

If LDA (PF1_pointer),Y is a valid memory pointer the LDA (PF1_Pointer+1),Y probably isn't. You need something like this
Code:
LDY #0
LDA (PF1_pointer),Y ; Fetch first byte
STA XXX ; And do something with it
INY
LDA (PF1_pointer),Y ; Fetch following byte.
STA YYY ; ...

_________________
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 05, 2007 8:23 pm 
Offline

Joined: Sun Mar 04, 2007 1:47 am
Posts: 19
BitWise,
I'm not sure I understand you. In my example, PF1_pointer is a 2 byte pointer to some location past zero page memory, say $FFAA.
The first byte contains the low byte of the address #$AA and the second byte contains the high byte of the address #$FF.
I need to use the pointer to somehow load the value at $FFAA into a register.

Can LDA (PF1_pointer), #0 do this?

Thanks for the input.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 05, 2007 8:35 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
When you do LDY #0, LDA (PF1_pointer),Y, the processor reads two bytes in ZP to get the 16-bit address at PF1_pointer, and adds the Y value to it to get the address of the one byte it will read into the accumulator. The Y being outside the parentheses means the Y value is not added until after the address is read from ZP. So LDA (anything),Y will always read two consecutive ZP bytes, and of course put one byte at the final resulting address into A.
Quote:
Can LDA (PF1_pointer), #0 do this?

LDA (PF1_pointer),Y can do it, all in one instruction if 0 is already in Y. The way you wrote it, although not a legal notation, is what LDA (PF1_pointer) on the 65c02 would do, without your needing to load 0 into Y first.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 05, 2007 9:27 pm 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
wstjohn wrote:
BitWise,
I'm not sure I understand you. In my example, PF1_pointer is a 2 byte pointer to some location past zero page memory, say $FFAA.
The first byte contains the low byte of the address #$AA and the second byte contains the high byte of the address #$FF.
I need to use the pointer to somehow load the value at $FFAA into a register.

Can LDA (PF1_pointer), #0 do this?

Thanks for the input.

So what you what is:
Code:
DATAVAL EQU $FFAA
ZPPTR   EQU $80

 LDA #<DATAVAL ; Should evaluate to $AA
 STA ZPPTR
 LDA #>DATAVAL ; Should evaluate to $FF
 STA ZPPTR+1

 ; then either

 LDY #0
 LDA (ZPPTR),Y ; A contains byte at DATAVAL ($FFAA) address

 ; or

 LDX #0
 LDA (ZPPTR,X)  ; A contains byte at DATAVAL ($FFAA) address

As Garth points out the 65C02 has zero page indirect addressing mode (so you can drop the LDY #0 and change the final load to LDA (ZPPTR) ) but with earlier processors you must use index indirect or indirect indexed to access memory via a pointer on zero page.

The (),Y form is more useful if you are going to access several (usually contiguous) bytes from the same memory area.

_________________
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Mar 05, 2007 11:56 pm 
Offline

Joined: Sun Mar 04, 2007 1:47 am
Posts: 19
BitWise,
Yeah, that is exactly what I'm trying to do, and exactly the code I used.
But, what gets loaded into A is only the low byte, not both together!!!

Is this what should happen?

Code:
pointer   .word
data = $9955
...
 LDA #<data
 STA pointer
 LDA #>data
 STA pointer+1
...
;at this point I have verified that pointer contains #$55
;and pointer+1 contains #$99
...
;however, after this:
LDA  (pointer)
STA  PF0
;PF0 contains the data from $55, not from $9955

???


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Mar 06, 2007 12:22 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8521
Location: Southern California
Are you using actual hardware, or a simulator that might have a bug in it?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Mar 06, 2007 1:07 am 
Offline

Joined: Sun Mar 04, 2007 1:47 am
Posts: 19
I'm using DASM to compile it and Stella to simulate the Atari VCS...


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Mar 06, 2007 1:07 am 
Offline

Joined: Sun Mar 04, 2007 1:47 am
Posts: 19
I also used z26 and got the same result.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 56 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 12 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: