Original Post

Hey, I’m attempting to get some barebones output prepared so I can do some reverse engineering, but my emulator tests have been less than promising, so I’m hoping someone could point out what I’m forgetting to do/doing wrong.

All I’m trying to do is produce the following image on both screens:

The way I’m attempting to do this is as follows:

* Initialize PSW to 0x00000000 and disable interrupts with SEI
* Initialize BG map, window params, windows and OAM (0x00020000 to 0x0003FFFF) to 0xFF – Method taken from VB Wario Land
* Initialize character (0x00078000 to 0x0007FFFF) to 0x00 – Also taken from VB Wario Land
* Make character 1 (0x00078010 to 0x0007801F) full; set all bytes to 0xFF
* In BG map 0, set cells 0, 2 and 65 to character 1 with palette 0. This means, as halfwords, set each of 0x00020000, 0x00020004 and 0x00020082 to 01 00
* Set all brightness registers (0x0005F824, 0x0005F826 and 0x0005F828), as halfwords, to 2A 00
* Set BG palette 0 (0x0005F860) as halfword to FF 00
* Set clear color (0x0005F870) as halfword to 00 00
* Configure window 0 (0x0003D800 to 0x0003D820) as such:
– * Left=true, right=true, BGs wide=2^0, BGs tall=2^0, base BG=0 — 0x0003D800 as halfword = 00 C0
– * Window width = 4 characters (64 pixels) — 0x0002000E as halfword = 04 00
– * Window height = 64 pixels — 0x00020010 as halfword = 40 00
– * All other fields = 0
* Initialize “column tables” as outlined in David Tucker’s document (link). Written as halfwords with only the lower 8 bits significant.
* Re-enable interrupts with CLI
* HALT forever in a loop
* All interrupts except for Reset are simply RETI

As far as I can tell, everything looks good, but when I run it in an emulator I just get a black display. If anyone could point out what the problem is, such as something else I need to enable somewhere, it’d be super appreciated.

20 Replies

Nice to see another coder trying to learn. Wish I could help you out, but all I can give you is my support 🙂

Good luck sir

-Eric

Are you doing everything in assembly? That’s overkill (though you did mention wanting to learn how to reverse engineer…), we usually use C.

You don’t seem to have initialized the WAM. There is also a bunch of VIP registers you need to set to turn on the display. I don’t know what they do, since the library nicely hides the details away from me, but the libgccvb vbDisplayOn function does this before initializing the BRTx/GPLTx/JPLTx/BKCOL registers:

VIP_REGS[REST] = 0;
VIP_REGS[XPCTRL] = VIP_REGS[XPSTTS] | 2;
VIP_REGS[DPCTRL] = VIP_REGS[DPSTTS] | 0x0302;
VIP_REGS[FRMCYC] = 0;
VIP_REGS[INTCLR] = VIP_REGS[INTPND];
while (!(VIP_REGS[DPSTTS] & 0x3C));  //required?

I am indeed using assembly; manually and with a hex editor no less. I’m in the process of documenting the system internals, since existing information on the Virtual Boy is only some 75% of what the silly thing actually does. To that end, I’ve prepared a system and will be getting a FlashBoy in before long to fill in the rest of the holes in our development docs.

Having said all that, I’m no newcomer to reverse engineering. As part of my documentation efforts, I figure the best sure-fire way to do it right is to start at the very bottom and work up, hence why I’m hand-coding a ROM file for basic output. By the time I’m done, we’ll have a document at our disposal that looks something like this.

Thanks for the tip about the component registers. I’ll look into those and see if I can get the displays to provide more useful output. (-:

Is that necessary? We already have Nintendo’s Virtual Boy Development Manual, which describes probably everything anyone would want. IMO, what we need is easy to understand documentation on the VSU and the VIP (for things such as scaling and rotation).

I don’t want to discourage you, but I don’t want you to waste your time rediscovering things.

We already have Nintendo’s Virtual Boy Development Manual

Do we now? All I’ve been able to hunt down is David Tucker’s doc. Do you have a link to the official manual?

Dear lord, it’s full of stars. And just like that, my plans take a sharp turn to the left. (-:

Okay, I’ve picked through the writes to the VIP control registers. Tomorrow I’ll look into trying these out in an emulator.

VIP_REGS[REST] = 0;

REST is the duration of LED emissions while all three brightness values are disabled. In this case, 0 since you can’t see anything.

VIP_REGS[XPCTRL] = VIP_REGS[XPSTTS] | 2;

Sets XPCTRL.XPEN, which enables VIP drawing. This one’s kinda important.

VIP_REGS[DPCTRL] = VIP_REGS[DPSTTS] | 0x0302;

Sets:
* DPCTRL.LOCK to 1, preventing the VIP from reading the column table every frame
* DPCTRL.SYNCE to 1, indicating that the servo controller should send left and right sync signals to the VIP
* DPCTRL.DISP to 1, enabling the display subsystem. That’s another important one.

VIP_REGS[FRMCYC] = 0;

Specifies the VIP should display 1 image per game frame.

VIP_REGS[INTCLR] = VIP_REGS[INTPND];

Clears all pending VIP interrupt condition flags.

while (!(VIP_REGS[DPSTTS] & 0x3C));  //required?

Waits until the changes to DPCTRL take effect, and neither the left nor right displays are being shown.

Hey Guy,
I’m probably one of the few guys around here who has screwed around with doing pure assembly for VB. That said I still don’t know a ton of what’s going on with the system, and I’ve certainly never attempted to hack code in a hex editor
All I’ve really been able to

do so far is get an assembly version of DisplayOn working. The gccVB compiler will take assembly files and create working object code. Also, the really awesome thing to use is Mednafen and its debugger. Mednafen is one of the emulators out there. It’s debugger will show you all the registers (even VIP) and let you root around in the loaded memory space. You can set break points and do single stepping as well. Since you seem to know how to read/write assembly, this is probably a must-do for you.

Keep on keepin’ on brotha!

Also, the really awesome thing to use is Mednafen and its debugger. Mednafen is one of the emulators out there. It’s debugger will show you all the registers (even VIP) and let you root around in the loaded memory space.

Duly noted, and thanks for the tip. (-:

One of the things I want to do is make a programmer/hacking focused emulator of my own. It’s not because there isn’t one; I just want to make an emulator and Virtual Boy sounded like a good project. I originally considered NES, and that one’s been emulated out the wazoo.

Anyhoo, the point is that when it comes to spiffy Virtual Boy emulation, I hope to bring something to the table!
__________

In other news, I got my first ROM up and running! It won’t work on a real Virtual Boy, however, because the VIP column table isn’t initialized. But with that one exception, it works like a charm.

My first (and second) attempt was to produce the image I posted in the original post, but it didn’t work. Why didn’t it work? Who the crap knows; there was a fair amount of code and I had no idea which part of it was wrong. So instead I pulled back a step and consulted Occam, who recommended I do the simplest thing that could possibly work.

So rather than three squares, which is more involved than one might think, I just set out for the simplest output possible: change the color of the screen. And that, much to my delight, worked like a charm. The program does the following:

* Run a dummy loop for 0xFFFF iterations to allow the system pseudo-RAM to warm up. This is specified in the dev manual, and the exact method was taken from Wario Land.
* Clear the status register and disable interrupts. This was also taken from Wario Land.
* Configure World 31 as the control world; no worlds will be drawn to the framebuffers. Come to think of it, I think I was trying to use World 0 in my other program. Whoops!
* Set BRTC to 127 and REST to 0. This controls brightness values.
* Set BKCOL to 3, meaning to use the brightness timing specified by BRTC.
* Set all flags in DPCTRL. This includes the enable flag and display reset signal. The display isn’t active with this off.
* Set the XPEN flag in XPCTRL. This enables drawing by the VIP, which is required for the clear color to change.
* Idle forever in a loop. Just call HALT over and over.

The ROM itself is attached to this post. Its code is as follows:

; Delay to allow pseudo-RAM to warm up
07000000  20 B0 FF FF  ORI     FFFFh, r0, r1
07000004  3F 44        ADD     -1h, r1
07000006  FE 95        BNE     07000004

; Clear status and disable interrupts
07000008  05 70        LDSR    r0, PSW
0700000A  00 78        SEI

; Set World 31 as the control world
0700000C  20 A0 40 00  MOVEA   0040h, r0, r1 ; END = True
07000010  40 A0 BE 3D  MOVEA   3DBEh, r0, r2 ; r2 = 0x0003DBE0;
07000014  44 50        SHL     4, r2
07000016  22 D4 00 00  ST.H    r1, 0h[r2]

; Set BRTC to 127 and REST to 0
0700001A  20 A0 7F 00  MOVEA   007Fh, r0, r1
0700001E  40 BC 06 00  MOVHI   0006h, r0, r2
07000022  22 D4 28 F8  ST.H    r1, F828h[r2] ; BRTC
07000026  02 D4 2A F8  ST.H    r0, F82Ah[r2] ; REST

; Set BKCOL to 3
0700002A  23 40        MOV     3h, r1
0700002C  22 D4 70 F8  ST.H    r1, F870[r2]  ; BKCOL

; Set DPCTRL to 0x0703: LOCK, SYNCE, RE, DISP, DPRST
07000030  20 A0 03 07  MOVEA   0703h, r0, r1
07000034  22 D4 22 F8  ST.H    r1, F822[r2]  ; DPCTRL

; Set XPCTRL to 0x0002: XPEN
07000038  22 40        MOV     2h, r1
0700003A  22 D4 42 F8  ST.H    r1, F842h[r2] ; XPCTRL

; Idle forever
0700003E  00 68        HALT
07000040  FE 8B        BR      0700003E

The reset handler is fairly uneventful:

FFFFFFF0  20 BC 00 07  MOVHI   0700h, r0, r1 ; main() code is at 0x07000000
FFFFFFF4  01 18        JMP     r1
Attachments:

Got it! Only took four tries, but after I knew what I was doing, it all went smoothly.

Memo to self: if it doesn’t show up, you forgot something.

ROM is attached to this post.

Attachments:

Holy cow that’s some awesome work. Keep at it man! Hopefully you’ll pave the way for anyone else with similar interests or provide new insight to get some more speed out of our little red boxen.

Is the Nintendo tech manual hosted somewhere? It’d be neat to browse. I’m guessing Big N isn’t too fond of that one being out in the wild… or maybe they don’t care since the VB is sort the red-headed stepchild… haha.

jrronimo wrote:
Is the Nintendo tech manual hosted somewhere? It’d be neat to browse. I’m guessing Big N isn’t too fond of that one being out in the wild…

No matter. We’ve got something better: the Sacred Tech Scroll!

… The tech manual is hosted on this very site. But even it is far from complete!

Parasyte wrote:
But even it is far from complete!

Exactly! Better use the Sacred Tech Scroll instead!

Dully noted! Cheers, guys!

I’m waiting for it to get more complete. 🙂

In the meantime, I’m in a bit of a holding pattern on my own projects before I could even begin to contribute.

Parasyte wrote:
I’m waiting for it to get more complete. 🙂

You’ll be waiting a while. There’s barely anything left to document. Just some stuff like floating-point instructions setting the carry flag and such.

Not quite; the operation of the VIP is entirely undocumented. It’s essentially a black box that just “works”, on the principles of magic and voodoo, for all we know.

There is absolutely no information on how long it takes to render anything, with exception that it will set the OVERTIME flag in XPSTTS when drawing takes longer than 20 * (FRMCYC + 1) ms. (Which itself will trigger the TIMEERR interrupt.) How does the VIP use the “write prohibited” work areas within the world attributes? So many questions remaining in just this one area alone.

There are also a number of questions about the NVC. Especially the pipeline. We can gleam a little info from the [much better documented] v850, disregarding that the upgraded architecture has a more refined (efficient) pipeline. The pipeline explains the instruction cycle counts. And yet nothing has explained the cycle counts for float or bitstring instructions. And then there’s also the multiple-load and multiple-store limitations.

(As far as I can tell, load instructions have their memory access stage where you expect to find the execute stage on other instructions. This explains why it’s more efficient to group loads; the memory access stage in a load conflicts with the memory access stage on the preceding instruction. But just try to explain why it’s more efficient to separate stores! These cases seem to be mutually exclusive!)

Anyway, it’s nice to see a “reimagining” of VB technical documentation, and by far the best resource apart from Nintendo’s Virtual Boy Development Manual.

Parasyte wrote:
Not quite; the operation of the VIP is entirely undocumented. It’s essentially a black box that just “works”, on the principles of magic and voodoo, for all we know.

What are you expecting, circuit diagrams? That’s beyond the scope of the document; hardly a reason to label it incomplete.

You’ll notice many editor’s notes throughout the document for things remaining to be tested. Feel free to run some trials so we can get rid of them. (-:

  • This reply was modified 11 years, 2 months ago by Guy Perfect.

Like I said, I would love to. I just have other things to get finished before I can.

Also, everything I mentioned would be valuable information for developers to create optimization strategies based on how much work the hardware has to do. There is also emulation accuracy to consider, so I don’t see it beyond the scope of technical documentation at all.

 

Write a reply

You must be logged in to reply to this topic.