We're using cookies to ensure you get the best experience on our website. More info
Understood
@blitterRegistered December 14, 2007Active 1 week ago
161 Replies made

An UncleTusk Dragon Hopper box, cool! Too bad the ESRB icon on it is placed in violation of guidelines. 😛

ElmerPCFX wrote:
Then you’d just have to fix the linker script to make sure that those sections really are put within the top 32KB of the cartridge.

Top 32KB? Is that because the displacement is signed? What if gp was set to the middle of WRAM? Then all variable accesses (minus constants of course) could be in the ZDA section. 🙂

ElmerPCFX wrote:
But seriously … how are you telling the compiler that the variables in the .data section can be accessed GP-relative?

That’s one of the main reasons to put stuff in the .sdata/.sbss sections with the “-msda=??” compiler switch … so that the compiler knows to generate GP-relative code.

I’m not. 😉 I write everything in assembly. And you’re right– gccVB doesn’t know a thing about SDA variables.

Are you only accessing variables from assembly language that way?

Yep.

Are you using your own linker script?

Yep. I’ve attached it, though I can’t say I’m all too proud of it. I just tweak it here and there.

There are a couple of potential benefits to programming the game to believe that it’s running at $F0000000-$FFFFFFF, although I can’t see that Nintendo actually took any advantage of it.

Do tell! Shifting my ROM up to that area costs me nothing, so if there are extra benefits I’d love to know what they are.

ElmerPCFX wrote:
I personally favor doing as-little-as-possible in crt0.S, and leaving non-critical startup functions to calls inside main().

🙂

The VirtualBoy docs are pretty insistent that you wait 200us before accessing WRAM, and I don’t see that crt0.s is actually complying with that warning.

I’ve tested this particular project on real hardware many times, and never ran into problems. 200us translates to about 4000 clock cycles on the VB, which would pass long before the initialization of data and bss is finished. It is very possible that my luck is due to this project not being terribly dependent on the initial state of RAM, though, so if prematurely accessing WRAM produces garbage, my guess is it simply isn’t affecting my code.

One thing is pretty apparent to me though: it doesn’t seem to have any other effects on the hardware.

I can’t see that the linker script is actually mapping the .sdata/.sbss sections into the VirtualBoy’s WRAM, and I certainly don’t see the GP register being set to a “reasonable” value for using GP-relative addressing.

Unless I’m missing something, that means that all your C variable accesses are going to go through slow 32-bit loads, which seems like a terrible waste when you’ve got the capability for fast-access to 64KB of GP-relative variables.

For the VBJaEngine/GCC4.4 versions, you are correct. However in my version, notice that I set sp and gp to the same value– the top of WRAM. Thanks to WRAM being mirrored every 64KB, gp-relative accesses work just fine. 😉

For example, here is a crt0.s that I use for a small project I wrote to test the timer interrupt. It assumes an interrupt handler exists at $07000000 (in my case, provided in a separate .S file) and enables the instruction cache immediately before jumping to it. However if the timer interrupt is not used, that vector can easily be stubbed out as the others are.

IMO the startup code that comes with 2.95 (and thereafter crept in to version 4 and later) already does way too much. All the crt0.s file *must* do, from my own experiments, is initialize the registers, set up the data and bss sections, provide the vector table, and call main(). That’s it. The 2.95 crt0.s does a whole bunch of other possibly unnecessary stuff like clearing VRAM, clearing audio RAM, setting the column table, etc. With *maybe* the exception of the column table, these things should be done as necessary either at the beginning of main() or where appropriate. I don’t use the crt0.s that comes with gccVB but instead provide my own as tailored to the specific project. This includes the interrupt handler as well– in many cases I don’t even use interrupts at all, so I stub out those vectors with reti instructions. I figure since each project needs its own crt0.s anyway because of the ROM info table, I may as well customize it to the project’s needs.

Maybe the ROM info table doesn’t belong in crt0.s. It should be possible to create a separate .s file that when assembled just contains the ROM info table, and then place that in its proper location within the ROM at link time. In any case, I don’t know where this base crt0.s came from, but I think it could stand to be pared down quite a bit.

Nitrosoxide wrote:
If Xcode supports writing C code… couldn’t I write my C Programs in Xcode?

You can use Xcode as a glorified text editor, but that’s it as far as the VB goes. You will need to then drop to a command line to use a V810-patched version of GCC to compile your C code for the V810, since Xcode is hardwired to use Apple’s tools. If you like using IDEs, then I prefer Eclipse (or TextWrangler/BBEdit in a pinch).

I don’t think learning a high-level language like Swift was learning with the “crutch of a modern high-level language “. Honestly, learning it has made a lot of basic programming concepts accessible to me, like variables, functions , etc. None of this made sense before and I’ve tried to learn to program many times.

A lot of that is thanks to TreeHouse’s great lectures on Swift. They have really good visual animations that make it a lot easier to grasp the basics. I highly recommend their lectures.

It’s the first place that made this stuff make sense and I actually went to a paid school for programming, which was a colossal rip off / waste of time.

If anyone’s interested in Treehouse: Here’s referral link that gets me a discount if anyone’s interested in a free month.
http://goo.gl/s5mNb3

Having a good grip on Swift and glancing at an overview of the C Programming language… well it’s not super different from basic concepts I learned in Swift..
Functions, loops, etc , I know what all these things are.

As Swift can get me employed for iOS development, it’s a skill I want and am happy to have.
Learning C is another great skill to have.

And it mixes with Swift since I can when creating programs, Swift and Objective-C and C code can be used in a single program. I can directly use C from Swift.

Learning how to play piano might help me learn music, but it’s not going to develop my trumpet embouchure. Yes Swift and any number of other programming languages can teach basic concepts, but if you think that continuing to focus on mastering Swift will make you a better VB programmer, then you’re wasting your time. Learn C.

By “solid coding background” what exactly, what would you say helped you the most before you tried tackling VB or while adjacently tackling it? Is all I really need just a good C foundation?
Or are there specific areas to focus on in C?

Probably my 20 years of programming experience, but don’t let that discourage you. As HorvatM and thunderstruck pointed out, games can be written entirely in C and libgccvb provides convenience functions that can abstract away some of the nitty-gritty confusing details. Ultimately though, it’s important to understand that consoles built prior to around the 2010s were very specialized machines and as such, coding for them was and is very different from coding for a traditional PC or smartphone architecture with standard video, sound, and audio interfaces. The Virtual Boy (and I believe the N64) shipped *without an operating system*– everything had to be provided by the programmer. Contrast this with a framework like SpriteKit, or an engine like Unity, where as ElmerPCFX so eloquently put it, “60% of the work”– the hard, low-level engine stuff– is already done for you.

A good C foundation will go a long way to helping you write your first Virtual Boy application. C is a pretty simple language– there’s not really “areas to focus on” so much as there are not really areas to focus on in, say, English. Take ElmerPCFX’s advice– grab a copy of K&R C from Amazon, pore through it, and write some simple command-line based PC apps in C first to get a grasp of how to “speak” C. After that, then you can dip your toes in the red and black pool, so to speak. 🙂

The Virtual Boy is based on the NEC V810 32-bit microprocessor. To write software for the VB you typically use GCC, which is a free, open-source compiler suite. GCC takes your C code and generates V810 assembly instructions which are then assembled to native V810 machine code intended to run directly on the Virtual Boy’s CPU. From there the machine code is fed to a couple more auxiliary tools which package the code into a ROM file readable by an emulator such as Mednafen (or burnable to a FlashBoy). The Tech Scroll I linked details the memory map and hardware registers of the Virtual Boy itself, which when read/written according to the spec will make the Virtual Boy do the special functions it’s known for.

The Virtual Boy doesn’t have an API or anything analogous to SpriteKit or other high-level frameworks. Anything that isn’t handled by the hardware itself has to be written, from scratch, by the programmer in software. There’s no C standard library, no STL, nothing.*

(*Well, there are some community-contributed utility and convenience functions in libgccvb, but I typically just hit the memory and registers directly for better efficiency.)

The closest thing available to a Virtual Boy development “tutorial” is the Development Wiki found here: http://www.planetvb.com/modules/dokuwiki/doku.php But ultimately this will point you to sample code which when reading is the best teaching tool available.

If you’re expecting some kind of guide that holds your hand every step of the way– sort of a step-by-step Virtual Boy “Hello World” from start to finish– I don’t think that exists. Homebrew in general, not just for the Virtual Boy, presumes you have a solid coding background and also makes the assumption that you’re willing to get your hands dirty in reverse-engineering and bootstrap your own development environment. In my case, I build GCC from source code, install Eclipse, set up a Makefile-based project, write Makefiles that point to my GCC toolchain, then from Eclipse I can edit my code and Makefiles, build my project, and launch my ROM from Mednafen to debug (in assembly, no less). But that’s certainly not the only setup, and likely not a very common one since I do my development on a Mac and most VB developers use Windows.

The Virtual Boy is not a good platform to learn to code on, but if you insist, I would recommend finding a Windows machine or VM, going to the Development Wiki I linked above, setting up a development environment using gccVB 2.95 (for now), and trying to build the samples linked under the “Getting Started” section. You’re going to find the most support from this forum when using the Windows-based tools.

ElmerPCFX wrote:

blitter wrote:

That is a cool trick! I hadn’t thought to investigate the in.* instructions to see what they actually do. I’ll have to use that in my projects now, thanks. 🙂

It’s a nice trick since Nintendo made the I/O address space just by a copy of the normal address space … but note that you don’t save the extra cycle on multiple loads that you do with the “ld” instruction.

Do you mean grouping “ld” instructions together to speed up the data fetch pipeline? “in” doesn’t follow those rules?

ElmerPCFX wrote:
The compiler doesn’t really seem to understand that “ld.*” is automatically sign-extending a 16-bit/8-bit read from memory.

The compiler doesn’t know that it can use “in.*” on the VirtualBoy to zero-extend reads from memory (that trick won’t work on the PC-FX).

That is a cool trick! I hadn’t thought to investigate the in.* instructions to see what they actually do. I’ll have to use that in my projects now, thanks. 🙂

ElmerPCFX wrote:
I took a quick look at the libgccvb source code, and was surprised to see so many uses of “u8” and “u16” in the code.

The V810 CPU was designed to handle 32-bit variables … and it doesn’t do any arithmetic operations on 16-bit or 8-bit values.

That means that the compiler needs to do a lot of masking/sign-extending when it’s asked to deal with 16-bit or 8-bit variables, just so that it keeps the results correct within the limits of 16-bit or 8-bit rounding.

You really should be using “int” and “unsigned” as much as possible, and avoid “short” and “char” variables.

According to David Tucker’s unofficial Virtual Boy specification:

The external data buss [sic] supports both a 32-bit data mode and a 16-bit mode, but the VB only utilizes the 16-bit mode.

Now, I don’t know where he got that info, since I can’t find mention in the official Nintendo docs of the width of the data bus at all, but in the symposium PDFs there is sample code that copies data in memory using short* and char* pointers, so that suggests to me that the VB uses the V810’s 16-bit bus mode. 32-bit pointers are not used in Nintendo’s sample code. So, while arithmetic operations probably should operate on 32-bit values for best performance, is it efficient to load 32-bit values from RAM/ROM on a 16-bit wide data bus (assuming this is how the VB is configured)?

Nitrosoxide wrote:
I’d actually like to create something on iOS that I port to Oculus Rift and VB. Not sure how feasible that is. 

Keep in mind this is a longer term goal , so if things could get easier in a year or due to more development resources or upgrades on the VBDE that would be cool.

While this is a noble goal, you will find it very difficult. The VB is an *extremely* limited platform compared to a smartphone or Oculus-powered PC. For starters, you have the NEC v810 CPU clocked at 20Mhz with only 64KB of pseudo-static RAM and typically up to 2MB of ROM space when using a FlashBoy Plus. Yes you can eke some performance out of the system if you know a few tricks, but that comes with experience and even so, there are hard limits as to what the circa-1995 machine can do. It’s a much easier path to design and write something for the VB first, then port later to more recent powerful platforms.

Nitrosoxide wrote:
Swift -> VB Programming … What do I need to study?

With the new release of the VBDE is assembly language knowledge still required, or is it now possible to get away with creating something with a high level programming language?

Learn C. Your Swift knowledge is mostly useless for homebrew purposes. NEC v810 assembly knowledge is a big plus, but even so, many homebrew games are written in pure C. You should at least have an idea of what your C code is compiled to, as when writing in C for any platform.

Using Mac OS X would it be possible to create something without installing a Virtual Windows system (without making it harder on myself)?

Yay, another Mac user! Mac binaries of what little exists of the VB dev toolchain are few and far between– I might be the only one producing them. However, user ElmerPCFX is hard at work taking what are buggy patches intended for gcc 2.95 and revitalizing them for gcc 4. http://www.planetvb.com/modules/newbb/viewtopic.php?topic_id=6456&forum=2 I can send you my binaries but I must warn you, they are buggy.

Any help or books to read or tutorials would be awesome to help me on my path.

Have you checked out the Sacred Tech Scroll? http://www.planetvb.com/content/downloads/documents/stsvb.html Outside of Nintendo’s official documentation it’s probably the most thorough doc detailing the hardware.

I also don’t know if I’ve mentioned this anywhere else here, but I do *not* know GCC’s internals. At all. So, my patches are more hacks or bandaids to work around problems I encounter than anything else. I share them just in case they might help other devs, but please don’t accept them as attempts to properly fix any problems (though if I happen to fix anything then AFAIC that’s purely a coincidence. 🙂 )

ElmerPCFX wrote:
I looked at the thread, and it’s pretty obvious that the problem is in the symbol-relocation code in binutils.

A quick comparison of the binutils 2.20.1 patch, my binutils 2.23.2 patch, and the current V850 code shows that there’s a bug in the binutils 2.20.1 patch in the R_V810_26_PCREL relocation.

insn |=1;

should be

insn |=2;

The patch that you’re using loses the top 4 bits of the 26-bit relative address.

With the bug, the maximum relocation is 0x003fffff … which corresponds nicely to your observed bad-offset of 0x00400000.

I don’t know-for-sure that fixing that will make your problem go away, but I think that it’s pretty likely.

Thank you! I might be able to bring up a gccVB build chain this weekend and test that fix for myself. I agree; it looks likely.

I don’t know how-easy it is for you to recompile binutils and test that … I’ve had a lot of trouble compiling old versions of binutils and GCC with newer versions of the GNU build tools.

I’m using msys2, which keeps very current on all the latest versions of the GNU tools, and I need a bunch of extra patches to compile binutils 2.32.2, and any GCC that’s older than 4.7.

I do all my VB dev in Mac OS X. Specifically, I build the toolchain in 10.6 with an older version of GCC installed via macports. The build products continue to work in the latest version of OS X El Capitan, plus as a bonus I can build PPC versions too.

HorvatM wrote:
Bitstring instructions, probably.

Precisely.

ElmerPCFX wrote:
I’m sorry, but that’s a completely unhelpful answer.

Sure … he’s trying to move the hard-frame-pointer away from the register that are used by the bitstring instructions.

Why? Are you guys doing bitstring instructions in inline-assembly within the C code? If so … are you telling the compiler what registers you clobber?

Yes, and yes. It has been quite a while but as I recall either r29 was ignored when I specified it in the clobber list or I got some kind of error.

Are you doing bitstring instructions from assembly? … If so, it makes little difference whether the compiler puts its frame-pointer in R29 … especially since you’re probably compiling with “omit-frame-pointers” anyway.

Anything I’m doing from non-inline assembly the compiler should not touch, period, other than to assemble it. But for what it’s worth I use -fomit-frame-pointers in my Makefiles. Again, it’s been a while so I don’t remember the exact problem moving the frame register solved, but it was definitely related to the bitstring instructions.

Do you realize the effect that moving that definition has on the compiled-code when the compiler does need a frame pointer … especially if you’re using function-prologues?

Frame pointers and backtraces in my experience are pretty useless in VB homebrew since source-level debugging is pretty nonexistent above the assembly code level. Maybe it was possible with Nintendo’s official tools and development hardware, but I for one have never used their tools much less *seen* official VB dev hardware, and I can’t name any forum regulars who have either. Thus, and I’m sorry, but I care little about what happens to the frame pointer. 🙂 As for function prologues, I ran some simple tests before publicizing those patches and didn’t run into problems, but caveat emptor, YMMV, etc.

Hi ElmerPCFX, welcome to PVB! Glad to meet another fellow programmer with an interest in improving our little homebrew toolchain. 🙂

Please check out my thread here http://www.planetvb.com/modules/newbb/viewtopic.php?topic_id=5252 about GCC 4 and generating PC-relative jumps. I threw together a tool that hacks around the problem by poking at the output ELF file, but if you have a solid grasp of what GCC actually does behind the scenes to exhibit this unwanted behavior, then hopefully you perhaps have a better idea of what a proper solution might be. This bug (among others) is kind of what has put the brakes on my VB development since I’d much rather be fighting my *own* code versus GCC’s code.

I’ve since switched to writing purely in assembly, and FWIW I completely ignore NEC’s register allocations, save for those used by the mul/mulu/bitstring/etc. instructions. The VB itself doesn’t care either. One of my patches to GCC was to rename ‘ep’ so that the assembler would recognize ‘r30’ as a valid alias! 🙂

Guy Perfect wrote:
… You know, I think it actually is possible for a program to run in VIP memory, thereby potentially throwing an exception. I’m gonna try that!

It definitely is. I’ve crashed into VIP memory many a time debugging this problem: http://www.planetvb.com/modules/newbb/viewtopic.php?topic_id=5252&forum=2 😉

RunnerPack wrote:
BTW, it didn’t actually disappear “for good”, since the Wii and GB/DS families of consoles have them (although in the Wiis’ case it’s called “-“). Also, the “Z” button on the GC controller was mostly relegated to the function of a Select button in many games (and the Game Boy Player), likely due to its awkward placement.

Fun fact: the Select button is deprecated with the latest 3DS games. Nintendo has both the Select and Start buttons wired together in software, making them each behave as a Start button. The Select button exists on the 3DS only for backward compatibility reasons. Looks like the final nail in its coffin…

KR155E wrote:
Here’s a proof of concept, a full-screen vertical wave effect applied to the VBJaEngine Platformer Demo! Amazingly, the performance is hardly affected by it, at least on Mednafen. I assume that it’s not that great on hardware, but I am too afraid to test. 😉

In my experience Mednafen always runs faster than real hardware, but I can’t always tell how much until I actually measure it.

  1. (addend & 0xfffe) << 16) | ((addend & 0x3f0000) >> 16 []
  2. (addend & 0xfffe) << 16) | ((addend & 0x3ff0000) >> 16 []