We're using cookies to ensure you get the best experience on our website. More info
Understood
@guyperfectRegistered December 4, 2012Active 5 months, 3 weeks ago
375 Replies made

Since things are coming along, I wanted to share some technical stuffs.

Both Utopia Sound and Utopia Music require the application to allocate object memory, meaning you can declare a byte array on the stack if you don’t want your program to be using some kind of fancy malloc/free setup. They don’t make any assumptions regarding where the memory comes from. When you’re done with it, just deallocate it and that’s the end of that.

Utopia Sound’s Architecture

Utopia Sound is based on two simple object types: Mixer and Sound. The Mixer maintains a collection of Sounds. By implementation, it’s technically a linked list, but the bytes available for instantiating Sounds are allocated once by the application and given to the API. New sounds can be configured and played by the Mixer until memory for new sounds runs out. The back-end algorithm that drives memory management is extremely simple and runs in O(1) time with just a handful of bus operations. The overhead introduced by Utopia Sound is negligible.

Sounds are conceptual little sound channels in and of themselves. They’re driven by an application-defined callback function, meaning there’s no convoluted sound effect or music note format that the library tries to force on you. From the data side, you can actually precompile Sound handler functions and incorporate them into your program as binary resources (or share them with other developers, etc.). Sounds are assigned to a hardware channel, and have a priority value. The callback function simply assigns VSU-compliant register values to the Sound object, and the callback’s return value can signal to the Mixer that the Sound has finished playing.

Each audio frame, as given by the application (usually by VIP or timer interrupts), the Mixer will process all of its currently active Sounds. If a Sound ends, it will be removed from the linked list and placed back into the pool of available bytes. The Mixer will automatically determine which Sound (if any) currently has ownership of a given VSU channel. At the end of the audio frame (usually the first thing after the CPU wakes from halt status following an interrupt), the application invokes a “render” command to the Mixer, which then updates the VSU registers with the values of the Sounds determined to be in ownership of each channel.

Pause and resume commands are also available on the Mixer.

Utopia Music’s Architecture

Utopia Music builds upon Utopia Sound. Specifically, it supplies a flexible Sound handler function that takes care of all of the operations needed for playing music notes. But Utopia Music isn’t a mere list of music notes…

The two highest-order object types in Utopia Music are the Event List and the Event. Playback begins on a top-level Event List known as the Root Event List, and the Events included therein represent the entire track. Each Event has a timestamp, a type field, and whatever additional information is needed according to its type. The following Event types are part of the current spec:

* Event List Call – An Event List can spawn child Event Lists, which are executed in parallel. That is to say, all active Event Lists within a Utopia Music context are processed simultaneously. Event List Calls have a duration field, which will cause the child Event List to repeat from the beginning until the duration expires.

* Note – The elementary music note. Each Note has a duration and a VSU channel on which it plays, as well as dynamic envelopes for each of volume, pitch and panning. If only one value is desired, simply define only one element in the respective envelope (the composer application simplifies this distinction). Otherwise, a note can, for instance, begin to modulate over time to mimic the style of a real-life string instrument.

* Tempo Change – For the Root Event List only, this is a simple two-value gradient for tempo. It starts at the starting value, then gradually changes linearly to the ending value over the time specified by its duration. Tempo Change events present in child Event Lists have no effect.

* Voice Change – Used to reconfigure the VSU channels. This Event type specifies the VSU channel to modify and the VSU wave bank to switch to.

* Sample Update – Used to reconfigure VSU wave memory. This Event will only succeed while no sounds are being played, as per the hardware limitation. It specifies a VSU wave to update, and the index of a wave in the music file to load from.

* End – Signifies the end of the Event List. If an Event List was called with a duration, then reaching one of these events will cause the Event List to reset and start playing again from its beginning. This is great for something like a drum loop or a chiptune arpeggio. When an Event List ends, all of its Notes, and all of its child Event Lists (and all of their Notes, recursively), end. If the Root Event List hits an End event, the music stops then and there.

* Operation – A simple CPU-style operation. Each music context has an application-defined number of bytes associated with it for the purpose of scratch memory within the music program itself. An Operation has a left operand, an operation ID, and a right operand, and produces a result. All three values can come and go through music memory. While the operations do not themselves have any effect on the audio being produced, they can be used to direct the flow of the soundtrack via conditional execution using Goto (see below)

* Goto – Moves the current position within an Event List to some arbitrary location within that Event List. The branch is conditional: Goto will not occur if the result of the most recent Operation (see above) was zero. On the one hand, conditional execution can be used to, say, play the same loop exactly 3 times before exiting. A clever program can allow the music to change dramtically depending on game circumstances (time is running out, the character dives underwater, etc), by writing to the music context’s memory from the game program.

Each Event List schedules its Events on a time scale, which can be either Beats (which changes with the track’s tempo) or Realtime (which ignores tempo). Beats should be used in most cases, but Realtime is essential for chiptune-style arpeggios, which need to play at a particular rate due to the way the human brain perceives them. Individual property envelopes of Notes can also operate on either Beats or Realtime.

Event Lists and the Utopia Music context have volume and panning controls that influence the final intensity of sounds being played. Event Lists have dynamic envelopes just like Notes, while the main context only includes master values to be controlled by the application.

But What of MIDI?

The question came up before regarding MIDI and whether it can be converted to Utopia Music in lieu of not having to learn another composer. While MIDI can be converted to UM to an extent, it’s not really a smooth transition because, as you can see above, it’s apples to oranges.

At the current time, I have no plans to include any conversion utility in the composer, but don’t let that stop you from convincing me it’s a good idea. (-:

On July 20 of 1944, Operation Valkyrie was carried, out, detonating a bomb in the Wolf’s Lair Nazi field headquarters near Rastenburg, East Prussia. The motivation behind the attack was an attempted assassination of Adolph Hitler, Führer of the Third Reich, predominantly for humanitarian reasons–keeping Germany out of war and ending Hitler’s tyrannical regime.

The bomb was detonated in a small conference room where Hitler was present, but somehow or other he survived. There were splinters of furniture and the room’s construction all over the place, and even a Virtual Boy unit was found in the debris, but how Hitler survived remains unknown to this day.

In the 2010 episode of MythBusters, also called Operation Valkyrie, Adam and Jamie investigated the claim that the reason Hitler survived was because the meeting location was changed from an underground bunker to an above-ground meeting room with windows. In their full-scale test, they determined that the windows didn’t do much to alleviate the “getting blown to bits” issue, and subsequently busted the myth.

The MythBusters further examined the circumstances in order to determine what was the reason Hitler survived. Turning their attention to the Virtual Boy unit, they ran some experiments and determined that Hitler survived the bombing because the feet of the Virtual Boy were pointed towards the user at the time the assassination was attempted.

Happy new “I’m gonna stop talking-big-without-delivering-on-it” day! (-:

It’s that time of month again! That didn’t sound right, did it?

I’m working on the audio project, of course. I find myself wanting to work on it. Like, even after a full day at work, I come home and think, “this is how I want to spend my free time”. It’s awesome that I’m doing that again. I was doing that back in August and it was awesome then too. (-:

I’ve also been, um… doing… something else. The awesomeness of that other activity rivals the awesomeness of this one.

There’s one other thing I’m doing. I’m working on version 1.0 of the Sacred Tech Scroll. The new document is being redone from the ground up, using the original as a source but for the most part containing new material. I explain things better, the presentation is cleaner, and I’ve hopefully removed all of the ambiguity (such as tables with no column headings). Oh yeah, and I’m incorporating new information as it becomes available (Nintendo instruction cycle counts, MPYHW’s operation, etc). The changelog between v1.0 and the last published version v0.91 is huuuuuge. But it’s the Virtual Boy’s 20th birthday, so I’m gonna make sure we get that information right this time around.

Utopia Sound was, as expected, totally redone from scratch, and it’s finished and fully commented. I used a few different approaches this time, and the API as a whole became leaner and somehow the back-end code is simpler and smaller… Oh well, I won’t complain.

Since I also implemented Utopia Sound in Java, I’ve got a nice little sound rendering engine that produces bona fide, no-holds-barred identical output to the hardware when requested. This is true even so far as to make identical noise samples, which I’ve demonstrated with an attached audio file. The first sound played is a recording from the hardware, and the second sound played is the output using the same parameters from the Java rendering engine.

I spent the day researching some long-standing what-ifs on the hardware, such as the condition for integer division overflow, the exception handler addresses for the TRAP instruction, and the behavior of shift instructions by register. Some things I’d made assumptions about, but I wanted to nail it down once and for all by seeing it with my own eyes. The last thing I tested was when the VSU noise generator reinitializes its shift register, and updated the Java rendering engine to match (it resets the register not only when specifying the tap location, but any time the play control register is written).

My newfound zeal for Virtual Boy can be attributed to Nintendo, ultimately. Releasing new Super Smash Bros. games got me back into that series, which led me to doing some hacking on the Nintendo 64 game, which in turn led me down the right path to get in touch with some contacts that holy-cow totally got me the resources I needed to do a Nintendo 64 Sacred Tech Scroll! I’m not going anywhere near that project for a while yet, but working with N64 a bit got me to remember just how much I love this stuff. (-:

2015 is going to be an awesome year for Virtual Boy. My so-called “resolutions” with regards to Virtual Boy are as follows:

* Complete v1.0 of the Sacred Tech Scroll, making everyone experts once and for all
* Complete Utopia Sound and Utopia Music, both for development and the composer application
* Find dasi and get that silly devkitV810 out to the world
* Finally make that blessed VB emulator with all those debugging features
* Compose an album on Virtual Boy for the 20th anniversary event. Yeah, you heard me.

Attachments:

e5frog wrote:
There’s over 8kB of unused space in the rom […]

Every Virtual Boy cartridge has to be some power of 2 bytes in size because of the way address mirroring has to work (the reset code always loads from bus address 0xFFFFFFF0). All games have padding accordingly. The only thing that the 8KB in Mario’s Tennis means is that the game was somewhere between 256KB and 512KB in size.

On the other hand, we’ve got lots of space for extra data even without changing the size of the ROM image. (-:

Development is going well! Having a Utopia Audio implementation in Java is quite refreshing, and I’m super excited about being able to hear all the pretty sounds on the desktop end without having to prepare test files for the Virtual Boy first. (-:

But… (you knew that was coming!)… while I find the work fascinating and will continue to work on it, I’m not outright obsessed with it like I was in August. Back when I first caught wind of the VB20 anniversary, every second of free time I had went to the project. It was very productive, certainly, and was also very entertaining.

I find myself sitting here thinking, “ugh, there’s more to do by tomorrow”. What I’d like to be thinking is “okay, what’s next?” but you know how it goes. (-: If I don’t let off the gas a bit, it’s going to feel like work and not play, and I’m actually rather worried about that getting in the way of doing a good job rather than a fast job.

Now I remember why I don’t do deadlines as a policy.

I’d like to nix the “homework” thing and just get this ready as I can, without feeling like the world’s going to end if I don’t have everything just-so by some arbitrary dates. I still want to do the Christmas thing, buuuut… Please understand that if I don’t have it ready by Christmas, it’s because I’ll be doing a better job rather than one filled with hype. (-:

So instead, a progress report…

What I’ve gotten ready since Thursday is a reference implementation of Utopia Audio in C for Virtual Boy, and the better part (probably 85%-90%) of the Java implementation. I keep hopping back and forth to make sure the logic is the same in both versions, because that means the output will also be the same in both versions (what’s the point of having a composer if it sounds different on the hardware?).

Since I’m also starting at the audio end instead of the application end, what I’ve pretty much constructed is a mostly-functional VSU emulator (Utopia Music doesn’t use the envelope or frequency modification features) and an audio engine to drive it. And holy heck, it sure came together fast! I’m really looking forward to where this is going.

Now that I’m not trying to get this done “on time”, watch as productivity skyrockets…

It’s been ten years or more since the last time I did audio in Java, and I’m pleased to see that it’s the same as it’s ever been. If you’ve ever wanted to work with it but couldn’t make your way around the API, well, here’s what I know!

The Java Sound API is package javax.sound, and the PCM subset of that is javax.sound.sampled. Within sampled, there is an AudioSystem class that acts as the point of communication between Java applications and the system’s audio hardware. From AudioSystem, you can query installed audio hardware and its capabilities, or you can request some kind of a data line that supports the capabilities you desire. That’s what I’m doing with this Virtual Boy project.

Opening a PCM output stream deals with two particular data classes: AudioFormat, which does what it says on the tin; and Line.Info, which specifies stream capabilities. Through [font=Courier New]AudioSystem.getLine()[/font], you can produce a SourceDataLine, and from there you can [font=Courier New]open()[/font], [font=Courier New]start()[/font] and [font=Courier New]write()[/font] sample data as bytes.

Here’s a code excerpt I put together while reorienting myself with the API:

// Specify an audio format
AudioFormat fmt = new AudioFormat(
    48000.0f, // Rate, in samples per second, of the audio stream
    16,       // Number of bits per sample
    2,        // Number of channels (2 = stereo)
    true,     // Sample data is signed
    false     // Sample data is big-endian
);

/*
  AudioFormat has another constructor that allows you to specify the data type
  and frame size/rate information. In addition to integer samples, it also
  supports float, A-law and u-law.
*/

// Specify an output stream with the given audio format
DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt);
         
// Request an output stream with the given format
SourceDataLine line = null;
try {
    line = (SourceDataLine) AudioSystem.getLine(info);
    line.open(fmt);
} catch (Exception e) { line = null; }

// No appropriate playback devices are available
if (line == null) {
    System.err.println("Error opening audio output stream.");
    return;
}

// Put the output stream in playback status
line.start();

// Read file data until the whole file has played
for (;;) {
    byte[] data = fileRead(file, 48000 * 4 * 5); // 5-second buffer
    if (data.length == 0) break;                 // Loop exit condition
    line.write(data, 0, data.length);            // Send to output
}

// Close the stream like a good programmer
line.close();

[font=Arial][size=24px]The Month of Sound

That’s right! Now that I completed the new Pokémon game and accidentally discovered that the big green thing can one-shot the twisted triangle thing, I’m ready to make that Virtual Boy Christmas gift a reality!

Starting today, and over the next four weeks (it’s 28 days ’til Christmas), I will not only be developing the promised audio architecture and composer for Virtual Boy software, but I will be chronicling the technical details here in this thread in the spirit of furthering understanding for the general public!

I will be supplying “due dates” to each post here, as though it were a school assignment and I have to get my homework done on time. Provided I don’t encounter any real-life catastrophes or other unexpected happenings, I should be able to stick to my posted schedule.

Let’s get this show on the road. Grab a seat, heat up some popcorn, and get ready to learn.
__________

[size=24px]Three-in-One

This project consists of three major components: the sound/music engine specification, the C library that will drive the Virtual Boy hardware, and the Java program that will be used to produce the music tracks in question.

Why Java? Because everyone can use it. I could go with C via SDL or somesuch, but no matter how you slice it, it’s gonna take some kind of third-party library, and Java is both trusted and secure, so it makes it the natural choice. Plus, it’s going to be way easier for other people to peer into the Java code. We won’t get a bunch of questions along the lines of “How do I OpenGL” or whatever.

My first swing at the project started with the sound library, then the music specification, then the music library, then finally the composer. When I got to the composer stage, I realized I’d have to re-implement pretty much everything I’d implemented for the hardware… again. And when I started doing that, I realized that certain tweaks here and there would make the whole thing make so much more sense in Java, and there’s no reason it couldn’t work the same way in the C library. Thus began the loop of factoring and refactoring that took two and a half months to stop.

Today, I’m smarter than I once was. I will be developing the C and Java code in parallel to ensure that A) both bits of code work the same way and B) I won’t have to go back and retrace my steps later on. It should go a lot more smoothly this time around, and I invite the rest of you peek in to what I’m doing.

[size=24px]Do You Hear What I Hear?

All of this starts at the lowest level: sound. The Virtual Boy makes it easy by providing audio hardware that Just Plain Works™ once you set a few memory values. Java, on the other hand, doesn’t work the same way. You have to prepare a PCM buffer and set up an audio stream to play it on. Java is far more flexible, of course, but it also means there has to be more overhead to get it to produce the same output.

Ah, but do we necessarily want the same output? Not necessarily. Virtual Boy’s audio boils down to 10-bit digital stereo at 41,700hz using 32-sample waves at 64 steps per sample (and effectively 16 levels of volume). That’s rather restrictive, but the resolution is high enough that it can still sound pretty good. Java, on the other hand, gives us the option to, for instance, have 24-bit digital stereo at 96,000hz using waves of arbitrary sample count and samples with greater depth than the output stream. What do we take away from all this? Java can produce better sound than the Virtual Boy, even when following all of the same rules.

What I intend for the composer is that it can play music in two modes: high-precision mode and hardware mode. High-precision mode will construct a PCM stream with as much… well, precision… as is available, using fine-grained interpolation of samples, higher sample depth for waves, and all music engine configuration happens on a per-sample basis rather than per-frame (more on that later). This will allow for higher-quality clips to be available for soundtrack releases, whereas the lower-quality version shows the artist exactly how it will sound on the hardware.

[size=24px]Utopia Audio

When I said “the C library”, what I really meant was “the two C libraries”. Utopia Audio is a gift in and of itself that makes audio programming on Virtual Boy a whole lot easier. Utopia Music, on the other hand, is a music engine that is built on Utopia Audio. But I already covered this in an earlier post, so I’ll spare you the details here.

Utopia Audio’s abstract outline looks like this:

* The application allocates a buffer of “sound” objects, which is used to configure a “mixer” object
* The application requests an unused sound object from the mixer
* The sound is configured with application data, a priority and a handler function, then given to the mixer to play
* The mixer maintains state information for each sound until such a time that the handler functions stop them
* According to the rules of priority, the mixer will update the hardware channels with data from the appropriate sound

It’s not a complicated setup by any stretch of the imagination, but it abstracts away the nitty-gritties of configuring the hardware, and allows the application dynamic control over sound contexts instead. There’s very little actual wizardry involved, but there’s a big benefit in changing the paradigm from “how do I do this” to “what do I want to do”.

This abstraction takes the form of the Sound context itself. In its simplest form, it’s a memory structure that keeps track of all of the VSU channel properties, which are only actually written to the VSU registers when A) the sound has priority on the channel and B) the value actually changes. Sound management itself takes place in an application-defined function referenced by address, which uses its own data linked to the Sound object via a void pointer. I know that sounds kinda hocus-pocus, but I’ve used it in practice and it’s really quite nice. (-:

[size=24px]Sample This!

Utopia Audio is pretty straightforward in C on Virtual Boy, but as mentioned before, there are differences in the audio subsystems on Java. The bridge between the two will have to be a sort of VSU emulator, but with a few key differences; namely the ones that pertain to the high-precision and hardware rendering modes…

Wave
The wave feature of the Virtual Boy VSU isn’t anything the application has to worry about, but it needs to be implemented from scratch in Java. Rather than an array of 32 bytes where only the lower 6 bits are significant, it will be an array of an arbitrary number of floats. When the samples are updated, a 32-byte array is also constructed, where the floats are converted into bytes in VB format. That way, the high-precision sampler can interpolate the floats, and the hardware renderer can sample the bytes without interpolation.

Sound
This works the same way as the Sound object in the C version of the library. It has in-memory values for each attribute of an output channel, but again with higher precision where applicable. Frequency will have greater depth; volume and panning will be floats instead of 4-bit integers; etc. The rest of it will just be the same as the C library.

Mixer
All of the prioritization and processing present in the C version of the Mixer object will take place in the Java version as well, but the Java version has one key additional feature: sampling. Since there is no VSU hardware to convert wave and channel data into something we can listen to, that logic will be the responsibility of the Mixer, meaning it will have to live up to its name. This will take the form of a [/font][font=Courier New]render()[/font][font=Arial] method that supplies an output buffer in the format of the output stream. The Mixer will simply render audio one sample at a time until the buffer is full.

The output of the Mixer will then either be sent to the system’s speakers, or written to a .wav file, depending on the user’s preference.

[size=24px]Due Dates

* Assignment is due by end of day November 30, 2014 for 3 points.
* If finished by end of day November 28, 2014, an additional 2 points of extra credit.
* If late, -1 point for each day after the due date.

Let’s see how many points I have by the end of this.
[/font]

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

A keen observer will notice that it’s been more than a month since I’ve had anything to say. (-:

The reason for that is simple, and one I didn’t think would hold up the works quite like it did: I’m a perfectionist (surprise!). One of my habits when making software is to just tear the whole darn thing down and start over from the beginning, using what I learned and innovated last time in the new design. The upside is that the result is always really slick. The downside is that I start over a lot, and that takes hecka time.

Another problem is that my co-worker hasn’t really delivered. He went and got himself fired due to attendance issues and I haven’t heard from him since, meaning he took the character design plans with him. (-: Oh well, that’s how things go. So I’m not going to make such a push to have a game ready for VB20, but I do still want to make the game if someone wants to help with character and graphic design, so I won’t spill all the details of the project just yet.

Anyhoo, back to starting over. If I’d been keeping up with the “post a month” theme regarding the music engine and composer project, it would have been three months’ worth of “Okay, I know I said this is where I was last month, but it’s better now!” soooooo, that’s why I haven’t said exactly that. However, I feel quite firmly that I’ve got the specifics down to the point that I won’t really be making them any better through further revisions, so I’m ready to make an announcement…

As a Christmas gift to the Virtual Boy community, I’ll do everything in my power to have the music project completed in its entirety, and with the level of quality that I aim for. And then, if no other project comes up, I’ll at least work towards producing a digital album that runs on the Virtual Boy for the VB20 event. These goals are in the right level of ambition for me, and I’m confident that I’ll deliver on everything this paragraph promises. You’re invited to hold me to that. (-:

I just… need to finish the new Pokémon game first. And play some more of the new Super Smash Bros. game. So gimme a couple more days, please. (-:

I’ve put a great deal of thought into the best way to have a Virtual Boy emulator on 3DS/ARM. I’ve got concepts drafted up for both an interpreter core and a recompiler core, and have just short of made one on an earlier ARM system as a proof of concept.

Depending on how feasible 3DS homebrew is, I’ll be all over it. I’ll even buy a new system if it means being unable to update the firmware ever again. (-:

It’s fake. I know this for two reasons: 1) Although the author did his homework, there’s one big fat inconsistency with the presentation. 2) The author said it was fake right there in the video title.

Take a look. We know the VB logos are in the extreme corners of the calibration screen, so we know the following region of the video represents a 384×224 area:

The game image takes up all but 32 pixels’ worth of full screen dimensions, meaning it’s supposed to represent 352×224 pixels:

The blocks Mario is standing on are 16 pixels wide, and there are 16 of them visible at a time. So 256 pixels, which is fewer than 352. Not out of the question, but Virtual Boy can’t do that kind of interpolation. Furthermore, the actual area of the level visible in a window that size (352×224) is this:

Naturally, I didn’t have to go through all of that. I just wanted to see if I could prove it wasn’t real. (-:

How did I know it was doctored before I proved it? Take a good long look at the video title and don’t look away until you figure it out:

I’d like to get devkitV810 out there, but it’s dasi’s project and I don’t want to put it out until he feels it’s ready. Problem is, I can’t get ahold of him. |-:

libvue isn’t packaged with devkitv810 just yet, but the plan is to put it in there for the formal release. Even without that, it’s just two files: a .S assembly file and a .h header. And a .html for documentation. (-:

For the record, devkitV810 isn’t based on the same code branch as gccvb. dasi modified it himself to make a compiler for both Virtual Boy as well as PC-FX, which it does to a T. It’s still got a few outstanding issues (standard libraries aren’t linking correctly, for instance), so I’d really rather not make it available without his blessing.

speedyink wrote:
I’ve beaten the normal quest, but I can’t get past the first boss on the second quest. He moves too fast for me to avoid him..

You need to dash by holding the L or R button. It’s very tricky to beat him without dashing.

Tauwasser wrote:
So they use the same mnemonic as all the other platforms out there and make it mean the opposite of what it does on every other platform?

Let’s take a look:

NES – 2A03, based on the MOS Technology 6502 – Status register has interrupt disable flag. Instructions [font=Courier New]SEI[/font] and [font=Courier New]CLI[/font] are present, which disable and enable interrupts, respectively.

SNES – 65C816, based on the Ricoh 5A22 – Status register has interrupt disable flag, [font=Courier New]SEI[/font] and [font=Courier New]CLI[/font], just like NES. In fact, most of the instructions are binary-compatible.

Game Boy – Unnamed CPU, based on the Sharp LR35902, itself based on the Zilog Z80 – No on-chip interrupt support, but the system contains an I/O register at bus address 0xFFFF, in which individual bits do need to be set to enable interrupts. There is a master interrupt control register, and it needs to be cleared to disable all interrupts.

Game Boy Advance – Stock ARM ARM7TDMI – No on-chip interrupt support, but an I/O register is present here too, requiring bits to be set to enable interrupts. However, master interrupt control can be set to disable all interrupts.

Nintendo DS – Stock ARM ARM7TDMI and ARM946E-S – Similar to GB and GBA, with I/O register where bits need to be set. Likewise, the master interrupt control can be set to disable all interrupts.

*35 minutes of frustrated web searching later*

It occurs to me that the world needs an N64 Sacred Tech Scroll…

Nintendo 64 – Stock NEC VR4300, based on the MIPS Technologies R4300i – Status register (which I learned about in a PDF document and cannot provide a link to) contains an interrupt enable flag, which must be cleared to disable interrupts.

cr1901 wrote:
Does the stub crt0 re-enable interrupts, because I somehow doubt there’s anything “magic” about unconditionally jumping to the reset vector location.

This would be my guess. If the crt0 has an implicit [font=Courier New]CLI[/font] in there, then interrupts will be enabled even if you bite your tongue really hard.

cr1901 wrote:
Finally, is the following line in the Sacred Tech Scroll relevant?:

When PSW is initialized, the NP flag is set. This must be reset manually using the LDSR instruction. Otherwise, any exceptions or interrupts that occur will result in an immediate deadlock.

No, that was me making an error. A reexamination of the V810 documents revealed that interrupts are implicitly ignored during any exception processing: that is, if [font=Courier New]NP[/font] or [font=Courier New]EP[/font] is set, not just [font=Courier New]ID[/font]. If any other exception occurs, like zero division or an invalid opcode, then a deadlock will still take place.

I have a new draft of the document in the works, and in it, this particular mishap has already been corrected.

Tauwasser wrote:
But sei enables interrupts. cli disables them.

Other way around. The bit being set in the status register is called [font=Courier New]ID[/font], standing for Interrupt Disable. When the bit is set, not cleared, interrupts will be ignored.

It’s my understanding that VIP memory is read/written by the VIP itself using the same or a similar I/O interface accessible by the CPU. As in, the VIP has to issue its own reads and writes, rather than change the values in its memory directly. I might be completely off here, but it lines up with what I’ve experienced (like the way my F-Zero project died when it came time to overlap some pixels).

I do know that window parameter memory has some scratch areas, such as those reserved regions of affine parameters. The VIP uses those areas to store working variables while it’s drawing. Again, it sounds to me as if the VIP is a sort of coprocessor that accesses video memory the same way the main IC does.

If that’s the case–and again, I could be totally wrong–then there will not be any restrictions regarding how or when VIP memory is accessed. After a write process completes, the data can be read. Is there a sort of mini bus in there that prevents the VIP and CPU from accessing the memory simultaneously? I have no idea how it works, but the mystical back of my brain where thoughts happen without my knowledge suggests that such conflicts are never an issue.

Here, have this salt shaker so you can take a few grains with what I just said. (-:

The two-pronged screwdriver is the way to go, but make sure the screwdriver you pick for the job is straight and true. A lot of cheaper screwdrivers are somewhat warped and won’t cooperate very well when attempting to access the deeper sockets on the device.

I’m not sure how screws are sized in your area, but the correct size screw in the US to replace the ones the system comes with are #4 and a half inch long. I prefer the ones with the flat heads because that makes it easier to get the screw into them when it’s time to do or undo them.

There’s plenty that Mednafen doesn’t emulate, and not just trivial things like the behavior of [font=Courier New]MPYHW[/font] when fed out-of-range operands. For instance, the VIP can raise an interrupt when the specified group of 8 rows of pixels is being drawn. Mednafen doesn’t support that; not even in the slightest. And the VSU will refuse any write requests to wave memory while sound is being generated on any channel. Mednafen lets you rewrite wave memory at any time.

More importantly, though, Mednafen’s timing isn’t especially accurate with regards to how much the VIP can draw in any given frame. And that’s understandable, considering the VIP will take different drawing times depending on exactly what it’s configured to draw. It’s not an easy thing to accommodate, and, well, sometimes things that run just fine in the emulator don’t work so well on the hardware.

I’m reminded of the vintage days of internet emulation, where people were developing against NESticle for lack of a way to burn ROMs for use on the NES hardware. But there was a bit of a problem… See, the NES’s “picture processing unit,” or PPU, has a status register that the CPU can query. One of the bits in that value indicates that the PPU is currently in the vertical blanking period, and therefore raising a VBlank interrupt. The way NESticle had this implemented, that bit was set in the register all the time until VBlank ended. But on the hardware, the act of reading from that register is how the very interrupt itself is acknowledged, meaning subsequent reads will show that bit to be clear, even if the PPU is still blanking scanlines.

Consequently, a not-insignificant number of homebrew programs broke when attempting to run them on the hardware, even though they worked in the go-to emulator of the day. In some respects, that’s what we’re facing with Mednafen.

jrronimo wrote:
I’ve always thought it would be great to try and be a Virtual Boy chiptune artist. 😀 Maybe when you’re done I’ll be able to!

Well this puts things into perspective. Thank you for the comment. (-:

This past week has been kind of humdrum. I hadn’t met my September 1 goal of having a composer ready, and as I worked through my full-time job during the week, I wasn’t especially motivated to just crank out code like I’d been doing–mostly because I didn’t have a solid plan for all the little details of the composer like I did for the music and sound engines. It really wasn’t all that productive a week.

On the other hand, I spent much more time on Saturday than I expected on what I thought would be a small little feature. The Samples window allows you to create wave patterns to use on the audio channels. The composer itself operates in a high-precision mode that uses floating-point precision for everything and a very high sampling rate. In the case of waves, by default it uses 250 samples (compared to the VB’s 32), but the size is configurable. If nothing else, you can generate a list of sample values externally and paste in the numbers into a text box, and it will read them in as wave data. It will also convert them to the corresponding Virtual Boy values (and display them in place of the high-precision values if you desire), allow importing and exporting, hand-drawing of waves using the mouse… I guess it shouldn’t have been a surprise that it would take as long as it did. (-:

Either way, faced with the fact that every user interface element will be a project in its own right, I’m still coming to terms with the realization that in order to do this right, it’s going to take more time than I wanted to spend on it. How much time? I really can’t estimate it at this point, but I’m reeeeeeeeeally hoping to formally have the composer done by month’s end.

But what you just said right here–the thing I quoted above? That makes it all worth it. It’s people like you whom this project is for. Not for me specifically, and it’s not for the community to stare at and congratulate with a thumbs-up and a golf clap. So instead of spending my remaining hour tonight breeding a perfect-IV Clauncher that knows Entrainment, I spent it loading up a sheet of paper with my signature soft-blue ink and window designs.

I’ll be keeping in mind what you said. And now, I can’t wait to get back to work on this tomorrow once I get home. (-:

cr1901 wrote:
Does anyone familiar with disassembling commercial games know whether any commercial games implemented a small heap manager in the VB RAM for maintaining data structures like event queues and possibly alternative stacks for interrupt processing and the like?

I might just be totally wrong here, but I’d like to believe that no commercial games used a heap allocation method akin to malloc() and free(). It’s far simpler to use pre-allocated static memory and use the stack by declaring struct variables in high-order functions.

Virtual Boy has 64KB of on-board memory. If you’re considering setting up a paging system, be careful you don’t wind up using it all just trying to keep track of where it is.

cr1901 wrote:
Like it or not, at some point, I’m going to have to write an event queue..

[…]

Event queues are really the only way I know how to deal with asynchronous hardware processing in a controlled manner, where the game logic still proceeds when a hardware request needs to be made (i.e. no polling) without worrying about being interrupted at any point after processing is done (i.e. defer response to “hardware done” interrupts).

I won’t pretend to know exactly what you have in mind, but I can tell you how I handle things…

My programs have two “threads”, if you will, that run side-by-side to present the user experience: there’s the audio thread, and the video/game thread. I put “threads” in quotation marks because it’s not all that fancy–I didn’t design an OS or anything. It’s just logical processing of interrupts that mimic two distinct code contexts.

Games for earlier systems lumped all operations into one code path. The NSF file format actually specifies whether to process audio programs 50 times a second or 60 times a second, according to the video framerate of the game it came from… but I digress.

My audio thread runs on the timer interrupt, at something like 80 or 100 times a second in order to give a little more precision than the 50fps video clock. If my audio worked just as well at 50 audio frames per second, then I’d definitely be running it on the video/game thread all at once.

The video/game thread is the game logic and processing timed around the performance of the video hardware. It basically comes in four stages in a loop:

* Read game pad state
* Process one video frame’s (1/50 second) worth of game
* [font=Courier New]HALT[/font] and wait for the previous frame to finish drawing (not to be confused with finished displaying)
* Update video memory to reflect the frame that was just processed

This is a streamlined approach: use of the CPU’s [font=Courier New]HALT[/font] instruction only happens as a necessity because video resources are in use. The frame that is processed starting with reading the game pad state is the frame after the one currently being drawn, and the frame currently being drawn is the frame after the one currently being displayed. So it has the usual double-buffered drawback: what the user sees is actually 2 video frames in the past.

In practice, the processing of the audio thread happens much the same way: schedule + [font=Courier New]HALT[/font] + update hardware. As such, I’ve got the code to do it plugged in up there with the video stuff, but exactly which type of frame to process depends on the interrupts that occurred (which use static global variables to indicate they’ve completed–my interrupt handlers are quite barren).

Audio needs to have higher priority than video. That is to say, if you had to pick which one was going to happen, you should always make sure audio is the one that happens. I personally do a lot of bench testing to establish metrics that will prevent the audio+video from running into overtime even in a worst-case scenario.

Other programmers have other approaches: I know for a fact that the GBA Pokémon games process all of the audio through interrupts, since whenever you crash the game by putting a hacked mon in the PC, the music keeps playing…