Skip to content

Instantly share code, notes, and snippets.

Per Vognsen pervognsen

Block or report user

Report or block pervognsen

Hide content and notifications from this user.

Learn more about blocking users

Contact Support about this user’s behavior.

Learn more about reporting abuse

Report abuse
View GitHub Profile

Every emulator should have most of these input-related features but I haven't found anything with more than a small fraction:

Default and custom input profiles. Custom profiles can have game-specific input bindings. Bindings in custom profiles set to the 'default' value defer to the binding in the default profile; it's important that custom profiles aren't just initialized as a copy of the then-current default profile as this makes it impossible to later change some non-overridden binding in the default profile and have it automatically propagate to existing custom profiles.

The emulator should remember which custom profile was last used for which game, based on the ROM hash or filename. (The emulator should also automatically save any relevant per-game emulator settings, but I think you want that separate from input profiles. As an example of what not to do, if I set the CPU overclocking for Metal Slug in MAME to 200% to

View segarray.ion
typedef T = int;
var segs: T**;
var seg: T*;
var segcap = 1;
var segidx = 1;
func grow() {
seg = 0;
asetcap(seg, segcap);
apush(segs, seg);
View dispose.ion
struct File {
base: Disposable;
libc_file: libc.FILE*;
func file_dispose(data: void*) {
self: File* = data;
if (self.libc_file) {
View type_normalization.ion
func normalize_func(type: Type*): Type* {
key: char[];
num_params := alen(type.tfunc.params);
for (i := 0; i < num_params; i++) {
param := normalize(type.tfunc.params[i]);
acatn(key, (:char*)param, sizeof(param));
ret := normalize(type.tfunc.ret);
acatn(key, (:char*)ret, sizeof(ret));
normalized := agetn(normalized_funcs, key, alen(key));

We were having a discussion about compilation and linking performance on Twitter and I decided to do some measurements of the current Ion compiler, which is written in C. It's built via a main.c file that #includes everything else. The codebase contained 8,840 lines of code when I measured this. It only has a handful of external includes for the C standard library.

Here I'm doing a full rebuild with fast-debug flags, using the /Bt flag to give a timing breakdown between frontend, backend and link:

OptRef: Total time = 0.000s
OptIcf: Total time = 0.015s
Pass 1: Interval #1, time = 0.062s
Pass 2: Interval #2, time = 0.016s
View dispose.ion
typedef DisposeFunc = func(void*);
typedef DisposeMark = usize;
struct Disposable {
dispose: DisposeFunc;
mark: DisposeMark;
var disposables: Disposable*[];
View allocators.ion
func noop_free(data: void*, ptr: void*) {
struct TempAllocator {
base: Allocator;
start: void*;
next: void*;
end: void*;
View probe.ion
for (i := h) {
i &= index.mask;
if (slot := &index.slots[i]; slot.i == HASH_EMPTY || (slot.h == h && memcmp(a + slot.i*stride, x, size) == 0)) {
return slot;
View namemap2.ion
struct NameNode {
len: uint32;
buf: char[1];
struct NameMap {
nodes: {uint64, NameNode*}[];
collisions: NameNode*[];
View namemap.c
struct std_NameNode {
std_NameNode (*next);
uint32_t len;
char (buf[1]);
struct tuple4 {
ullong _0;
std_NameNode (*_1);
You can’t perform that action at this time.