PV-1000 test and characterization ROMs

Discussion of development of software for any "obsolete" computer or video game system. See the WSdev wiki and ObscureDev wiki for more information on certain platforms.
Post Reply
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

PV-1000 test and characterization ROMs

Post by lidnariq »

Over the past two months, I have been working on reverse engineering a very silly video game console made by Casio.

As part of this, I've had to write a large number of tests. Source is included, and should be considered under CC-0 or MIT-0. Most assemble with debian's "z80asm"; a few assemble with sdcc's sdasz80 and sdcc.

In no particular order:
scanwfe.zip
(8.01 KiB) Downloaded 32 times
ScanWFE checks all 256 possible values written to configuration port $FE. A "pass" result will start with (in big black digits) 00 01 02 and 0F in tiny digits, like this:
crop_IMG_4113.jpg
and will then proceed to 04 05 06 with 0F; 08 09 0A with 0F; 0C 0D 0E with 0F; 10 11 12 with 1F; [...] 7C 7D 7E with 7F; B8 B9 BA with BF; BC BD BE with BF; repeat those two for a total eight times; and finally a solid white screen for a while.

toggle.zip
(9.06 KiB) Downloaded 30 times
This one turned out to be a surprisingly good test for exact raster timing. The CPU just runs in an infinite loop, enabling and disabling video and waiting a variable number of T states each time. This happens to produce an almost- stable image that looks like this:
toggle-on-hardware.jpg
"Almost" stable because there's one pair of adjacent scanlines about 20% of the way down the screen that toggles back and forth which one is enabled.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: PV-1000 test and characterization ROMs

Post by lidnariq »

Digital captures (24MSa/sec) of "toggle" were taken too:
black=csync – yellow=colorburst – dkyellow=cburst AND csync – grey=blanking – white=red video
black=csync – yellow=colorburst – dkyellow=cburst AND csync – grey=blanking – white=red video
green=tilemap fetch – blue=pattern fetch ­— red=CPU fetch – yellow=errors??<br />(/rd asserted when darker)
green=tilemap fetch – blue=pattern fetch ­— red=CPU fetch – yellow=errors??
(/rd asserted when darker)
wff-v2.zip
(4.44 KiB) Downloaded 27 times
"wffv2" scans the 16 possible values for the upper 4 bits written to configuration port $FF.
A pass result will show the following two-digit pairs in the center of the screen, one at a time.
these twelve: 0R 00 2R 22 4R 44 6R 66 RR RR RR RR
then a white screen with an R
then a white screen
then a white screen with an R
then a white screen
and then repeat
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: PV-1000 test and characterization ROMs

Post by lidnariq »

twinkle.zip
(1.54 KiB) Downloaded 23 times
"Twinkle" plays "Twinkle, Twinkle, Little Star" while scanning the bottom 4 bits written to configuration port $FF. This one establishes that
1- the bit order of border color bits is BGR (byte & 4 = blue; byte & 1 = red), the opposite of what MAME does
2- border is visible on top and bottom, not sides
3- byte & 8 disables rendering and that displays solid border color
4- the Z80 gets to run at full 3.6MHz speed when the ASIC isn't stealing time to render the display
twinkle-two-frames.jpg
twinkle-two-frames.jpg (4.56 KiB) Viewed 2237 times
(This one was written before "toggle")
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: PV-1000 test and characterization ROMs

Post by lidnariq »

joystick.zip
(1.96 KiB) Downloaded 29 times
"joystick" measures how long it takes for button press information to propagate through the manually-scanned matrix of buttons.
shrunk.jpg
The top four rows measure in units of 3 3/4 T states; the bottom four in units of 21 T states.

This established that it takes almost no time (top-most row has one zero: 11 T states for in a,(c) plus one nop making 15 T states) from when the value is written to configuration port FD until pressed buttons can be detected by reading port FD. Unfortunately, it also establishes that it takes an effective eternity (6th row has six 1s: least 21 T states per 1 on screen due to speed of inir making 126 to 146 T states) to detect a button is not pressed.


irqtiming.zip
(1.59 KiB) Downloaded 29 times
"irqtiming" displays a small white bar in the border whenever an IRQ is fired, then switches back to red border.
IRQ overhead means there's a 55 T state delay from assertion to bar, or roughly 70 pixels.
The number in the center of the screen is the value written to configuration port FC, choosing whether interrupt cause 1 (end of vblank) or 2 (matrix scan assistance) is enabled.
irqs-wFC=2.jpg
irqs-wFC=1.jpg
Par
Posts: 3
Joined: Sun May 28, 2023 11:45 pm

Re: PV-1000 test and characterization ROMs

Post by Par »

I was made aware of your work on the NESDev PV-1000 wiki pages some time last month (not too long after the PV-1000 drivers for MAME had been updated.). I've been meaning to get in touch since then, but there was a lot of stuff I felt I had to do first.

I messed around with the PV-1000 from the end of 2020 through most of 2022 (I had pretty much been away from it since August of 2022), and during that time I did a lot of experimentation through programming to try to figure out how the system works. The bulk of what I learned was acquired by writing and running my own programs on two different PV-1000s with a 32KB EPROM cartridge I scrapped together (also from disassembling and comparing bits of the officially released programs, and sources like Enri's website). I always felt guilty that I hadn't shared what I learned anywhere online, but I didn't have a good place to post the information, and the thought of trying to put everything together always felt too overwhelming.

When I found out about the wiki pages, I knew quite a bit of information that was unknown (and/or just not mentioned) on the wiki at the time. Since then, I've been trying to put some stuff together to send off to you, but progression went WAAAY slower than I was hoping it would. (I'm a slow writer to begin with, and there was just too much I wanted to convey. I also wanted to go back and revise some old test programs/make some new ones, and I got caught up in doing a lot more experimentation.) I feel like you've already figured out a lot of this stuff at this point (and you appear to be able to do it at a deeper hardware level than I can), but I'm going to send my original message in its entirety. There's still a bit of new stuff in there as well, along with data from the test programs (and the test programs themselves) that I'm hoping can bolster or help confirm your own research.

If you're interested in looking at the information I've put together, it's currently just up on a Google Docs page at:
https://docs.google.com/document/d/1l5k ... 89Lqs8GDXg
I hope it's okay if I add this to your thread (I was originally planning to DM it to you, but I just registered my account and don't have permission to do that.)

I still haven’t had a chance to check the programs you’ve uploaded here, but that’s my next PV-1000 related activity.

Anyway, thank you for all the work you've already done for the wiki (and that thanks extends to your work elsewhere on NESdev as well). It's nice to have a good PV-1000 resource online, and it’s helped me understand some things I hadn't been able to figure out on my own.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: PV-1000 test and characterization ROMs

Post by lidnariq »

I understand that the XOR/ring modulation bit modifies the sound, but if all channels have been muted with #$3F, and I play #$1F on channel 1, I'd expect it to sound the same every time, but it doesn't. Additionally, the order of channel loudness (where square 1 is the quietest, square 3 is the loudest, and square 2 is somewhere in-between) seems to be inconsistent while doing this.
The very newest release of MAME (0.254) should accurately emulate audio, even if none of the rest. Does it sound like what you've experienced?

If not, could you make an audio recording of the sounds you get?

Due to XOR modulation, we expect some random differences in volume: if channels F8 and FA are stopped, they'll have an random value (low or high). If channel F9 is then making sound, the pins for F8 and F9 will be either in phase (and louder) or out of phase (and much quieter)
NOTE: As shown above, for whatever reason, the 2P joystick inputs that appear at bits 3 and 2 when reading joystick register $FD also appear in the same order and position within the returned byte when reading interrupt register $FC. Even if we FULLY STOP reading from/writing to joystick register $FD, the 2P bits in $FC will continue to be updated and show the current state of whichever two inputs we selected to fetch when we last wrote to $FD.
What on earth.

Utterly bizarre.
(By the way, it seems safe to use RET rather than RETI when leaving the interrupt handler. Out of the official games, only the Jaleco ones [Dirty Chameleon & Naughty Boy] use RETI.)
Entertaining stupid Z80-ism. There's no behavioral difference between RET and RETI - the only difference is if external hardware is snooping.
After INT1 occurs, and prior to the game screen being drawn, ANY adjustment to the cycle value will show up in the border (i.e. adjusting the cycle value by just 1 will cause the colors in the border to be adjusted by a small amount). After the game screen has been drawn, you need to adjust the cycle value by 4 before you see a change in the border (and the border colors get adjusted in larger, less precise steps). I wonder… does this still happen if you turn the screen off mid-draw, or don't have it draw at all? I STILL HAVEN'T EXPERIMENTED WITH THIS!!!
^-- Is this behavior interesting/understood?
I don't understand what you mean, unfortunately, so I can't say if it's expected or not.
It looks like you might get 230 cycles each scanline, but I don't know if my sample size is enough to say for sure…
Yes. 230.4 Z80 T states per scanline - each scanline is 288 x 4 = 1152 main clocks, 1152 ÷ 5 = 230.4
I tried to see if I could get a sense of how many cycles you get per scanline when the game screen is being drawn. It seems like you generally get 31 cycles per line.
Lowest value should be 288-248 = 40 pixels; 40 x 4 = 160 main clocks; 160 ÷ 5 = 32 T states.
Highest value should add 5 more T states before BUSACK (Because BUSREQ can interrupt instructions at beginning of any M state, but can't interrupt T states)
I really don’t like doing this, but occasionally, I've tried "frying" with the PV-1000. (I don't know if this term is used outside of Atari 2600 circles, but it's the only word I know for it.)
I'd call that "browning out" - deliberately providing too low of a voltage.

Lots of useful input, thank you.

I meant to ask the person who has the PV-1000 about the pinning of the controller - TeamEurope has a custom-built transplant into a NES controller shell, but I can't find contact information so I can't ask them.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: PV-1000 test and characterization ROMs

Post by lidnariq »

A diagram that I have been meaning to upload to the wiki, but I am worried it has too much going on, and would appreciate other eyes:
pink=assert INT16/Matrix<br />white=assert INT1/prerender
pink=assert INT16/Matrix
white=assert INT1/prerender
pv1000-video-timing-3.png (7.63 KiB) Viewed 2081 times
Or maybe it doesn't explain things well enough?
pv1000-video-timing-4.png
pv1000-video-timing-4.png (9.94 KiB) Viewed 2078 times
EDIT: notice that these specify the wrong tilemap fetch timing, two pixels too early
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: PV-1000 test and characterization ROMs

Post by lidnariq »

Another test ROM I'd written was how I determined which port acknowledged IRQs, but I figure that's not necessary anymore.

The last test ROM of interest was just displaying what various ordered dithers looked like:
Attachments
IMG_4110.jpg
IMG_4104-noaudio.mp4
very wiggly
(717.74 KiB) Downloaded 23 times
dither-no-ei.zip
(5.64 KiB) Downloaded 23 times
Par
Posts: 3
Joined: Sun May 28, 2023 11:45 pm

Re: PV-1000 test and characterization ROMs

Post by Par »

lidnariq wrote: Mon May 29, 2023 1:38 pm The very newest release of MAME (0.254) should accurately emulate audio, even if none of the rest. Does it sound like what you've experienced?
I finally checked out the updated audio emulation in MAME 0.254. As far as I could tell, it seems to behave in the same ways that my hardware does. I don't think there's an issue.

lidnariq wrote: Mon May 29, 2023 1:38 pm
After INT1 occurs, and prior to the game screen being drawn, ANY adjustment to the cycle value will show up in the border (i.e. adjusting the cycle value by just 1 will cause the colors in the border to be adjusted by a small amount). After the game screen has been drawn, you need to adjust the cycle value by 4 before you see a change in the border (and the border colors get adjusted in larger, less precise steps). I wonder… does this still happen if you turn the screen off mid-draw, or don't have it draw at all? I STILL HAVEN'T EXPERIMENTED WITH THIS!!!
^-- Is this behavior interesting/understood?
I don't understand what you mean, unfortunately, so I can't say if it's expected or not.
I'm sorry that my explanation wasn't clear. I made a video that will hopefully do a better job of describing what I was seeing. It's up at https://youtu.be/KUArcE8lqVs .

Since recording the footage, I've been experimenting using modified versions of the screen split tool, but I haven't been able to draw any real conclusions from my testing. I find that, if I start the screen split delaying routine (magenta area) somewhere below the rendered game screen, then each time I adjust the cycle count, the position of the split will be updated. If I gradually make the split delaying routine take place earlier and earlier, so that more of it takes place during render, I'll eventually lose the ability to affect the border split with each cycle added. (It also doesn't always move 1 big step per 4 cycles exactly as shown in the video). I don't know if there's anything special going on, or if the behavior I'm seeing is just timing/BUSREQ related.

lidnariq wrote: Mon May 29, 2023 1:38 pm
I tried to see if I could get a sense of how many cycles you get per scanline when the game screen is being drawn. It seems like you generally get 31 cycles per line.
Lowest value should be 288-248 = 40 pixels; 40 x 4 = 160 main clocks; 160 ÷ 5 = 32 T states.
I made an off-by-one mistake when I calculated the cycle values per scanline in this part of my document. (I was supposed to add 1 to each result as 0 was representing a cycle.) With a +1 adjustment applied, it's a closer match to your values. I corrected this in the original document (along with a few other very minor things) just to make sure that it doesn't cause confusion for someone in the future. (I kept a log of what I changed, and put a copy of the old version inside the Google Drive directory with the programs.)

lidnariq wrote: Mon May 29, 2023 1:38 pm I meant to ask the person who has the PV-1000 about the pinning of the controller - TeamEurope has a custom-built transplant into a NES controller shell, but I can't find contact information so I can't ask them.
Unfortunately, I haven't tried mapping out the inner workings of a joystick. Are you looking for a complete schematic, or do you just need to know how the Mini-DIN pins connect to the pads on the PCB?

In the footer on the Team-Europe blog ( https://team-europe.blogspot.com ), I see two different obfuscated contact email addresses listed. Do these show up for you?

lidnariq wrote: Mon May 29, 2023 3:02 pm A diagram that I have been meaning to upload to the wiki, but I am worried it has too much going on, and would appreciate other eyes:
I don't know if I'm the right person to gauge these video timing diagrams because I really haven't tried interpreting diagrams like these in the past, and I'm not too familiar with all of the different events that occur during a TV's drawing process. (I had to look up some of the terms on these diagrams.)

I feel like the horizontal dimension lines of the more complex diagram are essential for my understanding. This especially applies to the lines that define the bounds of the BUSREQ assert and the game screen area. Without those, I fail to recognize the 'transparency layer' that represents the BUSREQ assert period, and instead find myself confused about what the tinted colors represent. (I think it's also easy to miss the sliver of blue to the left of the colorburst area without the lines.)

Also, at the very start, I saw your note about how pink represents INT16/Matrix IRQs, but did not notice the tiny pink ticks that represent the IRQs. The only pink I could see was in the vertical red bars (tinted pink by the transparency). I found it helpful that the more complex diagram clearly defines both.

In the more complex diagram, I wasn't able understand the lines surrounding "28 tilemap fetches drawn" on my own. (My brother was the one that figured this out, but he was stumped for a while too.) Now that I know, it seems pretty obvious--the top line represents the time range (in pixels) in which data for all visible tiles is fetched, and the bottom line represents the time range in which all visible tiles are drawn. I can't really think of a better way to represent this using simple lines.

I appreciate that the diagrams are the exact pixel size of the video. As I was studying them, I also worked through the information on the rendering page trying to grasp its contents. It helped that I could easily find and mark pixel positions on the diagram. I *think* I understand how things work now... but I found that some pixel values from the rendering page aren't lining up with the marks on the diagram.

The issues are under #5 on the rendering page. The page claims that:
  • $B81D is fetched at pixels 260-261. On the diagram, I see it at 258-259.
  • $B81E is fetched at pixels 268-269. On the diagram, I see it at 266-267
  • /BUSREQ is released at pixels 270- . Elsewhere on the page, it says it runs through 267. The diagram depicts it running through 267.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: PV-1000 test and characterization ROMs

Post by lidnariq »

Par wrote: Fri Jun 02, 2023 5:14 am Since recording the footage, I've been experimenting using modified versions of the screen split tool, but I haven't been able to draw any real conclusions from my testing. I find that, if I start the screen split delaying routine (magenta area) somewhere below the rendered game screen, then each time I adjust the cycle count, the position of the split will be updated. If I gradually make the split delaying routine take place earlier and earlier, so that more of it takes place during render, I'll eventually lose the ability to affect the border split with each cycle added. (It also doesn't always move 1 big step per 4 cycles exactly as shown in the video). I don't know if there's anything special going on, or if the behavior I'm seeing is just timing/BUSREQ related.
My suspicion is that it is BUSREQ related - and conveniently there's even an easy test to find out. Just disable rendering and see if you get the same symptoms, or if this behavior happens even without that.
Unfortunately, I haven't tried mapping out the inner workings of a joystick. Are you looking for a complete schematic, or do you just need to know how the Mini-DIN pins connect to the pads on the PCB?
Just the mapping of Mini-DIN8 pins to the pads on the PCB. Or to the colors of the wires. https://commons.wikimedia.org/wiki/File ... -Open2.jpg
In the footer on the Team-Europe blog ( https://team-europe.blogspot.com ), I see two different obfuscated contact email addresses listed. Do these show up for you?
Somehow I didn't notice them...
The issues are under #5 on the rendering page. The page claims that:
  • $B81D is fetched at pixels 260-261. On the diagram, I see it at 258-259.
  • $B81E is fetched at pixels 268-269. On the diagram, I see it at 266-267
  • /BUSREQ is released at pixels 270- . Elsewhere on the page, it says it runs through 267. The diagram depicts it running through 267.
I am very grateful for your taking a close look at this, I made a number of off-by-one errors. Only the last fetches had I measured correctly, all the others were too early, including as reconstructed on the diagram.

This diagram shifts the tilemap fetches to match the hardware recordings, and I've updated the wiki page.
Attachments
pv1000-video-timing-5.png
pv1000-video-timing-5.png (10.02 KiB) Viewed 1904 times
Par
Posts: 3
Joined: Sun May 28, 2023 11:45 pm

Re: PV-1000 test and characterization ROMs

Post by Par »

lidnariq wrote: Fri Jun 02, 2023 11:58 am My suspicion is that it is BUSREQ related - and conveniently there's even an easy test to find out. Just disable rendering and see if you get the same symptoms, or if this behavior happens even without that.
Yeah, I believe you're correct.

Visibly, the magenta area (split delaying routine) needs to pass through the rendered tilemap for a change in behavior to happen. If rendering is disabled for the duration of the magenta area, then behavior will never be altered--each time I adjust the cycle count, the split will move on-screen.

I just couldn't figure out how passing through the rendered area would completely change how the border color split would move anywhere after the tilemap. (It was almost as if a state was being set.) Now that I've thought more about how my code handles 1 cycle adjustments to the delay value, I'm pretty sure I understand...

The split delaying routine looks at the delay value the user has entered and does a modulo 4. Based on the result, it branches to one of four paths (to run an instruction with a T-state value of either 4, 5, 6 or 7), then converges again. At the end of everything, it performs the rest of the specified delay by jumping appropriately into an area of NOPs (4 T-states each).

If the branching code fully executes before render, and the magenta area extends through the rendered tilemap, then I think that any positional difference that was a result of the four-way-branch will be flattened out the first time that /BUSREQ gets released. So below the tilemap, you just end up seeing the result of the NOPs.

The same effect can happen if the branching area executes during render (like I was experimenting with in modified versions of the split program). The branch that adds 7 T-states does it with an instruction that takes 2 M-cycles, so split results depend on how that lines up with /BUSREQ.


lidnariq wrote: Fri Jun 02, 2023 11:58 am Just the mapping of Mini-DIN8 pins to the pads on the PCB. Or to the colors of the wires. https://commons.wikimedia.org/wiki/File ... -Open2.jpg
If you check out this picture of a torn apart controller that was sold on Yahoo Auctions, you can see that there are pin number labels on the PCB that are obscured in the Wikimedia image. -- https://auctions.c.yimg.jp/images.aucti ... n57618.jpg
(The full auction page [with other possibly useful images] can be found at https://page.auctions.yahoo.co.jp/jp/au ... 1056374094 . I'm not sure how long this will stay up because the auction ended quite a while ago.)

Code: Select all

Text representation of joystick's PCB markings:
Pin     Color 
2       W   (white)
7       GR  (green)
6       BR  (brown)
3       BK  (black)
5       BL  ( blue)
4       GY  ( gray)
(NOTE: The physical wire colors correctly matched the PCB labels in both of my joysticks) 
I checked continuity between a joystick's PCB solder points and connector pins, and found that the numbers printed on the PCB matched the numbering system you used on the controller port pinout page. I made updated diagrams based on the results...

  • Looking into exposed end of joystick's Mini-DIN-8 connector:
    (The pin numbers here are flipped horizontally from how they're depicted in your diagram on the controller port pinout page. So when we turn this end around and insert it into the joystick port in front of us, the pin numbers line up correctly.)

    Code: Select all

                       [GR]
                       GPI2
                         7
                      ___|___
      [BR] GPO52 ---6/-O O O-\8--- GND
                    /         \
    [BK] GPO53 ---3|-O   O   O-|5--- GPO55 [BL]          Looking into exposed end of joystick's Mini-DIN-8 connector
                    \    |    /
             n/c ---1]-O | O-[2--- GPI1 [W]
                      ---|---
                         |
                         4  
                       GPO54
                       [GY]                
    
  • Looking into PV-1000's joystick port:
    (Same orientation as on controller port pinout page)

    Code: Select all

                       [GR]
                       GPI2
                         7
                      ___|___
             GND ---8/-O O O-\6--- GPO52 [BR] 
                    /         \
    [BL] GPO55 ---5|-O   O   O-|3--- GPO53 [BK]          Looking into PV-1000's joystick port
                    \    |    /
        [W] GPI1 ---2]-O | O-[1--- n/c
                      ---|---
                         |
                         4
                       GPO54
                       [GY]
    

lidnariq wrote: Fri Jun 02, 2023 11:58 am This diagram shifts the tilemap fetches to match the hardware recordings, and I've updated the wiki page.
I pulled the new diagram into my image editor and confirmed the pixel positions for the revised information on the rendering page. Everything looks good to me except for the last line of #4, regarding the draw position of $B802's bitplanes. I think the values here should have remained 52-59 (from the older version of the page), as the pixel position of the drawn screen did not move. If this is true, the 'draw position line' below "28 tilemap fetches drawn" needs to be moved two pixels left.

Also, now that the final tilemap fetch ($B81E) is no longer under the /BUSREQ assert period transparency layer, its red bar shows up in orange. The note about "red = tilemap fetch" isn't always accurate now (but the "31 tilemap fetches per scanline" arrows help clear things up).
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: PV-1000 test and characterization ROMs

Post by lidnariq »

Par wrote: Sat Jun 03, 2023 4:45 am I made updated diagrams based on the results...
Thank you very much! I have used this to deduce which pin on the jack is what bit in port $FD, and from that which pin on the ASIC is which bit, and updated all the pages to match. And I will also update my reverse-engineered schematic.
I think the values here should have remained 52-59 (from the older version of the page), as the pixel position of the drawn screen did not move.
You're absolutely right. I've fixed the page.
Also, now that the final tilemap fetch ($B81E) is no longer under the /BUSREQ assert period transparency layer, its red bar shows up in orange. The note about "red = tilemap fetch" isn't always accurate now (but the "31 tilemap fetches per scanline" arrows help clear things up).
It was always a transparent layer (alpha 50%) so there's going to be some unintuitive color shifts ... especially because I stacked the blue "busreq" layer above the red "tilemap fetch" layer. I could flip those around:
pv1000-video-timing-6.png
pv1000-video-timing-6.png (10.04 KiB) Viewed 1792 times
but it's still going to vary.


At this point I don't think there's any questions remaining - do you agree?

The next major objective is submitting changes to an emulator to increase their accuracy to the point where we don't have to develop on hardware.
Post Reply