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

Guy Perfect wrote:

KR155E wrote:
I have been thinking about design tricks and came up with a question to those who have worked with direct screen draw: is it possible (and feasible) to do “post processing” on the Virtual Boy? i.e. can we manipulate the frame buffers after the VIP has done its job and written the next frame to it?

Yes, framebuffer memory can be accessed by the CPU after VIP drawing operations but before scanning to the displays. It’s certainly possible. Feasible, like blitter shows, is another matter. (-:

Any plans to RE the VIP timings so that I *can* race the beam? While its utility might be limited, it’d be pretty cool regardless. 😀

KR155E wrote:
I have been thinking about design tricks and came up with a question to those who have worked with direct screen draw: is it possible (and feasible) to do “post processing” on the Virtual Boy? i.e. can we manipulate the frame buffers after the VIP has done its job and written the next frame to it?

Yep. In fact you pretty much have to wait until the VIP is done drawing to ensure that what you write will not be overwritten by the VIP’s blitting ops. Granted, if the VIP is pretty busy during a frame, you won’t have much time to do your own direct drawing, but if you had to you probably could play with the FRMCYC register to allow yourself more time, at the expense of framerate. I suppose if you were *really* careful with your timing you could “race the beam” and do your direct drawing in parallel with the VIP, but the exact timings of where and when the VIP blits pixels during its busy stage is a mystery to me.

I am thinking about a full screen HBias effect as en example, where we shift some rows by some pixels to create a wavy screen. Another example would be to only render to a fourth of the screen through the VIP and then scale that portion up to full screen by replacing each pixel of the original image with four pixels.

These things are all technically possible, however they are very slow, as they all have to be done in software. You probably could pull it off at full framerate with clever coding, a sparse scene for the VIP to render, and not much else going on in your game loop, but as an example, my dither demo runs at almost fullscreen and doesn’t run at 50Hz. I’d have to rewrite it in asm to squeeze more speed out of it, and that’s with nothing else happening in my loop.

Yet another example would be to add “glitches” of various kinds, like offsetting some rows, inverting portions of the screen, etc.

Small effects that are localized to portions of the screen are better candidates as general case effects IMO.

I simply use Mednafen in side-by-side mode and relax my eyes. Don’t need any fancy glasses. If for some reason I did, I’d use my Oculus Rift or Gear VR. 🙂

Hyper Fighting. 😉

3DBoyColor wrote:
Also, Game Boy is a 4-bit handheld portable? What?

I thought the same thing. The Z80 workalike at the heart of the Game Boy is still very much an 8-bit machine as its predecessors. Sounds like somebody got fed info from a non-technical person. 😉

No not really. A small part of the CPU’s time is dedicated to setting up the VIP to draw. If it had to draw two completely different screens then the worst that would happen is that the rendering code would take twice as long, but that wouldn’t be half the time in a typical game. The remainder of the frame time is used by the CPU to do things like game logic, sound, etc. that are independent of how much is rendered.

No.

No.

Headphones are headphones. As long as they use the standard 3.5mm plug as most consumer audio equipment, they’ll work fine with the VB. I use my Sennheisers when testing my audio code.

Haha, a Cybiko! I have a couple of those somewhere… 🙂

cr1901 wrote:
I found a valid reason for 3): Branch instructions have a 9-bit displacement. Relative jumps have a 26-bit displacement. If it’s necessary to jump further than +/-256 bytes, you’ll have to do something like: be/jr.

Derp. Looking at the v810 architecture manual, you are absolutely right. On the bright side, that’s one less bug to fix in GCC. 🙂

And don’t call me Amy.

Surely you can’t be serious. 😉

One of the members here already started on an implementation of LLVM/v810… Maybe it was Parasyte? dasi? As I recall there wasn’t much progress on it.

v810 support hasn’t been in GCC mainline since version 2.x IIRC. I got the 4.4.2 patches from dasi; perhaps he wrote them originally but I honestly have no idea. I think the v810 patches are largely based on existing support for the v850, which is similar.

The 4.8 patches are part of “devkitV810,” which as far as I can tell is just a fancy name for GCC + some auxiliary tools. It’s supposedly being worked on by dasi and/or Guy Perfect, but I haven’t seen or heard anything from either of them regarding that project in a long time. I think they might be floating around out there on a Git server somewhere…

Off the top of my head:

1) Biggest problem so far is that GCCVB 4.x will sometimes generate relative jumps that are offset by some power of two ahead of where their proper destination should be. This becomes a huge problem when these jumps are executed repeatedly, as eventually the PC will wrap and wind up in video memory or elsewhere. I wrote a tool that operates on the final .elf file and attempts to correct these bogus jumps, but it’s more of a bandaid than a solution. http://www.planetvb.com/modules/newbb/viewtopic.php?post_id=31203#forumpost31203

2) Optimization is lousy. It’s better in 4.x but still carries the baggage from the 2.x patches upon which the v810 support is based. So some operations such as 32-bit loads and subroutine calls are hardcoded as a certain sequence of assembly instructions when the compiler might be able to be clever about it (for example, doing several consecutive loads of RAM addresses– movhi hi(0x05000000),rN should only need to be done once)

3) Found a bug recently in the version of gas that ships with GCCVB 4.x where sometimes a bne instruction– written in the assembly source *as a bne instruction*– will assemble to a be and a jr instruction. There is no reason whatsoever that I can think of why this should happen.

4) The frame pointer is assigned to register r29 I think, which is normally used by the bitstring instructions. I’ve never seen documentation for the v810 that says where the frame pointer should go, but since the frame pointer is irrelevant for VB development, I just pass -fomit-frame-pointer when compiling. I mention it here for completeness.

D’oh, I meant MinGW. Whenever I use the GCC suite in Windows I’m conditioned to assume it’s Cygwin.

And yeah, 32-bit multi-char literals have been a staple of Mac development since the dawn of time. Tells you where I wrote it. 😉

I know that linker order can affect the visibility of symbols across object files, but I’ve never before seen a case where the order can directly affect the addresses generated for visible symbols. I fear something more sinister is at play here. At any rate, switching the linker order can appear to fix some instances of this problem, but I’ve run into this when building assembly-based projects too, where multiple symbols may be defined within a single translation unit, and a deliberate order determines where the assembly is placed in the binary. Changing the linker order here means changing the layout of the binary, which in my case could break execution since pieces of my code expect functions to live in certain areas of ROM.

That said, and since I have not the desire to dig into GCC to find the root cause of this (I’d rather be developing for the VB itself), I decided to hack my way around this problem by writing a small tool that patches ELF files with bad jumps. As an example:

mbp:jmptool blitter$ ./jmptool ../../isrtest/output/IsrTest.elf IsrTest_fixed.elf
Total ELF sections: 12
Last ELF section address is 0x0707FDE0, size is 0x00000220, last byte + 1 is 0x07080000
disp26 mask is 0x0007FFFF
disp26 shift is 7
Found a bad jump at 0x0700003A: jr	0x07400022 [(int26)0x003FFFE8]
	Correcting to 0x07000022 [(int26)0x03FFFFE8]
Found a bad jump at 0x070000AC: jr	0x07400022 [(int26)0x003FFF76]
	Correcting to 0x07000022 [(int26)0x03FFFF76]
Found a bad jump at 0x07003472: jal	0x07403404 [(int26)0x003FFF92]
	Correcting to 0x07003404 [(int26)0x03FFFF92]
mbp:jmptool blitter$

Keen eyes may notice that the bad jumps are 8 bits away from their corrected versions– the bad jumps are coded as 18-bit displacements when they should be 26-bit. Maybe this can help somebody (dasi? Guy Perfect?) but I’ve given up solving this problem since GCC is quite the complicated beast and this tool works well enough when stuck between ld and objcopy. 🙂

I built this tool for OS X and also in Cygwin on my Windows 8.1 machine, but the source is included too just in case. Hope this helps someone else out there.

Attachments:

+1 for Tempest/T3K. I wonder if Jeff Minter would consider a VB side project…

I believe Nintendo’s sanctioned way according to the manual is with the legs pointing away from you, so that the controller is behind the system and you look like you’re “hugging” the VB while in use. I play this way and it’s very comfortable. Holding the controller in front of me with the legs pointing towards my body makes me feel like I have T-rex arms and gets tiresome after a while.