xzerix Posted July 27, 2011 Share Posted July 27, 2011 Hi All. I'm trying to create a simple(?) screen from Atari Basic. I'm aiming for 24 lines of Antic mode 4, but with each line having a choice of a different value for colour1, colour 2 and the character set (to make my life easier when wrting the game, or so I thought). Here's what I want to attempt with my DLI (it's a modification of the example in De Re Atari...) ORIGINAL DE RE: PHA TXA PHA INC COUNTR LDX COUNTR LDA COLTAB,X Use page two for color table STA WSYNC Wait STA COLBAK CPX #$4F Last line? BNE ENDDLI No, exit LDA #$00 Yes, reset counter STA COUNTR ENDDLI PLA TAX PLA Restore accumulator RTI MINE PHA TXA PHA INC COUNTR LDX COUNTR LDA COLTAB1,X Use end of page 6 for color table STA WSYNC Wait STA COLPF1 LDA COLTAB2, X A Second table for PF2 STA COLPF2 LDA CHARTAB, X A Third table for Character set STA CHBASE CPX #$23 Last line? (23 because I'm useing a 24 line screen all with interrupts) BNE ENDDLI No, exit LDA #$00 Yes, reset counter STA COUNTR ENDDLI PLA TAX PLA Restore accumulator RTI Can i get away with all the code after the wsync or will I get a flicker? I can't think of any other way to change three registers per DLI. Cheers, -Peter. Quote Link to comment Share on other sites More sharing options...
Rybags Posted July 27, 2011 Share Posted July 27, 2011 Should be OK. The trick with multiple stores is to preload 2 or more registers before the WSync. But if you're pushing 2 or 3 registers to the stack, it leaves less time. Also, it's not always a good idea to rely on the DLIs alone to reset your counter. Best to have a VBlank routine that does that. Using Altirra in debug/single step mode is a good way to guage what's happening where. Enable full-width screen then use F11 to step through. Set a memory access trap to stop the machine when your DLI occurs. BA R 200 is a good way. Press F8 if the trap hits too early, once execution gets to where you want to single-step just press F11 to go 1 instruction at a time, there should be a yellow/black line overlayed on the screen that shows where in the scanline you are. Quote Link to comment Share on other sites More sharing options...
simonl Posted July 27, 2011 Share Posted July 27, 2011 The other option is to have different DLI routines for each line and then you can skip the indexed addressing etc e.g. IGDLI1 PHA STX RESTDLIX1+1 LDX CHBASTAB LDA PF3COLORTAB STA WSYNC STA COLPF3 STX CHBAS IGDLICHL1 LDA #<IGDLI2 STA VDSLSTL IGDLICHH1 LDA #>IGDLI2 STA VDSLSTH RESTDLIX1 LDX #$FF PLA RTI IGDLI2 PHA STX RESTDLIX2+1 LDX CHBASTAB+1 LDA PF3COLORTAB+1 STA WSYNC STX CHBAS STA COLPF3 IGDLICHL2 LDA #<IGDLI3 STA VDSLSTL IGDLICHH2 LDA #>IGDLI3 STA VDSLSTH RESTDLIX2 LDX #$FF PLA RTI ; etc. and so on, or even use immediate mode: IGDLI1 PHA STX RESTDLIX1+1 CHTAB1 LDX #$FF PF3COL1 LDA #$FF STA WSYNC STA COLPF3 STX CHBAS IGDLICHL1 LDA #<IGDLI2 STA VDSLSTL IGDLICHH1 LDA #>IGDLI2 STA VDSLSTH RESTDLIX1 LDX #$FF PLA RTI IGDLI2 PHA STX RESTDLIX2+1 CHTAB2 LDX #$FF PF3COL2 LDA #$FF STA WSYNC STX CHBAS STA COLPF3 IGDLICHL2 LDA #<IGDLI3 STA VDSLSTL IGDLICHH2 LDA #>IGDLI3 STA VDSLSTH RESTDLIX2 LDX #$FF PLA RTI ; etc. and in VBI store to CHTAB1+1, CHTAB2+1, PF3COL1+1, PF3COL2+1 and so on Quote Link to comment Share on other sites More sharing options...
+Stephen Posted July 27, 2011 Share Posted July 27, 2011 Should be OK. The trick with multiple stores is to preload 2 or more registers before the WSync. But if you're pushing 2 or 3 registers to the stack, it leaves less time. Also, it's not always a good idea to rely on the DLIs alone to reset your counter. Best to have a VBlank routine that does that. Using Altirra in debug/single step mode is a good way to guage what's happening where. Enable full-width screen then use F11 to step through. Set a memory access trap to stop the machine when your DLI occurs. BA R 200 is a good way. Press F8 if the trap hits too early, once execution gets to where you want to single-step just press F11 to go 1 instruction at a time, there should be a yellow/black line overlayed on the screen that shows where in the scanline you are. Man - I really have to RTFM on Altirra, and learn the debugger!!! Quote Link to comment Share on other sites More sharing options...
phaeron Posted July 28, 2011 Share Posted July 28, 2011 Altirra knows most of the public OS symbols, so you can just type: ba r vdslst I profiled the execution of the DLI routine, and I'm not sure that the De Re Atari DLI handler is a good starting point. It's intended for a Gr.7 screen (IR mode D) screen, but the timing constraints are tighter for an IR mode 4 screen, for which it is dangerously close to missing a scanline. This is what the timing looks like on one run: - NMI interrupt (DLI) 1: 63: 19 | A=00 X=05 Y=FD S=EA P=3C | C018: 2C 0F D4 LC018 BIT NMIST 1: 63: 28 | A=00 X=05 Y=FD S=EA P=BE | C01B: 10 03 BPL $C020 1: 63: 36 | A=00 X=05 Y=FD S=EA P=BE | C01D: 6C 00 02 JMP (VDSLST) 1: 63: 56 | A=00 X=05 Y=FD S=EA P=BE | 0600: 48 PHA 1: 63: 64 | A=00 X=05 Y=FD S=E9 P=BE | 0601: 8A TXA 1: 63: 68 | A=05 X=05 Y=FD S=E9 P=3C | 0602: 48 PHA 1: 63: 74 | A=05 X=05 Y=FD S=E8 P=3C | 0603: E6 00 INC COUNTR 1: 63: 84 | A=05 X=05 Y=FD S=E8 P=BC | 0605: A6 00 LDX COUNTR 1: 63: 90 | A=05 X=DD Y=FD S=E8 P=BC | 0607: BD 00 04 LDA $0400,X ;$04DD 1: 63: 98 | A=00 X=DD Y=FD S=E8 P=3E | 060A: 8D 0A D4 STA WSYNC 1: 63:103 | A=00 X=DD Y=FD S=E8 P=3E | 060D: 8D 17 D0 STA COLPF1 1: 63:108 | A=00 X=DD Y=FD S=E8 P=3E | 0610: BD 01 04 LDA $0401,X ;$04DE 1: 63:112 | A=00 X=DD Y=FD S=E8 P=3E | 0613: 8D 18 D0 STA COLPF2 1: 64: 3 | A=00 X=DD Y=FD S=E8 P=3E | 0616: BD 00 04 LDA $0400,X ;$04DD 1: 64: 7 | A=00 X=DD Y=FD S=E8 P=3E | 0619: 8D 09 D4 STA CHBASE 1: 64: 11 | A=00 X=DD Y=FD S=E8 P=3E | 061C: E0 23 CPX #$23 1: 64: 13 | A=00 X=DD Y=FD S=E8 P=BD | 061E: D0 04 BNE $0624 1: 64: 16 | A=00 X=DD Y=FD S=E8 P=BD | 0624: 68 L0624 PLA 1: 64:101 | A=05 X=DD Y=FD S=E9 P=3D | 0625: AA TAX 1: 64:103 | A=05 X=05 Y=FD S=E9 P=3D | 0626: 68 PLA ...and this is what the DMA timing diagram looks like for the scanline where the DLI starts: Altirra> .dma 1 1 1 2 3 4 5 6 7 8 9 0 1 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 .D...................C.C.CRC.CRC.CRC.CRC.CRC.CRC.CRC.CRC.CRC.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.C.............. Legend: (M)issile (P)layer (D)isplayList (R)efresh Play(F)ield (C)haracter (V)irtual In the debugger, DLIs fire at cycle 10 or later, and STA WSYNC resumes execution at 105 with possibly one cycle already executed on the next instruction. The last cycle of STA WSYNC needs to execute by cycle 103, so that's 90 cycles available up to that point, with 40 cycles taken by playfield DMA and 9 cycles by refresh DMA, leaving 41 cycles. The accounting looks like this: Finish current instruction: 0-7 cycles Interrupt sequence: 7 cycles OS dispatch (BIT abs / Bcc not taken / JMP (abs)): 11 cycles User DLI routine: 20 cycles This adds up to 45 cycles, which means this routine will occasionally miss a scan line. In De Re Atari's terms, Phase One is too long. Here's an trace of this occurring, due to a seven cycle instruction running in mainline: Altirra> bx "pc=$0610 and vpos > 63" Breakpoint 0 set at PC=$0610 with condition: vpos>63 Altirra> g Breakpoint 0 hit (12891: 64,108) PC=0610 A=01 X=01 Y=98 S=E2 P=34 ( I ) 0610: BD 01 04 LDA $0401,X [$0402] = $02 Altirra> h 15 14) T=00603| 63, 0 A=42 X=00 Y=98 S=e6 P=76 ( V1B IZ ) 0686: 68 PLA 13) T=00603| 63, 4 A=42 X=00 Y=98 S=e7 P=74 ( V1B I ) 0687: 4C 80 06 JMP $0680 [$0680] = $A2 12) T=00603| 63, 7 A=42 X=00 Y=98 S=e7 P=74 ( V1B I ) 0680: A2 00 LDX #$00 11) T=00603| 63, 9 A=42 X=00 Y=98 S=e7 P=76 ( V1B IZ ) 0682: 3E FF 06 ROL $06FF,X [$06FF] = $00 10) T=00603| 63, 28 A=42 X=00 Y=98 S=e4 P=76 ( V1B IZ ) C018: 2C 0F D4 LC018 BIT NMIST [$D40F] = $9F 9) T=00603| 63, 44 A=42 X=00 Y=98 S=e4 P=b4 (N 1B I ) C01B: 10 03 BPL $C020 T=00603| 63, 52 A=42 X=00 Y=98 S=e4 P=b4 (N 1B I ) C01D: 6C 00 02 JMP (VDSLST) [$0600] = $48 7) T=00603| 63, 66 A=42 X=00 Y=98 S=e4 P=b4 (N 1B I ) 0600: 48 PHA 6) T=00603| 63, 72 A=42 X=00 Y=98 S=e3 P=b4 (N 1B I ) 0601: 8A TXA 5) T=00603| 63, 76 A=00 X=00 Y=98 S=e3 P=36 ( 1B IZ ) 0602: 48 PHA 4) T=00603| 63, 82 A=00 X=00 Y=98 S=e2 P=36 ( 1B IZ ) 0603: E6 00 INC COUNTR [$00] = $01 3) T=00603| 63, 92 A=00 X=00 Y=98 S=e2 P=34 ( 1B I ) 0605: A6 00 LDX COUNTR [$00] = $01 2) T=00603| 63, 98 A=00 X=01 Y=98 S=e2 P=34 ( 1B I ) 0607: BD 00 04 LDA $0400,X [$0401] = $01 1) T=00603| 63,103 A=01 X=01 Y=98 S=e2 P=34 ( 1B I ) 060A: 8D 0A D4 STA WSYNC [$D40A] = $FF 0) T=00603| 63,107 A=01 X=01 Y=98 S=e2 P=34 ( 1B I ) 060D: 8D 17 D0 STA COLPF1 [$D017] = $0F One way to fix this would be to move the INC COUNTR statement to the end of the DLI (Phase Three) and rotate the tables to match. The other critical part of the DLI is Phase Two, which has to execute before a wall of DMA on the next scanline: 1 2 3 4 5 6 7 8 9 0 1 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 .D................F.FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCRC.............. Legend: (M)issile (P)layer (D)isplayList (R)efresh Play(F)ield (C)haracter (V)irtual Starting after the STA WSYNC, there are 31 cycles available, plus one bonus cycle. This is pretty relaxed and you've got 20 cycles assuming no page crossings, so that should be fine. Quote Link to comment Share on other sites More sharing options...
xzerix Posted July 28, 2011 Author Share Posted July 28, 2011 Wow, that looks complex. It may be that the "DeRe" way of doing things will be "Good enough" for what I want. I've got a busy workload for the rest of the week - No Atari time :*( Thanks for your help, guys. Will post what I settle on sometime this weekend. Cheers! Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted July 28, 2011 Share Posted July 28, 2011 Man - I really have to RTFM on Altirra, and learn the debugger!!! Same here! Quote Link to comment Share on other sites More sharing options...
Chilly Willy Posted July 28, 2011 Share Posted July 28, 2011 CPX #$23 Last line? (23 because I'm useing a 24 line screen all with interrupts) $23 is not 24 lines, it's 36 lines. Hexadecimal FTW! Quote Link to comment Share on other sites More sharing options...
xzerix Posted August 8, 2011 Author Share Posted August 8, 2011 CPX #$23 Last line? (23 because I'm useing a 24 line screen all with interrupts) $23 is not 24 lines, it's 36 lines. Hexadecimal FTW! Doh! I made the mistake of thinking $0000-$01ff was 2k the other day. Here's the code I eventually came up with. Not pretty but is (seems) to work... I was worried that the interrupt may turn "on" in the middle of drawing a frame, but it seems to work from the top, by luck or by Judgement... 1000 REM INITIALISE MULTI DLI SCREEN 1010 CHBASE=152*256 1020 OPEN #1,4,0,"H:A4ALIAS.SET" 1030 FOR I=0 TO 1023:GET #1,L 1040 POKE CHBASE+I,L 1050 NEXT I:POKE 756,152 1060 GRAPHICS 0:POKE 752,1 1070 DL=PEEK(560)+PEEK(561) 1080 PAGE6=1536 1090 REM READ IN DLI ROUTINE TO PAGE6 1100 RESTORE 1120 1110 FOR I=0 TO 40:READ J 1120 POKE PAGE6+I,J:NEXT I 1130 DATA 72,138,72,238,40,6 1140 DATA 174,40,6,189,64,6 1150 DATA 141,23,208,189,96,6 1160 DATA 141,24,208,189,128,6 1170 DATA 141,9,212,224 1180 DATA 24 1190 DATA 208,5,169,0,141,40,6 1200 DATA 104,170,104,64 1210 DATA 0 1220 REM INITISE TABLE FOR COL1 1230 RESTORE 1260 1240 FOR I=0 TO 23:READ J 1250 POKE PAGE6+64+I,J:NEXT I 1260 DATA 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14 1270 REM TABLE FOR COL2 1280 RESTORE 1310 1290 FOR I=0 TO 23:READ J 1300 POKE PAGE6+96+I,J:NEXT I 1310 DATA 16,32,48,64,80,96,112,128 1320 DATA 16,32,48,64,80,96,112,128 1330 DATA 16,32,48,64,80,96,112,128 1340 REM TABLE FOR VCSET 1350 RESTORE 1380 1360 FOR I=0 TO 23:READ J 1370 POKE PAGE6+128+I,J:NEXT I 1380 DATA 152,152,152,152,152,152,152,152 1390 DATA 152,152,152,152,152,152,152,152 1400 DATA 152,152,152,152,152,152,152,152 1410 DL=PEEK(560)+PEEK(561)*256 1420 POKE DL+3,128+64+4 1430 FOR I=6 TO 28:POKE DL+I,128+4 1440 NEXT I 1460 POKE 512,0:POKE 513,6 1470 POKE 54286,192 Quote Link to comment Share on other sites More sharing options...
+therealbountybob Posted August 9, 2011 Share Posted August 9, 2011 Hi, Out of all the atari assembly language books I've read "Assembly Language Programming for the Atari Computers" has been particularly good; checkout chapter 8 for some good info and example DLI code Quote Link to comment Share on other sites More sharing options...
xzerix Posted August 9, 2011 Author Share Posted August 9, 2011 Hi, Out of all the atari assembly language books I've read "Assembly Language Programming for the Atari Computers" has been particularly good; checkout chapter 8 for some good info and example DLI code Cheers trbb, Just had a quick peek at that (am at work so couldn't linger.. ) Looks just the ticket. Scrolling was my next project as well! 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.