Browse Source

New blog. poggers.

master
h34ting4ppliance 11 months ago
parent
commit
e1779b85db
4 changed files with 315 additions and 0 deletions
  1. +71
    -0
      500.html
  2. +1
    -0
      src/b.md
  3. +241
    -0
      src/b/vicera_part1.md
  4. +2
    -0
      src/index.md

+ 71
- 0
500.html View File

@ -0,0 +1,71 @@
<html>
<head>
<title>Matthilde's Home</title>
<meta charset="utf-8" />
<meta name="description" content="Epic Site." />
<style>
body
{
margin-top: 10%;
margin-bottom: 10%;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
max-width: 800px;
text-align: center;
}
div#content
{
max-width: 700px;
margin-top: 30px;
margin-left: auto;
margin-right: auto;
padding-left: 5%;
padding-right: 5%;
left: 0;
right: 0;
text-align: left;
}
img
{
max-width: 100%;
height: auto;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
}
pre
{
margin: 8px;
padding: 8px;
background-color: lightgrey;
}
</style>
</head>
<body>
<h1>Matthilde's Home Page</h1>
<h3 style="font-weight: normal"><i>Oopsie Doopsie &gt;~&lt;</i></h3>
<hr>
<h3 style="font-weight: normal">[ Ouchie ]</p></h4>
<div id="content">
<h1>502 Bad Gateway</h1>
<p>Looks like my website is offline. If you see this, that probably means I am experiencing issues with my webserver. <a href="https://tilde.team/~microwave">My tilde</a> however, is probably still available.</p>
</div>
<hr>
<span style="font-family: monospace; font-weight: bold">-- EOF --</span>
</body>
</html>

+ 1
- 0
src/b.md View File

@ -2,5 +2,6 @@
Here is my awesome blog where I will post awesome posts. Anyways, pick a post
[-=- New Project: the VICERA Fantasy Computer (Part I) -=-](b/vicera_part1.html)
[-=- Switching from CloudFlare to a VPS -=-](/b/bye_cloudflare.html)
[-=- Roguelike in 350 lines of C -=-](/b/c_roguelike.html)

+ 241
- 0
src/b/vicera_part1.md View File

@ -0,0 +1,241 @@
# The VICERA: Part I
## Introduction
This project is probably the biggest I have ever done so far in my life. Which
is not even finished yet. I have already worked on it for now a month and I
think it deserves it's very own series of blog.
VICERA is a 8-bit fantasy console heavily inspired by many aspects of the
Gameboy architecture (mostly in the CPU). All the core components are written
in standard C. Only `main.c` and the SDL front-end aren't. That means it is
pretty much portable and writing your own front-end should not be a difficult
task.
To people who doesn't know what fantasy consoles are: They are most likely game
engines running on a virtual machine specifically designed for it simulating
the harsh hardware limitations of retro consoles or computers.
So far, the console, still in development, has arrived at a point of stability
and it can now be used. At the time of writing, no games has been created on it
yet. You can build it yourself from source by cloning [this repository](https://github.com/vicera/vicera).
This blog will be divided into multiple parts.
**NOTE**: This blog is really long.
## 0. The console
So the projects starts here. Nothing, just my whiteboard to start designing the
whole project. I first started designing the whole thing in a "quick" way to
get an approximative idea of how the project is going to look like.
So I started thinking, and I thought about a simple console, easy to implement
which would be also easily portable with pretty harsh hardware limitations.
At this point I started looking up this [Gameboy Programming Manual](http://marc.rawer.de/Gameboy/Docs/GBCPUman.pdf)
and this is where I started having a more precise idea of the CPU.
## 1. The CPU
So that said, the CPU will be close to the Gameboy architecture, but with less
instructions, registers and flags so it is easy to implement (plus 2
instructions taken from the Intel x86 architecture).
To know about the CPU architecture, you can look up the [VICERA documentation](/vicera/p/cpu.html).
It documents everything about the CPU.
The implementation wasn't a difficult task but more of a boring, repetitive
task most of the time. I had to write a function for every instructions and then
write a huge switch-case block.
The CPU has 7 registers, a stack pointer, a program counter, 2 flags and needs
64 KiB of memory. So I have made a `struct` to carry all this information
through all the functions:
struct CPU {
// 64kb Memory bank.
BYTE memory[0x10000];
// Registers
BYTE registers[REGSIZE];
// Program Counter
WORD pc;
// Stack pointer
WORD sp;
// Flags
BYTE flags;
// Is it running?
BYTE running;
}
Oh I forgot to mention that I have defined `BYTE` and `WORD` to shorten the
definition of specific integers,
// Types definitions
typedef unsigned char BYTE;
typedef unsigned short int WORD;
Every instruction has it's own function. We will use the `xor` instruction as an
example for my blog:
// xor r
// XOR instruction with a register as an argument.
void xor_r(struct CPU* cpu, int reg_a)
{
// Takes the register from an intermediate function named get_register
BYTE *r = get_register(cpu, reg_a);
// Performs a XOR operation with the taken value
cpu->registers[REG_A] ^= *r;
}
// xor n
// Same thing but with a direct value.
void xor_n(struct CPU* cpu, BYTE byte_a)
{
cpu->registers[REG_A] ^= byte_a;
}
As mentionned in this block of code, I have used a few intermediate functions
to avoid repetition and makes development easier. Here two of those:
// BYTE, BYTE -> WORD
// converts two bytes into a word.
WORD btoword(BYTE byte_a, BYTE byte_b)
{
return (byte_a * 0x100) + byte_b;
}
// struct *CPU -> WORD
// returns a 16-bit value from the two following bytes
// in the RAM starting from (PC + 1)
WORD memword(struct CPU *cpu)
{
return btoword(cpu->memory[cpu->pc + 1],
cpu->memory[cpu->pc + 2]);
}
I have also made two debugging functions to dump memory or registers.
Both named respectively `dump_memory` and `dump_registers`.
There comes the really long O' big switch-case block. I have setted up a big
`enum` with all the instructions then bound every opcode into their matching
function.
Now I have finished implementing the CPU, what now? How can I program it?
To answer this question, I have wrote a little toy assembler (which can be
found in the GitHub repo, refer to the _External Links_ at the bottom of the
blog.) which has the very basic features of a typical assembler, such as
assembling bytecode (of course), labels and that's it. Yea this is it, just
bytecode and labels. But it was enough to play arround with the CPU and write
some basic programs. But having just a CPU is boring, we need more...
## The GPU
Of course, what would be a video game console without a display? The GPU was
pretty easy to implement. It took me only an hour or two to implement just the
GPU and half an hour to implement the SDL front-end.
The GPU will have a 256x256 which only 160x160 of the canvas can be displayed
by the console screen. It has 3 registers in the memory. One that increments
on screen refresh, and two to scroll arround the screen, letting the programmer
point where to display.
Like the CPU, the GPU has it's own struct so I can carry arround all the needed
data when calling functions,
// GPU struct
struct GPU
{
// The screen itself.
char screen[SCREEN_X][SCREEN_Y];
// Scrolling
struct GPU_Point scroll;
// Pointer to CPU struct
struct CPU *cpu;
}
The GPU works with tiles and sprites, that means that there is no direct
modification of the screen buffer from the CPU. The GPU don't even have any
direct communication with the CPU, it is independent. The usage of the CPU
struct is only to access the memory.
So the rest of implementation is inserting in the buffer the tiles and sprites
specified in the memory between 0x8000 and 0x9000 (VRAM, again, for all that
technical information, you can refer to the documentation in the _External Links_)
The SDL impl. was also really simple:
- Spawn a renderer and a window.
- Make a loop.
- Call `render_screen` from the GPU.
- Place pixels from the buffer from `SCROLLX`x`SCROLLY` to `(SCROLLX + 160) % 256`x`(SCROLLY + 160) % 256`
- Update screen
- Continue the loop until the CPU halts or the user exits the app.
## The SPU
There is not much information about it since I haven't really worked on it yet.
The actual design is that there are 3 channels, one for melody, one for bass, and
one for noise (cool for SFXs).
There is a small impl. that you can look up on the GitHub repo (`spu.c` and
`spu.h`) but no SDL front-end for now.
## Configuration
The configuration was not an easy task since I have never really parsed strings
in C. So I decided to make a configuration system that is convenient to use and
easy to implement. I thought about the INI files, so I did a simplified version
of INI. (basically INI without sections)
The implementation was easy like I expected it to be, just a few `strtok` calls
and an handler. You write a function that consumes two strings as arguments and
the parser will call this function everytime it parses a value. I got inspired
from [this simple INI Parser](https://github.com/benhoyt/inih).
Here is the default configuration for the VICERA:
# This is the default configuration
# Directional arrows -> Keyboard arrows
# A, B -> Z, X
# Start, Select -> Enter, Backspace
# Directional arrows
controller.left = 1073741903
controller.down = 1073741905
controller.right = 1073741904
controller.up = 1073741906
# Buttons
controller.a = 122
controller.b = 120
controller.start = 13
controller.select = 8
## Conclusion
I have learned a lot from this project that is not even finished. I have
learned more about how a CPU works, how these old handheld Nintendo classics
worked (I did lots of research while working on this project) and how to plan
and maintain a project properly.
I also got more confident writing programs in C by writing this fantasy console.
Right now I am improving the programming experience by optimizing a few things
in the CPU and by writing an assembler.
Once done, I will try and port a C compiler for the CPU.
See you later for the Part 2 if ever I write it!
## External Links
Here is a few links and websites I have visited while programming the VICERA.
[The Gameboy CPU Manual](http://marc.rawer.de/Gameboy/Docs/GBCPUman.pdf)
[(almost) Z80 Assembly programming for the Gameboy and Gameboy Color](https://www.chibiakumas.com/z80/Gameboy.php)
[VICERA official GitHub repository](https://github.com/vicera/vicera)
[VICERA official documentation](https://h3liu.ml/vicera/)
[SDL 2.0 Wiki](https://wiki.libsdl.org)
[INIH: A simple C INI parser](https://github.com/benhoyt/inih)

+ 2
- 0
src/index.md View File

@ -5,3 +5,5 @@ This is where you can get to know me and look at what I make. I will also post b
Also look at [my shitpost website](http://matthilde.is-dummy-thi.cc).
You should also check out [my best friend's site.](//solarr.h3liu.ml) (she makes art).

Loading…
Cancel
Save