> I'd never thought I'd say this, but the Nes is too fast!
> I'm trying to kill about 3/4 of a second. I've come up with this:
> [long string of nops]
> This just loops about 255*3 then comes back. Is there an opcode better
> that nop? Or a whole better why to do it?
Um, there is a better way. The following will take about 750000 cycles.
Fine-tuning the initial values of X and Y is left as an exercice for the
reader.
LDY #$AC
LDX #0
.1 JSR .2
DEX
BNE .1
DEY
BNE .1
.2 RTS
Challenge: can you come up with a shorter routine that waits for about
3/4 of a second?
It could be interesting to try to come up with 6502 "busy beavers".
A busy beaver is a program that eventually terminates (in other words,
it doesn't enter an infinite loop). The idea is to come up with the
program of length N that works for the longest time before terminating.
To preserve the theoretical flavor of the problem, assume 64k of RAM
and no ROM routines to call.
[Crossposted to comp.sys.apple2 and comp.sys.cbm, where 6502 coders live.]
Paul Guertin
p...@sff.net
> I'd never thought I'd say this, but the Nes is too fast!
> I'm trying to kill about 3/4 of a second. I've come up with this:
> [long string of nops]
> This just loops about 255*3 then comes back. Is there an opcode better
> that nop? Or a whole better why to do it?
If you're doing this on a Commodore product, the easiest (and most
dependable) way is just to watch the "jiffy timer", which is updated
by the interrupt services 60 times a second. Count 45 jiffy changes,
and you're there.
On most other platforms, you'll have an I/O chip that contains a timer
.. set it and have it signal or interrupt you.
Paul Guertin posted code for a decent delay loop. On a machine such
as the Commodore 128, you have to watch it, though: the clock speed
can be changed by the user. And new architectures which fit the 6502
family with a high-speed clock raise the same problems. Look to a
jiffy or hardware timer of some sort. Some even watch the video
raster to get timing data; again, this can be tricky since vertical
retrace differs in different parts of the world.
--Jim
"Um, there is a better way. The following will take about 750000 cycles.
Fine-tuning the initial values of X and Y is left as an exercice for the
reader.
LDY #$AC
LDX #0
.1 JSR .2
DEX
BNE .1
DEY
BNE .1
.2 RTS
Challenge: can you come up with a shorter routine that waits for about
3/4 of a second?".
I can eliminate the LDX #$00.
LDY #$AD
L JSR R
DEX
BNE L
DEY
BNE L
R RTS
should take from 749260 to 753595 clock cycles, depending on the starting value
of X (max. for 0 and min. for 1).
Paul also said,
'It could be interesting to try to come up with 6502 "busy beavers".
A busy beaver is a program that eventually terminates (in other words,
it doesn't enter an infinite loop). The idea is to come up with the
program of length N that works for the longest time before terminating.
To preserve the theoretical flavor of the problem, assume 64k of RAM
and no ROM routines to call.'.
To try to preserve my remaining sanity, I didn't consier the case of 64
Kbytes of RAM. But I DID want to get a ballpark figure for the resulting time
interval, so I considered the case of 2314 bytes. The routine uses 2058 bytes:
LDA #$00
TAX
L STA $1000,X
INX
BNE L
00 INC $1000,X
JSR R
01 BNE 00
INC $1000,X
JSR R
02 BNE 01
INC $1000,X
JSR R
03 BNE 02
...
...
...
INC $1000,X
JSR R
FF BNE FE
INC $1000,X
JSR R
BNE FF
R RTS
Counting the page from $1000 to $10FF, a total of 2314 bytes are used. I
get 7.1E617 cycles. For a 1 MHz clock, that's about 2E602 centuries. I don't
know whether that's the best that can be done with 2314 bytes, and I CERTAINLY
don't know the answer to your question. A very intersting problem, Paul.
--
When backing up your hard drive, shift into reverse gear S M O O T H L Y.
John
That's if you're using the pure code, and not watching TI$, right?
My own code usually has some wierd type of timer. From an interupt, I
have a portion such as:
LDA RASTER
EOR #$FF
STA RASTER
Remember, that's played from an interupt, so it is executed once every
1/60th of a second. (1/50th a la PAL).
Now, in your code have something like:
LDA RASTER
- CMP RASTER
BEQ -
Loops until the value of RASTER changes, which is every 1/60th of a
second. Now, multiply this by however long you want it to occur. IE:
For one second, you would do that 60 times.
Drawback is obvious: the smallest time slice you could get is 1/60th of
a second. Of course, you could probably software-hack a method of
getting down to multiples of 1/60th of a second, ie: 1/30th of a second,
1/120th of a second, etc.
-p
> --Jim
--
Cyberad/RPG aka Patrick M Pritchard * http://www.interlog.com/~cr
PLUR- Peace Love Unity Respect -Live It, Love It, Be It, BELIEVE!
RENEGADE PROGRAMMING GROUP IN 1999 -- Taking It To The Next Level
> Now, in your code have something like:
> LDA RASTER
> - CMP RASTER
> BEQ -
> Loops until the value of RASTER changes, which is every 1/60th of a
> second. Now, multiply this by however long you want it to occur. IE:
> For one second, you would do that 60 times.
> Drawback is obvious: the smallest time slice you could get is 1/60th of
> a second. Of course, you could probably software-hack a method of
> getting down to multiples of 1/60th of a second, ie: 1/30th of a second,
> 1/120th of a second, etc.
Well, you will almost never get a multiple of 1/60th of a second exactly,
because the time you have to wait for the first raster varies.
Thus you get in average (N+0.5)/60th of a second when you wait for N
rasters.
And again, what others mentioned, in some parts of the world you'd
even get (N+0.5)/50th of a second, which is about 17% off.
The most correct way would be to determine the clock frequency
of the machine (by testing whether it is an NTSC or PAL machine)
and then compute the exact number of cycles for the amount of time
to wait and set a CIA timer with it.
Don't know how this works on a SuperCPU machine, though. But assuming
the base machine still runs at the same clock as without, this
should work as well.
Andre
--
Email address may be invalid. Use "fachat AT physik DOT tu-chemnitz DOT de"
------Fight SPAM - join CAUCE http://www.cauce.org------Thanks, spammers...
Andre Fachat, Institute of physics, Technische Universität Chemnitz, FRG
http://www.tu-chemnitz.de/~fachat
LDA #$00
TAX
L STA $1000,X
INX
BNE L
00 INC $1000,X
JSR R
01 BNE 00
INC $1000,X
JSR R
02 BNE 01
INC $1000,X
JSR R
03 BNE 02
...
...
...
INC $1000,X
JSR R
FF BNE FE
INC $1000,X
JSR R
BNE FF
R RTS
John goofed; the addresses in page $1000 must all be different. The
correct routine is:
LDA #$00
TAX
L STA $1000,X
INX
BNE L
00 INC $1001,X
JSR R
01 BNE 00
INC $1002,X
JSR R
02 BNE 01
INC $1003,X
JSR R
03 BNE 02
...
...
...
INC $10FE,X
JSR R
FF BNE FE
INC $10FF,X
JSR R
BNE FF
R RTS
John, you should be more careful when you transcribe your notes. And don't
blame your mistakes on the enfeebled, dilapidated, decrepit, CompuServe
Newsserver. After all, CompuServe DID increase its fiscal 1999 Newsserver
budget grom $19.95 to $29.95.
> And again, what others mentioned, in some parts of the world you'd
> even get (N+0.5)/50th of a second, which is about 17% off.
>
Whoops! I thought I had mentioned that, sorry!
> The most correct way would be to determine the clock frequency
> of the machine (by testing whether it is an NTSC or PAL machine)
> and then compute the exact number of cycles for the amount of time
> to wait and set a CIA timer with it.
Agreed. Totally forgot about the CIA timers as well.
Treat almost all RAM as a very long binary number, the rest is the program.
Increment that number from 000..000 to 111..111. When it wraps stop.
Assuming that the code increments approx every 10us and we have a 500000
bit number, the time to run would be of the order of 10^150000 seconds.
As there are only about 10^7 seconds in a year, I have no intention of
running such a program.
P.S. I had to use logs to work this out - probably the first time since
high school.
--
David Wilson School of IT & CS, Uni of Wollongong, Australia da...@uow.edu.au
"The most correct way would be to determine the clock frequency
of the machine (by testing whether it is an NTSC or PAL machine)
and then compute the exact number of cycles for the amount of time
to wait and set a CIA timer with it.".
For short term accuracy, that is correct. But for long term accuracy, the
crystal oscillator is not nearly so good as the TOD clocks (in countries where
the power-line frequency is adjusted to make electric clocks read Coordinated
Universal Time). A typical crystal has a tolerance of 500 parts per million
(ppm), amd a temperature stability of 50 ppm over the specified temperature
range. But even if the total figure were only 25 ppm (a likely situation), a
timer that used that frequency would have an error of over 13 minutes/year.
The short term accuracy of the power-line frequency can be poor, if heavy loads
are suddenly put onto the dynamos. But long term, the power-line is the next
best thing to an atomic clock.
But using a 1 MHz (approx.) crystal for timing, still gives an uncertainty
of one count; that is inherent in all counters. Of course, 1 us is better than
20 ms (PAL frame rate). And I might mention to Patrick that an interrupt
routine is not needed to use VIC as a timer. Just read VIC register $12, and
loop until you read, say, $80. Then
increment your counter, wait about 70 clock cycles (to get off the current
scanning line), and go back into the loop.
> p...@sff.net (Paul Guertin) writes:
> >It could be interesting to try to come up with 6502 "busy beavers".
> >A busy beaver is a program that eventually terminates (in other words,
> >it doesn't enter an infinite loop). The idea is to come up with the
> >program of length N that works for the longest time before terminating.
> >To preserve the theoretical flavor of the problem, assume 64k of RAM
> >and no ROM routines to call.
>
> Treat almost all RAM as a very long binary number, the rest is the program.
> Increment that number from 000..000 to 111..111. When it wraps stop.
Right, that's the asymptotic optimum for large N, but I was more
interested in smaller values of N.
Assume the routine must return to the caller with a RTS. So for N=1..7
we can start with the following:
length 1: RTS
length 2: NOP; RTS
length 3: PHA; PLA; RTS
length 4: JSR FOO; FOO: RTS
length 5: JSR FOO; FOO: NOP RTS (I think this can be improved)
length 6: LDX #0; FOO: DEX; BNE FOO; RTS
length 7: FOO: DEC BAR+1; BAR: LDA #0; BNE FOO; RTS
I have no idea if they are optimal (in the sense that no routine of the
same length takes longer to return). Any takers?
Paul Guertin
let's see...comp.sys.cbm (Commodore 8-bits)...comp.sys.apple2...I'd guess
so.
White Flame (aka David Holz)
http://fly.to/theflame