Skip to content

Instantly share code, notes, and snippets.

@Bananattack
Last active January 25, 2019 17:13
Show Gist options
  • Save Bananattack/4a8bf0e1e8710dd4dfcbd2d25beda1ac to your computer and use it in GitHub Desktop.
Save Bananattack/4a8bf0e1e8710dd4dfcbd2d25beda1ac to your computer and use it in GitHub Desktop.
// Linearly interpolate between two values using progress as weight between them.
//
// Arguments:
// b = start (0 .. 255)
// c = end (0 .. 255)
// e = progress (0 .. 64),
// 0 = 100% start, 0% end
// 32 = 50% start, 50% end
// 64 = 0% start; 100% end
//
// Dirty: a, h, l, d, e
inline func interpolate(start : u8 in b, end : u8 in h, progress : u8 in e) : u8 in a {
// if end < start, invert progress, swap (end, start).
// This is because the multiplication below is unsigned.
a = h;
if a < b {
e = a = 64 - e;
a = b;
b = h;
}
// result = ((end - start) * progress) / 64 + start
// temp = end - start.
h = a = a - b;
// temp *= progress
hl = h_times_e(h, e);
// temp /= 64.
// The max product is 255 * 64, or 00111111 11000000.
// To divide by 64, we would need to shift right by 6.
// We could instead just shift left by 2 to get the same pattern.
// (but with the result in h instead of l)
inline for in 1 .. 2 {
hl += hl;
}
// result = temp + start
return h + b;
}
// Multiplies h * e as two unsigned 8-bit integers and returns their 16-bit unsigned product in hl.
//
// Arguments:
// h = left-hand side
// e = right-hand side
//
// Result:
// hl = 16-bit unsigned product
//
// Dirty: h, l, d
//
// Adapted from: http://sgate.emt.bme.hu/patai/publications/z80guide/part4.html#mul8
inline func h_times_e(left : u8 in h, right : u8 in e) : u16 in hl {
l = d = 0;
inline for in 1 .. 8 {
hl += hl;
if carry {
hl += de;
}
}
return hl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment