When would you use LD A,R ?

edited November 2009 in Development
Can anyone tell me a practical use of LD A,R and LD R,A I am confused when you would need to use it?

Cheers
Post edited by robpearmain on
«1

Comments

  • edited November 2009
    Can anyone tell me a practical use of LD A,R and LD R,A I am confused when you would need to use it?

    Cheers

    See speedlock loaders :smile:
  • edited November 2009
    Primitive random number generator :)
  • edited November 2009
    Ditto what Ralf said. Not much good for repeated use (because it just loops around a lot), but quite handy for seeding a proper pseudo-random number generator if you want a program to generate different results each time you run it. (For 128 values of 'different results', anyway. Don't run an online casino off it.)

    Also, a less obvious one: for finding out whether interrupts are enabled. (A side effect of LD A,R and LD A,I is to set the P/V flag to the current interrupt state)
  • edited November 2009
    Fast flag using bit 7 (that doesn't change with the auto-increment). Frobush uses it in his sound routines, modifying bit 7 in the interrupt routine, and checking that bit every little while in his sound routines so the game continues after the interrupt.
  • edited November 2009
    Right, I was checking a sound routine when it got me to ask the question.

    Thanks
  • edited November 2009
    Ralf wrote: »
    Primitive random number generator :)

    I may have to use that in one of my projects since I don't have FRAMES to use.
  • edited November 2009
    Can anyone tell me a practical use of LD A,R and LD R,A I am confused when you would need to use it?

    Interface 1 uses LD A,R as a random number when two or more Spectrums try to claim the network at the same time. Lowest value wins.

    The ZX80 and ZX81 use LD R,A to directly set the refresh register when generating the display during interrupts.
  • edited November 2009
    aowen wrote: »
    I may have to use that in one of my projects since I don't have FRAMES to use.

    It's probably a decent seed if it's grabbed after an initial menu screen where the player has to do something to start the game. As long as you double it up or somesuch since a 7-bit seed value probably isn't ideal for the 16-bit prngs that everyone uses.
  • edited November 2009
    It's probably a decent seed if it's grabbed after an initial menu screen where the player has to do something to start the game. As long as you double it up or somesuch since a 7-bit seed value probably isn't ideal for the 16-bit prngs that everyone uses.

    I was planning on grabbing it after the player has been through a fairly large number of screens of text, so it will be determined by how long it takes them to read it. That way there should still be some variance even when starting the game from a snapshot.
  • edited November 2009
    gasman wrote: »
    Also, a less obvious one: for finding out whether interrupts are enabled. (A side effect of LD A,R and LD A,I is to set the P/V flag to the current interrupt state)

    I didn't know that! I have a rather messy routine to detect the interrupt enabled state in my snapshot routine that I can now get rid of :-)

    On the same subject, is there an easy way to find the interrupt mode as well, without having to enable interrupts and wait 20ms and find out whether 0x0038 is called or an IM2 routine is called?
  • edited November 2009
    I'm sure I mentioned it at some point in the Goldfinch thread... :-)

    I'm not aware of any direct way to read interrupt mode - my NMI code for Gasware (which was copiously borrowed from the equivalent routine in Fatware) goes the long-winded route of setting up an IM2 handler and waiting to see if it gets called.
  • edited November 2009
    Metalbrain wrote: »
    Fast flag using bit 7 (that doesn't change with the auto-increment). Frobush uses it in his sound routines, modifying bit 7 in the interrupt routine, and checking that bit every little while in his sound routines so the game continues after the interrupt.

    Crappy FroCode...
    ;****************************************
    ; WORK THE INTERRUPTS...
    ;****************************************
    
    Interrupt:
                     	push	        af
    
    			ld		a,0x80			; flag the interrupt
    			ld		r,a
    
    			ld		a,(SpeedFlag)		; increase timer
    			inc		a
    			ld		(SpeedFlag),a
    
    			pop		af
    			ei
    			reti
    
    ;****************************************
    ; START SOUND FX...
    ;****************************************
    
    GoFX:
    ;			ex		af,af
    ;			ld		a,(FXNumber)		; sound already playing - priority?
    ;			or		a
    ;			ret		nz
    ;			ex		af,af
    
    GoFXForce:
                    	ld		(FXNumber),a		; current FX number
    			add		a,a
    			add		a,FXTable-2 & 0xff
    			ld		l,a
    			ld		h,FXTable / 0x100
    			ld		a,(hl)
    			inc		l
    			ld		h,(hl)
    			ld		l,a
    			ld		(FXPointer),hl		; current FX data
    			ret
    
    ;****************************************
    ; WAIT FOR FLYBACK...
    ;****************************************
    
    WaitVBlank:
                    	xor		a
    			ld		r,a                     ; clear interrupt flag
    			ei
    
    			ld		a,(FXNumber)            ; playing a sound effect?
    			or		a
    			jr		nz,Beeper               ; if so then play
    
    WaitInt:	
                            ld		a,r                     ; if not then just wait for flyback
    			jp		p,WaitInt
    			di
    			ret
    
    ;****************************************
    ; IN GAME BEEPER ROUTINES...
    ;****************************************
    
    Beeper:		
                            ld		hl,(FXPointer)		; table pointer
    
    			ld		a,(hl)	                ; frequency + code
    			inc		hl
    			cp		LASTFXCODE		; new control code?
    			jr		nc,PlayFX0
    
    			add		a,a
    			jr		nz,PlayFX
    			ld		(FXNumber),a		; no more sound
    			jr		WaitInt
    
    PlayFX:		
                            push  	hl
    			add		a,FXRout & 0xff         ; choose beeper routine
    			ld		l,a
    			ld		h,FXRout / 0x100
    			ld		a,(hl)
    			inc		l
    			ld		h,(hl)
    			ld		l,a
    			ld		(FXCode),hl	        ; change current beeper routine
    			pop		hl
    			ld		a,(hl)
    
    PlayFX0:	        ld		(FXPointer),hl		; ready for next time
    			ld		e,a		        ; current frequency
    			ld		d,a
    			ld		hl,PlayOut	        ; return address
    			push	        hl                      ; onto stack
    			ld		hl,(FXCode)
    			jp              (hl)                    ; beeper effect till interrupt
    
    PlayOut:
    	                xor		a                       ; and relax
    			out		(BEEPPORT),a
    			di
    			ret
    
    ;****************************************
    ; NORMAL BEEP...
    ;****************************************
    
    Beep:
            		ld		a,0x10
    			out		(BEEPPORT),a
    			ld		b,e
    Beep0:
            		ld		a,r                     ; exit on flyback  
    			ret		m
    			djnz	        Beep0
    			jr		Beep1                   ; this is right!
    
    Beep1:
            		ld		a,0
    			out		(BEEPPORT),a
    			ld		b,d
    Beep2:
            		ld		a,r                     ; exit on flyback
    			ret		m
    			djnz	        Beep2
    			jr		Beep
    
    
  • edited November 2009
    Winston wrote: »
    I didn't know that! I have a rather messy routine to detect the interrupt enabled state in my snapshot routine that I can now get rid of :-)

    I was wondering why you were doing things that way. I assume you knew something I didn't...
    On the same subject, is there an easy way to find the interrupt mode as well, without having to enable interrupts and wait 20ms and find out whether 0x0038 is called or an IM2 routine is called?

    Not that I know of. In practice, a pretty good test is to test the value of I.
  • edited November 2009
    Metalbrain wrote: »
    Fast flag using bit 7 (that doesn't change with the auto-increment). Frobush uses it in his sound routines, modifying bit 7 in the interrupt routine, and checking that bit every little while in his sound routines so the game continues after the interrupt.
    Me too. Use it to mark when "something interesting" has happened in an interrupt routine. Usually when I want to wait for a frame that I may be counting. When I hit the frame count, I set bit 7 of R. When the main code wants to see if the frame count has been reached, it tests the bit (and sit and spin until it does).
  • edited November 2009
    I was wondering why you were doing things that way. I assume you knew something I didn't...

    That is often a rather poor assumption, I'm afraid :-)
  • edited November 2009
    Not that I know of. In practice, a pretty good test is to test the value of I.

    Pretty good, but not 100%.
    I sometimes set I-reg to ANY value and just set IM 1.
    IM 1 doesn't need I at all.

    I.e. when IM 2 is set and I want to deactivate IM 2 I only set IM 1.
  • edited November 2009
    Dr BEEP wrote: »
    Pretty good, but not 100%.

    Well, yes. I thought I made it fairly clear that I knew it wasn't perfect. As we've been through already on this front, it's a tradeoff between perfection and size.
  • edited November 2009
    gasman wrote: »
    goes the long-winded route of setting up an IM2 handler and waiting to see if it gets called.

    That's what I did (although I realise now for some reason, I'm also checking the IM 1 counter for no good reason...well, I know the good reason, it's called "sloppy thinking", my excuse "insufficient caffiene")
  • edited November 2009
    Well, yes. I thought I made it fairly clear that I knew it wasn't perfect. As we've been through already on this front, it's a tradeoff between perfection and size.

    Yes you did, it is also no offence; only an example in which it won't work.
  • edited November 2009
    You can use R register for counting loops. So you don't need a INC or DEC instruction and the loop can be faster.
    Ultra-speed loading of k7zx uses these LD a,r and LD R,a instructions.
  • edited November 2009
    LD A, R can be used to stop your memory from refreshing, creating random s**t on your screen and RAM in general:
            XOR A
    loop:   LD R, A
            JR loop
    

    Just don't expect the code to run forever as eventually the program itself will die as the RAM holding it is staved of oxygen!
    :-)
  • edited November 2009
    BloodBaz wrote: »
    LD A, R can be used to stop your memory from refreshing, creating random s**t on your screen and RAM in general:
            XOR A
    loop:   LD R, A
            JR loop
    
    Just don't expect the code to run forever as eventually the program itself will die as the RAM holding it is staved of oxygen!
    :-)
    I hate to be picky but...

    thats not LD A,R is it.
    I wanna tell you a story 'bout a woman I know...
  • edited November 2009
    karingal wrote: »
    I hate to be picky but...

    thats not LD A,R is it.

    The code is right - the description is wrong.
  • edited November 2009
    Ooops. At least my code was bug free!
  • edited November 2009
    BloodBaz wrote: »
    Ooops. At least my code was bug free!

    Well, I'm afraid that is just not good enough!

    For your homework I want you to write out...

    "I must not mess with my "r"s until I understand the true meaning."

    ...500 times, and write a 1000 word essay on the importance and relevance of the cultural significance of the curviture of the inside of a ping pong ball in today's society.

    On my desk by 9.30am tomorrow!
  • edited November 2009
    frobush wrote: »

    ...500 times, and write a 1000 word essay on the importance and relevance of the cultural significance of the curviture of the inside of a ping pong ball in today's society.

    aR,

    bed h's gonna cheat by if <500 print and the random-Sinterklaas-poet
    my old website http://home.hccnet.nl/c.born/ has changed to http://www.cborn.nl/zxfiles/ so just click it and select a file
  • edited November 2009
    BloodBaz wrote: »
            XOR A
    loop:   LD R, A
            JR loop
    

    Just don't expect the code to run forever as eventually the program itself will die as the RAM holding it is staved of oxygen!
    :-)

    That code could run forever if interrupts were disabled and possibly also if they were enabled. Returning to BASIC again might pose a problem.
  • edited November 2009
    Bob Stains wrote: »
    That code could run forever if interrupts were disabled and possibly also if they were enabled. Returning to BASIC again might pose a problem.

    ie the by-product of this executing is it refreshing itself (or more correctly the DRAM memory rows which hold this chunk of code). Stuff stored in other memory rows would "melt away".

    (For the non techie-peeps ;) )

    BASIC would crash and interrupts almost certainly as the env variables disappear....
  • edited November 2009
    Hmmm...

    That's got me thinking.
    One thing I lack on a freshly powered up Speccy is a source of randomness. I need to generate a random number for the initial transaction ID for DHCP, and also for the initial source port for UDP where the source port wasn't specified.

    Practically speaking, the random number generator doesn't have to be particularly good, but it's best to have some randomness rather than none at all. At the moment, all I do is checksum a chunk of lower RAM in whatever state it was in on power up (RAM doesn't start set at zero - it only ends up at zero after the program in ROM clears it down). The chunk of RAM that I use is the sysvars area, so it also gets perturbed by BASIC to give a little bit of randomness on RESET, too. (This obviously falls down if someone's been playing a game that overwrites the sysvars).

    However, I wonder if setting a chunk of RAM to 0xFF, then doing a loop for a while with XOR A/LD R, A will also give random enough results too, different bits are likely to decay at different rates.
  • edited November 2009
    Probably best to avoid bit-rot as a source of randomness because it won't work with clones and modern hardware that use self-refreshing DRAM or SRAM.
Sign In or Register to comment.