texacala Posted August 18, 2011 Share Posted August 18, 2011 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. Quote Link to comment Share on other sites More sharing options...
Rybags Posted August 18, 2011 Share Posted August 18, 2011 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. Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted August 18, 2011 Share Posted August 18, 2011 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 Quote Link to comment Share on other sites More sharing options...
texacala Posted August 19, 2011 Author Share Posted August 19, 2011 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. Quote Link to comment Share on other sites More sharing options...
Bryan Posted August 19, 2011 Share Posted August 19, 2011 .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." Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted August 19, 2011 Share Posted August 19, 2011 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 Quote Link to comment Share on other sites More sharing options...
Bryan Posted August 19, 2011 Share Posted August 19, 2011 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. Quote Link to comment Share on other sites More sharing options...
Tyrop Posted August 19, 2011 Share Posted August 19, 2011 (edited) .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 August 19, 2011 by Tyrop Quote Link to comment Share on other sites More sharing options...
texacala Posted August 19, 2011 Author Share Posted August 19, 2011 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. 1 Quote Link to comment Share on other sites More sharing options...
+therealbountybob Posted August 22, 2011 Share Posted August 22, 2011 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 Quote Link to comment Share on other sites More sharing options...
texacala Posted October 10, 2011 Author Share Posted October 10, 2011 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. Quote Link to comment Share on other sites More sharing options...
kenfused Posted October 10, 2011 Share Posted October 10, 2011 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. Quote Link to comment Share on other sites More sharing options...
texacala Posted October 10, 2011 Author Share Posted October 10, 2011 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? Quote Link to comment Share on other sites More sharing options...
Bryan Posted October 10, 2011 Share Posted October 10, 2011 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. Quote Link to comment Share on other sites More sharing options...
MaPa Posted October 10, 2011 Share Posted October 10, 2011 (edited) 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 October 10, 2011 by MaPa Quote Link to comment Share on other sites More sharing options...
texacala Posted October 10, 2011 Author Share Posted October 10, 2011 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. Quote Link to comment Share on other sites More sharing options...
+Stephen Posted October 10, 2011 Share Posted October 10, 2011 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". Quote Link to comment Share on other sites More sharing options...
texacala Posted October 12, 2011 Author Share Posted October 12, 2011 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... Quote Link to comment Share on other sites More sharing options...
Rybags Posted October 12, 2011 Share Posted October 12, 2011 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. Quote Link to comment Share on other sites More sharing options...
Bryan Posted October 12, 2011 Share Posted October 12, 2011 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. 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.