It’s finally happening for real this time! Working behind the scenes with some community members, I decided to take an honest swing at an in-house PVB emulator at a full-time capacity. This will be my actual day job. So for the first time in history, I’m going to put my skills to work and produce some actual results. (-:
This community has always been amazing, and I have a good feeling about the emulator initiative going forward. The official project page can be found here:
http://perfectkiosk.net/
__________
So why should you care? Aren’t there Virtual Boy emulators out there already? Let’s see what the project page has to say…
The initiative has four primary objectives:
Nintendo 3DS Emulator
I’m sure most of us thought about Virtual Boy when we first heard about the Nintendo 3DS. A custom emulator specifically designed to run on 3DS can take full advantage of the system’s power and capabilities, giving us true stereo Virtual Boy on the go.Reverse Engineering
Any time we want to learn about how a game works or make changes to it, we need the right tools to dig in and take a look around. A cross-platform desktop application is just the ticket for providing the user with the right kit to expose all the deepest secrets buried within Virtual Boy software.TAS
The tool-assisted speedrun is a cornerstone of video game culture, and like reverse engineering, we need the right tools at our disposal in order to get the job done right. The aforementioned desktop application pulls double duty by bringing TAS-focused utilities to the party.Documentation
Comprehensive documentation of the Virtual Boy’s internals will come from emulator research, and it’s a perfect way for homebrew authors and modders to learn about the system’s features. Those who remember the Sacred Tech Scroll document I wrote can look forward to a brand new version of it.
For further reading of what exactly is planned, refer to the technical document trail on the project page.
__________
How exactly are we gonna pull this off? Glad you asked…
I have enough money in savings to begin work immediately (2018-04-18), but within a few weeks, I’m going to need to rely on financial support from the gaming community. We’ll be reaching out to other sites to gather support, since this undertaking spans a broader scope than what solely applies to Planet Virtual Boy.
A conservative estimate of my monthly expenses comes out to around $500 USD, and with enough interest, I’ll be able to keep this up full-time. By “full-time”, what I mean is 40 productive hours every single week, with status reports and a detailed outline of the development requirements. Planet Virtual Boy has its own developer working for it to make this dream come true. (-:
Donations are managed through a Patreon page:
https://patreon.com/GuyPerfect
__________
For now, this thread will be the place to be notified of progress and for general discussion of the initiative. Thanks again for being such a great community, and for giving me a chance to do what I really love. <3
Special thanks to Fire-WSP, STEREO BOY and KR155E for their assistance in getting the ball rolling.
--Guy Perfect
- This topic was modified 5 years, 7 months ago by Guy Perfect.
To the future Java developer who stumbles on this thread in a web search while trying to do something similar:
Modern Java applications use the Swing API for user interface stuff. The JComponent class used by all Swing controls supplies a pantComponent() method, which can be overridden to provide arbitrary graphical commands to the Java2D graphical subsystem each time the component is drawn to the screen. While paintComponent() receives a Graphics object as its argument, it is an instance of Graphics2D and can safely be cast as such.
If you intend to circumvent the intrinsic drawing functionality provided by Java2D, the most comprehensive low-level control over pixel operations is given by Graphics2D.setComposite() using a custom Composite object. In doing so, you’ll ultimately implement CompositeContext.compose(), which operates on two input Raster objects (one for input source pixels and one for input destination pixels), and a WriteableRaster object for output.
When performing raster operations, you get access to individual component samples for each pixel in the area to be drawn for both the input and output contexts. Care must be taken, as the storage primitive type and number of components per pixel may be different between source and destination. While the methods to access pixel data are able to do type conversions for you, the logic regarding how many components each pixel has is the responsibility of the program. Furthermore, I couldn’t find any simple way to determine the significance of the ordering of pixel components (Does red come first? Last? How about alpha?), but I didn’t really look into it…
Note: Composite requires the execution environment to be allowed to read pixels from the device. This is a potential security risk and may be restricted in some cases such as applets.
While it’s absolutely possible to, for instance, process all of the transformations necessary to render an affine world from within a Composite object, performance considerations suggest that might not be a great idea. Java2D is capable of optimizing image processing through a number of means, most notably caching the contents of BufferedImage objects in some device-compatible way. Accessing simulated VIP memory each time an image is drawn makes caching completely impossible and offers no benefits over pre-rendering the world into a BufferedImage to begin with.
On the opposite end of the spectrum, the VIP debugger window allows the user to select which palette to preview graphics with, meaning just one cached BufferedImage isn’t sufficient for every variation on the output for any given image.
At first I considered using indexed colors on a BufferedImage object. The idea was that the pixel data can be cached as usual, but before drawing the image I could update the palette according to the colors I needed it to use. However, BufferedImage color models happen to be immutable, preventing this from being an option.
The only other solution I found was the variant of Graphics2D.drawImage() that accepts a BufferedImageOp. The filter() method of BufferedImageOp accepts a BufferedImage as input and transforms its pixels (coordinates and colors) into an output BufferedImage. Bulk operations can be performed via getRGB() and setRGB() as usual, and a palette can be dynamically applied to an image in this manner.
While at face value it doesn’t look like this approach would provide any benefits over changing the contents of the source BufferedImage before drawing it, it’s quite likely that the destination BufferedImage object passed to the filter() method is of a different disposition than the ones you can create in userland. According to accounts from developers who have used BufferedImageOp, its performance benefits are significant.
Tomorrow, I will rework the Characters tab to use this technique and then I’ll be able to move onto the remaining tabs.
Great work Guy!
I’m trying to work out how you’re going to have to pull this off. The character memory looks good; I like all the options. So now you have to do the Background Segments, Object memory, and Windows. That’s going to be intense!
Since those sections of memory all reference char memory, are you going to be able to visually show each of those memory spaces? Maybe if you’re looking at a background segment, when you hover over a tile, you can see the values of all the fields in that cell.
And then with all the VIP registers, it would be cool to have those all transformed in to a readable table. It’s just too cool man!
Well, I’m not happy with BufferedImageOp’s performance. I’m afraid we might have to let him go…
Before resorting to the Composite approach, I took the YOLO route and just told the characters to draw themselves to the screen using the built-in Graphics.fillRect() method, one for each pixel of each character being drawn… And it really worked quite well! Ordinarily I hate the idea of calling a graphics method on a per-pixel basis, but when that’s the fastest solution available, sometimes crazy ideas pan out!
Yeti_dude wrote:
Since those sections of memory all reference char memory, are you going to be able to visually show each of those memory spaces? Maybe if you’re looking at a background segment, when you hover over a tile, you can see the values of all the fields in that cell.
You’ve got the right idea. Each graphical element type will have its own tab: these include Characters, BG Maps, Objects, Worlds and Frame Buffer. All of the properties of all of them will be user-editable right there in the VIP debugger window.
I’m not a believer of the mouse-hover ideology, so in this software, if you want to select a character for review from the output, you have to click on it. The idea is that actions are dictated by the user, and it’s up to them to decide what happens. It’s kinda like a link in a web page opening a new browser tab or window. That’s discouraged, since a middle-click or control-click will explicitly do that anyway, so links should never try to make that decision for the user.
This is a work post.
Still working on the VIP debugger window, but I’ve finally hammered out all the rough spots and what’s left is just a matter of sitting down and doing it–which is quite fun and has been keeping me awake at night! I’d be farther along by now, of course, but a day went to R&D regarding the character subsystem and another day went to replacing my hot water heater… But that hasn’t discouraged progress, no siree.
Attached to this post is a JAR file containing the current build of the application, which contains the Characters and BG Maps tabs of the VIP debugger window. I reworked several things on the back-end to improve simplicity and resource management, and the GridBagLayout error I was encountering before seems to have vanished, so that’s good.
Let’s take a quick look at what’s in there…
Characters
All of the features for this tab are the same as they were in this post, but the presentation is a bit different. You can view all 2,048 character patterns in VIP memory, previewing with any palette or a set of generic colors, and even edit the pixel data by hand.
BG Maps
New to the party is this tab, which displays any of the 64×64 character BG maps in VIP memory. Each individual cell of a BG map contains various properties, such as which character to draw, with what palette, and any flipping that needs to be applied. As expected, all fields can be edited to apply changes back into the emulation state.
The upper Index field selects the BG map displayed in the window, from 0 to 15.
The Index field inside the Cell group selects the global BG map cell, which starts at 0 for the first cell in BG map 0 all the way up to 65535, which technically comes from memory reserved for OBJ attributes, but can be indexed as though it were the 4,096th cell of BG map 15. Changing this field will update the contents of the window to display the corresponding cell from the correct BG map.
Alternatively, the Address field allows you to enter the exact bus address of the cell to select, which will likewise update the window accordingly.
Character, Palette, Horizontal flip and Vertical flip are the formal properties of the selected cell. Only BG palettes can be used here for obvious reasons. Changing any of these fields will write changes back into the emulation state and update the contents of the debugger UI.
Scale works as it does on the Characters tab: by sliding it to the right, the preview of the BG map in the right-hand region of the window will grow.
Checking “Generic colors” will use the generic red gradient colors for all characters in the display. This is primarily useful for previewing graphics while the brightness settings of the VIP are dark or invisible, but ordinarily you won’t need to use it.
Checking “Show grid” will display a grid pattern between BG map cells as seen on the Characters tab. This can be useful for identifying the scope of a cell when the pixels it represents blend together with neighboring cells.
Looks like Wario Land’s precaution screen has an easter egg. The O in “IMPORTANT:” has a smiley face in it.
This is a work post.
Development of VIP debugger tabs is ongoing, creeping steadily closer to its completed state. I keep reworking the back-end, since every iteration brings new insights and I want to make sure it’s as good as it can be while still fulfilling all of the requirements. I feel like I’ve boiled it down to its essential format now, so fortunately all that’s left is plopping down some controls and coding in their event handlers.
Working with the Java2D API has been a reliable headache since I started work on this window. It’s completely lacking what I consider to be basic, barebones functionality such as volatile palettes and rudimentary block transfer compositing, and working around that has been an exercise in head-shakery. What I ultimately wound up with has the best performance of everything I tried, but I’ll always know that behind the scenes, it’s inelegant and sub-optimal. Perhaps it’s not one of the intended uses of Java2D, but they wouldn’t have to go out of their way to support doing stuff like this…
On the bright side, this window is the last big chunk of the picky graphics stuff. What’s left after this is sweet, sweet data-centric processing that I do have control over. The worst is nearly over. (-:
Important Notice
Once again, I’d like to thank all of the financial supporters, Patreon or otherwise.
The good news is that in a little over a month, 18 Patrons have pledged $122/mo (gross), and that’s awesome! It’s good to know that Virtual Boy still means enough to people that they’d be willing to support something like this, especially considering the only real confidence they had was that some dude said he was worth it.
The bad news is that in a little over a month, the level of interest has pretty much established itself and settled in place. Regrettably, the bills don’t have the same enthusiasm for Virtual Boy that the rest of us do. There’s no great way to say it, but the truth is that the current level of support is insufficient to keep the project moving at its current pace. I unfortunately don’t think it will be sustainable going forward.
Later this week, in the interest of living indoors and eating food daily, I will be submitting applications for employment seeking another source of income. Depending on how that goes, my time to work on the emulator initiative may become limited, being relegated to time off that isn’t spent doing other things. I will continue to work at it on at least a weekly basis at worst, but it won’t be anything like this past month.
To the current Patrons: be advised that beginning in the month of June, I will likely be doing other work instead of focusing on this emulator initiative. I don’t want anyone to feel betrayed by sending their money into a black hole–if you chose to donate in the interest of producing results, then you may consider canceling your Patronage, as I can’t guarantee that your generosity will be spent towards that end.
To everyone, know that the project isn’t dying–far from it. This is still my passion and is first-and-foremost in my list of things to do in my spare time. I may not end up getting to do this as my day job, but at least for the last month I did get to live that dream. (-:
I was wondering when this would happen, but I still have faith in this project (even if I regrettably cannot invest) – you’re doing a great job GuyPerfect, so keep on chipping away at it!
I’m sorry I wasn’t able to really contribute. I wish I had a job so I could throw you guys money for these projects. Good luck with job hunting. It’s the biggest hurdle.
In light of the recent situation, an anonymous benefactor plunked down enough money to keep the project going for a couple more months. We back in business, bois!
Wow, that’s amazing! Virtual Boy is getting major love on many fronts this year. You have been creating a 3D Virtual Boy emulation for 3DS, which I am stoked about. I am working on the portable stereoscopic version for PocketCHIP with another member here (that I’m not sure wants to be named as of yet.) melott124 has also been diligently working on a multicart for roms that you can write to yourself (similar to everyone’s darling the FlashBoy), with a rom dumper as well.
This is truly the year of VB!
Amazing! Thank you mysterious benefactors for allowing this to continue!! <3
This is a work post.
Okay, I admit, I slouched a bit for a couple of days. I was thinking the project would get demoted to “personal project” status and didn’t really grind at it like I have been. But since it’s once again officially my job, I went ahead and finished up the Objects tab this afternoon:
By this point you know what to expect from those controls on the left. Editing those will change the current emulation state to match.
The right-hand side is a different story. That area displays a simulation of what the object looks like in the scene. The black rectangle is 384×224 pixels, which is the size of the system’s frame buffer. So by previewing an object in this tab, you’ll see exactly where and how it contributes to the final frame image.
This marks the first instance of stereoscopy in the project. The only available method to achieve this in Java is the usual anaglyph, which encodes each eye’s image with specific colors such that they can be masked out for the appropriate eye with a set of 3D glasses worn by the viewer.
The most common anaglyph configuration is red for the left eye and cyan for the right eye. Ordinarily this can lead to a color imbalance because of the way the human eye is more sensitive to green light than either red or blue light, causing erroneous distribution of light intensity for each eye.
However, as you can see in this macro example, the overlapping pixels are not white, but sort of a light peach color. I’ve done my best to equalize the apparent intensity of colors by default, although this will of course be configurable by the user.
Because the human eye is so sensitive to green light as compared to red and blue, I recommend using green-magenta anaglyph glasses instead of red-cyan, if you can get your hands on some. I want to say it’s fairly common in the wild, so it shouldn’t be hard to find a set. The amount of color correction needed for this combination is less than in the first example.
Attachments:
That’s great news! I’ll definitely add myself to the list of patreons, I wish I could do a decent amount but I can’t at this time, but I hope to at least help a little.
So now just “worlds” and the framebuffer tabs?
The registers in the VIP are pretty extensive, will there be a tab that just collects all those together?
Worlds, Scene, Framebuffer and Registers tabs remain. There are many fields between many registers, so depending on how much space things take up, there might be multiple tabs. On the one hand, the window can be resized, but on the other hand, there is such a thing as “too cluttered”, and lots of emulators have that.
Request regarding 3D:
Would it be possible to include a scanline interleaved mode? My PC monitor is passive 3D, which uses the same type of polarized glasses you get at the movie theater to send every other scanline to one or the other eye. I’ll be fine with anaglyph, but if it’s not too much trouble, this mode would be nice to have. Also, you should include a swap button, since the vertical position of the window will determine which eye sees which image (and some people have anaglyph glasses with red on the wrong side).
Happy Memorial Day weekend to those who observe it! I had hot dogs. Delicious, char-grilled hot dogs.
I’ll see about scanline interleaving. There’s no graceful way to pull that off, especially in Java, but where there’s a will, there’s a way!
Still workin’ on that Worlds tab. Tabs are of course related to one another, plus the VIP brightness and anaglyph colors, so it’s important to make sure everything’s following the same rules and duplication is kept to a minimum. It’s been an interesting game of cat and mouse each time I add a tab, as something winds up getting revised or rewritten in order to accommodate the new tab’s needs.
The approach I’m going with processes the output image directly without going through the hoops of drawing every individual element of every world. For each pixel in the image, worlds are sampled from front to back (the hardware draws back to front). The world itself handles the details of how to find out what the pixel value is, depending on its coordinates, background or object group. As soon as a left or right pixel receives a value, that pixel is no longer processed. Once both eyes receive pixel values, drawing ends for that pixel and the process moves onto the next one.
I’m considering adding a feature to the emulation core that can process VIP rendering either as efficiently as possible using the above method, or as accurately possible using some method calibrated to the VIP operations on the hardware (which needs to be researched someday). That way, time-critical applications like 3DS can just produce a frame image as fast as possible, while development settings can help profile performance without running on the hardware.