^ see above
LOCATION DESCRIPTION | |
0x60818 camera x, left to right increasing |
"use strict"; | |
function matchWildcard(match, str) { | |
match = match.replace(/\*+/, '*'); | |
let sn = 0; | |
let m, s; | |
for (let mn = 0; mn < match.length; mn++, sn++) { | |
m = match[mn]; | |
s = str[sn]; | |
if (m === '*') { | |
// Bail out at end of match |
This article is an extract of months of reading about the PS1 GPU and its inner workings. Writing a PS1 emulator is no mean feat, so I would like to help anyone who finds that there is not enough info online about the GPU. I tried to keep it as simple as possible so that it can be understandable by anyone with some basic familiarity with how GPUs work. There might be mistakes in my thinking throughout so any corrections are welcome. Introduction
The PS1 GPU is arguably one of the most complex parts of the whole machine. It does not have any shader support, so it has specialized functions for drawing specific shapes (See NOCASH PSX docs for more info on those). The simple ones such as "Draw monochrome quad" are easy to understand and implement. But how about the textured ones? I always had no clue on how these work. I mean there is some information online about it, but I could not wrap my head around why there are things called "Textured Pages" and "CLUT tables" and how texels get fetched from VRAM. So I am w
type Stringable = string | { toString(): string } | |
export function toCSV <T extends Stringable>(items: T[][]): string { | |
return items.map(row => row.join(',')).join('\n') | |
} | |
export function markdownTable (items: Stringable[][]): string { | |
const asStrings = items.map( | |
row => row.map(item => typeof item === 'string' ? item : item.toString()) | |
) |
TRNAD53 is a cut scene file from the original Final Fantasy VII. A map, at the North Cave, where Sapphire Weapon sleeps, Sephiroth waits, and Aeris' theme plays. Discovered early on in leaks of cut content, TRNAD53 has garnered all kind of wild theories over the years. In this video I want to dig into the data and uncover the truth | |
I've been into the FF modding scene for a while, but Final Fantasy VII has always fascinated me. It's a weird game in some ways, halfway between the classic 16 bit era and the modern, cinematic era. It's development process was turbulent: originally FFVII was about a New York detective chasing an elusive man; but somehow this became cyberpunk mercenary Cloud Strife chasing Sephiroth through Midgar and beyond. | |
TRNAD53 also has had a turbulent history of rumours and fan theories. Was it an early version of where Cloud gives Sephiroth the Black Materia? Was it an early script where Aeris dies at the North Cave? It *was* known Aeris has post death dialog files, files that come before |
async function addAwait (a, b) { | |
const resolved = await a | |
return a + b | |
} | |
function addOptimised (a, b) { | |
if (a instanceof Promise) { | |
return a.then(resolved => resolved + b) | |
} else { | |
return a + b |
Micro-frontends are a strategy for splitting user interfaces up into separately deployable units. This gives teams great latitude to choose their own technologies and think in terms of self-contained programs. However, the "per page frontend" approach has disadvantages: pages cannot be shared by teams; sub-frontends are hard to modal-ise; and the user must download and execute duplicate JavaScript. Nano-frontends are an alternative that give teams similar freedoms but provide opt-in optimisations to improve user experience.
Write your frontends as libraries that take a) a DOM element to render in and b) a set of common dependencies to call (e.g. React). Then allow a scaffold app to render the entire thing and inject the dependencies. Libraries can be published by writing artefacts to S3 and then monitoring for changes using SNS/SQS.
I had some fun with TypeScript union distributions this weekend. This is a (kinda) hack around conditional types that lets you access the individual members of a union in a generic type.
A usecase for this might be when your function accepts items from a union of types, but you want all your function parameters to be consistent in which 'branch' of the union they specify.
Let's say you have a type representing some events (this is a contrived example but simple)
type Events =
| { kind: 'loading', data: void }
// Fun with distributions | |
// You probably know that TypeScript has union types | |
type StringsAndNumbers = string | number; | |
// You also probably know about 'discriminated unions' or 'tagged unions', | |
// representing different kinds of structs | |
type Eventing = |