Incorrect IRQ timings in Oric emulators
New day, new version.
I've been working a bit with Xeron to find out what the problems were, so here are the results with a new version of Oricutron versus my Pravet 8D using version 1.5 of the benchmark test:
So as you can see the TIMER2 OFFSET is now identical between the two versions ($0011), the SEI tests return exactly the same number of cycles as well ($4E33).
There are still some differences, but they are being worked on.
I've been working a bit with Xeron to find out what the problems were, so here are the results with a new version of Oricutron versus my Pravet 8D using version 1.5 of the benchmark test:
So as you can see the TIMER2 OFFSET is now identical between the two versions ($0011), the SEI tests return exactly the same number of cycles as well ($4E33).
There are still some differences, but they are being worked on.
Actually the current SVN version is a bit closer. Here is with overlay:
and here is without:
As you can see, in both cases the ROM IRQ has a matching minimum, and the maximum is very close.
The "SEI" cases are identical, as are the 16KHz cases.
So we're very close, but I really have no idea why the other cases don't match :-/
and here is without:
As you can see, in both cases the ROM IRQ has a matching minimum, and the maximum is very close.
The "SEI" cases are identical, as are the 16KHz cases.
So we're very close, but I really have no idea why the other cases don't match :-/
Indeed, way better results
So, if the 16khz IRQ is identical, we can probably assume that IRQ timings are now correct. So based on that, this must be something timed differently in the sample sound replay code. (at the end of http://miniserve.defence-force.org/svn/ ... giplayer.s)
I guess I will try to compare the timings of the internal code, without running an IRQ at all
So, if the 16khz IRQ is identical, we can probably assume that IRQ timings are now correct. So based on that, this must be something timed differently in the sample sound replay code. (at the end of http://miniserve.defence-force.org/svn/ ... giplayer.s)
I guess I will try to compare the timings of the internal code, without running an IRQ at all
Oh look
Everything is spot-on except for that pesky sample routine now! (the same is true in ROM-only mode).
When calculating instruction cycles, (zp,x) and (zp),y page boundary checks got broken at some point.
Also "INC zeropage" was in the wrong part of the switch statement.
Just have to figure out the erroneous instruction(s) in the sample routine now...
Everything is spot-on except for that pesky sample routine now! (the same is true in ROM-only mode).
When calculating instruction cycles, (zp,x) and (zp),y page boundary checks got broken at some point.
Also "INC zeropage" was in the wrong part of the switch statement.
Just have to figure out the erroneous instruction(s) in the sample routine now...
So, some more tests, this time I tested specifically if the actual timing of the sample replay code is taking the same time on the various machines.
What I did is to manually call the IRQ using BRK while having the interupts disabled (SEI). Here is the result on four machines:
The reference machine, Pravetz 8D
Oricutron, 100% accurate using the WIP3 version:
MESS, which would be also accurate if it did not have the wrong timer_2 reading (add +2 everywhere and you get the good value)
Euphoric, which has impossible to understand results Oo:
We are getting close
What I did is to manually call the IRQ using BRK while having the interupts disabled (SEI). Here is the result on four machines:
The reference machine, Pravetz 8D
Oricutron, 100% accurate using the WIP3 version:
MESS, which would be also accurate if it did not have the wrong timer_2 reading (add +2 everywhere and you get the good value)
Euphoric, which has impossible to understand results Oo:
We are getting close
This thread is a little bit too complicated for me, but this sprang to mind and I wondered if it could help you understand what happens with Euphoric:
Build 1008 changes
------------------
- modified the 6502 emulator in order to be able to detect a timer countdown before an interrupt is raised. Thanks to Simon for having spotted a bug in M.A.R.C that exploits this "feature"... Also, quite heavily changed the 6502 emulator at the same time to simplify it, and found that some undocumented opcodes are bogged... (not fixed yet)
Build 1008 changes
------------------
- modified the 6502 emulator in order to be able to detect a timer countdown before an interrupt is raised. Thanks to Simon for having spotted a bug in M.A.R.C that exploits this "feature"... Also, quite heavily changed the 6502 emulator at the same time to simplify it, and found that some undocumented opcodes are bogged... (not fixed yet)
Ha, 1008, I was doing my tests with version 1007, guess I could take a look at what the results are with the new version.
About the difficulty, well it's actually conceptually relatively simple, it's just hard to explain
I was thinking of perhaps writing an article about that in the CEO Mag, with first things related to the timings in emulators, and then second how to profile/time your code (without having to do manual clock cycle counting).
Do you think André would be interested?
About the difficulty, well it's actually conceptually relatively simple, it's just hard to explain
I was thinking of perhaps writing an article about that in the CEO Mag, with first things related to the timings in emulators, and then second how to profile/time your code (without having to do manual clock cycle counting).
Do you think André would be interested?
New day, new test.
Yesterday I was trying to figure out why the last test was giving different MAX results for the sample player (about 250 cycles difference) while all other tests gave correct results.
I had a theory about perhaps the timer2 registers not behaving in the same way when wrapping around (it's a 16 bit value that we need to read as two separate bytes so what may happen if you read them while the value is about to impact the second byte, like going from 0100 to 00FF, are you going to read 00/01, FF/00, 00/00, FF/01?)
So wrote a new test, that basically increase a temporization delay one cycle by one cycle, and display the values, then I compared on the various machines. Here are the results:
Pravetz:
Oricutron (Wip 3):
Euphoric (1011):
Mess:
As far as my tired eyes can tell, Oricutron gives absolutely the same result as the Pravetz, including the broken values: 00FA 00FB 01FC 01FD 01FE 01FF 0100 0101 0102 0103 0104... (guess I need to learn how to read the timer correctly if I want to make a decent profiler, but at least the emulator correctly emulates my crappy code).
Mess is consistent, starts with two missing cycles, and consistently misses two cycles everywhere.
Euphoric is globally once cycle too large, but there are also some strange things like double values (2A 2A) and backward sequences (5C 5D 5E <b>5C<b> 60).
Guess we are not done yet
As before the tests source code and executable program are on the SVN server http://miniserve.defence-force.org/svn/ ... Benchmark/
Yesterday I was trying to figure out why the last test was giving different MAX results for the sample player (about 250 cycles difference) while all other tests gave correct results.
I had a theory about perhaps the timer2 registers not behaving in the same way when wrapping around (it's a 16 bit value that we need to read as two separate bytes so what may happen if you read them while the value is about to impact the second byte, like going from 0100 to 00FF, are you going to read 00/01, FF/00, 00/00, FF/01?)
So wrote a new test, that basically increase a temporization delay one cycle by one cycle, and display the values, then I compared on the various machines. Here are the results:
Pravetz:
Oricutron (Wip 3):
Euphoric (1011):
Mess:
As far as my tired eyes can tell, Oricutron gives absolutely the same result as the Pravetz, including the broken values: 00FA 00FB 01FC 01FD 01FE 01FF 0100 0101 0102 0103 0104... (guess I need to learn how to read the timer correctly if I want to make a decent profiler, but at least the emulator correctly emulates my crappy code).
Mess is consistent, starts with two missing cycles, and consistently misses two cycles everywhere.
Euphoric is globally once cycle too large, but there are also some strange things like double values (2A 2A) and backward sequences (5C 5D 5E <b>5C<b> 60).
Guess we are not done yet
As before the tests source code and executable program are on the SVN server http://miniserve.defence-force.org/svn/ ... Benchmark/
Well, I know why we get a 6DB5 result in Oricutron. Quite late into the benchmark, we get what should be a 6CB5 run, but the Timer 1 interrupt kicks in right in the middle of the timer 2 read code.
So, it loads the low 8 bits into A, the interrupt kicks in, THEN it reads the high 8 bits into X. The interrupt takes long enough for the high byte to change, so thats why you get $6DB5 instead of $6CB5.
Now, since the VIA/CPU interractions are supposed to be cycle exact, we should get an identical run to the real hw, so I need to figure out how my timers differ from the real hardware.
So, it loads the low 8 bits into A, the interrupt kicks in, THEN it reads the high 8 bits into X. The interrupt takes long enough for the high byte to change, so thats why you get $6DB5 instead of $6CB5.
Now, since the VIA/CPU interractions are supposed to be cycle exact, we should get an identical run to the real hw, so I need to figure out how my timers differ from the real hardware.
Last edited by Xeron on Thu Aug 18, 2011 6:29 pm, edited 1 time in total.
Good news for all the users of Euphoric, the results of the build 1013 (you can fetch it on http://oric.free.fr/emulator.html) are now much better.
With the IRQ Benchmark 1.7 the following changes are visible:
- the Timer 2 offset is now correct ($11) and the timer 2 reading test also give the same values as on the real machine (the weird duplicated or going backward values are gone)
- the results of the BRK test are also correct (6C/64 everywhere)
- the SEI tests correctly give $4E33 independently of if the IRQ is setup or not.
The only values that are still wrong are the number of emulated IRQ on the high frequency timer tests, not sure if this can be fixed, but that's definitely an improvement.
Thanks Fabrice for the quick fix
With the IRQ Benchmark 1.7 the following changes are visible:
- the Timer 2 offset is now correct ($11) and the timer 2 reading test also give the same values as on the real machine (the weird duplicated or going backward values are gone)
- the results of the BRK test are also correct (6C/64 everywhere)
- the SEI tests correctly give $4E33 independently of if the IRQ is setup or not.
The only values that are still wrong are the number of emulated IRQ on the high frequency timer tests, not sure if this can be fixed, but that's definitely an improvement.
Thanks Fabrice for the quick fix