While hacking with the VIP recently I noticed some odd behavior when strobing DPRST
: the background color would shift from full brightness to a dark shade of red, despite my not changing the value of BKCOL
. Chapter 29 of Nintendo’s official Virtual Boy development manual says that other than the SYNCE
, RE
, and DISP
flags, the values of the other registers are “indeterminate” after a DPRST
. What I found to be odd is that this aforementioned behavior is reliably reproducible on my VB hardware. Are the results of a DPRST
really “indeterminate” or is there an observable pattern to it? I did some digging and came up with some numbers and conclusions.
Attached to this post is a small program I wrote that first initializes the VIP registers to a known state and then invokes DPRST
in various ways, reading out the values of each readable VIP register after each invocation and then printing them to the screen for examination. Each button press will advance to the next method of invoking DPRST
. These test “classes” are, in order:
- “INITED” : setting all writable VIP registers to known values
- “NOT INITED” : strobing
DPRST | DPEN
then reading back the VIP registers - “DPRST ONLY” : strobing only
DPRST
(DPEN
is not set), then reading back the VIP registers - “BKCOL INITED FIRST” : strobing
DPRST | DPEN
, setting onlyBKCOL
to a known value, then reading back the VIP registers - “REST AND FRMCYC NOT INITED” : strobing
DPRST | DPEN
, then setting the brightness registers in a specific order, then reading back the VIP registers
This test class is repeated four additional times, each with an increasing number of nop
instructions between the st.h
to DPCTRL
and the first read from VIP registers -> NVC registers
This test class is repeated four additional times, each with an increasing number of nop
instructions between the st.h
to DPCTRL
and the first read from VIP registers -> NVC registers
This test class is repeated nineteen additional times: four total times each for increasing values of BKCOL
, then five total times each with an increasing number of nop
instructions between the st.h
to DPCTRL
and the st.h
to BKCOL
This test class is repeated two additional times, then five total times within each of these with an increasing number of nop
instructions between the st.h
to DPCTRL
and the first st.h
to BKCOL
:
- “BRTA INITED FIRST” :
BRTA
is set first, thenBRTB
, thenBRTC
- “BRTB INITED FIRST” :
BRTB
is set first, thenBRTA
, thenBRTC
- “BRTC INITED FIRST” :
BRTC
is set first, thenBRTA
, thenBRTB
The test suite then repeats itself, going back to the first “INITED” state.
Here is a link to a Google sheet containing results from my running this test suite five times in a row on one Virtual Boy unit. I have bolded results that differ from the final “settled” result, and I have additionally italicized results that differ between subsequent passes, demonstrating that the time necessary for DPRST
to complete is variable and unpredictable, but also that the VIP registers that are affected by a DPRST
always arrive at the same result for a given test class after three NVC cycles. The four nop
s case is tested to prove that its results are identical to the three nop
s case. https://docs.google.com/spreadsheets/d/1lkFya5fQmpeXU7G6pVVEHpGNzQEouu4-tpy44-VpqzE/edit?usp=sharing
The tl;dr of what I found is two-fold:
DPRST
is not instantaneous; it takes a few NVC cycles to complete. The total cycle cost is unpredictable–even across subsequent passes–and does not seem to follow a pattern, however I did observe on my hardware thatDPRST
would always complete by the time a load/store instruction was executed a minimum of three NVC cycles after the initialDPRST
strobe. In other words, sometimesDPRST
takes fewer than three NVC cycles + a load/store to complete, but it would always be finished by that time at the latest on my hardware.- Absent of explicit values to reinitialize the display registers after a
DPRST
, the VIP will use the last value it sees on the data bus as a seed value when resetting the display registers.
In both cases above, when strobing DPRST
by writing 0x0303
to DPCTRL
, without doing any further memory accesses for at least three NVC cycles thereafter, the last value on the data bus therefore remains 0x0303
and the BRTx
registers are all each reset to 0x0003
, resulting in a very dark palette and thus explaining the color shift I described at the beginning of this post. The same is true in the “DPRST ONLY” case where only 0x0301
is written to DPCTRL
: the BRTx
registers are all each reset to 0x0001
. Likewise, if one of the BRTx
registers is initialized before DPRST
completes, the VIP uses that value on the data bus as a seed for the remaining uninitialized display registers, resulting in REST
, FRMCYC
, and CTA
each having the same initial value as that written BRTx
register.
None of the currently-maintained Virtual Boy emulators that I know of as of the time of this writing get this right; Mednafen treats a DPRST
as an instantaneous action that resets none of the display registers other than the SYNCE
, RE
, and DISP
flags in DPSTTS
. I encourage anyone else interested in this little science experiment to run my attached program on their own Virtual Boy hardware to provide more data points here. Though what I’ve discovered about DPRST
‘s behavior here doesn’t affect any commercial games to my knowledge, since there’s a pattern to at least some of it I think it would be worth proper emulation for accuracy’s sake.
Attachments:
No replies yet.