Compare commits

...

2 Commits

Author SHA1 Message Date
Riyyi 07fde286c4 Add two more programming articles 2 months ago
Riyyi d76464d4f3 Finish utility library article 2 months ago
  1. 20
      content/articles/blaze-lisp.md
  2. 33
      content/articles/garbage.md
  3. 121
      content/articles/utility-library.md
  4. BIN
      public/img/garbage-preview.webm
  5. BIN
      public/img/garbage.png

20
content/articles/blaze-lisp.md

@ -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

33
content/articles/garbage.md

@ -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!
![garbage](/img/garbage.png "garbage")
Preview video of the boot sequence and intro of the Dr. Mario game.
::VideoLazy{:src="/img/garbage-preview.webm"}
::

121
content/articles/utility-library.md

@ -24,11 +24,128 @@ my projects and create one cohesive style.
## 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
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

BIN
public/img/garbage-preview.webm

Binary file not shown.

BIN
public/img/garbage.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Loading…
Cancel
Save