Jump to content
IGNORED

.BYTE directive is confusing me


Recommended Posts

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

.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
Link to comment
Share on other sites

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:

Link to comment
Share on other sites

  • 1 month later...

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

  • Like 1
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...