Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411512 Posts in 69376 Topics- by 58430 Members - Latest Member: Jesse Webb

April 26, 2024, 06:09:10 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsVO-EM: Virtual game console running in a virtual machine running in my PC
Pages: [1] 2
Print
Author Topic: VO-EM: Virtual game console running in a virtual machine running in my PC  (Read 3231 times)
voidSkipper
Level 2
**


View Profile
« on: June 09, 2016, 11:20:54 PM »

I don't know if this really belongs here.

Because it's not a game, per se.

I've always been the type to roll my own engine and reinvent the wheel. When I tried to go pro as an indie the year I graduated highschool, I quickly realised that the more time I have, the more time I waste reinventing wheels. It became quickly apparent that I don't actually like making games that much, I just like making wheels.

At the moment I have a lot of free time at work and I've decided to waste it reinventing another wheel, this time for hobby reasons instead of out of delusions of pro-dev-ism.

So I designed a game console. It's kinda like the GBA with less buttons. Then I built an emulator for it. In Flash.

Here's the emulator running a little overworld test I wrote... The sprites are straight out of Pokemon Ruby, because I wanted to stare at something other than programmer art while testing it.


I have a proprietry-ish (it's like the gameboy but modified for 15 bit colour) image format for the GPU, so I wrote a converter for it. But then the freeware tile editor I was using got annoying, so I ended up reinventing the wheel and now I have a whole tile and palette editor studio, complete with assembly exporter.


The CPU driving this thing is actually the theoretical DLX machine that some older computer science students might be familiar with. It's a 32 bit CPU with a very consistent opcode format making it quite easy to understand.

It runs at a whopping 2.4khz 72khz. I'm so great at math.

The assembler was the only wheel I didn't reinvent; my professor wrote a lovely one back when I was in university, so I'm using it with his permission. I'm trying to gain additional permission to decompile it and add some features, though...

The overworld demo code looks like this:
http://pastebin.com/9xAqihhf

The assembler was never really designed for embedding binaries so I had to do a kind of nasty solution.

My current to-do list is:
-Write exception handler system (the BIOS takes over unhandled exceptions to bluescreen the device)
-Write a cartridge loader (at the moment, the cartridge is baked into the device at compile time)
-Write a cartridge exporter (at the moment, it embeds .dlx DLX executable files. I want something cooler. With banked memory.)


Is this something people want to hear more about? This is kinda a confessional thread, really. I'd love to answer any questions or have people reassure me that I'm crazy in a way that isn't entirely socially unacceptable.

Thanks.

Edit: This project now has a wiki.

Edit: This project now has a website.
« Last Edit: July 03, 2016, 08:42:26 PM by voidSkipper » Logged
voidSkipper
Level 2
**


View Profile
« Reply #1 on: June 15, 2016, 10:54:38 PM »

Today I designed and built a concept for the "cartridge" for this virtual console. I also built an exporter app to convert the .dlx executables generated by the assembler into cartridge files understood by the emulator.

Essentially the "executable" file for the console.

This is it:


The top left square contains information about this particular cartridge.

The left side is for the cartridge "label" or "art", what have you.

The right side contains six banks of read-only memory, the first bank being unswitchable and the following five being switchable. Each bank contains up to 16kb of memory.

The stripe on the bottom right is 4kb of cartridge RAM. This area persists when the game is closed, so it can be used to store save file data.

The encoding is pretty simple - each pixel contains 3 byes of data encoded one each in the RGB channels. At the moment, the alpha channel is randomized to 0x80+-0x10. I'm thinking at some stage I may replace the randomization with some kind of image encoding so that the semitransparent data blocks will also contain an image.

Of course, a PNG is a horrible way to contain an executable, but it also looks very cool so I don't care.
« Last Edit: June 15, 2016, 11:07:57 PM by voidSkipper » Logged
lithander
Level 3
***


View Profile WWW
« Reply #2 on: June 16, 2016, 03:04:23 AM »

It became quickly apparent that I don't actually like making games that much, I just like making wheels.

Haha, I can relate! Smiley That's why having a dayjob that forces me to make decisions that are most efficient is good to keep me in check. On the other hand my hobby projects have become more and more crazy and detached from practicallity over time...

http://blog.pixelpracht.net/?p=537 (you might like this one!)
http://blog.pixelpracht.net/?p=431

Is this something people want to hear more about? This is kinda a confessional thread, really. I'd love to answer any questions or have people reassure me that I'm crazy in a way that isn't entirely socially unacceptable.

Sure! I think that kind of stuff where the goal is not to produce a fun game but just to tinker around, finding some cool solutions to made-up problems within (artificial) constraints... I think that's as close to an engineer producing art as it gets.
« Last Edit: June 16, 2016, 03:14:06 AM by lithander » Logged

voidSkipper
Level 2
**


View Profile
« Reply #3 on: June 16, 2016, 03:26:14 PM »

It became quickly apparent that I don't actually like making games that much, I just like making wheels.

Haha, I can relate! Smiley That's why having a dayjob that forces me to make decisions that are most efficient is good to keep me in check. On the other hand my hobby projects have become more and more crazy and detached from practicallity over time...

http://blog.pixelpracht.net/?p=537 (you might like this one!)
http://blog.pixelpracht.net/?p=431

Is this something people want to hear more about? This is kinda a confessional thread, really. I'd love to answer any questions or have people reassure me that I'm crazy in a way that isn't entirely socially unacceptable.

Sure! I think that kind of stuff where the goal is not to produce a fun game but just to tinker around, finding some cool solutions to made-up problems within (artificial) constraints... I think that's as close to an engineer producing art as it gets.

Thanks for your reply!

Core Society is absolutely gorgeous. I can't help but think that it could be interesting to run an evolution experiment with it - populating all cores with initially random data, using some kind of metric to determine which cores are 'successful', repopulating by replacing unsuccessful cores with some kind of mutated version of the successful ones, and repeating the process to see if some kind of algorithm emerges.
Logged
lithander
Level 3
***


View Profile WWW
« Reply #4 on: June 16, 2016, 03:45:44 PM »

That was my original plan. Creating something that if left alone would evolve. Cores can copy their code into neighboring cores - which could be seen as reproduction. They can die if they get overwritten from neighboring cores or if their execution stalls for other reasons. And they can cooperate by transfering energy. For an intelligent designer it's easy to setup scenarios like that... all that is missing is some kind of "mutation" mechanism where every instruction or copy-instruction has a small chance to fail and produce some random result. But I didn't find a good "seed" configuration + mutation mechanism that would actually grow and evolve. Didn't spend too much time trying, though. Give it a try if you like Wink
Logged

voidSkipper
Level 2
**


View Profile
« Reply #5 on: June 19, 2016, 03:24:29 PM »

That was my original plan. Creating something that if left alone would evolve. Cores can copy their code into neighboring cores - which could be seen as reproduction. They can die if they get overwritten from neighboring cores or if their execution stalls for other reasons. And they can cooperate by transfering energy. For an intelligent designer it's easy to setup scenarios like that... all that is missing is some kind of "mutation" mechanism where every instruction or copy-instruction has a small chance to fail and produce some random result. But I didn't find a good "seed" configuration + mutation mechanism that would actually grow and evolve. Didn't spend too much time trying, though. Give it a try if you like Wink

I feel like going down that rabbit hole might lead to me getting nerd-sniped Tongue
Logged
zminusone
Level 1
*



View Profile WWW
« Reply #6 on: June 19, 2016, 08:07:18 PM »

You're a badass.
Logged

voidSkipper
Level 2
**


View Profile
« Reply #7 on: June 21, 2016, 04:01:24 PM »

You're a badass.

That's what my mum tells me, anyway  Cool

Yesterday, I spent quite a while restructuring the layout of this project - I'd originally just been expanding on a single Flash project file for the emulator, but I didn't really want all of the classes pertaining to the emulator tied to that project, since that's the "debugger" rather than the release emulator. It also meant I had copies of files laying around, for example, when I needed a ROM object in the cartridge exporter. All actual hardware and datatypes are in their own file now, which can be included in any project that needs them.

Prior to that, I wrote the error handlers I mentioned in my to-do list above - if an exception is thrown and the program isn't expressly listening for an exception (for example, an illegal operation or misaligned read/write occurs), the device now loads a BIOS and exception handler, which displays the nature of the error before halting execution. You can see the source code for the BIOS here:

http://hastebin.com/ulilowomac.avrasm

Obviously, I could've just written this in flash and hard-coded it into the emulator, but where's the fun in that?

Next, I began work on writing the loader for image- rather than text-based cartridges. (The .dlx executable format is literally a plain-text file that tells the compiler what data to load into which address). Unfortunately, I overlooked something, and attempting to load my demo cartridge crashed the emulator. Fortunately, that also let me see my new error handlers in action!



The font was something drawn in 3 minutes with a mouse out of frustration that I couldn't find a plain, monospaced, uncompressed font that was nicely layed out in ascii order  Big Laff

Finally, I've updated the information side of the debug emulator to have "pages" where you can inspect different parts of the device in real-time. Currently shown is the GPU (I should say PPU) page, which shows sprite and tile memory, as well as palette memory. You can scroll through the palettes to colourise the tiles and sprites, since the actual palette used is stored in instance and tilemap memory, where the image data area just holds an index with no color. The console that was previously shown in the bottom left now has a full page of its own, with enough room to actually see what's going on.
« Last Edit: June 21, 2016, 04:13:36 PM by voidSkipper » Logged
ProgramGamer
Administrator
Level 10
******


aka Mireille


View Profile
« Reply #8 on: June 21, 2016, 04:05:38 PM »

Will we be able to make metaphorical cars with your metaphorical wheel?
Logged

voidSkipper
Level 2
**


View Profile
« Reply #9 on: June 21, 2016, 04:21:30 PM »

Will we be able to make metaphorical cars with your metaphorical wheel?

Yes, once I get the loader working (the reason for the error is pretty horrendous - I completely forgot to include the "start position" part of the executable in the cartridge info, so it was trying to execute from the start of the exception handler table), I'll upload all of the tools and the debugger itself somewhere and perhaps write up a bit of a wiki to explain how to build things for it.

I imagine there are still a lot of bugs so any spontaneous wheel delaminations at highway speed will not be covered by your insurance.
Logged
voidSkipper
Level 2
**


View Profile
« Reply #10 on: June 21, 2016, 10:33:49 PM »

I encountered a strange issue where all of my colour values in the cartridge were off by a very small (<5) amount. This was solved by changing the transparancy to zero.

I'm not sure if this is a problem in the Adobe png encoder, or a problem in the Adobe png loader, but either way it's very frustrating because the cartridges don't look anywhere near as cool with solid black backgrounds.

Either way, the emulator now loads properly from the cartridge.

Here is a shot of it in-use, showing the VRAM explorer from the previous update, this time showing both sprite and tile data, as well as the respective palette data. This is very helpful for debugging purposes!

Logged
lithander
Level 3
***


View Profile WWW
« Reply #11 on: June 22, 2016, 12:41:24 AM »

When you embed images in Flash usually they are compressed using JPG compression unless you explicitly specify that you don't want that. Even images with an alpha channel (like PNGs) get their RGB channels compressed by default and the alpha channel encoded seperately.

If you embed resources in code there are optional parameters that let you tweak the compression ratio and also disable it completely.

[Embed(mime Type="image/jpeg", source="test.png", compression="true", quality="80")]

... just set compression to false.

I haven't used flash in the last couple years. Isn't it a kinda deprecated platform by now?

P.S.: love the programmer's art ASCII font! Wink
« Last Edit: June 22, 2016, 12:47:30 AM by lithander » Logged

voidSkipper
Level 2
**


View Profile
« Reply #12 on: June 22, 2016, 12:48:23 AM »

When you embed images in Flash usually they are compressed using JPG compression unless you explicitly specify that you don't want that. Even images with an alpha channel (like PNGs) get their RGB channels compressed by default and the alpha channel encoded seperately.

Not sure how you embedd the images but if you embed resources in code there are optional parameters that let you tweak the compression ratio and also disable it completely.

[Embed(mime Type="image/jpeg", source="test.png", compression="true", quality="80")]

... just set compression to false.

I haven't used flash for like 5 years. Isn't that a kinda dead platform by now? =)

I'm loading them at runtime so I'll have to dig around for that option. It doesn't do it when the alpha is set to FF though, which is curious.

And yes, thanks to a few vested interests it's pretty much completely dead! Sure is a lot of fun to develop for, though.
Logged
lithander
Level 3
***


View Profile WWW
« Reply #13 on: June 22, 2016, 01:39:39 AM »

Have you evaluated OpenFL? It seems to be able to build not only SWFs but native binaries and HTML5 apps. Maybe it's a good way to enjoy coding in AS3 these days.
Logged

voidSkipper
Level 2
**


View Profile
« Reply #14 on: June 22, 2016, 04:35:58 PM »

I may well have a look into that, though I'll confess I've never done anything involving cross compilation before.

Flash does some very fucky things that you have to trick your way around with inline assembly, so I don't know how that's going to hold up when you compile it to a less fucky language.

Like, for example, Flash never (at least, not last I checked, I'm using an outdated compiler because I'm building this on my ancient eeepc at work) compiles switch statements to jump tables - it always does them assuming that you could be switching on all kinds of things even if you're switching on a uint. Which, for an emulator, is a big performance problem, since the core of it is basically always going to be a giant switch statement, and instead of being exactly the same amount of instructions no matter how big your switch, it ends up being linear and basically just like a giant if/else block. Of course, you can just write your own jump table with inline assembly and it works fine.
Logged
voidSkipper
Level 2
**


View Profile
« Reply #15 on: June 22, 2016, 11:36:37 PM »

Today was just minor bug squashing on the emulator front, but I spent quite a large chunk of it writing a wiki for the project.

I've currently described all of the hardware except for the CPU, which will hopefully get done tomorrow.

It desperately needs prettying up with pictures and better layout, but it'll do for now. 

Don't get excited about the link to the emulator itself; I haven't gotten around to uploading it yet.
Logged
voidSkipper
Level 2
**


View Profile
« Reply #16 on: June 23, 2016, 10:43:44 PM »

Today I spent a large amount of time updating the wiki, including writing pages for the CPU and a list and description of the instructions.

I'm not very good at explaining things so I don't know if it's very readable and any feedback would be great. It starts getting really gnarly at http://wiki.vo-em.com/index.php?title=Instructions but it'd be great to know if http://wiki.vo-em.com/index.php?title=GPU makes any sense too.

I also uploaded the tools and debugger as-is onto the website at http://vo-em.com

Almost everything you do in the tile editor currently crashes the program, so probably don't use that.

The exporter is useless without the assembler and I'm still working on integrating that so it's just there for completion's sake at the moment.

Pretty much all you can do is download my demo cartridge from the Cartridge Gallery, then load it in the debugger.

Oh and I'm pretty sure I accidentally uploaded the version of the debugger with no version checking, so if you try to load a random png that isn't a cartridge it'll probably crash your browser tab.
Logged
voidSkipper
Level 2
**


View Profile
« Reply #17 on: June 26, 2016, 11:24:45 PM »

Today I wrote up a basic template file for writing programs, as well as an address file for the linker.

I also uploaded the assembler tools suite I've been using.

It's now technically possible to "build cars with my wheel", but the assembly tools are all command line so you'd have to be a very smart cookie to figure them out without instruction.

I will be writing a guide to the tools and toolchain usage tomorrow.
Logged
voidSkipper
Level 2
**


View Profile
« Reply #18 on: July 01, 2016, 01:38:32 AM »

I'm currently working on a "hello world" tutorial, as part of the start of a series of tutorials on programming for this thing. I figure if I make something ridiculous, it might as well be educational.

Previously when working on programs for the console, I'd used flash's "trace" feature to debug problems in my assembly, but obviously that's not something the "end-user" (if there is such a thing) could do.

As such, I've gradually been adding debug tools to the emulator that make it easier to write programs for it.

Today, I added a memory viewer that lets you directly look through device memory. There are a bunch of hotkeys to jump to useful addresses, and you can scroll manually with the square bracket ([]) keys. Here's what it looks like:



Ugly, but functional.

The system debug console is not used very much at the moment, but you can access it with the ` button. You can write to it from any page using the box at the bottom. At the moment, it only has the commands "peek" and "poke", for reading and writing to memory addresses. It is actually a fully-functioning console that I wrote for earlier projects, so I can add commands to it over time. I plan to have it so that clicking a memory address in the debug viewer will auto enter a poke command in the console input.

There's also a currently-unused breakpoint system which I plan on adding console functionality for.

Finally, I've been working on the wiki, mainly on a page explaining how to write for the assembler, which is now available on the homepage. You can read it here.

EDIT: Oh, I also added back in the functionality to load .dlx executables, since this is the "debug" player and it doesn't make sense to have to export a cartridge for every iteration of your development.
Logged
voidSkipper
Level 2
**


View Profile
« Reply #19 on: July 04, 2016, 03:49:02 PM »

Oh boy, when you get bugs in this sort of low-level thing, you really get bugs.

I had this assembly:
Code:
     addui     r1,r0,2#10000001     
     sh        TILE_MAP(r4),r1
     addui     r1,r1,1
     sh        TILE_MAP+2(r4),r1  
     addui     r1,r1,1
     sh        TILE_MAP+4(r4),r1  
     addui     r1,r1,1
     sh        TILE_MAP+6(r4),r1

Super innocuous, right? But every time, the value of r1 became ridiculous after the second operation. I spent ages trying to figure out how I could possibly have something wrong with an opcode as simple as "add integer unsigned". I even built some GUI elements that allow me to pause execution and step through, cpu cycle by cpu cycle.

The actual cause of the bug?

Code:
case OP_SH:
          bus.writeHalf(r[a_i] + a_Ksgn, r[a_j]);
break; //<-----------THIS
case OP_SLAI:
          r_write(a_j, r[a_i] << a_Kuns);
break;

The labeled break statement was missing in my CPU implementation, meaning every save halfword op was causing an unwanted shift left arithmetic immediate operation.

I guess I'd just never needed the value of the j argument register after doing a sh operation before...
Logged
Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic