diff --git a/compiler/res/prog8lib/math.p8 b/compiler/res/prog8lib/math.p8 index fdc461155..67c1a02ea 100644 --- a/compiler/res/prog8lib/math.p8 +++ b/compiler/res/prog8lib/math.p8 @@ -645,4 +645,12 @@ log2_tab cx16.r15 ^= $ffff cx16.r14 ^= $ffff } + + + sub lerp(ubyte v0, ubyte v1, ubyte t) -> ubyte { + ; Linear interpolation (LERP) + ; returns an interpolation between two inputs (v0, v1) for a parameter t in the interval [0, 255] + ; guarantees v = v1 when t = 255 + return v0 + msb(t as uword * (v1 - v0) + 255) + } } diff --git a/compiler/res/prog8lib/shared_floats_functions.p8 b/compiler/res/prog8lib/shared_floats_functions.p8 index 1bbb4e816..a32f2a1f8 100644 --- a/compiler/res/prog8lib/shared_floats_functions.p8 +++ b/compiler/res/prog8lib/shared_floats_functions.p8 @@ -256,4 +256,18 @@ inline asmsub pop() -> float @FAC1 { }} } +sub lerp(float v0, float v1, float t) -> float { + ; Linear interpolation (LERP) + ; Precise method, which guarantees v = v1 when t = 1. + ; returns an interpolation between two inputs (v0, v1) for a parameter t in the closed unit interval [0, 1] + return (1 - t) * v0 + t * v1 +} + +sub lerp_fast(float v0, float v1, float t) -> float { + ; Linear interpolation (LERP) + ; Imprecise (but slightly faster) method, which does not guarantee v = v1 when t = 1 + ; returns an interpolation between two inputs (v0, v1) for a parameter t in the closed unit interval [0, 1] + return v0 + t * (v1 - v0) +} + } diff --git a/compiler/res/prog8lib/virtual/floats.p8 b/compiler/res/prog8lib/virtual/floats.p8 index 0c8346241..0a51a974a 100644 --- a/compiler/res/prog8lib/virtual/floats.p8 +++ b/compiler/res/prog8lib/virtual/floats.p8 @@ -203,4 +203,18 @@ sub pop() -> float { }} } +sub lerp(float v0, float v1, float t) -> float { + ; Linear interpolation (LERP) + ; Precise method, which guarantees v = v1 when t = 1. + ; returns an interpolation between two inputs (v0, v1) for a parameter t in the closed unit interval [0, 1] + return (1 - t) * v0 + t * v1 +} + +sub lerp_fast(float v0, float v1, float t) -> float { + ; Linear interpolation (LERP) + ; Imprecise (but slightly faster) method, which does not guarantee v = v1 when t = 1 + ; returns an interpolation between two inputs (v0, v1) for a parameter t in the closed unit interval [0, 1] + return v0 + t * (v1 - v0) +} + } diff --git a/compiler/res/prog8lib/virtual/math.p8 b/compiler/res/prog8lib/virtual/math.p8 index e3bb11168..a9e12d57b 100644 --- a/compiler/res/prog8lib/virtual/math.p8 +++ b/compiler/res/prog8lib/virtual/math.p8 @@ -398,4 +398,12 @@ math { cx16.r15 ^= $ffff cx16.r14 ^= $ffff } + + + sub lerp(ubyte v0, ubyte v1, ubyte t) -> ubyte { + ; Linear interpolation (LERP) + ; returns an interpolation between two inputs (v0, v1) for a parameter t in the interval [0, 255] + ; guarantees v = v1 when t = 255 + return v0 + msb(t as uword * (v1 - v0) + 255) + } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 4e5414493..a7bc089de 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -5,6 +5,9 @@ replace zsound example by a zsmkit example contribute a short how-to to the zsmkit repo for building a suitable blob write a howto for integrating third party library code like zsmkit and vtui +can we make it so that math is not always included on 6502 target? (what does it need, move that to another library perhaps?) + + Improve register load order in subroutine call args assignments: in certain situations, the "wrong" order of evaluation of function call arguments is done which results in overwriting registers that already got their value, which requires a lot of stack juggling (especially on plain 6502 cpu!) diff --git a/examples/test.p8 b/examples/test.p8 index c64a2067f..c858b56e6 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,60 +1,20 @@ +%import math %import textio -%import diskio %option no_sysinit %zeropage basicsafe main { sub start() { - txt.print_ub(exists_byte("test.prg")) - txt.spc() - txt.print_ub(exists_byte("doesntexist.xxx")) - txt.nl() - txt.print_bool(exists_bool("test.prg")) - txt.spc() - txt.print_bool(exists_bool("doesntexist.xxx")) - txt.nl() - txt.print_bool(exists1("test.prg")) - txt.spc() - txt.print_bool(exists1("doesntexist.xxx")) - txt.nl() - txt.print_bool(exists2("test.prg")) - txt.spc() - txt.print_bool(exists2("doesntexist.xxx")) - txt.nl() - } + ubyte v1 = 100 + ubyte v2 = 200 - sub exists1(str filename) -> bool { - ; -- returns true if the given file exists on the disk, otherwise false - if exists_byte(filename)!=0 { - return true + for cx16.r0L in 0 to 255 step 16 { + txt.print_ub(math.lerp(v1, v2, cx16.r0L)) + txt.nl() } - return false + txt.print_ub(math.lerp(v1, v2, 255)) + txt.nl() } - sub exists2(str filename) -> bool { - ; -- returns true if the given file exists on the disk, otherwise false - if exists_bool(filename) { - return true - } - return false - } - - - sub exists_bool(str name) -> bool { - %ir {{ - loadm.w r65535,main.exists_bool.name - syscall 52 (r65535.w): r0.b - returnr.b r0 - }} - } - - sub exists_byte(str name) -> ubyte { - %ir {{ - loadm.w r65535,main.exists_byte.name - syscall 52 (r65535.w): r0.b - returnr.b r0 - }} - } } -