Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1366236 Posts in 64017 Topics- by 55908 Members - Latest Member: Stano28

September 19, 2019, 03:57:22 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsAthena - A 16-bit-era fantasy console
Pages: [1]
Print
Author Topic: Athena - A 16-bit-era fantasy console  (Read 898 times)
KillaMaaki
Level 0
**



View Profile
« on: September 06, 2019, 02:24:32 PM »

Hi all!
I wanted to make a thread for a new fantasy console I've been working on lately.
Basically, I follow someone on Twitter who does a lot of stuff with Pico-8 and at one point wondered why there weren't many prominent fantasy consoles focusing on the 16-bit-era of gaming rather than the 8-bit era.

That, coupled with some experience writing homebrew software for those 16-bit consoles (in particular, the Sega Genesis and the 32X addon) inspired me to being working on a new fantasy console I'm calling Athena.

One of my goals with the Athena is to create something that feels suitably retro to develop for too (in addition to playing games that look and feel the part)
In line with those goals, I intentionally chose NOT to base Athena on existing interpreted scripting languages and VMs, instead designing my own fantasy CPU for the job. This CPU has a fairly small and low level instruction set based on a load/store architecture, and runs at a simulated 20MHz. Working with graphics, sound, and other peripherals in Athena is done by directly manipulating registers and memory addresses.

However I also recognize that it's not going to be very fun for a pretty wide group of people to program things like this in raw assembly, so I'm also working with a friend of mine to implement a high-level language compiler, a dialect of Pascal we're currently referring to as Apollo - we figured Pascal would be itself a nice suitably retro choice of language! Smiley I'll also be writing some built-in libraries for this, to provide stuff like graphics routines, music & sfx playback, input, etc.

As far as what I've got right now:

- The CPU is just about fully implemented. I'm missing some interrupt support (right now things like invalid memory accesses, divide-by-zero, and invalid instructions just cause the CPU to halt in its tracks, but eventually I will have those instead jump into user-provided interrupt handling routines so you can write subroutines to gracefully handle those cases)

- Graphics are missing some horizontal / vertical flipping support in mode 2, but otherwise done. You get three modes - mode 0 is an EGA-inspired text mode (80 column x 60 row text grid, fixed 16 color palette, hardware cursor support), mode 1 is a 256-color bitmapped 320x200 display mode, and mode 2 is an accelerated 2D mode with three tile planes and up to 256 sprites

- Audio is done. You get two emulated YM2612 chips and four channels of ADPCM sample playback. Any of those can also be routed through a configurable echo effect (you can only route a whole chip at a time though, not individual channels). Basically somewhere in between a beefed-up Sega Genesis and an Amiga :D

- Keyboard input is done, you can set up an interrupt handler for hardware interrupts and write some code to read in keydown/keyup scancodes in that handler.

- Disk controller is done. Disk controller is pretty low level, you can query the disk for capacity as well as read in 512-byte segments of the disk's contents. There's also a firmware of sorts built into the VM that will scan the disk drive to see if a bootable disk has been inserted, and will boot from the disk if so

As far as what's NOT done:

- High level programming. Apollo's definitely far from done, we just got functions, return values, and inline assembly support implemented but it still doesn't have records or other higher level types yet.

- Mouse and gamepad input.

- Any kind of dev tools at all! Right now there's an assembler to assemble binaries for Athena, and a disk utility that can work with a custom virtual file system loosely inspired by FAT and make bootable disks, but no high level IDE, no art utilities, no music creation program, etc. This is all TBD.

But in any case here's a video of what I've got right now, inserting a disk and booting into a Pong clone demo I wrote in pure assembly :D





Thoughts? Suggestions? Etc? Smiley
Logged
ProgramGamer
Administrator
Level 10
******


The programmer of games


View Profile
« Reply #1 on: September 06, 2019, 07:13:14 PM »

Nice! I always like reading about fantasy consoles and emulators, so I'm posting to follow!
Logged

KillaMaaki
Level 0
**



View Profile
« Reply #2 on: September 07, 2019, 11:17:55 AM »

Not much visually to report, though I have now added gamepad support and made some little tweaks to mode 2 Smiley

- Gamepads can now be queried by setting the bus segment register to 8 (for controller 1) or 9 (for controller 2) and then reading memory location 0000h (which yields 8-bits packing the state of up, down, left, right, a, b, x, and y) or location 0001h (which yields 8-bits packing the state of select, start, left shoulder, and right shoulder). Right now this is any gamepad SDL supports out of the box mapped to a SNES-like gamepad layout.

- Mode 2 finally supports sprite and tile flipping flags. I also changed the algorithm to work one scanline at a time. At first I was gonna do a real quick and dirty H-Sync implementation, where you can write an interrupt that gets triggered every time a scanline is drawn, but the way I've been architecting this VM makes that a bit tricky (right now the CPU is run for some number of cycles depending on calculated delta time, then the screen is drawn, so the screen can't really wake the CPU back up every scanline in this design). Surely I could fix this, but I decided to go a different route instead.

So I borrowed a concept from the SNES. You now get an "HDMA" table in mode 2. This is pretty much nothing more than a table that specifies, for each scanline, an optional source address, destination address in VRAM, and number of bytes to copy, plus a few other features. This lets you set up a table to arbitrarily modify *anything* in VRAM on a per-scanline basis, up to 255 bytes per scanline. So this is how you'd implement neat per-scanline scrolling effects or palette changes or whatever else you wanted.

So that's graphics and gamepad input finished. This leaves mouse input (currently undecided on whether I want that polling-driven like the gamepads, or interrupt-driven like the keyboard), and then scripting language and dev tools I guess.

EDIT: OK I guess that's mouse support in too. It's a little weird in that it's a sort of hybrid - it triggers an interrupt to let you know if the mouse moves or one of the buttons is pressed/released, but the interrupt itself carries no data and instead you can poll segment 10 memory location 0000h for delta X, location 0002h for delta Y, and 0004h for left/right button state bitmask (and technically you can poll this whenever you want, as I made my pong demo do as a test to drive player 2's paddle with the mouse)
« Last Edit: September 07, 2019, 05:44:56 PM by KillaMaaki » Logged
KillaMaaki
Level 0
**



View Profile
« Reply #3 on: September 08, 2019, 01:51:18 AM »

Ended up tossing in some graphics options so now you can switch back and forth between window/fullscreen modes.
Also implemented configurable shader support today! :D

In a JSON file you can now define a set of render passes, which looks something like:

Code:
{
"depends": [
"shaders/crt/crt_core.glsl"
],
"passes": [
{
"vertex": "shaders/crt/vert_tv.glsl",
"fragment": "shaders/crt/frag_composite_encode.glsl",
"target_info": {
"width": 1920,
"height": 480,
"filter": "linear"
}
},
{
"vertex": "shaders/crt/vert_tv.glsl",
"fragment": "shaders/crt/frag_composite_decode.glsl"
},
{
"vertex": "shaders/vertex_default.glsl",
"fragment": "shaders/crt/frag_composite_final.glsl"
}
]
}

The "depends" array is a set of files appended as preamble to every vertex/fragment shader source. The "passes" array is a set of passes to apply, where each pass can define its vertex shader, its fragment shader, and optional target info (for now just render target dimensions & render target filter).

So for example I put together an NTSC effect using the system (a bit hard to tell with Youtube's compression I guess, though you can see the barrel distortion and if you reaaally pay attention to a stationary paddle you can sort of see crawling artifacts):




(video also shows off gamepad & mouse support - P1 is on gamepad, P2 is on mouse, also both players are me, and that was quite possibly the most awkwardly-controlled single player game of pong ever)
Logged
Cobralad
Cowardly Baby
Level 10
*****



View Profile
« Reply #4 on: September 08, 2019, 02:09:24 AM »

I follow someone on Twitter who does a lot of stuff with Pico-8 and at one point wondered why there weren't many prominent fantasy consoles focusing on the 16-bit-era of gaming rather than the 8-bit era.
is that guy from NY
Logged
KillaMaaki
Level 0
**



View Profile
« Reply #5 on: September 08, 2019, 09:14:53 AM »

is that guy from NY

No why do you ask
Logged
Cobralad
Cowardly Baby
Level 10
*****



View Profile
« Reply #6 on: September 08, 2019, 09:25:30 AM »

is he from sf
Logged
KillaMaaki
Level 0
**



View Profile
« Reply #7 on: September 08, 2019, 09:48:09 AM »

is he from sf

Why do you ask?
Logged
Cobralad
Cowardly Baby
Level 10
*****



View Profile
« Reply #8 on: September 08, 2019, 10:14:42 AM »

what rich place on western soil has spawned a dude who craves for fantasy 16 bit console
Logged
KillaMaaki
Level 0
**



View Profile
« Reply #9 on: September 08, 2019, 10:23:05 AM »

what rich place on western soil has spawned a dude who craves for fantasy 16 bit console

I interpreted it more as "idle wondering" than "craving" fwiw.
That said I do sorta crave it and seeing someone else even mention it was all the excuse I needed to be the change I wanted see in the world I guess haha.
Logged
jsnell
TIGBaby
*


View Profile
« Reply #10 on: September 08, 2019, 12:38:16 PM »

One of my goals with the Athena is to create something that feels suitably retro to develop for too (in addition to playing games that look and feel the part)
In line with those goals, I intentionally chose NOT to base Athena on existing interpreted scripting languages and VMs, instead designing my own fantasy CPU for the job. This CPU has a fairly small and low level instruction set based on a load/store architecture, and runs at a simulated 20MHz. Working with graphics, sound, and other peripherals in Athena is done by directly manipulating registers and memory addresses.

I love the concept! My interest in PICO-8 disappeared completely the moment I realized it was programmed in Lua Sad

But I'm curious about what made you go for what sounds like a comparatively fast CPU; it sounds like CPU-wise you're a lot closer to a Saturn, PC-FX or maybe even a PlayStation than what we'd usually consider a 16-bit console. (The SNES was rocking a 3.5MHz accumulator design).



Logged
KillaMaaki
Level 0
**



View Profile
« Reply #11 on: September 08, 2019, 03:48:19 PM »

One of my goals with the Athena is to create something that feels suitably retro to develop for too (in addition to playing games that look and feel the part)
In line with those goals, I intentionally chose NOT to base Athena on existing interpreted scripting languages and VMs, instead designing my own fantasy CPU for the job. This CPU has a fairly small and low level instruction set based on a load/store architecture, and runs at a simulated 20MHz. Working with graphics, sound, and other peripherals in Athena is done by directly manipulating registers and memory addresses.

I love the concept! My interest in PICO-8 disappeared completely the moment I realized it was programmed in Lua Sad

But I'm curious about what made you go for what sounds like a comparatively fast CPU; it sounds like CPU-wise you're a lot closer to a Saturn, PC-FX or maybe even a PlayStation than what we'd usually consider a 16-bit console. (The SNES was rocking a 3.5MHz accumulator design).

Actually, I took some inspiration from the 32X for that. The 32X rocked a pair of ~22 MHz Hitachi SH-2s. I originally wanted to go with an 8MHz CPU (just a bit of an edge over a Genesis) until I gave some thought to my bitmapped mode, and realized 8MHz would likely struggle with anything more than the most basic software rendering algorithms, so I decided to bump it up to something about as fast as the 32X for that purpose.

EDIT: That said, fwiw the CPU is pretty definitively 16-bit as that is the native word size and is the size of all of its registers. 32-bit math *can* be accomplished as there is a dedicated carry register to aid in multi-word arithmetic operations (and in fact the Apollo language will make use of this to seamlessly implement 32-bit numeric types, but 16-bit math is definitely more efficient and preferred where possible), and also with the bus segment register you get an effective 20 bit address space (16 bit address plus 4 bit segment).
« Last Edit: September 08, 2019, 04:12:11 PM by KillaMaaki » Logged
KillaMaaki
Level 0
**



View Profile
« Reply #12 on: September 10, 2019, 04:09:45 PM »

Not a lot to report since at the moment most further progress is dependent on getting the scripting language up and running, though as an aside...

I had the realization that Athena may actually be capable of playing back FMVs. So I set about prototyping a simple Cinepak/Smacker inspired compression scheme designed to work with the 256-color 320x200 bitmapped mode. Some early results of round-tripping some videos through it (it's not exactly the highest quality codec lol, but it does work!)
Posting the Streamable links because Youtube munches it too badly.

The opening of Lunar: The Silver Star on the Saturn (performs pretty well all things considered):
https://streamable.com/808av

The opening of Tales of Xillia 2 (does seem to perform noticeably worse on this one unfortunately):
https://streamable.com/axakq

I may want to toy around with the idea of providing a separate optional FMV playback library with a commandline FFMPEG-based conversion utility to go with it Smiley
Logged
ProgramGamer
Administrator
Level 10
******


The programmer of games


View Profile
« Reply #13 on: September 11, 2019, 04:30:27 AM »

inb4 Bad Apple running on Athena Wink
Logged

KillaMaaki
Level 0
**



View Profile
« Reply #14 on: September 11, 2019, 09:25:20 AM »

inb4 Bad Apple running on Athena Wink

Oh that's not a bad idea actually LMFAO
Logged
KillaMaaki
Level 0
**



View Profile
« Reply #15 on: September 11, 2019, 03:23:41 PM »

My friend's been making some progress on Apollo today (making progress on getting structs working) so I thought I might as well talk a bit about that.

The primary choice of high level language for Athena will be Apollo, a custom built dialect of Pascal. Just like many variants of Pascal, Apollo is a strictly typed & statically compiled procedural programming language.

Programs in Apollo are structured like this:

Code:
program MyProgram;
// uses, types, consts, global variables, procedures, and functions go here
begin
// program code goes here
end.

So, as an example, my Pong demo's main file might look a bit like (intentionally skipping over a lot of important details):

Code:
program Pong;
uses crt;

type
Ball = record
PosX, PosY : short;
VelX, VelY : short;
Speed : short;
end;

Paddle = record
Pos : short;
Input : short;
Score : byte;
end;

var
ball : Ball;
player1 : Paddle;
player2 : Paddle;

procedure Update();
begin
// update ball, get input and update players, wait for vsync, etc...
end;
begin
// initialize game state
ball.PosX := 160;
ball.PosY := 120;
ball.Speed := 1;
ball.VelX := 1;
ball.VelY := 1;

player1.Pos := 120;
player1.Input := 0;
player1.Score := 0;

player2.Pos := 120;
player2.Input := 0;
player2.Score := 0;

// infinite game loop
while true do
begin
Update();
end;
end.

Most of this is pretty standard Pascal but Apollo has some important changes:
  • The native numeric types in Apollo are byte, sbyte, short, and ushort, following C# style naming conventions. These are the only numeric types with direct compiler support, 32-bit types are emulated with higher level types.
  • In standard Pascal, you assign to a special compiler-generated local when you want to return a value, and use "exit" when you want to early out of a function. Apollo has a built in "return" which is syntactic sugar on top of assigning a return value and then exiting.
  • Not exactly foreign to some newer dialects of Pascal, but Apollo also has direct support for defining operator overloading on your record types. This is, in fact, how 32-bit types will work - they will actually be record types defined internally with arithmetic operator overloads that implement the necessary carry code.
  • Apollo has C-style pre increment and post increment operators, which standard Pascal does not have.
  • Normally Pascal variants depend on the order in which things are defined (you can't refer to something like a function or type before it is defined) and rely on forward declarations to deal with this restriction. Apollo technically supports forward declaration syntax for compatibility, but does not rely on it and you can refer to types and functions no matter what order they're defined in, which should be a lot more convenient.

EDIT
  • Normally, you can define an array in Pascal using something like "array [ 0 .. 9 ] of integer" which specifies the minimum and maximum indices of the array, but Apollo will also let you specify "array [10] of integer" which automatically translates to the aforementioned example (0-based indexing with this syntax, so minimum index is 0 and maximum is 9). You can use either one as preferred.
« Last Edit: September 12, 2019, 02:30:18 PM by KillaMaaki » Logged
ProgramGamer
Administrator
Level 10
******


The programmer of games


View Profile
« Reply #16 on: September 12, 2019, 02:42:13 PM »

Nice to see this is progressing steadily!

I've tried making scripting languages a few times but never really got to a point where I had something that was usable. maybe I just have to go through the baby steps of making an assembler first and then I'll be able to move on to higher level stuff. In any case, Apollo looks nice!
Logged

KillaMaaki
Level 0
**



View Profile
« Reply #17 on: September 13, 2019, 11:58:21 PM »

Something kinda funny we discovered today: we know we'll need a heap manager of some kind for Apollo so I set about writing my own naive heap management algorithm as replacements for the usual getmem/freemem functions.
Turns out my heap management code is a good unit test for Apollo itself, helped discover and fix a few edge cases with the parser & compiler.

FWIW this is the heap implementation: https://pastebin.com/XSergNUy

Also made significant progress on the video codec I'm currently referring to as Cronch Smiley
Converted it over to a commandline app using libavcodec and made some significant changes to it, not least of which are that now the 32 most used 4x4 blocks on a given frame are now Huffman coded into a tightly packed bitstream which adds a little extra savings, and it also now serializes into an actual file container instead of just round-tripping through FFMPEG. I also improved the color quantizing code.
The files are still pretty hefty, for example this example of me playing the Sonic 06 intro even without audio sits at a 32MB file. It's pretty big, but still a decent savings over uncompressed (which would be nearly 200MB for the same video).
So here's a decoder for Cronch video files I wrote in Unity playing back the Sonic 06 opening:
https://streamable.com/yef0e

EDIT: though I'm also considering adding an "interlaced mode" which would essentially serialize a series of 320x100 frames, decoding alternating scanlines on each frame, to effectively halve the amount of data to pack at the cost of interlacing artifacts.
Logged
KillaMaaki
Level 0
**



View Profile
« Reply #18 on: September 14, 2019, 01:25:11 PM »

Hm, ended up trying out a software-only interlaced mode and realized the only way I can do an interlaced mode is if the Athena directly supports it - the problem being if I paint some scanlines with one palette, then I swap the palette and paint some other scanlines, those first set of scanlines are then going to be switched over to a different palette and flash all sorts of weird funky colors.

So...

Hm. Debating on adding interlaced modes to support this, but a little hesitant to add extra features to the VM itself just to support some extra video playback modes.
Logged
KillaMaaki
Level 0
**



View Profile
« Reply #19 on: September 17, 2019, 01:58:12 PM »

Started writing the music tracker today, "Athena Compose" for lack of a more imaginative title lol.
But I started thinking about things, particularly the sound setup of the Athena.
The way you can imagine it, there are effectively four "chips". Two of these are off-the-shelf YM2612s. One is a fantasy 4 channel ADPCM playback. And the last one is a fantasy delay/echo chip.
But I started giving it some thought, and now I'm seriously considering tearing out the 4 channel fantasy chip and replacing it with an emulated 8-channel Ricoh RF5C68 chip (thought about writing a clone-ish, but I do actually really like the idea of just throwing in an actual chip emulation lol).

This would result in a few important changes:
- Samples would be raw uncompressed 8 bit PCM instead of the custom SNES-inspired ADPCM scheme I came up with.
- You could play back 8 simultaneous samples instead of just 4. This could give you more room for stuff like sound effects.
- Samples could be looped! This would allow you to, say, thicken up your FM instruments with some sampled instruments, like strings, choir, etc (things that are historically harder to do in pure FM synthesis)

Thoughts & opinions?
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic