repetto74 Posted June 10, 2017 Share Posted June 10, 2017 Hi guys, Could someone explain to me how this delay loop work ? 251 DELAY 252 LDX #15 253 LP1 LDY #255 254 LP2 DEY 255 BNE LP2 256 DEX 257 BNE LP1 260 RTS As far as I understood these are two nested counters to delay speed of execution (needed in ML coding to the speed of operations). X and Y registers are firstly loaded with respectively 15 and 255 but then I do not catch the meaning of the BNE statement. What is used to compare the Branch Not Equal statement? So Y and X registers values are both compared by default ? Sounds fuzzy to me. Quote Link to comment Share on other sites More sharing options...
RevEng Posted June 10, 2017 Share Posted June 10, 2017 The DEC opcode (in it's various forms) affect the S (sign of result) and Z (result=0) processor flags. So you don't actually need to do the compare - the branch opcode always just checks the relevant processor flags (BNE means Z not set) and acts accordingly. The CMP opcode mostly acts like a throw-the-result-away subtraction opcode. If you "CMP #13" before a branch, it subtracts 13 from A. If A is holding 13, the result will be "0" (processor flags are updated) and a following BEQ will branch. All of this essentially means that "CMP #0", "CPX #0", and "CPY #0" are always redundant, and can be skipped. 1 Quote Link to comment Share on other sites More sharing options...
repetto74 Posted June 10, 2017 Author Share Posted June 10, 2017 Ok Reveng this sounds more clear to me . So the BNE is referring to the CMP of X and Y registers to the #0 value which is set by default and as you said there is no need to code a CMP #0. Quote Link to comment Share on other sites More sharing options...
RevEng Posted June 10, 2017 Share Posted June 10, 2017 Ok Reveng this sounds more clear to me . So the BNE is referring to the CMP of X and Y registers to the #0 value which is set by default and as you said there is no need to code a CMP #0. Pretty much, but I like to think of it the other way around. CMP is something extra you need to do when you require a result/value/state that isn't already covered by the existing processor flags. These flags get set by decrementing, incrementing, shifting, etc., so often enough you don't need CMP, especially if you plan for it. When you can skip the CMP, your loops are a little bit quicker and are a couple bytes smaller. Nothing to get too religious over and waste a lot of time on - your coding time is probably your most precious resource - but something to keep in mind. Quote Link to comment Share on other sites More sharing options...
repetto74 Posted June 10, 2017 Author Share Posted June 10, 2017 Copied then Many thanks for your explanation on this ! 1 Quote Link to comment Share on other sites More sharing options...
Rybags Posted June 10, 2017 Share Posted June 10, 2017 One of the keys to learning 6502 and most assembly languages is to know how the flags are affected by various instructions. It saves doing unnecessary compare and other test instructions sometimes. And in some cases you can just use the flags as input to future operations, e.g. carry flag after bitshift to an ADC instruction. 2 Quote Link to comment Share on other sites More sharing options...
sanny Posted June 12, 2017 Share Posted June 12, 2017 Although it's irrelevant in a delay loop, I tend to write such things like that (no superfluous loading of Y in the outer loop): 251 DELAY 252 LDX #15 253 LDY #0 254 LP1 DEY 255 BNE LP1 256 DEX 257 BNE LP1 260 RTS Quote Link to comment Share on other sites More sharing options...
carlsson Posted June 12, 2017 Share Posted June 12, 2017 The first loop will though run for 15 * 255 = 3825 iterations, while the second loop will run for 15 * 256 = 3840 iterations. Small difference, and in practise one probably would wait for a raster interrupt or whichever similar construct there is rather than have a delay loop if your timing needs to be very precise. The first loop is easy to change so it runs for e.g. 14 * 193 = 2702 iterations, the second loop would always run in a multiple of 256 iterations. Quote Link to comment Share on other sites More sharing options...
repetto74 Posted June 12, 2017 Author Share Posted June 12, 2017 Hi have tried to code a small routine to cycle through border and background colors : 10 ;******************************* 20 ;* BACKGRND AND BORDER COLORS * 30 ;******************************* 40 ; 50 .OPT OBJ 60 *= $8000 70 CLR LDA 53770 80 STA 712 85 JMP DELAY 90 LDA 53770 0100 STA 710 0105 JMP DELAY 0110 JMP CLR 0251 DELAY 0252 LDX #15 0253 LDY #0 0254 LP1 DEY 0255 BNE LP1 0256 DEX 0257 BNE LP1 0260 RTS Actually I have a different behaviour when testing it with M65 DDT command : - without the delay loop the program will cycle colors at high speed in an endless loop - with the delay subroutine the program stops immediately and will display only one set of colors Cannot understand where I am wrong here. I would like to have colors being displayed slowly in an endless loop. Quote Link to comment Share on other sites More sharing options...
MaPa Posted June 12, 2017 Share Posted June 12, 2017 (edited) You can not to JMP to DELAY, you have to JSR (Jump to SubRoutine). Edited June 12, 2017 by MaPa 1 Quote Link to comment Share on other sites More sharing options...
repetto74 Posted June 12, 2017 Author Share Posted June 12, 2017 Dumb I am !!! Thanks Mapa Quote Link to comment Share on other sites More sharing options...
shanti77 Posted June 12, 2017 Share Posted June 12, 2017 If you use shadow registers better delay loop will be: Lda 20 Lp1 cmp 20 beq Lp1 Quote Link to comment Share on other sites More sharing options...
repetto74 Posted June 12, 2017 Author Share Posted June 12, 2017 Hi Shanti77, I am not an expert on ML codings I am learning honestly. Can you explain better this technique of shadow registers? Quote Link to comment Share on other sites More sharing options...
+David_P Posted June 12, 2017 Share Posted June 12, 2017 Alternatively, you could set an interrupt, then forget about it. Once the countdown timer reaches zero, your interrupt would be executed. Ideally, your interrupt routine would reset the timer for you as well, so it would trigger again... and again... and again... Quote Link to comment Share on other sites More sharing options...
shanti77 Posted June 13, 2017 Share Posted June 13, 2017 (edited) OS copy value from shadow registers to hardware registers every VBLK interrupt (every 1/50 sek PAL or 1/60 sek in NTSC). If you wrote something to this registers you see change only after VBLK interrupt (one time on all screen draw) 712 is shadow of register 53274 710 is shadow of register 53272 Try wrote something to this registers without delay, you see difference. Edited June 13, 2017 by shanti77 Quote Link to comment Share on other sites More sharing options...
Rybags Posted June 13, 2017 Share Posted June 13, 2017 Shadow colour registers are only copied once per frame. To do colour bar effects you should hit the GTIA registers directly. In cases of doing such video related stuff, delay loops are a poor way to synchronise things. The WSync register on Antic is the way to do as it halts the CPU until near the end of a scanline. Also once you get into such things, it's usually easiest doing them in a DLI. Quote Link to comment Share on other sites More sharing options...
tebe Posted June 13, 2017 Share Posted June 13, 2017 loop lda $d40b ; vcount bne loop 2 Quote Link to comment Share on other sites More sharing options...
repetto74 Posted June 13, 2017 Author Share Posted June 13, 2017 Ok guys thanks a lot for your advices I am a beginner in ML coding I need to get deeper into that and I know there are always better ways to code in ML for optimal execution :-) Quote Link to comment Share on other sites More sharing options...
repetto74 Posted June 13, 2017 Author Share Posted June 13, 2017 (edited) 10 ; 20 .OPT OBJ 30 *= $8000 40 CLR LDA 53770 50 STA 53274 60 LDA 53770 70 STA 53272 80 JMP CLR Yep this will give like the classic loading pattern of a C64 tape . How is that big difference? Ok I see, the VBLK act like a delay so when using the shadow register the video refresh is slower. Edited June 13, 2017 by repetto74 Quote Link to comment Share on other sites More sharing options...
GarthW Posted September 18, 2017 Share Posted September 18, 2017 I have a lot of tips of this kind in the Tips For Programming the 65(c )02 chapter of my 6502 primer. The following is one of them. An automatic compare-to-zero instruction is built into the following 65(C )02 instructions: LDA, LDX, LDY, INC, INX, INY, DEC, DEX, DEY, INA, DEA, AND, ORA, EOR, ASL, LSR, ROL, ROR, PLA, PLX, PLY, SBC, ADC, TAX, TXA, TAY, TYA, and TSX. This means that, for example, a CMP #0 after an LDA is redundant, a wasted instruction. The only time a 65c02 (CMOS) needs a compare-to-zero instruction after one of these is if you want to compare a register that was not involved in the previous instruction; for example, DEY CPX #0 (Note the Y and the X are not the same register.) If you can spare a register to which you can transfer the one you want to test, you can save a byte with the transfer instead of a compare instruction. The example above, if the contents of A don't need to be kept, could be changed to: DEY TXA and then you can branch on the N or Z flag which tell if X was negative or zero. The TXA isn't any faster (both TXA and CPX# take two clocks); but TXA takes only one byte, whereas the CPX #0 takes two bytes. The NMOS 6502 did have a bug in that the flags weren't always correct after a decimal-mode operation like ADC; so then you might have to follow it with the CMP #0 to get the N and Z flags right. It's best to just use the CMOS processor when possible. Note to admin: I have PM'ed about this kind of thing before, and gotten no answer. Whether in BBCode mode or otherwise, I can't find any way to keep the "#0" black in the code section, or put the C in 65C02 in parentheses without a space after it and keep it from turning it into the copyright sign, or other things I want to do. In BBCode mode, there's no line wrap as I'm writing. This kind of thing is why I don't post much on this forum. It's too discouraging. Please give the option to just do like the phpBB forums where we manually tell it everything we want, or even html as done in a plain text editor where we manually write all the tags.. Quote Link to comment Share on other sites More sharing options...
brokencodes Posted June 17, 2019 Share Posted June 17, 2019 On 9/17/2017 at 11:56 PM, GarthW said: I have a lot of tips of this kind in the Tips For Programming the 65(c )02 chapter of my 6502 primer. The following is one of them. An automatic compare-to-zero instruction is built into the following 65(C )02 instructions: LDA, LDX, LDY, INC, INX, INY, DEC, DEX, DEY, INA, DEA, AND, ORA, EOR, ASL, LSR, ROL, ROR, PLA, PLX, PLY, SBC, ADC, TAX, TXA, TAY, TYA, and TSX. This means that, for example, a CMP #0 after an LDA is redundant, a wasted instruction. The only time a 65c02 (CMOS) needs a compare-to-zero instruction after one of these is if you want to compare a register that was not involved in the previous instruction; for example, DEY CPX #0 (Note the Y and the X are not the same register.) If you can spare a register to which you can transfer the one you want to test, you can save a byte with the transfer instead of a compare instruction. The example above, if the contents of A don't need to be kept, could be changed to: DEY TXA and then you can branch on the N or Z flag which tell if X was negative or zero. The TXA isn't any faster (both TXA and CPX# take two clocks); but TXA takes only one byte, whereas the CPX #0 takes two bytes. The NMOS 6502 did have a bug in that the flags weren't always correct after a decimal-mode operation like ADC; so then you might have to follow it with the CMP #0 to get the N and Z flags right. It's best to just use the CMOS processor when possible. Note to admin: I have PM'ed about this kind of thing before, and gotten no answer. Whether in BBCode mode or otherwise, I can't find any way to keep the "#0" black in the code section, or put the C in 65C02 in parentheses without a space after it and keep it from turning it into the copyright sign, or other things I want to do. In BBCode mode, there's no line wrap as I'm writing. This kind of thing is why I don't post much on this forum. It's too discouraging. Please give the option to just do like the phpBB forums where we manually tell it everything we want, or even html as done in a plain text editor where we manually write all the tags.. 10 ;******************************* 20 ;* BACKGRND AND BORDER COLORS * 30 ;******************************* 40 ; 50 .OPT OBJ 60 *= $8000 70 CLR LDA 53770 80 STA 712 85 JMP DELAY 90 LDA 53770 0100 STA 710 0105 JMP DELAY 0110 JMP CLR 0251 DELAY 0252 LDX #15 0253 LDY #0 0254 LP1 DEY 0255 BNE LP1 0256 DEX 0257 BNE LP1 0260 RTS 65(C)02 Quote Link to comment Share on other sites More sharing options...
brokencodes Posted June 17, 2019 Share Posted June 17, 2019 code tags seem to work just fine... [ code ] and [ /code ] minus the spaces... at least then the forum software asks if you want to apply rich text formatting. 1 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted June 22, 2019 Share Posted June 22, 2019 if you need longer and more precise delays you can also use RTCLOK $12,$13 and $14 $14 increments by one every Vblank up to 255, then $13 increments by one etc. etc. Think I'm right in saying 50 counts/second for PAL and 60 counts/second NSTC sample code 1 ; Delay time is in the X register 10 DELAY LDA #0 20 STA $14 30 LOOP CPX $14 40 BNE LOOP 50 RTS 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.