Jump to content



2

.BYTE directive is confusing me


19 replies to this topic

#1 texacala OFFLINE  

texacala

    Star Raider

  • 98 posts

Posted Wed Aug 17, 2011 8:10 PM

I'm trying to learn how to build a display list and so far I've come up with:

10 ;start with the display list
20 ;
30 * = $3000
40 JMP INIT

300 DLIST ; start of display list instructions
310 .BYTE $70 $70 $70 $4D $20 $7C ; Screen RAM will begin at $7C20
320 .BYTE $0D $0D $0D $0D $0D $0D $0D $0D $0D $0D
330 .BYTE $0D $0D $0D $0D $0D $0D $0D $0D $0D $0D
340 .BYTE $0D $0D $0D $0D $0D $0D $0D $0D $0D $0D
350 .BYTE $0D $0D $0D $0D $0D $0D $0D $0D $0D $0D
360 .BYTE $0D $0D $0D $0D $0D $0D $0D $0D $0D $0D
370 .BYTE $0D $0D $0D $0D $0D $0D $0D $0D $0D $0D
380 .BYTE $0D $0D $0D $0D $0D $0D $0D $0D $0D $0D
390 .BYTE $0D $0D $0D $0D $0D $0D $0D $0D $0D $0D
400 .BYTE $0D $0D $0D $0D $0D $0D $0D $0D $0D $0D
410 .BYTE $0D $0D $0D $0D $0D ; 95 ANTIC D Mode lines
420 .BYTE $41 $A8 $7B ; Jump to beginning of Display List $7BA8

450 INIT ; first load in colors
480 LDA #0
490 STA $02C8 ; Color4 background black
500 LDA #4
510 STA $02C4 ; Color0 medium gray
520 LDA #10
530 STA $02C5 ; Color1 light gray
540 LDA #148
550 STA $02C6 ; Color2 blue

620 ; Run the display list
630 LDA #0
640 STA #$022F ; Turns off ANTIC
650 LDA #$DLIST&255
660 STA $0230 ;Storing starting address of custom Display List - low byte
670 LDA #$DLIST/256 ; High byte
680 STA $0231 ; Storing High byte
690 LDA #$22
700 STA $022F ; Turn ANTIC back on


I built this based on an example in Atari Roots. What I don't understand are lines 650 and 670. I know I've specified $7BA8 as the starting address for the DL in my list, but how on earth do the LDA instructions in lines 650 and 670 come up with these numbers? And is the BYTE directive the way to do this anyway? Apologies in advance if I seem like a total newb.

#2 Rybags ONLINE  

Rybags

    Quadrunner

  • 10,314 posts
  • Location:Australia

Posted Wed Aug 17, 2011 8:45 PM

number & 255 gives the low byte of a 16-bit number.

number / 256 gives the high byte (the result is truncated, not rounded, so e.g. 32766/256 gives 127)

In the case you have, it's dividing a label value - that's the usual usage, the label doesn't have to have a .byte associated, it could just as easily be a program instruction.

In more modern Assemblers, you can usually just use <label and >label to give the low/high byte values - saves a bit of typing and makes the program easier to read.

#3 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,545 posts
  • Location:Georgia, USA

Posted Wed Aug 17, 2011 8:47 PM

View Posttexacala, on Wed Aug 17, 2011 8:10 PM, said:

650 LDA #$DLIST&255
660 STA $0230 ;Storing starting address of custom Display List - low byte
670 LDA #$DLIST/256 ; High byte
680 STA $0231 ; Storing High byte
690 LDA #$22
700 STA $022F ; Turn ANTIC back on


I built this based on an example in Atari Roots. What I don't understand are lines 650 and 670. I know I've specified $7BA8 as the starting address for the DL in my list, but how on earth do the LDA instructions in lines 650 and 670 come up with these numbers?
#$DLIST&255 will be the lo byte of the address, and #$DLIST/256 will be the hi byte. For example, $7BA8&$FF will be $A8 (lo byte), and $7BA8/$100 will be $7B (hi byte). The math (bit AND or division) gets done as the LDA instruction is being assembled, so the result will be equivalent to LDA #$A8 and LDA #$7B. The syntax can vary depending on the assembler. For example, some assemblers would use #<$DLIST (or just #<DLIST) for the lo byte, and #>$DLIST (or #>DLIST) for the hi byte.

Michael

#4 texacala OFFLINE  

texacala

    Star Raider

  • 98 posts

Posted Thu Aug 18, 2011 8:35 PM

So I'm sort of getting it now. I thought the LDA instruction that referenced DLIST would load the *first* number in the .BYTE directive ($70). But is it backwards? The last two numbers listed are $A8 and $7B. For some reason I haven't tracked down a good explanation of what .BYTE actually does. Thank you guys for pointing me in the right direction.

#5 Bryan OFFLINE  

Bryan

    Quadrunner

  • 7,626 posts
  • Cruise Elroy = 4DB7
  • Location:Port St. Lucie, Florida

Posted Thu Aug 18, 2011 8:39 PM

.BYTE acts kinda like the DATA keyword in BASIC. It says, "here is a list of bytes to insert at this point in the assembly."

#6 SeaGtGruff OFFLINE  

SeaGtGruff

    River Patroller

  • 4,545 posts
  • Location:Georgia, USA

Posted Thu Aug 18, 2011 9:40 PM

View Posttexacala, on Thu Aug 18, 2011 8:35 PM, said:

So I'm sort of getting it now. I thought the LDA instruction that referenced DLIST would load the *first* number in the .BYTE directive ($70). But is it backwards? The last two numbers listed are $A8 and $7B. For some reason I haven't tracked down a good explanation of what .BYTE actually does. Thank you guys for pointing me in the right direction.
The 6502 processor likes addresses to be in "lo byte/hi byte" order-- the lo byte comes first, followed by the hi byte. So when you write an assembly instruction like "LDA $1234," or "JMP $2345," the machine code for those instructions would be stored in ROM as $AD, $34, $12 (where $AD is the hex code for the "LDA" op code with absolute addressing), and as $4C, $45, $23 (where $4C is the hex code for "JMP" with absolute addressing).

Michael

#7 Bryan OFFLINE  

Bryan

    Quadrunner

  • 7,626 posts
  • Cruise Elroy = 4DB7
  • Location:Port St. Lucie, Florida

Posted Thu Aug 18, 2011 10:11 PM

View Posttexacala, on Thu Aug 18, 2011 8:35 PM, said:

So I'm sort of getting it now. I thought the LDA instruction that referenced DLIST would load the *first* number in the .BYTE directive ($70). But is it backwards? The last two numbers listed are $A8 and $7B. For some reason I haven't tracked down a good explanation of what .BYTE actually does. Thank you guys for pointing me in the right direction.
That instruction isn't looking at any of the data. It's looking at the DLIST label itself. You start at $3000 and right before the DLIST is a jump instruction which takes 3 bytes. So, the DLIST label points to $3003. You need to put that address into $230 and $231, so you tell the assembler to break $3003 into 03 (lsb) and 30 (msb). You're working with the label address only (kinda like working with a pointer), not the data behind the .BYTE directive.

#8 Tyrop OFFLINE  

Tyrop

    Chopper Commander

  • 107 posts

Posted Thu Aug 18, 2011 10:57 PM

.BYTE is sort of like basic's Poke instruction. .BYTE $70 pokes $70 at the point of assembly, in your case, location $3002 receives the value $70.

I could be wrong, but I think DLIST is at $3002, not $3003. In your program, the first byte of your display list is at location $3002 (not $7BA8). But, I see that your jump instruction at the end of your display list (line 420) tells the computer to jump to location $7BA8. I am sure this is not what you want. You want the end of your display list to jump back to the beginning. So, what you really want is line 420 to read .BYTE $41 $02 $30. (If you really want your display list to begin at $7BA8, then you need to add *=7BA8 right before your DLIST label, and then you leave 420 as-is.)

Now, there is a little niftier way of coding this, hopefully not too confusing. You made a label called DLIST which is being assigned the value $3002. So, instead of using .BYTE $02 $30, you can use .WORD DLIST instead. .WORD takes a 2-byte number and assmbles it into two consecutive bytes with the low byte first. Hence, .WORD DLIST will poke $02 and then $30. Using this method, you would have line 420 as just .BYTE $41. Then, you would add line 430 .WORD DLIST. THis method makes for more portable coding because, if you ever change your origin (*=$3000) to something else, your jump instruction will automatically always have the correct value.

By the way, LDA DLIST is the same as LDA $3002. That would load $70 in the accumulator. If you use the MAC/65 assembler, LDA #<DLIST would load the low byte of a 2-byte value, in your case, $03, and LDA #>DLIST would load $30.

Edited by Tyrop, Thu Aug 18, 2011 11:26 PM.


#9 texacala OFFLINE  

texacala

    Star Raider

  • 98 posts

Posted Fri Aug 19, 2011 1:08 PM

Thank you for the help, it's starting to get more clear. I have to say, I don't know quite what's possessing me to tackle assembly but wow am I finding it challenging. I hope to get somewhere if I just keep reading and working with WUDSN and Altirra.

#10 therealbountybob OFFLINE  

therealbountybob

    River Patroller

  • 3,238 posts
  • Lost
  • Location:In Space

Posted Mon Aug 22, 2011 5:14 AM

View Posttexacala, on Fri Aug 19, 2011 1:08 PM, said:

Thank you for the help, it's starting to get more clear. I have to say, I don't know quite what's possessing me to tackle assembly but wow am I finding it challenging. I hope to get somewhere if I just keep reading and working with WUDSN and Altirra.
Hey! I just started coding my first assember DL yesterday using as/ed ... after tons of reading I thought I'd get started. Most of the books are written for using code with BASIC but I'm going straight for assembler directly.

A few tips (from a beginner so probably bleeding obvious!) I've been trying to fit my small code into areas so that I can run the program from debug without exiting the as/ed cart. I've been putting a loop waiting for start to be pressed to exit at the end of my programs. Also using the free Zero page locations as flags (I set $CB-$D1 as labels Z0-Z6)- setting them all to 0 at the start of my code and then storing values to them at various points, then can check the expected results from debug.

nice thread :thumbsup:

#11 texacala OFFLINE  

texacala

    Star Raider

  • 98 posts

Posted Sun Oct 9, 2011 8:03 PM

Well, I thought I was on the right track, *until* I started drawing to the screen. Here is my current version:


DLIST .BYTE $70,$70,$70,$4D,$00,$5D,$0D,$0D,$0D,$0D,$0D,$0D
.BYTE $0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D
.BYTE $0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D
.BYTE $0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D
.BYTE $0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D
.BYTE $0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D
.BYTE $0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D
.BYTE $0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D
.BYTE $0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D,$0D
.BYTE $0D,$0D,$0D,$0D,$0D ; 95 ANTIC D Mode lines
.BYTE $41; Jump to beginning of Display List
.WORD DLIST ; This should automatically calculate where DLIST begins


INITDL ; first load in colors
LDA #0
STA $02C8 ; Color4 background black
LDA #4
STA $02C4 ; Color0 medium gray
LDA #10
STA $02C5 ; Color1 light gray
LDA #148
STA $02C6 ; Color2 blue
LDA #0 ; Now run the display list
STA $022F ; Turn off ANTIC
LDA #DLIST&255
STA $0230 ;Store starting address of custom Display List - low byte
LDA #DLIST/256 ; High byte
STA $0231 ; Storing High byte
LDA #$22
STA $022F ; Turn ANTIC back on
RTS

Now I planned on clearing out about 2 Antic D screens of memory with:


CLRSCR ; Clear the screen RAM, 30 pages, about 2 ANTIC D screens

MEMTOCLR = $B0 ; Page Zero address to index - Lo Byte

LDA #$00
STA MEMTOCLR ; Lo Byte of start of Screen RAM
LDA #$5D
STA MEMTOCLR+1 ; Hi Byte of start of Screen RAM
LDA #0 ;RAM will be cleared with zeros
LDX #30 ;# of pages to clear
LOOP2 LDY #0 ;Countdown timer
LOOP1 STA (MEMTOCLR),Y ; Indexing $5D00 + Y
DEY ;Countdown starts at 255
BNE LOOP1 ;when we fall through to here we have cleared one page
INC MEMTOCLR+1 ;prepare to clear the next page
DEX ;decrease page counter
BNE LOOP2 ;if not zero, jump back and clear another page
RTS

Ok, no errors, but then here's the problem: If I draw to the screen using LDA #102 (or something similar) instead of LDA #0 above, I only draw 18 mode lines and then nothing else. It's as if my Antic D screen is only 18 modes total or so and then vanishes. So something must be off with my display list. Did I miss an instruction somewhere? I think my loops are counting correctly, it's the screen memory that's messed up somehow.

#12 kenfused OFFLINE  

kenfused

    Stargunner

  • 1,192 posts
  • Location:Columbus, Ohio

Posted Sun Oct 9, 2011 8:33 PM

View Posttexacala, on Sun Oct 9, 2011 8:03 PM, said:

Well, I thought I was on the right track, *until* I started drawing to the screen. Here is my current version:

...

Ok, no errors, but then here's the problem: If I draw to the screen using LDA #102 (or something similar) instead of LDA #0 above, I only draw 18 mode lines and then nothing else. It's as if my Antic D screen is only 18 modes total or so and then vanishes. So something must be off with my display list. Did I miss an instruction somewhere? I think my loops are counting correctly, it's the screen memory that's messed up somehow.
If your screen start at 5d00 you are going to cross a 4k boundary after about 19 scan lines. You either need to re-position your screen or add another lms dlist instruction.

#13 texacala OFFLINE  

texacala

    Star Raider

  • 98 posts

Posted Sun Oct 9, 2011 9:05 PM

Ah ha! I think that's it. I read about this problem in De Re Atari but I thought the boundary meant only 4k total per screen. In other words in Antic D, 96 mode lines with 40 bytes per line yields 3840 bytes per screen. But I think what you are saying is the way my screen RAM is positioned, my screen is only between $5D00 and $6000? Is that the boundary?

#14 Bryan OFFLINE  

Bryan

    Quadrunner

  • 7,626 posts
  • Cruise Elroy = 4DB7
  • Location:Port St. Lucie, Florida

Posted Sun Oct 9, 2011 9:41 PM

Yep, the DMA pointer cannot cross $0FFF-$1000, or $1FFF to $2000, etc.. without help because the counter doesn't extend to the 13th bit. Also remember that the display list fetch has a 1K boundary restriction.

#15 MaPa OFFLINE  

MaPa

    Dragonstomper

  • 564 posts
  • Location:Czech Republic

Posted Sun Oct 9, 2011 11:40 PM

View Posttexacala, on Sun Oct 9, 2011 9:05 PM, said:

Ah ha! I think that's it. I read about this problem in De Re Atari but I thought the boundary meant only 4k total per screen. In other words in Antic D, 96 mode lines with 40 bytes per line yields 3840 bytes per screen. But I think what you are saying is the way my screen RAM is positioned, my screen is only between $5D00 and $6000? Is that the boundary?
When ANTIC will reach $5fff, then the next bytes will be read from $5000 and forward instead of $6000 because of the 4k boundary.

Edited by MaPa, Sun Oct 9, 2011 11:41 PM.


#16 texacala OFFLINE  

texacala

    Star Raider

  • 98 posts

Posted Mon Oct 10, 2011 10:16 AM

Thanks guys, that solved the problem-- I just moved the start of screen RAM to $4000 and voilą, fixed. I think I'm developing a love/hate relationship with ANTIC.

#17 Stephen OFFLINE  

Stephen

    River Patroller

  • 3,240 posts
  • A8 Gear Head
  • Location:Akron, Ohio

Posted Mon Oct 10, 2011 10:47 AM

View Posttexacala, on Mon Oct 10, 2011 10:16 AM, said:

Thanks guys, that solved the problem-- I just moved the start of screen RAM to $4000 and voilà, fixed. I think I'm developing a love/hate relationship with ANTIC.
You love it :) It's all the limitations that make working with this system so "fun".

#18 texacala OFFLINE  

texacala

    Star Raider

  • 98 posts

Posted Tue Oct 11, 2011 10:36 PM

I guess I learned to love my dog in spite of his limitations (one of which being he's nine inches tall), so ok, there's hope yet! :)

So... if I want to vertical scroll over 8K or so of screen RAM, and my screen crosses a 4K boundary (which it eventually will), do I have to keep modifying my Display List every coarse scroll in order to add a second LMS instruction in the correct place? In other words, if the beginning of the screen RAM keeps changing position (moving the screen over RAM), does the DL have to be modified each time as well? I fear so...

#19 Rybags ONLINE  

Rybags

    Quadrunner

  • 10,314 posts
  • Location:Australia

Posted Wed Oct 12, 2011 12:18 AM

Yep.

And you get the added problem that 40 doesn't divide into 4,096 so scrolling bitmap screens isn't as simple as you'd think.

#20 Bryan OFFLINE  

Bryan

    Quadrunner

  • 7,626 posts
  • Cruise Elroy = 4DB7
  • Location:Port St. Lucie, Florida

Posted Wed Oct 12, 2011 7:38 AM

It's probably easier to arrange the screen differently for large scrolled bitmaps and load the pointer on each line. If you do something interleaved like:

4K: L0, L4, L8, L12
8K: L1, L5, L9, L13
12K: L2, L6, L10, L14
16K: L3, L7, L11, L15

You'll be able to scroll over large areas without having to worry about the left-over gap at the top of any 4K chunk. You can move vertically just by changing all the LSB's in the Dlist.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users