| Author |
Message |
FluBBa
Joined: 21 Jul 2005
Posts: 339
Location: GBG
|
|
 |
Posted: Sat Feb 23, 2008 10:13 pm |
|
|
The 2 most significant bits of the second byte you write to the VDP CTRL port desides what function you want to use (read, write, register & palette).
When writing to the registers some of the other 6 bits have meaning, depending on the VDP version (TMS9918, SMS/GG, MD) from 3 to 5 bits, the other ones are ignored.
So for the SMS you should only check the 4 least significant bits.
I hope that explains it well. =)
Last edited by FluBBa on Sun Feb 24, 2008 9:36 am; edited 1 time in total |
|
| Back to top |
|
 |
benryves
Joined: 12 Apr 2005
Posts: 364
Location: Purley, England
|
|
 |
Posted: Sat Feb 23, 2008 10:49 pm |
|
|
Cheers for the quick reply!
As far as I'm aware, this means that when the second byte is written to the control port, you should mask it with 0x0F and use this as the register index. I'm doing this, yet fail the test. Here's the relevant snippet from my code...
/// <summary>
/// Write a byte of data to the <see cref="VideoDisplayProcessor"/> control port.
/// </summary>
/// <param name="data">The data to write to the port.</param>
public void WriteControl(byte data) {
if (this.waitingForSecond) {
this.accessMode = (DataAccessMode)(data >> 6);
this.address = (ushort)((this.address & 0x00FF) + (data << 8));
switch (this.accessMode) {
case DataAccessMode.VideoRamReadWrite: // 0
this.readBuffer = this.vram[this.address & 0x3FFF];
++this.address;
break;
case DataAccessMode.RegisterWrite: // 2
this.registers[data & 0x0F] = (byte)(address & 0xFF);
this.UpdateIrq();
break;
}
this.waitingForSecond = false;
} else {
this.address = (ushort)((this.address & 0xFF00) + data);
this.waitingForSecond = true;
}
} |
I have a myriad other VDP bugs (for example, I have no horizontal counter emulation at all!) so it might be something completely unrelated.
Thank you for this very useful tool! It's helped me greatly so far. :-)
|
|
| Back to top |
|
 |
FluBBa
Joined: 21 Jul 2005
Posts: 339
Location: GBG
|
|
 |
Posted: Sun Feb 24, 2008 9:43 am |
|
|
I think that test was timing dependant before, I've uploaded a new version again.
The test works by enabling and disabling the line interrupt (through register $00, $10, $20 & $30) so that must be working as well.
I think it was just timing problem before your code looks ok, test it again.
|
|
| Back to top |
|
 |
benryves
Joined: 12 Apr 2005
Posts: 364
Location: Purley, England
|
|
 |
Posted: Sun Feb 24, 2008 3:48 pm |
|
|
I'm still failing the test here. I do have some line-interrupt timing problems (which may or may not be CPU-related) in certain games, though, so I'll try and sort those out first!
Edit: Paul Baker pointed out the bug in my interrupt code, so the test now passes. Sorry for that!
|
|
| Back to top |
|
 |
Christophe
Joined: 23 Feb 2007
Posts: 18
|
|
 |
Posted: Wed Feb 27, 2008 5:50 pm |
|
|
thanks for taking the time doing this ;)
hum, I only failed at the test checking correct "HCOUNTER values" :strangely, I use the table from SMS Plus, which have the following values (342 pixel entries):0x00-0xe9,0x94-0xff
From your readme:
| Quote:
|
|
The values are the HClock (0-220,350-511) divided by 2
|
I don't understand, this makes more than 342 pixels ?
|
|
| Back to top |
|
 |
FluBBa
Joined: 21 Jul 2005
Posts: 339
Location: GBG
|
|
 |
Posted: Wed Feb 27, 2008 9:28 pm |
|
|
The values should be between 0xE9 -> 0xFF & 0x00 -> 0x93 (or how ever you want to count).
Every third value is repeated once. On my 2 SMS they are like this:
0x00, 0x01, 0x02, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06...
Though on my MD I don get a definitive sequence, it repeates both 0x00, 0x01 & 0x02 depending on how it feels when I turn it on.
I will try to fix up the test later to account for this.
|
|
| Back to top |
|
 |
Guest
Guest
|
|
 |
Posted: Thu Feb 28, 2008 4:31 am |
|
|
| Isn't the horizontal counter only used for the light gun and nothing else ?
|
|
| Back to top |
|
 |
FluBBa
Joined: 21 Jul 2005
Posts: 339
Location: GBG
|
|
 |
Posted: Thu Feb 28, 2008 7:31 am |
|
|
| Nope, I'm using it right now in my test program as you can see :P
|
|
| Back to top |
|
 |
Christophe
Joined: 23 Feb 2007
Posts: 18
|
|
 |
Posted: Thu Feb 28, 2008 10:26 am |
|
|
| FluBBa wrote:
|
The values should be between 0xE9 -> 0xFF & 0x00 -> 0x93 (or how ever you want to count).
Every third value is repeated once. On my 2 SMS they are like this:
0x00, 0x01, 0x02, 0x02, 0x03, 0x04, 0x05, 0x05, 0x06...
Though on my MD I don get a definitive sequence, it repeates both 0x00, 0x01 & 0x02 depending on how it feels when I turn it on.
I will try to fix up the test later to account for this.
|
thanks, this was definitely a mistake in the table I used, I fixed this (it was even described in GG docs and it's the same for genesis in h32 mode)
About the repetitive value,doesn't it depend on read timings ?
btw, I always thought that hc latch could only work with external peripheral driving TH, that is when TH is set to input only (on the genesis for example, it seems that you can not trigger INT2 by setting TH to output and writing 0 then 1 into TH bit)
|
|
| Back to top |
|
 |
FluBBa
Joined: 21 Jul 2005
Posts: 339
Location: GBG
|
|
 |
Posted: Thu Feb 28, 2008 12:25 pm |
|
|
| Christophe wrote:
|
|
About the repetitive value,doesn't it depend on read timings ?
|
It depends on the syncronisation between the VDP clock and the CPU clock.
| Christophe wrote:
|
|
btw, I always thought that hc latch could only work with external peripheral driving TH, that is when TH is set to input only (on the genesis for example, it seems that you can not trigger INT2 by setting TH to output and writing 0 then 1 into TH bit)
|
I don't know how the MD acts in MD mode as I don't have a flashcart for the MD, the HCount latch works just fine in SMS mode (except that the repeating values are not the same all the time).
|
|
| Back to top |
|
 |
FluBBa
Joined: 21 Jul 2005
Posts: 339
Location: GBG
|
|
 |
Posted: Thu Mar 27, 2008 4:19 pm |
|
|
| Added 2 new test for line interrupt and vblank interrupt, plus some very preliminary mode5 palette test.
|
|
| Back to top |
|
 |
benryves
Joined: 12 Apr 2005
Posts: 364
Location: Purley, England
|
|
 |
Posted: Sat Apr 05, 2008 7:06 pm |
|
|
I don't quite follow how you measure the HCount values, especially the offsets (eg your "0xE9 -> 0xFF & 0x00 -> 0x93" statement - why do you start at $E9?)
When the H counter is latched, my current logic simply takes the number of CPU cycles that have executed since the start of the current scanline, multiplies by 342 then divides by 228. This fails the test!
I've attached two screenshots - the first is generated when I take the main SMS test, the second when I take the HCount timing test. I haven't found any emulators that pass the test, so have nothing to compare them against!
This is the last test I'm failing, so am naturally quite eager to correct my bugs!
|
|
| Back to top |
|
 |
FluBBa
Joined: 21 Jul 2005
Posts: 339
Location: GBG
|
|
 |
Posted: Sat Apr 05, 2008 9:07 pm |
|
|
Are you sure you're not dividing first and then multiply? (use paranthesis)
Even if you had the wrong numbers in your calculation you shouldn't end up with the same number 13 times =)
0xE9 is -23, that's ~46 vdp clocks before the screen starts, 0 is on pixel 0.
You also can use SMSAdvance on Visualboy Advance to see what the values should be.
|
|
| Back to top |
|
 |
benryves
Joined: 12 Apr 2005
Posts: 364
Location: Purley, England
|
|
 |
Posted: Sat Apr 05, 2008 10:21 pm |
|
|
| FluBBa wrote:
|
|
Are you sure you're not dividing first and then multiply? (use paranthesis)
|
Yes, the exact code is as follows:
/// <summary>
/// Latches the value of the horizontal counter.
/// </summary>
public void LatchHorizontalCounter() {
int ExecutedCycles = this.Emulator.TotalExecutedCycles - this.CpuCyclesAtStartOfScanline;
int PixelsDrawn = (ExecutedCycles * 342) / this.CpuCyclesPerScanline;
this.HorizontalCounter = (byte)(PixelsDrawn / 2);
} |
(I did forget to mention that I divided the number of pixels drawn by two).
I'm not quite sure how your test works, so I'm also not quite sure where I'm going wrong. If I rig LatchHorizontalCounter to simply increment HorizontalCounter by one (or any other number) each time it's called, the test results show a smoothly incrementing value to reflect that (however, for such a test to work, you'd need to poll the counter in < 1 CPU cycle, which isn't going to happen). If I just return ExecutedCycles directly (a value which changes wildly each call) I get similar results to the previous screenshots - long runs of identical numbers.
Could it be because scanlines aren't exactly 228 clock cycles long? On average they are, but some are a little longer (and some a little shorter) as not all sequences of instructions will fit into the 228 clock cycle designation.
Thank you very much for your patience, but I'm absolutely stumped here!
EDIT: My assumption - that scanlines aren't exactly 228 cycles long - seems to be vaguely correct. Rather than use the total number of CPU cycles that have been executed to calculate the offset from the start of the current scanline, I use a secondary counter that increments in fixed 228 increments and calculate the pixel offset based on that. I still get the wrong values, but at least they're only out in so far as they increment in the sequence 0, 0, 1, 2, 3, 3, 4, 5, 6, 6, ...
|
|
| Back to top |
|
 |
FluBBa
Joined: 21 Jul 2005
Posts: 339
Location: GBG
|
|
 |
Posted: Sun Apr 06, 2008 10:06 am |
|
|
My calculation is something like this:
HCount = (590 - (scanLineCycle*3))/4;
Where scanLineCount should be between 0 & 227 (228 cycles).
|
|
| Back to top |
|
 |
dj_yt
Joined: 15 Dec 2006
Posts: 59
Location: UK
|
|
 |
Posted: Wed May 14, 2008 12:39 pm |
|
|
Nice utility. The latest mobile version of JavaGear I have in the works passes the first screen of tests no problem.
Obviously on a mobile based emulator there is still a need to ensure speed is pretty good, and not to add unnecessary complexity.
With the line interrupt test (last test screen 2), it currently fails as both frame int and line int are set simultaneously, at the very last stage of the test. Can anyone recommend a lightweight way of implementing the correct behaviour?
|
|
| Back to top |
|
 |
FluBBa
Joined: 21 Jul 2005
Posts: 339
Location: GBG
|
|
 |
Posted: Wed May 14, 2008 7:53 pm |
|
|
| dj_yt wrote:
|
|
Obviously on a mobile based emulator there is still a need to ensure speed is pretty good, and not to add unnecessary complexity.
|
I guess you haven't worked with a 16MHz ARM machine ;)
If you are talking about the HCounter I don't think you should put too much effort into that.
The frame interrupt is taken at the begining of line 0xC1 (193), the line interrupt happens between line 0x00 and 0xC0 (0 to 192) (Bock take note).
|
|
| Back to top |
|
 |
dj_yt
Joined: 15 Dec 2006
Posts: 59
Location: UK
|
|
 |
Posted: Wed May 14, 2008 9:44 pm |
|
|
Trust me - the performance you get out of some Java phones when emulating a CPU, is probably the equivalent of a 16Mhz ARM processor running asm emulation. :)
Thanks for the clarification on the frame interrupt. I was setting the frame interrupt flag on line 192 and then actually allowing the interrupt to be triggered from line 193. Correcting this to the way you describe fixed the text.
|
|
| Back to top |
|
 |
Christophe
Joined: 23 Feb 2007
Posts: 18
|
|
 |
Posted: Tue May 20, 2008 9:45 am |
|
|
from the WIKI:
| Quote:
|
|
The latter is a special case - the system hardware is designed so that the HCounter is automatically latched when either controller's TH line is active (0), and cannot be freely read.
|
your test is waiting for HC to change on a TH 0->1 transition. Emulating the contrary (like described in Wiki and docs) makes the test failed
so, who is right ?
|
|
| Back to top |
|
 |
Maxim
Site Admin
Joined: 19 Oct 1999
Posts: 7468
Location: London, UK
|
|
 |
Posted: Tue May 20, 2008 10:13 am |
|
|
| The wiki may be wrong. I didn't confirm the details on hardware, just based on my own understanding of how things work and the official docs.
|
|
| Back to top |
|
 |