Quote from: Cas on January 01, 2026, 10:11:03 PMNumber of spheres then?
at least one
Quote...A car model will exhibit the bug if and only if it has at least one sphere primitive...
Herr Otto Partz says you're all nothing but pipsqueaks!
This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
Show posts MenuQuote from: Cas on January 01, 2026, 10:11:03 PMNumber of spheres then?
Quote...A car model will exhibit the bug if and only if it has at least one sphere primitive...
QuoteThis project aims to implement all the functionality of the 1995 game Whiplash/Fatal Racing in a way that builds and runs on modern PC
Quote from: Cas on November 20, 2025, 11:13:40 PMI realise all this may not matter to many people. Some of us may be very picky with their food, but can sleep anywhere, while others can eat rubbish, but then need a comfy mattress. I like clean, logical, comprehensive code... I don't like using black boxes
QuoteI just find that SDL is in itself like a language and programming for it in C is a very different experience from just making a C program (or C++).

void vec_transform(const VECTOR* src, const MATRIX* mat, VECTOR* dst)
{
dst->x = ((int32_t)mat->m11 * src->x + (int32_t)mat->m12 * src->y + (int32_t)mat->m13 * src->z) >> SCALE_BITS;
dst->y = ((int32_t)mat->m21 * src->x + (int32_t)mat->m22 * src->y + (int32_t)mat->m23 * src->z) >> SCALE_BITS;
dst->z = ((int32_t)mat->m31 * src->x + (int32_t)mat->m32 * src->y + (int32_t)mat->m33 * src->z) >> SCALE_BITS;
}
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "stunts_math.hpp"
namespace math_h_test
{
#define SCALE_BITS 14
#define SCALE (1 << SCALE_BITS)
// 0x400 steps = 2Pi
#define ANGLE_TO_RAD(a) ((a) * (M_PI / 512.0))
#define RAD_TO_ANGLE(r) ((r) * (512.0 / M_PI))
#define TO_FIXED(x) ((int16_t)lround((x) * SCALE))
#define FROM_FIXED(x) ((double)(x) / SCALE)
int16_t int_sin_math(uint16_t angle)
{
return TO_FIXED(sin(ANGLE_TO_RAD(angle)));
}
int16_t int_cos_math(uint16_t angle)
{
return TO_FIXED(cos(ANGLE_TO_RAD(angle)));
}
int16_t int_atan2_math(int16_t x, int16_t y)
{
double ang = atan2((double)x, (double)y);
return (int16_t)lround(RAD_TO_ANGLE(ang));
}
int16_t int_hypot_math(int16_t x, int16_t y)
{
return TO_FIXED(hypot(FROM_FIXED(x), FROM_FIXED(y)));
}
int16_t int_hypot_3d_math(const VECTOR* v)
{
double dx = FROM_FIXED(v->x);
double dy = FROM_FIXED(v->y);
double dz = FROM_FIXED(v->z);
return TO_FIXED(sqrt(dx * dx + dy * dy + dz * dz));
}
void test_sin_cos(void)
{
printf("=== SIN/COS compare ===\n");
int max_diff_sin = 0, max_diff_cos = 0;
for (int a = -0x400; a <= 0x400; ++a) {
int16_t ref_sin = int_sin((uint16_t)a);
int16_t ref_cos = int_cos((uint16_t)a);
int16_t new_sin = int_sin_math((uint16_t)a);
int16_t new_cos = int_cos_math((uint16_t)a);
int diff_sin = abs(ref_sin - new_sin);
assert(diff_sin == 0);
int diff_cos = abs(ref_cos - new_cos);
assert(diff_cos == 0);
}
}
void test_atan2(void)
{
printf("=== ATAN2 Compare ===\n");
int max_diff = 0;
for (int y = -0x400; y <= 0x400; y += 64) {
for (int x = -0x400; x <= 0x400; x += 64) {
int16_t ref = int_atan2(x, y);
int16_t newv = int_atan2_math(x, y);
int diff = abs(ref - newv);
assert(diff <= 1);
}
}
}
void test_hypot(void)
{
printf("=== HYPOT Compare ===\n");
int max_diff = 0;
for (int y = -0x400; y <= 0x400; y += 64) {
for (int x = -0x400; x <= 0x400; x += 64) {
int16_t ref = int_hypot(x, y);
int16_t newv = int_hypot_math(x, y);
int diff = abs(ref - newv);
assert(diff <= 3);
if (diff > 1)
printf("hypot(%4d,%4d): ref=%5d new=%5d diff=%3d\n",
x, y, ref, newv, diff);
}
}
}
void test_hypot3d(void)
{
printf("=== HYPOT_3D Compare ===\n");
int max_diff = 0;
VECTOR v;
for (int z = -0x200; z <= 0x200; z += 64)
for (int y = -0x200; y <= 0x200; y += 64)
for (int x = -0x200; x <= 0x200; x += 64) {
v.x = x; v.y = y; v.z = z;
int16_t ref = int_hypot_3d(&v);
int16_t newv = int_hypot_3d_math(&v);
int diff = abs(ref - newv);
assert(diff <= 4);
if (diff > 1)
printf("hypot3d(%4d,%4d,%4d): ref=%5d new=%5d diff=%3d\n",
x, y, z, ref, newv, diff);
}
}
int main(void)
{
test_sin_cos();
test_atan2();
test_hypot();
test_hypot3d();
return 0;
}
}
int16_t sine_table2[SIN_STEPS + 1];
for (int i = 0; i <= SIN_STEPS; ++i) { // +1 for last 90 degree
double angle = (M_PI / 2.0) * i / SIN_STEPS; // 0 .. Pi/2
int16_t val = (int16_t)round(SIN_SCALE * sin(angle));
sine_table2[i] = val;
}#define ATAN_STEPS 0x100 // 256 steps
#define ATAN_SCALE 128.0 / (M_PI / 4.0) // map radians 0..Pi/4 --> 0..128
std::vector<uint8_t> atan_table2(ATAN_STEPS + 1);
for (int i = 0; i <= ATAN_STEPS; ++i) {
double ratio = (double)i / ATAN_STEPS; // x/y ratio, 0..1
double angle = atan(ratio); // radians, 0..Pi/4
uint8_t val = (uint8_t)round(angle * ATAN_SCALE);
atan_table2[i] = val;
}
int16_t int_atan2(int16_t x, int16_t y)
{
if (x == 0 && y == 0) return 0;
double ang = atan2((double)x, (double)y);
int16_t v = round(ang * 512.0 / M_PI);
if (v > 512) v = 512;
if (v < -511) v = -511;
return v;
}
int16_t int_sin(uint16_t angle) {
double radians = angle * M_PI / 512.0; // 10-Bit angle -> 0..2Pi
return (int16_t)(sin(radians) * SCALE + 0.5); // rounded
}
int16_t a;
__asm{
mov ax,0
push ax
push ax
mov ax,1234
call int_atan2_asm
add sp,4
mov a,ax
}
printf("a:%d\n", a);
return 0;
const int16_t min = -2;
const int16_t max = +2;
for(int i = min; i < max; ++i)
{
printf("[%d](x=0,y=0) a: %d, c: %d\n", i, int_atan2_asm(0, 0),int_atan2(0, 0));
}
for (int16_t x = min; x < max; ++x)
{
for (int16_t y = min; y < max; ++y)
{
int16_t a = int_atan2_asm(x, y);
int16_t c = int_atan2(x, y);
printf("x=%d, y=%d -> C=%d, ASM=%d\n", x, y, c, a);
}
}
[-2](x=0,y=0) a: 0, c: 0
[-1](x=0,y=0) a: 0, c: 0
[0](x=0,y=0) a: 0, c: 0
[1](x=0,y=0) a: 0, c: 0
x=-2, y=-2 -> C=-384, ASM=-384
x=-2, y=-1 -> C=-332, ASM=-332
x=-2, y=0 -> C=-256, ASM=-256
x=-2, y=1 -> C=-180, ASM=-180
x=-1, y=-2 -> C=-436, ASM=-436
x=-1, y=-1 -> C=-384, ASM=-384
x=-1, y=0 -> C=-256, ASM=-256
x=-1, y=1 -> C=-128, ASM=-128
x=0, y=-2 -> C=512, ASM=512
x=0, y=-1 -> C=512, ASM=512
x=0, y=0 -> C=0, ASM=28 <======= ???
x=0, y=1 -> C=0, ASM=0
x=1, y=-2 -> C=436, ASM=436
x=1, y=-1 -> C=384, ASM=384
x=1, y=0 -> C=256, ASM=256
x=1, y=1 -> C=128, ASM=128 int16_t c = int_atan2(x, y);
int16_t a = int_atan2_asm(x, y);Quote from: dstien on October 09, 2025, 07:44:31 PMQuotecompile with current Watcom V2 on Windows for DOS 16bit Model small exe using wcl+wasm
the test run was done on a real DOS 6.22 on VMWare Player (because dosbox failed to run the complete test without hanging)
Does this include the fix I pushed the other day? Strangely I can't reproduce it on my end with dosemu2 or DOSBox. Could you attach the exe file? I'm keen to have a look.
Quotepeak values crashes both implementations
mkfs.msdos -C myfloppy.img 1440
mcopy -i myfloppy.img test16.exe ::/
mdir -i myfloppy.img ::/
Quote from: Daniel3D on October 08, 2025, 09:44:09 AMStill, the fact remains that IDA is a pain in the but, especially for those that don't use it enough to warrant a paid licence. So whatever way you look at it, the Ghidra conversion makes a huge difference.
const int16_t min = -1000;
const int16_t max = +1000;
for (int16_t x = min; x < max; ++x)
{
for (int16_t y = min; y < max; ++y)
{
int16_t a = int_atan2_asm(x, y);
int16_t c = int_atan2(x, y);
if(c != a)
{
printf("x=%d, y=%d -> C=%d, ASM=%d %s\n",
x, y, c, a, (c == a) ? "OK" : "!!FEHLER!!");
}
}
}