Compare commits
2
Commits
d033523e88
...
07fde286c4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07fde286c4 | ||
|
|
d76464d4f3 |
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
title: "blaze lisp"
|
||||||
|
description: "An implementation of the MAL (Make a Lisp) project."
|
||||||
|
navigation: false
|
||||||
|
date: "2023-03-18"
|
||||||
|
img: "/img/.png"
|
||||||
|
tags:
|
||||||
|
- C++20
|
||||||
|
- CMake
|
||||||
|
- Software
|
||||||
|
---
|
||||||
|
|
||||||
|
<small>An implementation of the MAL (Make a Lisp) project.<br>
|
||||||
|
Repository at
|
||||||
|
[GitHub](https://github.com/riyyi/blaze){target="_blank"},
|
||||||
|
[GitLab](https://gitlab.com/riyyi/blaze){target="_blank"} or
|
||||||
|
[Gitea](https://git.riyyi.com/riyyi/blaze){target="_blank"}.
|
||||||
|
</small>
|
||||||
|
|
||||||
|
TODO
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
title: "GarbAGE (Garbage Accurate GameBoy Emulator)"
|
||||||
|
description: "GameBoy Emulator that is not that accurate."
|
||||||
|
navigation: false
|
||||||
|
date: "2022-08-17"
|
||||||
|
img: "/img/garbage.png"
|
||||||
|
tags:
|
||||||
|
- C++20
|
||||||
|
- CMake
|
||||||
|
- Software
|
||||||
|
---
|
||||||
|
|
||||||
|
<small>GarbAGE (Garbage Accurate GameBoy Emulator).<br>
|
||||||
|
Repository at
|
||||||
|
[GitHub](https://github.com/riyyi/garbage){target="_blank"},
|
||||||
|
[GitLab](https://gitlab.com/riyyi/garbage){target="_blank"} or
|
||||||
|
[Gitea](https://git.riyyi.com/riyyi/garbage){target="_blank"}.
|
||||||
|
</small>
|
||||||
|
|
||||||
|
This is an exploration into emulators by me and a friend of mine. The only thing
|
||||||
|
thats really implemented are the CPU opcodes. The cool thing however, is that
|
||||||
|
for the rendering portion of the application we are using my own
|
||||||
|
[game engine](/articles/inferno)! No other libraries were used.
|
||||||
|
|
||||||
|
The simplest game to test is Dr. Mario and even that one doesnt render
|
||||||
|
correctly, but we do get graphics that you can make out, pretty cool!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Preview video of the boot sequence and intro of the Dr. Mario game.
|
||||||
|
|
||||||
|
::VideoLazy{:src="/img/garbage-preview.webm"}
|
||||||
|
::
|
||||||
@@ -24,11 +24,128 @@ my projects and create one cohesive style.
|
|||||||
|
|
||||||
## Argument parsing
|
## Argument parsing
|
||||||
|
|
||||||
placeholder
|
This is a simple argument parsing feature, with the attempt of making it simpler
|
||||||
|
to use than getopt. All you have to do is specify the variables you want to use,
|
||||||
|
then add the options and arguments on the `ArgParser` object and finally call
|
||||||
|
the `parse` function.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ruc/argparser.h"
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[])
|
||||||
|
{
|
||||||
|
bool verbose = false;
|
||||||
|
std::vector<std::string> targets {};
|
||||||
|
|
||||||
|
ruc::ArgParser argParser;
|
||||||
|
argParser.addOption(verbose, 'v', "verbose", nullptr, nullptr);
|
||||||
|
argParser.addArgument(targets, "targets", nullptr, nullptr, ruc::ArgParser::Required::No);
|
||||||
|
argParser.parse(argc, argv);
|
||||||
|
|
||||||
|
// Do some work here..
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `nullptr`'s in the above example were going to be used for automatic help
|
||||||
|
string generation, but that isn't implemented yet.
|
||||||
|
|
||||||
## Formatting library
|
## Formatting library
|
||||||
|
|
||||||
placeholder
|
This is basically a partial copy of the `fmt` library, from before that became
|
||||||
|
part of the C++20 standard and I didn't want to use an additional dependency in
|
||||||
|
my projects, because that is less fun!
|
||||||
|
|
||||||
|
The part of `fmt` that is implement is the
|
||||||
|
"[mini-language](https://fmt.dev/11.1/syntax/#format-specification-mini-language)",
|
||||||
|
which is a very convenient API.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "ruc/format/format.h"
|
||||||
|
#include "ruc/format/print.h"
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[])
|
||||||
|
{
|
||||||
|
std::string fmt = format(
|
||||||
|
R"(
|
||||||
|
number {}
|
||||||
|
string {}
|
||||||
|
bool {}j
|
||||||
|
double {}
|
||||||
|
double {:.2} with 2 precision
|
||||||
|
)", 123, "this is a string", true, 456.789, 3.14159265359);
|
||||||
|
print("{}\n", fmt);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Which results the the output.
|
||||||
|
|
||||||
|
```
|
||||||
|
number 123
|
||||||
|
string this is a string
|
||||||
|
bool true
|
||||||
|
double 456.789000
|
||||||
|
double 3.14 with 2 precision
|
||||||
|
```
|
||||||
|
|
||||||
|
The implementation consists of 2 major parts, the parsing of the format string
|
||||||
|
and the `format` and `print` functions. The parsing part isn't that complex, so
|
||||||
|
wont be discussed here. The other secion is interesting, however.
|
||||||
|
|
||||||
|
The functions are implemented with variadic arguments using type erasure, this
|
||||||
|
improves both compile time and binary size significantly. What it also does, is
|
||||||
|
allow the library to work on types that are specified by the user and are
|
||||||
|
therefor not part of the library.
|
||||||
|
|
||||||
|
The formatter implements all the primitives and some of the STL types, it can be
|
||||||
|
extended by the user. The basic use-case is to specify to just the `format`
|
||||||
|
function, but the `parser` function can also be overwritten.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// In the header we are extending the existing formatter for vectors,
|
||||||
|
// so we take advantage of their nice formatting automatically
|
||||||
|
template<>
|
||||||
|
struct ruc::format::Formatter<glm::vec4> : Formatter<std::vector<float>> {
|
||||||
|
void format(Builder& builder, glm::vec4 value) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Then in the implementation, we implement the format functon
|
||||||
|
void ruc::format::Formatter<glm::vec4>::format(Builder& builder, glm::vec4 value) const
|
||||||
|
{
|
||||||
|
return Formatter<std::vector<float>>::format(builder, { value.x, value.y, value.z, value.w });
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Users can even extend formatters based on their own formats. In this example we
|
||||||
|
are extending the vector (`glm::vec4`) formatter, so we can also print matrices
|
||||||
|
(`glm::mat4`).
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<>
|
||||||
|
struct ruc::format::Formatter<glm::mat4> : Formatter<glm::vec4> {
|
||||||
|
void format(Builder& builder, glm::mat4 value) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ruc::format::Formatter<glm::mat4>::format(Builder& builder, glm::mat4 value) const
|
||||||
|
{
|
||||||
|
builder.putString("mat4 ");
|
||||||
|
Formatter<glm::vec4>::format(builder, value[0]);
|
||||||
|
builder.putString("\n ");
|
||||||
|
Formatter<glm::vec4>::format(builder, value[1]);
|
||||||
|
builder.putString("\n ");
|
||||||
|
Formatter<glm::vec4>::format(builder, value[2]);
|
||||||
|
builder.putString("\n ");
|
||||||
|
return Formatter<glm::vec4>::format(builder, value[3]);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## JSON parsing
|
## JSON parsing
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 140 KiB |
Reference in New Issue
Block a user