diff --git a/.gitignore b/.gitignore index 9a98fbea..30e5a509 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ obj/ out/ .vs/ dist/ -build/ +build*/ # Files generated during build, so they're ignored to keep them out of git diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c026cb0..3c92c9b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,8 +18,10 @@ endif() include(CMakeDependentOption) include(TargetChompSources) -find_package(AudioMan) -find_package(BRender REQUIRED) +if (CMAKE_SIZEOF_VOID_P EQUAL 4) + find_package(AudioMan) +endif() +# find_package(BRender REQUIRED) # Options option(BUILD_PACKAGES "Build packages for 3DMM" ON) @@ -44,12 +46,18 @@ endif() # Local Tooling add_compile_definitions( $<$:WIN> - $<$:IN_80386> $<$:DEBUG> ) -if (NOT CMAKE_SIZEOF_VOID_P EQUAL 4) - message(FATAL_ERROR "Cannot compile for 64-bit yet") +if (CMAKE_SIZEOF_VOID_P EQUAL 4) + add_compile_definitions( + $<$:IN_80386> + # IN_80386 implies LITTLE_ENDIAN + ) +else() + add_compile_definitions( + LITTLE_ENDIAN + ) endif() # NOTE: kcdc-386 and kcd2-386 prevent cross compiling at this time. @@ -262,20 +270,115 @@ target_link_libraries(kauai $<$:mpr>) add_library(brender) -target_sources(brender - PRIVATE - "${PROJECT_SOURCE_DIR}/bren/bwld.cpp" - "${PROJECT_SOURCE_DIR}/bren/stderr.c" - "${PROJECT_SOURCE_DIR}/bren/stdfile.c" - "${PROJECT_SOURCE_DIR}/bren/stdmem.c" - "${PROJECT_SOURCE_DIR}/bren/tmap.cpp" - "${PROJECT_SOURCE_DIR}/bren/zbmp.cpp" +target_sources(brender PRIVATE + "${PROJECT_SOURCE_DIR}/bren/bwld.cpp" + "${PROJECT_SOURCE_DIR}/bren/stderr.c" + "${PROJECT_SOURCE_DIR}/bren/stdfile.c" + "${PROJECT_SOURCE_DIR}/bren/stdmem.c" + "${PROJECT_SOURCE_DIR}/bren/tmap.cpp" + "${PROJECT_SOURCE_DIR}/bren/zbmp.cpp" + + "${PROJECT_SOURCE_DIR}/bren/FW/actsupt.c" + "${PROJECT_SOURCE_DIR}/bren/FW/angles.c" + "${PROJECT_SOURCE_DIR}/bren/FW/brlists.c" + "${PROJECT_SOURCE_DIR}/bren/FW/brqsort.c" + "${PROJECT_SOURCE_DIR}/bren/FW/bswap.c" + "${PROJECT_SOURCE_DIR}/bren/FW/custsupt.c" + "${PROJECT_SOURCE_DIR}/bren/FW/datafile.c" + "${PROJECT_SOURCE_DIR}/bren/FW/def_mdl.c" + "${PROJECT_SOURCE_DIR}/bren/FW/def_mat.c" + "${PROJECT_SOURCE_DIR}/bren/FW/diag.c" + "${PROJECT_SOURCE_DIR}/bren/FW/envmap.c" + "${PROJECT_SOURCE_DIR}/bren/FW/error.c" + "${PROJECT_SOURCE_DIR}/bren/FW/ffhooks.c" + "${PROJECT_SOURCE_DIR}/bren/FW/file.c" + "${PROJECT_SOURCE_DIR}/bren/FW/fileops.c" + "${PROJECT_SOURCE_DIR}/bren/FW/fixed.c" + "${PROJECT_SOURCE_DIR}/bren/FW/fontptrs.c" + "${PROJECT_SOURCE_DIR}/bren/FW/fwsetup.c" + "${PROJECT_SOURCE_DIR}/bren/FW/light8.c" + "${PROJECT_SOURCE_DIR}/bren/FW/light8o.c" + "${PROJECT_SOURCE_DIR}/bren/FW/light24.c" + "${PROJECT_SOURCE_DIR}/bren/FW/light24o.c" + "${PROJECT_SOURCE_DIR}/bren/FW/logprint.c" + "${PROJECT_SOURCE_DIR}/bren/FW/matrix23.c" + "${PROJECT_SOURCE_DIR}/bren/FW/matrix34.c" + "${PROJECT_SOURCE_DIR}/bren/FW/matrix4.c" + "${PROJECT_SOURCE_DIR}/bren/FW/mem.c" + "${PROJECT_SOURCE_DIR}/bren/FW/onscreen.c" + "${PROJECT_SOURCE_DIR}/bren/FW/pick.c" + "${PROJECT_SOURCE_DIR}/bren/FW/pixelmap.c" + "${PROJECT_SOURCE_DIR}/bren/FW/pmdsptch.c" + "${PROJECT_SOURCE_DIR}/bren/FW/pmgenops.c" + "${PROJECT_SOURCE_DIR}/bren/FW/pmmemops.c" + "${PROJECT_SOURCE_DIR}/bren/FW/pool.c" + "${PROJECT_SOURCE_DIR}/bren/FW/prelight.c" + "${PROJECT_SOURCE_DIR}/bren/FW/prepmatl.c" + "${PROJECT_SOURCE_DIR}/bren/FW/prepmesh.c" + "${PROJECT_SOURCE_DIR}/bren/FW/prepmap.c" + "${PROJECT_SOURCE_DIR}/bren/FW/preptab.c" + "${PROJECT_SOURCE_DIR}/bren/FW/quat.c" + "${PROJECT_SOURCE_DIR}/bren/FW/quantize.c" + "${PROJECT_SOURCE_DIR}/bren/FW/register.c" + "${PROJECT_SOURCE_DIR}/bren/FW/regsupt.c" + "${PROJECT_SOURCE_DIR}/bren/FW/resource.c" + "${PROJECT_SOURCE_DIR}/bren/FW/scalar.c" + "${PROJECT_SOURCE_DIR}/bren/FW/scale.c" + "${PROJECT_SOURCE_DIR}/bren/FW/scratch.c" + "${PROJECT_SOURCE_DIR}/bren/FW/scrstr.c" + "${PROJECT_SOURCE_DIR}/bren/FW/surface.c" + "${PROJECT_SOURCE_DIR}/bren/FW/transfrm.c" + "${PROJECT_SOURCE_DIR}/bren/FW/vector.c" + + "${PROJECT_SOURCE_DIR}/bren/FW/fixed_agnostic.c" + "${PROJECT_SOURCE_DIR}/bren/FW/blockops.c" + "${PROJECT_SOURCE_DIR}/bren/FW/font_f_3x5.c" + "${PROJECT_SOURCE_DIR}/bren/FW/font_p_4x6.c" + "${PROJECT_SOURCE_DIR}/bren/FW/font_p_7x9.c" + "${PROJECT_SOURCE_DIR}/bren/FW/memloops.c" + + "${PROJECT_SOURCE_DIR}/bren/ZB/awtmz.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/bbox.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/decalz.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/dither.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/frcp.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/l_piz.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/p_piz.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/perspz.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/zbclip.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/zbmatl.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/zbmesh.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/zbmeshe.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/zbmeshp.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/zbrendr.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/zbsetup.c" + + "${PROJECT_SOURCE_DIR}/bren/ZB/mesh_agnostic.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/safediv.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/t_piza.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/ti8_pizp.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/ti8_piz.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/tt15_piz.c" + "${PROJECT_SOURCE_DIR}/bren/ZB/tt24_piz.c" +) +target_include_directories(brender PUBLIC + "${PROJECT_SOURCE_DIR}/BREN/INC" + "${PROJECT_SOURCE_DIR}/bren/FW" +) +if (CMAKE_C_BYTE_ORDER MATCHES BIG_ENDIAN) + target_compile_definitions (brender PUBLIC "BR_ENDIAN_BIG=1") +else() + target_compile_definitions (brender PUBLIC "BR_ENDIAN_BIG=0") +endif() +if (CMAKE_C_BYTE_ORDER MATCHES LITTLE_ENDIAN) + target_compile_definitions (brender PUBLIC "BR_ENDIAN_LITTLE=1") +else() + target_compile_definitions (brender PUBLIC "BR_ENDIAN_LITTLE=0") +endif () +target_link_libraries(brender PUBLIC + kauai + #BRender::Libraries ) -target_include_directories(brender PUBLIC "${PROJECT_SOURCE_DIR}/BREN/INC") -target_link_libraries(brender - PUBLIC - kauai - BRender::Libraries) add_library(engine) target_sources(engine diff --git a/bren/FW/actsupt.c b/bren/FW/actsupt.c new file mode 100644 index 00000000..02d31ec2 --- /dev/null +++ b/bren/FW/actsupt.c @@ -0,0 +1,782 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: actsupt.c 1.9 1995/08/31 16:29:18 sam Exp $ + * $Locker: $ + * + * Actor support routines + */ +#include + +#include "fw.h" +#include "shortcut.h" +#include "brassert.h" +#include "datafile.h" + +static char rscid[] = "$Id: actsupt.c 1.9 1995/08/31 16:29:18 sam Exp $"; + +/* + * Invoke a callback for each one of an actors children + */ +br_uint_32 BR_PUBLIC_ENTRY BrActorEnum(br_actor *parent, br_actor_enum_cbfn *callback, void *arg) +{ + br_actor *a, *next; + br_uint_32 r; + + UASSERT(parent != NULL); + UASSERT(callback != NULL); + + a = parent->children; + + while (a) + { + next = a->next; + + if ((r = callback(a, arg))) + return r; + + a = next; + } + + return 0; +} + +/* + * Find all the named actors matching a pattern in the given hierachy + * + */ +br_uint_32 BR_PUBLIC_ENTRY BrActorSearchMany(br_actor *root, char *pattern, br_actor **actors, int max) +{ + br_actor *a; + char *sub; + int n, remaining = max; + + UASSERT(root != NULL); + UASSERT(actors != NULL); + + /* + * Take first component of path, and match it against all children + * of the root actor + */ + + while (*pattern == '/') + pattern++; + + for (sub = pattern; (*sub != '\0') && (*sub != '/'); sub++) + ; + + while (*sub == '/') + sub++; + + BR_FOR_SIMPLELIST(&root->children, a) + { + + /* + * Abort if no more space for results + */ + if (remaining <= 0) + break; + + if (NamePatternMatch(pattern, a->identifier)) + { + /* + * If there is more path + * recurse with remainder of path + * else + * add actor to accumulated list + */ + + if (*sub != '\0') + { + n = BrActorSearchMany(a, sub, actors, remaining); + actors += n; + remaining -= n; + } + else + { + *actors++ = a; + remaining--; + } + } + } + + return max - remaining; +} + +/* + * Find the first named actor matching a pattern in the given hierachy + */ +br_actor *BR_PUBLIC_ENTRY BrActorSearch(br_actor *root, char *pattern) +{ + br_actor *a; + + UASSERT(root != NULL); + + if (BrActorSearchMany(root, pattern, &a, 1) == 1) + return a; + else + return NULL; +} + +/* + * Recursive function to propgate depth number down a hierachy + */ +static void RenumberActor(br_actor *a, int d) +{ + br_actor *ac; + + a->depth = d; + + BR_FOR_SIMPLELIST(&a->children, ac) + RenumberActor(ac, d + 1); +} + +/* + * Add an actor to the children of the given parent + */ +br_actor *BR_PUBLIC_ENTRY BrActorAdd(br_actor *parent, br_actor *a) +{ + br_actor *ac; + + UASSERT(a != NULL); + UASSERT(parent != NULL); + UASSERT(a->prev == NULL); + + /* + * Link this actor into sibling list of parent + */ + BR_SIMPLEADDHEAD(&parent->children, a); + a->parent = parent; + + /* + * Update depth for added hierachy + */ + a->depth = parent->depth + 1; + + BR_FOR_SIMPLELIST(&a->children, ac) + RenumberActor(ac, a->depth + 1); + + return a; +} + +br_actor *BR_PUBLIC_ENTRY BrActorRemove(br_actor *a) +{ + br_actor *ac; + + UASSERT(a != NULL); + UASSERT(a->prev != NULL); + + BR_SIMPLEREMOVE(a); + + /* + * Renumber the removed hierachy + */ + a->depth = 0; + a->parent = NULL; + + BR_FOR_SIMPLELIST(&a->children, ac) + RenumberActor(ac, 1); + + return a; +} + +/* + * Move an actor in the heirachy, but preserve it's apparent world + * transform by manipulating the transform + */ +void BR_PUBLIC_ENTRY BrActorRelink(br_actor *parent, br_actor *a) +{ + br_matrix34 mat; + + UASSERT(parent != NULL); + UASSERT(a != NULL); + + /* + * Catch simple case + */ + if (a->parent == parent) + return; + + /* + * Find the transform we need + */ + BrActorToActorMatrix34(&mat, a, parent); + + /* + * Convert matrix into actors transform + */ + BrMatrix34ToTransform(&a->t, &mat); + + /* + * Re-attach into the hierachy + */ + BrActorAdd(parent, BrActorRemove(a)); +} + +/* + * Allocate a new actor structure and return a pointer to it + * + * Model actors are allocated from a pool associated with the renderer - + * this is a very common case and is worth the speedup + * + * All other actor types come from the normal heap - and include any + * type specific data bocks + * + */ +br_actor *BR_PUBLIC_ENTRY BrActorAllocate(br_uint_8 type, void *type_data) +{ + br_actor *a = NULL; + br_light *light; + br_camera *camera; + br_bounds *bounds; + br_vector4 *clip_plane; + + UASSERT(type < BR_ACTOR_MAX); + + a = BrResAllocate(fw.res, sizeof(*a), BR_MEMORY_ACTOR); + + /* + * Initialise common fields + */ + BrSimpleNewList((struct br_simple_list *)&a->children); + a->type = type; + a->depth = 0; + a->t.type = BR_TRANSFORM_MATRIX34; + BrMatrix34Identity(&a->t.t.mat); + + if (type_data) + { + + /* + * Fill in the type_data pointer + */ + a->type_data = type_data; + } + else + { + /* + * No type data - allocate a default + */ + switch (type) + { + + case BR_ACTOR_LIGHT: + /* + * Setup to be a directional light source + */ + light = BrResAllocate(a, sizeof(*light), BR_MEMORY_LIGHT); + a->type_data = light; + + light->type = BR_LIGHT_DIRECT; + light->colour = BR_COLOUR_RGB(255, 255, 255); + light->attenuation_c = BR_SCALAR(1.0); + light->cone_outer = BR_ANGLE_DEG(15.0); + light->cone_inner = BR_ANGLE_DEG(10.0); + break; + + case BR_ACTOR_CAMERA: + /* + * Perspective camera, 45 degree FOV + */ + camera = BrResAllocate(a, sizeof(*camera), BR_MEMORY_CAMERA); + a->type_data = camera; + + camera->type = BR_CAMERA_PERSPECTIVE; + camera->field_of_view = BR_ANGLE_DEG(45); + camera->hither_z = BR_SCALAR(1.0); + camera->yon_z = BR_SCALAR(10.0); + camera->aspect = BR_SCALAR(1.0); + break; + + case BR_ACTOR_BOUNDS: + case BR_ACTOR_BOUNDS_CORRECT: + /* + * Allocate a bounds structure + */ + bounds = BrResAllocate(a, sizeof(*bounds), BR_MEMORY_BOUNDS); + a->type_data = bounds; + break; + + case BR_ACTOR_CLIP_PLANE: + /* + * Allocate a 4-vector + */ + clip_plane = BrResAllocate(a, sizeof(*clip_plane), BR_MEMORY_BOUNDS); + a->type_data = clip_plane; + break; + } + } + + return a; +} + +/* + * Free an actor + */ +static void InternalActorFree(br_actor *a) +{ + /* + * Release any children + */ + while (BR_SIMPLEHEAD(&a->children)) + InternalActorFree(BR_SIMPLEREMOVE(a->children)); + + /* + * Release this actor + */ + BrResFree(a); +} + +void BR_PUBLIC_ENTRY BrActorFree(br_actor *a) +{ + UASSERT(a->prev == NULL); + + InternalActorFree(a); +} + +/* + * Accumulate the transform between an actor and the root + * + * XXX Could accumulate a flag to say that matrix is only rotation + * and translation - makes invertion cheaper + * + * Returns a flag to indicate if the actor did have world + * as an ancestor + */ +int BrActorToRoot(br_actor *a, br_actor *world, br_matrix34 *m) +{ + UASSERT(a != NULL); + UASSERT(world != NULL); + UASSERT(m != NULL); + + /* + * Catch stupid case + */ + if (a == world) + { + BrMatrix34Identity(m); + return 1; + } + + /* + * Start with actor's transform + */ + BrMatrix34Transform(m, &a->t); + a = a->parent; + + /* + * Accumulate all the transforms up to the root (ignoring any + * identity transforms) + */ + for (; a && a != world; a = a->parent) + if (a->t.type != BR_TRANSFORM_IDENTITY) + BrMatrix34PostTransform(m, &a->t); + + return (a == world); +} + +/* + * Work out a camera 4x4 matrix + * + * Return type of transform, one of BR_VTOS_* + */ +int BrCameraToScreenMatrix4(br_matrix4 *mat, br_actor *camera) +{ + br_camera *camera_type; + br_matrix34 mat34; + + UASSERT(mat != NULL); + UASSERT(camera != NULL); + UASSERT(camera->type == BR_ACTOR_CAMERA); + UASSERT(camera->type_data != NULL); + + camera_type = camera->type_data; + + UASSERT(camera_type->hither_z > S0); + UASSERT(camera_type->hither_z < camera_type->yon_z); + + switch (camera_type->type) + { + + case BR_CAMERA_PERSPECTIVE_FOV: + + BrMatrix4Perspective(mat, camera_type->field_of_view, camera_type->aspect, -camera_type->hither_z, + -camera_type->yon_z); + + return BR_VTOS_PERSPECTIVE; + + case BR_CAMERA_PERSPECTIVE_WHD: + + return BR_VTOS_PERSPECTIVE; + + case BR_CAMERA_PARALLEL: + + if (camera_type->width == BR_SCALAR(0.0)) + BR_ERROR0("Parallel camera has zero width"); + + if (camera_type->height == BR_SCALAR(0.0)) + BR_ERROR0("Parallel camera has zero height"); + + if (camera_type->yon_z <= camera_type->hither_z) + BR_ERROR0("Parallel camera has invalid yon and hither"); + + BrMatrix34Scale(&mat34, BR_RCP(camera_type->width), BR_RCP(camera_type->height), + BR_RCP(camera_type->yon_z - camera_type->hither_z)); + BrMatrix34PreTranslate(&mat34, S0, S0, camera_type->hither_z); + + BrMatrix4Copy34(mat, &mat34); + return BR_VTOS_PARALLEL; + } + + return 0; +} + +/* + * Private routine that gets the COP in model space + */ +void BrVector3EyeInModel(br_vector3 *eye_m) +{ + switch (fw.vtos_type) + { + case BR_VTOS_PARALLEL: + BrVector3CopyMat34Row(&fw.eye_m, &fw.view_to_model, 2); + break; + + case BR_VTOS_PERSPECTIVE: + BrVector3CopyMat34Row(&fw.eye_m, &fw.view_to_model, 3); + break; +#if 0 + case BR_VTOS_4X4: { + br_matrix4 screen_to_model; + br_vector4 e; + + BrMatrix4Inverse(&screen_to_model, &model_to_screen); + + eye_m->v[X] = BR_DIV(screen_to_model.m[Z][X],screen_to_model.m[Z][W]); + eye_m->v[Y] = BR_DIV(screen_to_model.m[Z][Y],screen_to_model.m[Z][W]); + eye_m->v[Z] = BR_DIV(screen_to_model.m[Z][Z],screen_to_model.m[Z][W]); + + } + break; +#endif + } +} + +/* + * Accumulate the transform between one actor an another + * + * Returns a transform type that matches the combined result according + * to the combination rules in transfrm.c + * + */ +br_uint_8 BR_PUBLIC_ENTRY BrActorToActorMatrix34(br_matrix34 *m, br_actor *a, br_actor *b) +{ + int d, ad, bd; + br_matrix34 mata, matb, matc; + br_uint_8 at, bt; + + /* + * Spot trivial cases + */ + /* + * Same actor + */ + if (a == b) + { + BrMatrix34Identity(m); + return BR_TRANSFORM_IDENTITY; + } + + /* + * A is child of B + */ + if (a->parent == b) + { + BrMatrix34Transform(m, &a->t); + return a->t.type; + } + + /* + * B is child of A + */ + if (b->parent == a) + { + BrMatrix34Transform(&matb, &b->t); + + if (IS_LP(b->t.type)) + BrMatrix34LPInverse(m, &matb); + else + BrMatrix34Inverse(m, &matb); + + return b->t.type; + } + + /* + * Starting at the lowest actor, move up, accumulating transforms + * until we get to a common ancestor + */ + + at = BR_TRANSFORM_IDENTITY; + BrMatrix34Identity(&mata); + + bt = BR_TRANSFORM_IDENTITY; + BrMatrix34Identity(&matb); + + while (a && b && a != b) + { + + if (a->depth > b->depth) + { + + if (a->t.type != BR_TRANSFORM_IDENTITY) + { + BrMatrix34PostTransform(&mata, &a->t); + at = COMBINE_TRANSFORMS(at, a->t.type); + } + a = a->parent; + } + else if (b->depth > a->depth) + { + + if (b->t.type != BR_TRANSFORM_IDENTITY) + { + BrMatrix34PostTransform(&matb, &b->t); + bt = COMBINE_TRANSFORMS(bt, b->t.type); + } + b = b->parent; + } + else + { + + if (a->t.type != BR_TRANSFORM_IDENTITY) + { + BrMatrix34PostTransform(&mata, &a->t); + at = COMBINE_TRANSFORMS(at, a->t.type); + } + if (b->t.type != BR_TRANSFORM_IDENTITY) + { + BrMatrix34PostTransform(&matb, &b->t); + bt = COMBINE_TRANSFORMS(bt, b->t.type); + } + b = b->parent; + a = a->parent; + } + } + + /* + * We now have the tranforms from the actors up to a common parent + * compose A with inverse(B) to get A->B + */ + if (bt == BR_TRANSFORM_IDENTITY) + { + BrMatrix34Copy(m, &mata); + return at; + } + + if (at == BR_TRANSFORM_IDENTITY) + { + if (IS_LP(bt)) + { + BrMatrix34LPInverse(m, &matb); + } + else + BrMatrix34Inverse(m, &matb); + + return bt; + } + + if (IS_LP(bt)) + { + BrMatrix34LPInverse(&matc, &matb); + } + else + BrMatrix34Inverse(&matc, &matb); + + BrMatrix34Mul(m, &mata, &matc); + + return COMBINE_TRANSFORMS(at, bt); +} + +/* + * Accumulate the transform between an actor and the screen + * + */ +void BR_PUBLIC_ENTRY BrActorToScreenMatrix4(br_matrix4 *m, br_actor *a, br_actor *camera) +{ + br_matrix34 a2c; + + UASSERT(m != NULL); + UASSERT(a != NULL); + UASSERT(camera != NULL); + + /* + * Build camera to screen + */ + BrCameraToScreenMatrix4(m, camera); + + /* + * Only do more work if the actor is not the camera itself + */ + if (a != camera) + BrMatrix4Pre34(m, &a2c); +} +/* + * Transform a bounding box into another bounding box + * + * based on "Transforming Axis-Aligned Bounding Boxes" by James Avro - + * Gems I, page 548 + */ +static void BrMatrix34ApplyBounds(br_bounds *d, br_bounds *s, br_matrix34 *m) +{ + int i, j; + br_scalar a, b; + + /* + * Start with translation part + */ + d->min.v[0] = d->max.v[0] = m->m[3][0]; + d->min.v[1] = d->max.v[1] = m->m[3][1]; + d->min.v[2] = d->max.v[2] = m->m[3][2]; + + /* + * Add in extreme values obtained by computing the products + * of the min and maxes with the elements of the i'th row + * of the matrix + */ + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + a = BR_MUL(m->m[j][i], s->min.v[j]); + b = BR_MUL(m->m[j][i], s->max.v[j]); + if (a < b) + { + d->min.v[i] += a; + d->max.v[i] += b; + } + else + { + d->min.v[i] += b; + d->max.v[i] += a; + } + } + } +} + +/* + * Find the bounding box of an actor and all it's children + * + * + */ +static void ActorToBounds(br_bounds *dest, br_actor *ap, br_model *model) +{ + br_actor *a; + br_bounds new; + br_matrix34 m2v; + int i; + + /* + * Propogate default model + */ + if (ap->model != NULL) + model = ap->model; + + /* + * Prepend this transform + */ + m2v = fw.model_to_view; + BrMatrix34PreTransform(&fw.model_to_view, &ap->t); + + /* + * If actor has bounds, transform and compare + */ + if (ap->type == BR_ACTOR_MODEL) + { + BrMatrix34ApplyBounds(&new, &model->bounds, &fw.model_to_view); + + for (i = 0; i < 3; i++) + { + if (new.min.v[i] < dest->min.v[i]) + dest->min.v[i] = new.min.v[i]; + + if (new.max.v[i] > dest->max.v[i]) + dest->max.v[i] = new.max.v[i]; + } + } + + /* + * Recurse into children + */ + BR_FOR_SIMPLELIST(&ap->children, a) + ActorToBounds(dest, a, model); + + fw.model_to_view = m2v; +} + +br_bounds *BR_PUBLIC_ENTRY BrActorToBounds(br_bounds *b, br_actor *ap) +{ + br_matrix34 m2v = fw.model_to_view; + br_model *model; + br_actor *a; + + if (ap->model == NULL) + model = fw.default_model; + else + model = ap->model; + + BrMatrix34Identity(&fw.model_to_view); + + /* + * If actor has bounds, transform and compare + */ + if (ap->type == BR_ACTOR_MODEL) + { + *b = model->bounds; + } + else + { + /* + * Start with empty bounds + */ + b->min.v[0] = b->min.v[1] = b->min.v[2] = BR_SCALAR_MAX; + b->max.v[0] = b->max.v[1] = b->max.v[2] = BR_SCALAR_MIN; + } + + /* + * Recurse into children + */ + BR_FOR_SIMPLELIST(&ap->children, a) + ActorToBounds(b, a, model); + + fw.model_to_view = m2v; + return b; +} + +/* + * Find the transform that maps a 2 unit cube centred on origin to the given bounding box + */ +br_matrix34 *BR_PUBLIC_ENTRY BrBoundsToMatrix34(br_matrix34 *mat, br_bounds *bounds) +{ + int i; + br_vector3 tr, sc; + + /* + * Find the translation + */ + for (i = 0; i < 3; i++) + tr.v[i] = (BR_CONST_DIV(bounds->max.v[i], 2) + BR_CONST_DIV(bounds->min.v[i], 2)); + + /* + * Find the scale + */ + for (i = 0; i < 3; i++) + if (bounds->max.v[i] != bounds->min.v[i]) + sc.v[i] = BR_CONST_DIV(bounds->max.v[i], 2) - BR_CONST_DIV(bounds->min.v[i], 2); + else + sc.v[i] = BR_SCALAR(1.0); + + BrMatrix34Scale(mat, sc.v[0], sc.v[1], sc.v[2]); + BrMatrix34PostTranslate(mat, tr.v[0], tr.v[1], tr.v[2]); + + return mat; +} diff --git a/bren/FW/angles.c b/bren/FW/angles.c new file mode 100644 index 00000000..1e7f5841 --- /dev/null +++ b/bren/FW/angles.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: angles.c 1.12 1995/02/22 21:41:21 sam Exp $ + * $Locker: $ + * + * Euler angle manipulation - loosely based on - + * "Euler Angle Convertion" Ken Shoemake, Graphics Gems IV pp. 222 + * + */ +#include "fw.h" +#include "brassert.h" +#include "shortcut.h" + +static char rscid[] = "$Id: angles.c 1.12 1995/02/22 21:41:21 sam Exp $"; + +/* + * Table of axes for each order + */ +static struct order_info +{ + br_uint_8 a0; + br_uint_8 a1; + br_uint_8 a2; + br_uint_8 _pad[1]; +} OrderAxes[] = { + {0, 1, 2}, {1, 2, 0}, {2, 0, 1}, {0}, {0, 2, 1}, {1, 0, 2}, {2, 1, 0}, {0}, {0, 1, 2}, {1, 2, 0}, {2, 0, 1}, {0}, + {0, 2, 1}, {1, 0, 2}, {2, 1, 0}, {0}, {0, 1, 2}, {1, 2, 0}, {2, 0, 1}, {0}, {0, 2, 1}, {1, 0, 2}, {2, 1, 0}, {0}, + {0, 1, 2}, {1, 2, 0}, {2, 0, 1}, {0}, {0, 2, 1}, {1, 0, 2}, {2, 1, 0}, {0}, +}; + +br_matrix34 *BR_PUBLIC_ENTRY BrEulerToMatrix34(br_matrix34 *mat, br_euler *euler) +{ + br_uint_8 o = eO; + br_angle ti, tj, th; + br_scalar ci, cj, ch, si, sj, sh, cc, cs, sc, ss; + int a0, a1, a2; + + UASSERT(mat != NULL); + UASSERT(euler != NULL); + UASSERT(euler->order < BR_ASIZE(OrderAxes)); + + if (o & BR_EULER_FRAME) + ti = eZ, tj = eY, th = eX; + else + ti = eX, tj = eY, th = eZ; + + if (o & BR_EULER_PARITY) + ti = -ti, tj = -tj, th = -th; + + ci = BR_COS(ti); + cj = BR_COS(tj); + ch = BR_COS(th); + si = BR_SIN(ti); + sj = BR_SIN(tj); + sh = BR_SIN(th); + cc = BR_MUL(ci, ch); + cs = BR_MUL(ci, sh); + sc = BR_MUL(si, ch); + ss = BR_MUL(si, sh); + + a0 = OrderAxes[o].a0; + a1 = OrderAxes[o].a1; + a2 = OrderAxes[o].a2; + + if (o & BR_EULER_REPEAT) + { + M(a0, a0) = cj; + M(a1, a0) = BR_MUL(sj, si); + M(a2, a0) = BR_MUL(sj, ci); + M(a0, a1) = BR_MUL(sj, sh); + M(a1, a1) = -BR_MUL(cj, ss) + cc; + M(a2, a1) = -BR_MUL(cj, cs) - sc; + M(a0, a2) = -BR_MUL(sj, ch); + M(a1, a2) = BR_MUL(cj, sc) + cs; + M(a2, a2) = BR_MUL(cj, cc) - ss; + } + else + { + M(a0, a0) = BR_MUL(cj, ch); + M(a1, a0) = BR_MUL(sj, sc) - cs; + M(a2, a0) = BR_MUL(sj, cc) + ss; + M(a0, a1) = BR_MUL(cj, sh); + M(a1, a1) = BR_MUL(sj, ss) + cc; + M(a2, a1) = BR_MUL(sj, cs) - sc; + M(a0, a2) = -sj; + M(a1, a2) = BR_MUL(cj, si); + M(a2, a2) = BR_MUL(cj, ci); + } + + M(3, 0) = M(3, 1) = M(3, 2) = S0; + + return mat; +} + +br_euler *BR_PUBLIC_ENTRY BrMatrix34ToEuler(br_euler *euler, br_matrix34 *mat) +{ + br_uint_8 o = eO; + int a0, a1, a2; + + UASSERT(mat != NULL); + UASSERT(euler != NULL); + UASSERT(euler->order < BR_ASIZE(OrderAxes)); + + a0 = OrderAxes[o].a0; + a1 = OrderAxes[o].a1; + a2 = OrderAxes[o].a2; + + if (o & BR_EULER_REPEAT) + { + br_scalar sy; + + sy = BR_LENGTH2(M(a1, a0), M(a2, a0)); + + if (sy > BR_MUL(16, BR_SCALAR_EPSILON)) + { + eX = BR_ATAN2(M(a1, a0), M(a2, a0)); + eY = BR_ATAN2(sy, M(a0, a0)); + eZ = BR_ATAN2(M(a0, a1), -M(a0, a2)); + } + else + { + eX = BR_ATAN2(-M(a2, a1), M(a1, a1)); + eY = BR_ATAN2(sy, M(a0, a0)); + eZ = 0; + } + } + else + { + br_scalar cy; + + cy = BR_LENGTH2(M(a0, a0), M(a0, a1)); + + if (cy > BR_MUL(16, BR_SCALAR_EPSILON)) + { + eX = BR_ATAN2(M(a1, a2), M(a2, a2)); + eY = BR_ATAN2(-M(a0, a2), cy); + eZ = BR_ATAN2(M(a0, a1), M(a0, a0)); + } + else + { + eX = BR_ATAN2(-M(a2, a1), M(a1, a1)); + eY = BR_ATAN2(-M(a0, a2), cy); + eZ = 0; + } + } + + if (o & BR_EULER_PARITY) + { + eX = -eX; + eY = -eY; + eZ = -eZ; + } + + if (o & BR_EULER_FRAME) + { + br_angle t; + + t = eX; + eX = eZ; + eZ = t; + } + + return euler; +} + +br_matrix4 *BR_PUBLIC_ENTRY BrEulerToMatrix4(br_matrix4 *mat, br_euler *euler) +{ + br_matrix34 tmp; + + UASSERT(mat != NULL); + + BrEulerToMatrix34(&tmp, euler); + + BrMatrix4Copy34(mat, &tmp); + + return mat; +} + +br_euler *BR_PUBLIC_ENTRY BrMatrix4ToEuler(br_euler *dest, br_matrix4 *mat) +{ + br_matrix34 tmp; + + UASSERT(mat != NULL); + + BrMatrix34Copy4(&tmp, mat); + + return BrMatrix34ToEuler(dest, &tmp); +} + +br_quat *BR_PUBLIC_ENTRY BrEulerToQuat(br_quat *q, br_euler *euler) +{ + br_uint_8 o = eO; + br_angle ti, tj, th; + br_scalar ci, cj, ch, si, sj, sh, cc, cs, sc, ss; + int a0, a1, a2; + + UASSERT(q != NULL); + UASSERT(euler != NULL); + UASSERT(euler->order < BR_ASIZE(OrderAxes)); + + if (o & BR_EULER_FRAME) + ti = eZ / 2, tj = eY / 2, th = eX / 2; + else + ti = eX / 2, tj = eY / 2, th = eZ / 2; + + if (o & BR_EULER_PARITY) + tj = -tj; + + ci = BR_COS(ti); + cj = BR_COS(tj); + ch = BR_COS(th); + si = BR_SIN(ti); + sj = BR_SIN(tj); + sh = BR_SIN(th); + cc = BR_MUL(ci, ch); + cs = BR_MUL(ci, sh); + sc = BR_MUL(si, ch); + ss = BR_MUL(si, sh); + + a0 = OrderAxes[o].a0; + a1 = OrderAxes[o].a1; + a2 = OrderAxes[o].a2; + + if (o & BR_EULER_REPEAT) + { + qi(a0) = BR_MUL(cj, (cs + sc)); + qi(a1) = BR_MUL(sj, (cc + ss)); + qi(a2) = BR_MUL(sj, (cs - sc)); + qi(3) = BR_MUL(cj, (cc - ss)); + } + else + { + qi(a0) = BR_MUL(cj, sc) - BR_MUL(sj, cs); + qi(a1) = BR_MUL(cj, ss) + BR_MUL(sj, cc); + qi(a2) = BR_MUL(cj, cs) - BR_MUL(sj, sc); + qi(3) = BR_MUL(cj, cc) + BR_MUL(sj, ss); + } + + if (o & BR_EULER_PARITY) + qi(a1) = -qi(a1); + + return q; +} + +br_euler *BR_PUBLIC_ENTRY BrQuatToEuler(br_euler *euler, br_quat *q) +{ + br_matrix34 mat; + + /* + * Convert quat to matrix + */ + BrQuatToMatrix34(&mat, q); + + /* + * Generate a matrix from the quat + */ + return BrMatrix34ToEuler(euler, &mat); +} diff --git a/bren/FW/blockops.c b/bren/FW/blockops.c new file mode 100644 index 00000000..dc3dc6e8 --- /dev/null +++ b/bren/FW/blockops.c @@ -0,0 +1,28 @@ +#include +#include + +void BR_ASM_CALL BrBlockFill(void *dest_ptr, int value, int dwords) +{ + br_uint_32 *dword_dest_ptr = (br_uint_32 *)dest_ptr; + for (int i = 0; i < dwords; i++) + { + dword_dest_ptr[i] = value; + } +} + +void BR_ASM_CALL BrBlockCopy(void *dest_ptr, void *src_ptr, int dwords) +{ + br_uint_32 *dword_dest_ptr = (br_uint_32 *)dest_ptr; + br_uint_32 *dword_src_ptr = (br_uint_32 *)src_ptr; + for (int i = 0; i < dwords; i++) + { + dword_dest_ptr[i] = dword_src_ptr[i]; + } +} + +#if BR_HAS_FAR +void BR_ASM_CALL BrFarBlockCopy(void __far *dest_ptr, void *src_ptr, int dwords) +{ + BrBlockCopy(dest_ptr, src_ptr, dwords); +} +#endif \ No newline at end of file diff --git a/bren/FW/brassert.c b/bren/FW/brassert.c new file mode 100644 index 00000000..700d62f3 --- /dev/null +++ b/bren/FW/brassert.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: brassert.c 1.3 1995/05/25 13:23:08 sam Exp $ + * $Locker: $ + * + * Assertion support routines + */ +#include +#include + +#if DEBUG +void _BrAssert(char *condition, char *file, unsigned line) +{ + _ErrorOutput(); + printf("ASSERTION FAILED %s:%d: \"%s\"\n", file, line, condition); + _ErrorExit(10); +} +#endif + +#if PARANOID + +void _BrUAssert(char *condition, char *file, unsigned line) +{ + _ErrorOutput(); + printf("USER ASSERTION FAILED %s:%d: \"%s\"\n", file, line, condition); + _ErrorExit(10); +} +#endif diff --git a/bren/FW/brassert.h b/bren/FW/brassert.h new file mode 100644 index 00000000..e53a147e --- /dev/null +++ b/bren/FW/brassert.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: brassert.h 1.3 1995/02/22 21:41:23 sam Exp $ + * $Locker: $ + * + * Assertion macros + * + * assert() is for internal checks + * uassert() is for user checks + */ + +/* + * This file should _NOT_ have checks for single inclusion - + * it is legitimate to re-include it with DEBUG or PARANOID set diffently + */ +#undef ASSERT + +#if DEBUG +#define ASSERT(e) ((void)((e) || (_BrAssert(#e, __FILE__, __LINE__), 1))) +#else +#define ASSERT(ignore) ((void)0) +#endif + +#undef UASSERT + +#if PARANOID +#define UASSERT(e) ((void)((e) || (_BrUAssert(#e, __FILE__, __LINE__), 1))) +#else +#define UASSERT(ignore) ((void)0) +#endif diff --git a/bren/FW/brexcept.c b/bren/FW/brexcept.c new file mode 100644 index 00000000..dae7254d --- /dev/null +++ b/bren/FW/brexcept.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: brexcept.c 1.2 1995/07/28 19:01:34 sam Exp $ + * $Locker: $ + * + * Simple exception handling + */ +#include +#include +#include +#include + +#include "fw.h" + +/* + * Current head of exception handler chain + */ +br_exception_handler *_BrExceptionHandler = NULL; + +/* + * Temporary global used to pass exception value + */ +static void *exceptionValue; + +/* + * Add an exception handler to the stack - returns a point to exception handler + * into which the caller should save context + */ +br_exception_handler *_BrExceptionCatch(void) +{ + br_exception_handler *h; + + /* + * Create an anchor resource + */ + h = BrResAllocate(0, sizeof(*h), BR_MEMORY_EXCEPTION_HANDLER); + h->prev = _BrExceptionHandler; + + return _BrExceptionHandler; +} + +/* + * Unwind back to the last exception handler, passing a type and value + */ +void _BrExceptionThrow(br_int_32 type, void *value) +{ + br_exception_handler h, *old; + + /* + * Make sure exception stack does not underflow + */ + if (_BrExceptionHandler == NULL) + BR_ERROR("Unhandled exception: %d"); + + h = *_BrExceptionHandler; + old = _BrExceptionHandler; + + _BrExceptionHandler = _BrExceptionHandler->prev; + + /* + * Release all the attached resources + */ + BrResFree(old); + + /* + * Pop stack back down to handler context + */ + exceptionValue = value; + longjmp(h.context, type); +} + +/* + * Wrapper function used in BrExceptionCatch() macro to stash the + * value + * + * + */ +br_exception _BrExceptionValueFetch(br_exception type, void **evp) +{ + /* + * If type is a valid exception, save the exception value + */ + if (type && evp) + *evp = exceptionValue; + + return type; +} diff --git a/bren/FW/brexcept.h b/bren/FW/brexcept.h new file mode 100644 index 00000000..44970d41 --- /dev/null +++ b/bren/FW/brexcept.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: brexcept.h 1.2 1995/07/28 19:01:35 sam Exp $ + * $Locker: $ + * + * Simple exception handling + */ +#ifndef _BREXCEPT_H_ +#define _BREXCEPT_H_ + +#ifndef __H2INC__ +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + * Exception types are the same as error types + * + * A value of zero is reserved + */ + typedef br_error br_exception; + +/* + * Useful macros for generating types + */ +#define BR_EXCEPTION(num) BR_##_EXCEPTION_CLASS##_EXEPCTION_SUBCLASS##_##num + + /* + * Exception handler - allocated as a resource + */ + typedef struct br_exception_handler + { + struct br_exception_handler *prev; + + /* + * setjmp/longjmp context to throw to + */ +#ifndef __H2INC__ + jmp_buf context; +#endif + } br_exception_handler; + +/* + * Public macros + */ +#define BrExceptionCatch(evp) (_BrExceptionValueFetch((br_exception)setjmp(_BrExceptionCatch()->context), (evp))) +#define BrExceptionThrow(et, ev) _BrExceptionThrow((br_exception)(ev), (void *)(ev)) +#define BR_EXCEPTION_RESOURCE _BrExceptionHandler + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/bren/FW/brimage.h b/bren/FW/brimage.h new file mode 100644 index 00000000..c2c2afc6 --- /dev/null +++ b/bren/FW/brimage.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: brimage.h 1.1 1995/07/28 19:03:11 sam Exp $ + * $Locker: $ + * + */ +#ifndef _BRIMAGE_H_ +#define _BRIMAGE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + * In-memory structure describing a loaded image + */ + typedef struct br_image_section + { + char *name; + void *base; + br_size_t mem_offset; + br_size_t mem_size; + br_uint_32 data_offset; + br_uint_32 data_size; + } br_image_section; + + typedef struct br_image + { + /* + * Anchor block for list of images + */ + br_node node; + + /* + * DLL name + */ + char *identifier; + + /* + * Flag, true if DLL is resident + */ + br_boolean resident; + + /* + * Number of references to this DLL + */ + int ref_count; + + /* + * Table of exported functions + */ + br_uint_32 ordinal_base; + br_uint_32 n_functions; + void **functions; + + /* + * Name -> ordinal lookup + */ + br_uint_32 n_names; + char **names; + br_uint_16 *name_ordinals; + + /* + * Table of imported image pointers + */ + br_uint_16 n_imports; + struct br_image **imports; + + /* + * Image sections + */ + br_uint_16 n_sections; + br_image_section *sections; + + } br_image; + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/bren/FW/brlists.c b/bren/FW/brlists.c new file mode 100644 index 00000000..43df4562 --- /dev/null +++ b/bren/FW/brlists.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: brlists.c 1.4 1995/02/22 21:41:24 sam Exp $ + * $Locker: $ + * + * Doubly linked list support - has a full and simple version + */ + +#include "fw.h" + +static char rscid[] = "$Id: brlists.c 1.4 1995/02/22 21:41:24 sam Exp $"; + +/** + ** Full features list handling + **/ + +/* + * Initialse a list structure to be empty list + */ +void BR_PUBLIC_ENTRY BrNewList(struct br_list *list) +{ + list->head = (struct br_node *)&(list->_null); + list->tail = (struct br_node *)&(list->head); + list->_null = NULL; +} + +/* + * Add node at head of list + */ +void BR_PUBLIC_ENTRY BrAddHead(struct br_list *list, struct br_node *node) +{ + node->prev = (struct br_node *)&(list->head); + node->next = list->head; + node->next->prev = node; + list->head = node; +} + +/* + * Add node at tail of list + */ +void BR_PUBLIC_ENTRY BrAddTail(struct br_list *list, struct br_node *node) +{ + node->next = (struct br_node *)&(list->_null); + node->prev = list->tail; + node->prev->next = node; + list->tail = node; +} + +/* + * Take node of head of list and return pointer to it + */ +struct br_node *BR_PUBLIC_ENTRY BrRemHead(struct br_list *list) +{ + struct br_node *n = list->head; + + /* + * Trap case of empty list + */ + if (n == (struct br_node *)&(list->_null)) + return NULL; + + list->head = n->next; + + return n; +} + +/* + * Take node of tail of list and return pointer to it + */ +struct br_node *BR_PUBLIC_ENTRY BrRemTail(struct br_list *list) +{ + struct br_node *n = list->tail; + + /* + * Trap case of empty list + */ + if (n == (struct br_node *)&(list->head)) + return NULL; + + list->tail = n->prev; + + return n; +} + +/* + * Add a node to list following the node 'here' + */ +void BR_PUBLIC_ENTRY BrInsert(struct br_list *list, struct br_node *here, struct br_node *node) +{ + node->next = here->next; + node->prev = here; + + here->next->prev = node; + here->next = node; +} + +/* + * Remove a node from the containing list + */ +struct br_node *BR_PUBLIC_ENTRY BrRemove(struct br_node *node) +{ + node->next->prev = node->prev; + node->prev->next = node->next; + + return node; +} + +/** + ** Simple list handling + **/ + +void BR_PUBLIC_ENTRY BrSimpleNewList(struct br_simple_list *list) +{ + list->head = NULL; +} + +void BR_PUBLIC_ENTRY BrSimpleAddHead(struct br_simple_list *list, struct br_simple_node *node) +{ + node->next = list->head; + node->prev = &list->head; + + if (node->next) + node->next->prev = &node->next; + + list->head = node; +} + +struct br_simple_node *BR_PUBLIC_ENTRY BrSimpleRemHead(struct br_simple_list *list) +{ + struct br_simple_node *node = list->head; + + if (node) + BrSimpleRemove(node); + + return node; +} + +void BR_PUBLIC_ENTRY BrSimpleInsert(struct br_simple_list *list, struct br_simple_node *here, + struct br_simple_node *node) +{ + node->next = here->next; + node->prev = &here->next; + + if (node->next) + node->next->prev = &node->next; + + here->next = node; +} + +struct br_simple_node *BR_PUBLIC_ENTRY BrSimpleRemove(struct br_simple_node *node) +{ + *(node->prev) = node->next; + + if (node->next) + node->next->prev = node->prev; + + node->prev = NULL; + node->next = NULL; + + return node; +} diff --git a/bren/FW/brlists.h b/bren/FW/brlists.h new file mode 100644 index 00000000..557a6248 --- /dev/null +++ b/bren/FW/brlists.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: brlists.h 1.4 1995/02/22 21:41:25 sam Exp $ + * $Locker: $ + * + * Doubly linked list supoprt (Based on Amiga EXEC!) + */ +#ifndef _BRLISTS_H_ +#define _BRLISTS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + ** Full featued doubly linked lists + **/ + + /* + * Anchor structure at front of list entries + */ + typedef struct br_node + { + struct br_node *next; + struct br_node *prev; + } br_node; + + /* + * Anchor structure for whole list - looks like two nodes overlapping. + * The _null memeber is always NULL, providing the termination at + * both ends of the list + */ + typedef struct br_list + { + br_node *head; + br_node *_null; + br_node *tail; + } br_list; + +#define BR_HEAD(l) (void *)(((struct br_list *)(l))->head) +#define BR_TAIL(l) (void *)(((struct br_list *)(l))->tail) + +#define BR_NEXT(n) (void *)(((struct br_node *)(n))->next) +#define BR_PREV(n) (void *)(((struct br_node *)(n))->prev) +#define BR_INSERTED(n) (void *)(((struct br_node *)(n))->next) + +/* + * Walk a pointer forwards along a list + * + * eg: + * BR_FOR_LIST(sprites,sptr) { + * sptr->x = 10; + * } + */ +#define BR_FOR_LIST(list, ptr) for ((ptr) = BR_HEAD(list); BR_NEXT(ptr); ptr = BR_NEXT(ptr)) + +/* + * Walk a pointer backwards along a list + * + * eg: + * BR_FOR_LIST_R(sprites,sptr) { + * sptr->x = 10; + * } + */ +#define BR_FOR_LIST_R(list, ptr) for ((ptr) = BR_TAIL(list); BR_PREV(ptr); ptr = BR_PREV(ptr)) + +/* + * Macros around exported functions that hide type casting + */ +#define BR_ADDHEAD(l, n) BrAddHead((struct br_list *)(l), (struct br_node *)(n)) +#define BR_ADDTAIL(l, n) BrAddTail((struct br_list *)(l), (struct br_node *)(n)) +#define BR_REMHEAD(l) ((void *)BrRemHead((struct br_list *)(l))) +#define BR_REMTAIL(l) ((void *)BrRemTail((struct br_list *)(l))) +#define BR_INSERT(l, n1, n2) BrInsert((struct br_list *)(l), (struct br_node *)(n1), (struct br_node *)(n2)) +#define BR_REMOVE(n) ((void *)BrRemove((struct br_node *)(n))) + + /** + ** Simple lists that only use a single head pointer + **/ + typedef struct br_simple_node + { + struct br_simple_node *next; + struct br_simple_node **prev; + } br_simple_node; + + /* + * Anchor structure for whole list - just a single head pointer + */ + typedef struct br_simple_list + { + struct br_simple_node *head; + } br_simple_list; + +#define BR_SIMPLEHEAD(l) (void *)(((br_simple_list *)(l))->head) +#define BR_SIMPLENEXT(n) (void *)(((br_simple_node *)(n))->next) + +#define BR_SIMPLEINSERTED(n) (void *)(((br_simple_node *)(n))->prev) + +#define BR_FOR_SIMPLELIST(list, ptr) for ((ptr) = BR_SIMPLEHEAD(list); (ptr); (ptr) = BR_SIMPLENEXT(ptr)) + +/* + * Macros around exported functions that hide type casting + */ +#define BR_SIMPLEADDHEAD(l, n) BrSimpleAddHead((br_simple_list *)(l), (br_simple_node *)(n)) +#define BR_SIMPLEREMHEAD(l) ((void *)BrSimpleRemHead((br_simple_list *)(l))) +#define BR_SIMPLEINSERT(l, n1, n2) BrSimpleInsert((br_simple_list *)(l), (br_simple_node *)(n1), (br_simple_node *)(n2)) +#define BR_SIMPLEREMOVE(n) ((void *)BrSimpleRemove((br_simple_node *)(n))) + +/* + * Protoypes in lists.c + */ +#ifndef _NO_PROTOTYPES + void BR_PUBLIC_ENTRY BrNewList(br_list *list); + void BR_PUBLIC_ENTRY BrAddHead(br_list *list, br_node *node); + void BR_PUBLIC_ENTRY BrAddTail(br_list *list, br_node *node); + + br_node *BR_PUBLIC_ENTRY BrRemHead(br_list *list); + br_node *BR_PUBLIC_ENTRY BrRemTail(br_list *list); + + void BR_PUBLIC_ENTRY BrInsert(br_list *list, br_node *here, br_node *node); + br_node *BR_PUBLIC_ENTRY BrRemove(br_node *node); + + void BR_PUBLIC_ENTRY BrSimpleNewList(br_simple_list *list); + void BR_PUBLIC_ENTRY BrSimpleAddHead(br_simple_list *list, br_simple_node *node); + br_simple_node *BR_PUBLIC_ENTRY BrSimpleRemHead(br_simple_list *list); + void BR_PUBLIC_ENTRY BrSimpleInsert(br_simple_list *list, br_simple_node *here, br_simple_node *node); + br_simple_node *BR_PUBLIC_ENTRY BrSimpleRemove(br_simple_node *node); + +#endif + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/bren/FW/brqsort.c b/bren/FW/brqsort.c new file mode 100644 index 00000000..b64b1633 --- /dev/null +++ b/bren/FW/brqsort.c @@ -0,0 +1,192 @@ +/* + * $Id: brqsort.c 1.9 1995/05/25 13:23:09 sam Exp $ + * $Locker: $ + * + * Local quicksort for brender + * + * Based on a public domain verion by Raymond Gardner, + * Englewood CO February 1991 + */ + +#include "brender.h" + +#if !defined(__TARGET_MSC__) && (defined(__WATCOMC__) || defined(_MSC_VER)) +#include + +void BR_PUBLIC_ENTRY BrQsort(void *basep, unsigned int nelems, unsigned int size, br_qsort_cbfn *comp) +{ + qsort(basep, nelems, size, comp); +} + +#elif __IBMC__ +/* + * Pull qsort from a BRender specific DLL + */ +void _System BrSupport1(br_qsort_cbfn *comp, unsigned int size, void *basep, unsigned int nelems); + +void BR_PUBLIC_ENTRY BrQsort(void *basep, unsigned int nelems, unsigned int size, br_qsort_cbfn *comp) +{ + BrSupport1(comp, size, basep, nelems); +} +#else + +static void swap_chars(char *, char *, unsigned int); + +#define SWAP_INTS 1 + +/* +** Compile with -DSWAP_INTS if your machine can access an int at an +** arbitrary location with reasonable efficiency. (Some machines +** cannot access an int at an odd address at all, so be careful.) +*/ + +#ifdef SWAP_INTS +static void swap_ints(char *, char *, unsigned int); +static void swap_int_1(char *ap, char *bp, unsigned int nints); + +#define SWAP(a, b) (swap_func((char *)(a), (char *)(b), width)) +#else +#define SWAP(a, b) (swap_chars((char *)(a), (char *)(b), size)) +#endif + +#define COMP(a, b) ((*comp)((void *)(a), (void *)(b))) + +#define T 7 /* subfiles of T or fewer elements will */ +/* be sorted by a simple insertion sort */ +/* Note! T must be at least 3 */ + +void BR_PUBLIC_ENTRY BrQsort(void *basep, unsigned int nelems, unsigned int size, br_qsort_cbfn *comp) +{ + char *stack[40], **sp; /* stack and stack pointer */ + char *i, *j, *limit; /* scan and limit pointers */ + unsigned int thresh; /* size of T elements in bytes */ + char *base; /* base pointer as char * */ + +#ifdef SWAP_INTS + unsigned int width; /* width of array element */ + void (*swap_func)(char *, char *, unsigned int); /* swap func pointer*/ + + width = size; /* save size for swap routine */ + swap_func = swap_chars; /* choose swap function */ + if (size == sizeof(int)) + { /* size is == int */ + swap_func = swap_int_1; /* use int swap function */ + } + else if (size % sizeof(int) == 0) + { /* size is multiple of ints */ + width /= sizeof(int); /* set width in ints */ + swap_func = swap_ints; /* use int swap function */ + } +#endif + + base = (char *)basep; /* set up char * base pointer */ + thresh = T * size; /* init threshold */ + sp = stack; /* init stack pointer */ + limit = base + nelems * size; /* pointer past end of array */ + for (;;) + { /* repeat until break... */ + if ((unsigned)(limit - base) > thresh) + { /* if more than T elements */ + /* swap base with middle */ + SWAP((((limit - base) / size) / 2) * size + base, base); + i = base + size; /* i scans left to right */ + j = limit - size; /* j scans right to left */ + if (COMP(i, j) > 0) /* Sedgewick's */ + SWAP(i, j); /* three-element sort */ + if (COMP(base, j) > 0) /* sets things up */ + SWAP(base, j); /* so that */ + if (COMP(i, base) > 0) /* *i <= *base <= *j */ + SWAP(i, base); /* *base is pivot element */ + for (;;) + { /* loop until break */ + do /* move i right */ + i += size; /* until *i >= pivot */ + while (COMP(i, base) < 0); + do /* move j left */ + j -= size; /* until *j <= pivot */ + while (COMP(j, base) > 0); + if (i > j) /* if pointers crossed */ + break; /* break loop */ + SWAP(i, j); /* else swap elements, keep scanning*/ + } + SWAP(base, j); /* move pivot into correct place */ + if (j - base > limit - i) + { /* if left subfile larger */ + sp[0] = base; /* stack left subfile base */ + sp[1] = j; /* and limit */ + base = i; /* sort the right subfile */ + } + else + { /* else right subfile larger*/ + sp[0] = i; /* stack right subfile base */ + sp[1] = limit; /* and limit */ + limit = j; /* sort the left subfile */ + } + sp += 2; /* increment stack pointer */ + } + else + { /* else subfile is small, use insertion sort */ + for (j = base, i = j + size; i < limit; j = i, i += size) + for (; COMP(j, j + size) > 0; j -= size) + { + SWAP(j, j + size); + if (j == base) + break; + } + if (sp != stack) + { /* if any entries on stack */ + sp -= 2; /* pop the base and limit */ + base = sp[0]; + limit = sp[1]; + } + else /* else stack empty, done */ + break; + } + } +} + +/* +** swap nbytes between a and b +*/ + +static void swap_chars(char *a, char *b, unsigned int nbytes) +{ + char tmp; + do + { + tmp = *a; + *a++ = *b; + *b++ = tmp; + } while (--nbytes); +} + +#ifdef SWAP_INTS + +/* +** swap nints between a and b +*/ + +static void swap_ints(char *ap, char *bp, unsigned int nints) +{ + int *a = (int *)ap, *b = (int *)bp; + int tmp; + do + { + tmp = *a; + *a++ = *b; + *b++ = tmp; + } while (--nints); +} + +static void swap_int_1(char *ap, char *bp, unsigned int nints) +{ + int *a = (int *)ap, *b = (int *)bp; + int tmp; + + tmp = *a; + *a++ = *b; + *b++ = tmp; +} + +#endif +#endif diff --git a/bren/FW/bswap.c b/bren/FW/bswap.c new file mode 100644 index 00000000..b94a9bd7 --- /dev/null +++ b/bren/FW/bswap.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: bswap.c 1.12 1995/05/25 13:23:11 sam Exp $ + * $Locker: $ + * + * Byte swap routines for net<->host conversion + */ + +#include "fw.h" +#include "brassert.h" +#include "brhton.h" + +static char rscid[] = "$Id: bswap.c 1.12 1995/05/25 13:23:11 sam Exp $"; + +#ifndef __IBMC__ + +#undef _SWAP +#define _SWAP(a, b) \ + { \ + (a) ^= (b); \ + (b) ^= (a); \ + (a) ^= (b); \ + } + +/* + * Swap the bytes of a 4 byte word + */ +br_uint_32 BR_PUBLIC_ENTRY BrSwap32(br_uint_32 l) +{ + union { + unsigned long l; + unsigned char c[4]; + } u; + + u.l = l; + + _SWAP(u.c[0], u.c[3]); + _SWAP(u.c[1], u.c[2]); + + return u.l; +} + +/* + * Swap the bytes of a 2 byte word + */ +br_uint_16 BR_PUBLIC_ENTRY BrSwap16(br_uint_16 s) +{ + union { + unsigned short s; + unsigned char c[2]; + } u; + + u.s = s; + + _SWAP(u.c[0], u.c[1]); + + return u.s; +} + +/* + * Swap the bytes of a 4 byte float + */ +br_float BR_PUBLIC_ENTRY BrSwapFloat(br_float f) +{ + union { + br_float f; + unsigned char c[4]; + } u; + + u.f = f; + + _SWAP(u.c[0], u.c[3]); + _SWAP(u.c[1], u.c[2]); + + return u.f; +} + +/* + * Swap an array of items + * + */ +void *BR_PUBLIC_ENTRY BrSwapBlock(void *block, int count, int size) +{ + br_uint_8 *cp; + int i, k; + + ASSERT(block != NULL); + ASSERT(count != 0); + ASSERT(size != 0); + + /* + * Go through block swapping elements of the appropriate size + */ + switch (size) + { + case 1: + break; + + /* + * Special case loops for the common sizes + */ + case 2: + for (i = 0, cp = block; i < count; i++, cp += 2) + { + _SWAP(cp[0], cp[1]); + } + break; + + case 3: + for (i = 0, cp = block; i < count; i++, cp += 3) + { + _SWAP(cp[0], cp[2]); + } + break; + + case 4: + for (i = 0, cp = block; i < count; i++, cp += 4) + { + _SWAP(cp[0], cp[3]); + _SWAP(cp[1], cp[2]); + } + break; + + case 8: + for (i = 0, cp = block; i < count; i++, cp += 8) + { + _SWAP(cp[0], cp[7]); + _SWAP(cp[1], cp[6]); + _SWAP(cp[2], cp[5]); + _SWAP(cp[3], cp[4]); + } + break; + + default: + /* + * Do any other strange size the long way + */ + for (i = 0, cp = block; i < count; i++, cp += size) + { + for (k = 0; k < size / 2; k++) + _SWAP(cp[k], cp[size - k - 1]); + } + break; + } + + return block; +} + +#else + +/* + * Pull swap ops. from a BRender specific DLL + */ +br_uint_32 _System BrSupport2(br_uint_32 l); +br_uint_16 _System BrSupport3(br_uint_16 s); +br_float _System BrSupport4(br_float f); +void *_System BrSupport5(void *block, int count, int size); + +br_uint_32 BR_PUBLIC_ENTRY BrSwap32(br_uint_32 l) +{ + return BrSupport2(l); +} + +br_uint_16 BR_PUBLIC_ENTRY BrSwap16(br_uint_16 s) +{ + return BrSupport3(s); +} + +br_float BR_PUBLIC_ENTRY BrSwapFloat(br_float f) +{ + return BrSupport4(f); +} + +void *BR_PUBLIC_ENTRY BrSwapBlock(void *block, int count, int size) +{ + return BrSupport5(block, count, size); +} + +#endif diff --git a/bren/FW/custsupt.c b/bren/FW/custsupt.c new file mode 100644 index 00000000..27067df4 --- /dev/null +++ b/bren/FW/custsupt.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: custsupt.c 1.2 1995/02/22 21:41:27 sam Exp $ + * $Locker: $ + * + * Support routines for application + */ +#include + +#include "fw.h" +#include "shortcut.h" +#include "brassert.h" + +static char rscid[] = "$Id: custsupt.c 1.2 1995/02/22 21:41:27 sam Exp $"; + +/* + * Transform and project 0,0,0 into screen space + * + * Return 1 if point is behind eye + */ +br_uint_8 BR_PUBLIC_ENTRY BrOriginToScreenXY(br_vector2 *screen) +{ + int Behind; + UASSERT(fw.rendering); + + // Check the Range for possible overflow... + + if (fw.model_to_screen.m[3][3] < BR_SCALAR(1.0)) + { + screen->v[X] = BR_DIV(fw.vp_width, fw.model_to_screen.m[3][3]); + screen->v[Y] = BR_DIV(fw.vp_height, fw.model_to_screen.m[3][3]); + screen->v[X] = BR_MUL(screen->v[X], fw.model_to_screen.m[3][0]); + screen->v[Y] = BR_MUL(screen->v[Y], fw.model_to_screen.m[3][1]); + screen->v[X] += fw.vp_ox; + screen->v[Y] += fw.vp_oy; + } + else + { + screen->v[X] = fw.vp_ox + BR_MULDIV(fw.vp_width, fw.model_to_screen.m[3][0], fw.model_to_screen.m[3][3]); + screen->v[Y] = fw.vp_oy + BR_MULDIV(fw.vp_height, fw.model_to_screen.m[3][1], fw.model_to_screen.m[3][3]); + } + return (fw.model_to_screen.m[3][2] > BR_SCALAR(0.0)); +} + +/* + * Transform and project 0,0,0 into screen space, generate X,Y,Z and return outcode + * + * If the point is offscreen, it will not be projected + */ +br_uint_32 BR_PUBLIC_ENTRY BrOriginToScreenXYZO(br_vector3 *screen) +{ + br_uint_32 outcode; + + UASSERT(fw.rendering); + + OUTCODE_POINT(outcode, ((br_vector4 *)(fw.model_to_screen.m[3]))); + + if (!(outcode & OUTCODES_ALL)) + { + screen->v[X] = fw.vp_ox + BR_MULDIV(fw.vp_width, fw.model_to_screen.m[3][0], fw.model_to_screen.m[3][3]); + screen->v[Y] = fw.vp_oy + BR_MULDIV(fw.vp_height, fw.model_to_screen.m[3][1], fw.model_to_screen.m[3][3]); + screen->v[Z] = PERSP_DIV_Z(fw.model_to_screen.m[3][2], fw.model_to_screen.m[3][3]); + } + return outcode; +} + +/* + * Transform and project a single point into screen space + * + * Return 1 if point is behind eye + */ +br_uint_8 BR_PUBLIC_ENTRY BrPointToScreenXY(br_vector2 *screen, br_vector3 *point) +{ + br_vector4 sp; + + UASSERT(fw.rendering); + + BrMatrix4ApplyP(&sp, point, &fw.model_to_screen); + + screen->v[X] = fw.vp_ox + BR_MULDIV(fw.vp_width, sp.v[0], sp.v[3]); + screen->v[Y] = fw.vp_oy + BR_MULDIV(fw.vp_height, sp.v[1], sp.v[3]); + + return (sp.v[2] > BR_SCALAR(0.0)); +} + +/* + * Transform and project a single point into screen space + * + * Return 1 if point is behind eye + */ +br_uint_32 BR_PUBLIC_ENTRY BrPointToScreenXYZO(br_vector3 *screen, br_vector3 *point) +{ + br_vector4 sp; + br_uint_32 outcode; + + UASSERT(fw.rendering); + + BrMatrix4ApplyP(&sp, point, &fw.model_to_screen); + + OUTCODE_POINT(outcode, &sp); + + if (!(outcode & OUTCODES_ALL)) + { + screen->v[X] = fw.vp_ox + BR_MULDIV(fw.vp_width, sp.v[0], sp.v[3]); + screen->v[Y] = fw.vp_oy + BR_MULDIV(fw.vp_height, sp.v[1], sp.v[3]); + screen->v[Z] = PERSP_DIV_Z(sp.v[2], sp.v[3]); + } + return outcode; +} + +/* + * Transform and project many points into screen space + */ +void BR_PUBLIC_ENTRY BrPointToScreenXYMany(br_vector2 *screens, br_vector3 *points, br_uint_32 npoints) +{ + br_vector4 sp; + int i; + + UASSERT(fw.rendering); + + for (i = 0; i < npoints; i++, screens++, points++) + { + BrMatrix4ApplyP(&sp, points, &fw.model_to_screen); + + screens->v[X] = fw.vp_ox + BR_MULDIV(fw.vp_width, sp.v[0], sp.v[3]); + screens->v[Y] = fw.vp_oy + BR_MULDIV(fw.vp_height, sp.v[1], sp.v[3]); + } +} + +/* + * Transform and project many points into screen space, generate X,Y,Z + * + * Outcode each point, and if it is not on screen, don't project it + */ +void BR_PUBLIC_ENTRY BrPointToScreenXYZOMany(br_vector3 *screens, br_uint_32 *outcodes, br_vector3 *points, + br_uint_32 npoints) +{ + br_vector4 sp; + int i; + br_uint_32 outcode; + + UASSERT(fw.rendering); + + for (i = 0; i < npoints; i++, screens++, points++, outcodes++) + { + BrMatrix4ApplyP(&sp, points, &fw.model_to_screen); + + OUTCODE_POINT(outcode, &sp); + *outcodes = outcode; + + if (outcode & OUTCODES_ALL) + continue; + + screens->v[X] = fw.vp_ox + BR_MULDIV(fw.vp_width, sp.v[0], sp.v[3]); + screens->v[Y] = fw.vp_oy + BR_MULDIV(fw.vp_height, sp.v[1], sp.v[3]); + screens->v[Z] = PERSP_DIV_Z(sp.v[2], sp.v[3]); + } +} + +#if 0 +/* + * Transform and project many points into screen space, generate X,Y,Z + * + */ +void BR_PUBLIC_ENTRY BrPointToScreenXYZMany(br_vector3 *screens, br_vector3 *points, br_uint_32 npoints) +{ + br_vector4 sp; + int i; + br_uint_32 outcode; + + UASSERT(fw.rendering); + + for(i=0; i< npoints; i++, screens++, points++) { + BrMatrix4ApplyP(&sp,points,&fw.model_to_screen); + + screens->v[X] = fw.vp_ox + BR_MULDIV(fw.vp_width,sp.v[0],sp.v[3]); + screens->v[Y] = fw.vp_oy + BR_MULDIV(fw.vp_height,sp.v[1],sp.v[3]); + screens->v[Z] = PERSP_DIV_Z(sp.v[2],sp.v[3]); + } +} +#endif diff --git a/bren/FW/datafile.c b/bren/FW/datafile.c new file mode 100644 index 00000000..1876ecd9 --- /dev/null +++ b/bren/FW/datafile.c @@ -0,0 +1,1921 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: datafile.c 1.37 1995/08/31 16:29:19 sam Exp $ + * $Locker: $ + * + * Data file support routines + */ +#include +#include + +#include "fw.h" +#include "brassert.h" +#include "brhton.h" +#include "datafile.h" +#include "shortcut.h" +#include "ifile.h" + +static char rscid[] = "$Id: datafile.c 1.37 1995/08/31 16:29:19 sam Exp $"; + +#define CHUNK_LOG 0 + +/* + * maximum length of lines in text data files + */ +#define TEXTF_MAX_LINE 256 + +/* + * Number of bytes per line in block text mode + */ +#define TEXT_BLOCK_LINE 32 + +/* + * Debug printing while loading data files + */ +#define DATA_LOG 0 + +/* + * Local version of ispsace() + */ +#define ISSPACE(c) ((c) == ' ' || (c) == '\t') + +/* + * A Stack of generic data pointers used while interpreting incoming + * files + */ +#define DFSTACK_MAX 1024 + +static struct +{ + int type; + void *value; + int count; +} DatafileStack[DFSTACK_MAX]; + +static int DatafileStackTop = 0; + +/* + * Push a pointer to a vector of typed items onto stack + */ +void DfPush(int type, void *value, int count) +{ + ASSERT((type > DFST_NONE) && (type < DFST_MAX)); + ASSERT(value != NULL); + ASSERT(count > 0); + + if (DatafileStackTop >= DFSTACK_MAX) + BR_ERROR("DatafileStack Overflow"); + + DatafileStack[DatafileStackTop].type = type; + DatafileStack[DatafileStackTop].value = value; + DatafileStack[DatafileStackTop].count = count; + + DatafileStackTop++; +} + +/* + * Pop a pointer to a vector of items and the count - check the + * assumed type matches that popped from the stack. + */ +void *DfPop(int type, int *countp) +{ + ASSERT((type > DFST_NONE) && (type < DFST_MAX)); + + if (DatafileStackTop <= 0) + BR_ERROR("DatafileStack Underflow"); + + DatafileStackTop--; + + if (type != DatafileStack[DatafileStackTop].type) + BR_ERROR2("DatafileStack type mismatch, wanted %d, got %d", type, DatafileStack[DatafileStackTop].type); + + if (countp) + *countp = DatafileStack[DatafileStackTop].count; + + return DatafileStack[DatafileStackTop].value; +} + +/* + * Get a pointer to a vector of items and the count from the top of + * the stack - check the* assumed type matches that fetched. + */ +void *DfTop(int type, int *countp) +{ + ASSERT((type > DFST_NONE) && (type < DFST_MAX)); + + if (DatafileStackTop <= 0) + BR_ERROR("DatafileStack Underflow"); + + if (type != DatafileStack[DatafileStackTop - 1].type) + BR_ERROR2("DatafileStack type mismatch, wanted %d, got %d", type, DatafileStack[DatafileStackTop].type); + + if (countp) + *countp = DatafileStack[DatafileStackTop - 1].count; + + return DatafileStack[DatafileStackTop - 1].value; +} + +/* + * Find the type of the items on top of the stack - return DFST_NONE + * if stack is empty + */ +int DfTopType(void) +{ + if (DatafileStackTop <= 0) + return DFST_NONE; + + return DatafileStack[DatafileStackTop - 1].type; +} + +/* + * Get next line from input and break it into + * + * Return 0 at end of file + */ +static int TextReadLine(br_datafile *df, char **ident, char **data) +{ + char *cp; + + /* + * Consume blank lines + */ + do + { + + BrFileGetLine(_br_scratch_string, TEXTF_MAX_LINE, df->h); + + if (BrFileEof(df->h)) + return 0; + + /* + * Skip white to ident + */ + cp = _br_scratch_string; + while (ISSPACE(*cp)) + cp++; + + } while (*cp == '\0'); + + *ident = cp; + + /* + * Skip ident to white + */ + while (!ISSPACE(*cp) && *cp != '\0') + cp++; + + /* + * Terminate ident + */ + *cp++ = '\0'; + + /* + * Skip white to data + */ + while (ISSPACE(*cp)) + cp++; + + *data = cp; + + if (*cp == '"') + { + /* + * Null terminate data at closing quote + */ + cp++; + + while ((*cp != '"') && (*cp != '\0')) + cp++; + } + else + { + /* + * Null terminate data at next white space + */ + while (!ISSPACE(*cp) && *cp != '\0') + cp++; + } + + /* + * Terminate data + */ + *cp = '\0'; + + return 1; +} + +/** + ** reading and writing data files, both in binary and text formats + **/ +/* + * Names of various structure elements + */ +static char *member_type_names[] = { + "int_8", "uint_8", "int_16", "uint_16", "int_32", "uint_32", "fixed", "angle", + "float", "double", "scalar", "fraction", "ufraction", "enum_8", "enum_16", "enum_32", + "struct", "asciz", "colour", "vector2", "vector3", "vector4", +}; + +/* + * Write a structure to a binary file using the given template + * + */ +static br_uint_32 DfStructWriteBinary(br_datafile *df, br_file_struct *str, void *base) +{ + unsigned int m; + int i, n; + unsigned char *mp; + br_file_struct_member *sm; + + union { + unsigned char b[8]; + float f; + } conv; + + for (m = 0, sm = str->members; m < str->nmembers; m++, sm++) + { + /* + * Get pointer to source memory + */ + mp = (char *)base + sm->offset; + + /* + * Do type specific processing + */ + switch (sm->type) + { + + case FSM_INT_8: + case FSM_UINT_8: + case FSM_ENUM_8: + BrFilePutChar(mp[0], df->h); + break; + + case FSM_INT_16: + case FSM_UINT_16: + case FSM_ENUM_16: + case FSM_ANGLE: + BrFilePutChar(mp[BR_HTON_16(0)], df->h); + BrFilePutChar(mp[BR_HTON_16(1)], df->h); + break; + + case FSM_FLOAT: + case FSM_FIXED: + case FSM_INT_32: + case FSM_UINT_32: + case FSM_ENUM_32: + BrFilePutChar(mp[BR_HTON_32(0)], df->h); + + case FSM_COLOUR: + BrFilePutChar(mp[BR_HTON_32(1)], df->h); + BrFilePutChar(mp[BR_HTON_32(2)], df->h); + BrFilePutChar(mp[BR_HTON_32(3)], df->h); + break; + + case FSM_SCALAR: + conv.f = BrScalarToFloat(*((br_scalar *)mp)); + put_four: + BrFilePutChar(conv.b[BR_HTON_32(0)], df->h); + BrFilePutChar(conv.b[BR_HTON_32(1)], df->h); + BrFilePutChar(conv.b[BR_HTON_32(2)], df->h); + BrFilePutChar(conv.b[BR_HTON_32(3)], df->h); + break; + + case FSM_DOUBLE: + BrFilePutChar(mp[BR_HTON_D(0)], df->h); + BrFilePutChar(mp[BR_HTON_D(1)], df->h); + BrFilePutChar(mp[BR_HTON_D(2)], df->h); + BrFilePutChar(mp[BR_HTON_D(3)], df->h); + BrFilePutChar(mp[BR_HTON_D(4)], df->h); + BrFilePutChar(mp[BR_HTON_D(5)], df->h); + BrFilePutChar(mp[BR_HTON_D(6)], df->h); + BrFilePutChar(mp[BR_HTON_D(7)], df->h); + break; + + case FSM_FRACTION: + conv.f = BrScalarToFloat(BrFractionToScalar(*((br_fraction *)mp))); + goto put_four; + + case FSM_UFRACTION: + conv.f = BrScalarToFloat(BrUFractionToScalar(*((br_ufraction *)mp))); + goto put_four; + + case FSM_VECTOR2: + n = 2; + goto put_vector; + + case FSM_VECTOR3: + n = 3; + goto put_vector; + + case FSM_VECTOR4: + n = 4; + put_vector: + /* + * Assumes vector2 and vector3 are reduced versions of vector4 + */ + for (i = 0; i < n; i++) + { + conv.f = BrScalarToFloat(((br_vector4 *)mp)->v[i]); + + BrFilePutChar(conv.b[BR_HTON_32(0)], df->h); + BrFilePutChar(conv.b[BR_HTON_32(1)], df->h); + BrFilePutChar(conv.b[BR_HTON_32(2)], df->h); + BrFilePutChar(conv.b[BR_HTON_32(3)], df->h); + } + break; + + case FSM_STRUCT: + + DfStructWriteBinary(df, sm->extra, mp); + + break; + + case FSM_ASCIZ: + + if (*((char **)mp)) + BrFileWrite(*((char **)mp), 1, strlen(*((char **)mp)), df->h); + + BrFilePutChar('\0', df->h); + break; + } + } + + return 1; +} + +/* + * Read a structure from a binary file using the given template + * + */ +static br_uint_32 DfStructReadBinary(br_datafile *df, br_file_struct *str, void *base) +{ + char tmp_string[TEXTF_MAX_LINE]; + unsigned int m; + int i, c, n; + unsigned char *mp; + br_file_struct_member *sm; + + union { + unsigned char b[8]; + float f; + } conv; + + for (m = 0, sm = str->members; m < str->nmembers; m++, sm++) + { + /* + * Get pointer to destination memory + */ + mp = (char *)base + sm->offset; + + /* + * Do type specific processing + */ + switch (sm->type) + { + + case FSM_INT_8: + case FSM_UINT_8: + case FSM_ENUM_8: + mp[0] = BrFileGetChar(df->h); + break; + + case FSM_ANGLE: + case FSM_UINT_16: + case FSM_INT_16: + case FSM_ENUM_16: + mp[BR_NTOH_16(0)] = BrFileGetChar(df->h); + mp[BR_NTOH_16(1)] = BrFileGetChar(df->h); + break; + + case FSM_FLOAT: + case FSM_FIXED: + case FSM_INT_32: + case FSM_UINT_32: + case FSM_ENUM_32: + mp[BR_NTOH_32(0)] = BrFileGetChar(df->h); + + case FSM_COLOUR: + mp[BR_NTOH_32(1)] = BrFileGetChar(df->h); + mp[BR_NTOH_32(2)] = BrFileGetChar(df->h); + mp[BR_NTOH_32(3)] = BrFileGetChar(df->h); + break; + + case FSM_SCALAR: + conv.b[BR_NTOH_F(0)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(1)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(2)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(3)] = BrFileGetChar(df->h); + + *((br_scalar *)mp) = BrFloatToScalar(conv.f); + break; + + case FSM_DOUBLE: + mp[BR_NTOH_D(0)] = BrFileGetChar(df->h); + mp[BR_NTOH_D(1)] = BrFileGetChar(df->h); + mp[BR_NTOH_D(2)] = BrFileGetChar(df->h); + mp[BR_NTOH_D(3)] = BrFileGetChar(df->h); + mp[BR_NTOH_D(4)] = BrFileGetChar(df->h); + mp[BR_NTOH_D(5)] = BrFileGetChar(df->h); + mp[BR_NTOH_D(6)] = BrFileGetChar(df->h); + mp[BR_NTOH_D(7)] = BrFileGetChar(df->h); + break; + + case FSM_FRACTION: + conv.b[BR_NTOH_F(0)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(1)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(2)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(3)] = BrFileGetChar(df->h); + + *((br_fraction *)mp) = BrScalarToFraction(BrFloatToScalar(conv.f)); + + break; + + case FSM_UFRACTION: + conv.b[BR_NTOH_F(0)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(1)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(2)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(3)] = BrFileGetChar(df->h); + + *((br_ufraction *)mp) = BrScalarToUFraction(BrFloatToScalar(conv.f)); + break; + + case FSM_VECTOR2: + n = 2; + goto get_vector; + + case FSM_VECTOR3: + n = 3; + goto get_vector; + + case FSM_VECTOR4: + n = 4; + get_vector: + /* + * Assumes vector2 and vector3 are reduced versions of vector4 + */ + for (i = 0; i < n; i++) + { + + conv.b[BR_NTOH_F(0)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(1)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(2)] = BrFileGetChar(df->h); + conv.b[BR_NTOH_F(3)] = BrFileGetChar(df->h); + + ((br_vector4 *)mp)->v[i] = BrFloatToScalar(conv.f); + } + break; + + case FSM_STRUCT: + DfStructReadBinary(df, sm->extra, mp); + + break; + + case FSM_ASCIZ: + /* + * Read string into a temporary buffer + */ + for (i = 0; i < TEXTF_MAX_LINE - 1; i++) + { + c = BrFileGetChar(df->h); + if (c == '\0' || c == BR_EOF) + break; + + tmp_string[i] = c; + } + + /* + * Terminate it + */ + tmp_string[i] = '\0'; + + *((char **)mp) = BrResStrDup(df->res ? df->res : fw.res, tmp_string); + + break; + } + } + + return 1; +} + +/* + * Find the size a structure would occupy when written to a binary file + * + * If the structure instance is NULL, then ignore variable sized memebers + */ +static int DfStructSizeBinary(br_datafile *df, br_file_struct *str, void *base) +{ + unsigned char *mp; + unsigned int m; + br_file_struct_member *sm; + int bytes = 0; + + for (m = 0, sm = str->members; m < str->nmembers; m++, sm++) + { + + /* + * Do type specific processing + */ + switch (sm->type) + { + + case FSM_INT_8: + case FSM_UINT_8: + case FSM_ENUM_8: + bytes += 1; + break; + + case FSM_ANGLE: + case FSM_INT_16: + case FSM_UINT_16: + case FSM_ENUM_16: + bytes += 2; + break; + + case FSM_COLOUR: + bytes += 4; + break; + + case FSM_FIXED: + case FSM_INT_32: + case FSM_UINT_32: + case FSM_ENUM_32: + case FSM_SCALAR: + case FSM_FLOAT: + case FSM_FRACTION: + case FSM_UFRACTION: + bytes += 4; + break; + + case FSM_DOUBLE: + case FSM_VECTOR2: + bytes += 8; + break; + + case FSM_VECTOR3: + bytes += 12; + break; + + case FSM_VECTOR4: + bytes += 16; + break; + + case FSM_STRUCT: + bytes += DfStructSizeBinary(df, sm->extra, base ? ((char *)base + sm->offset) : NULL); + break; + + case FSM_ASCIZ: + mp = (char *)base + sm->offset; + + if (*((char **)mp)) + bytes += strlen(*((char **)mp)); + + bytes += 1; + break; + } + } + + return bytes; +} + +/* + * Lookup enums in tables + */ +static int EnumFromString(br_file_enum *e, char *str) +{ + unsigned int m; + + for (m = 0; m < e->nmembers; m++) + if ((e->members[m].name[0] == *str) && !strcmp(e->members[m].name, str)) + return e->members[m].value; + + BR_ERROR1("Unknown enum string: %s", str); + + return 0; +} + +static char *EnumToString(br_file_enum *e, int num) +{ + unsigned int m; + + for (m = 0; m < e->nmembers; m++) + if (num == e->members[m].value) + return e->members[m].name; + + BR_ERROR1("Unknown enum %d", num); + + return NULL; +} + +/* + * Write a structure to a text file using the given template + * + */ +static br_uint_32 StructWriteTextSub(br_datafile *df, br_file_struct *str, void *base, int indent); + +static br_uint_32 DfStructWriteText(br_datafile *df, br_file_struct *str, void *base) +{ + BrFilePrintf(df->h, " struct %s\n", str->name); + + StructWriteTextSub(df, str, base, 4); + + return 1; +} + +static br_uint_32 StructWriteTextSub(br_datafile *df, br_file_struct *str, void *base, int indent) +{ + unsigned int m; + int i, w, add_comment; + void *mp; + br_file_struct_member *sm; + + for (m = 0, sm = str->members; m < str->nmembers; m++, sm++) + { + /* + * Get pointer to source memory + */ + mp = (char *)base + sm->offset; + + /* + * Identifer at start of line + */ + for (i = 0; i < indent; i++) + BrFilePutChar(' ', df->h); + + ASSERT(sm->type < BR_ASIZE(member_type_names)); + + BrFilePrintf(df->h, "%-10s", member_type_names[sm->type]); + + /* + * By default, add member comment to end of line + */ + add_comment = 1; + + /* + * Do type specific processing + */ + switch (sm->type) + { + case FSM_INT_8: + w = BrFilePrintf(df->h, "%d", *((br_int_8 *)mp)); + break; + + case FSM_UINT_8: + w = BrFilePrintf(df->h, "%u", *((br_uint_8 *)mp)); + break; + + case FSM_INT_16: + w = BrFilePrintf(df->h, "%d", *((br_int_16 *)mp)); + break; + + case FSM_UINT_16: + w = BrFilePrintf(df->h, "%u", *((br_uint_16 *)mp)); + break; + + case FSM_COLOUR: + w = BrFilePrintf(df->h, "%d,%d,%d", BR_RED(*((br_colour *)mp)), BR_GRN(*((br_colour *)mp)), + BR_BLU(*((br_colour *)mp))); + break; + + case FSM_INT_32: + w = BrFilePrintf(df->h, "%d", *((br_int_32 *)mp)); + break; + + case FSM_UINT_32: + w = BrFilePrintf(df->h, "%u", *((br_uint_32 *)mp)); + break; + + case FSM_FIXED: + w = BrFilePrintf(df->h, "%g", BrFixedToFloat(*((br_fixed_ls *)mp))); + break; + + case FSM_ANGLE: + w = BrFilePrintf(df->h, "%g", BrScalarToFloat(BrAngleToDegree(*((br_angle *)mp)))); + break; + + case FSM_FLOAT: + w = BrFilePrintf(df->h, "%g", *((float *)mp)); + break; + + case FSM_DOUBLE: + w = BrFilePrintf(df->h, "%g", *((double *)mp)); + break; + + case FSM_SCALAR: + w = BrFilePrintf(df->h, "%g", BrScalarToFloat(*((br_scalar *)mp))); + break; + + case FSM_FRACTION: + w = BrFilePrintf(df->h, "%g", BrScalarToFloat(BrFractionToScalar(*((br_fraction *)mp)))); + break; + + case FSM_UFRACTION: + w = BrFilePrintf(df->h, "%g", BrScalarToFloat(BrUFractionToScalar(*((br_ufraction *)mp)))); + break; + + case FSM_ENUM_8: + w = BrFilePrintf(df->h, "%s", EnumToString(sm->extra, *((br_uint_8 *)mp))); + break; + + case FSM_ENUM_16: + w = BrFilePrintf(df->h, "%s", EnumToString(sm->extra, *((br_uint_16 *)mp))); + break; + + case FSM_ENUM_32: + w = BrFilePrintf(df->h, "%s", EnumToString(sm->extra, *((br_uint_32 *)mp))); + break; + + case FSM_VECTOR2: + w = BrFilePrintf(df->h, "%g,%g", BrScalarToFloat(((br_vector2 *)mp)->v[0]), + BrScalarToFloat(((br_vector2 *)mp)->v[1])); + break; + + case FSM_VECTOR3: + w = BrFilePrintf(df->h, "%g,%g,%g", BrScalarToFloat(((br_vector3 *)mp)->v[0]), + BrScalarToFloat(((br_vector3 *)mp)->v[1]), BrScalarToFloat(((br_vector3 *)mp)->v[2])); + break; + + case FSM_VECTOR4: + w = BrFilePrintf(df->h, "%g,%g,%g,%g", BrScalarToFloat(((br_vector4 *)mp)->v[0]), + BrScalarToFloat(((br_vector4 *)mp)->v[1]), BrScalarToFloat(((br_vector4 *)mp)->v[2]), + BrScalarToFloat(((br_vector4 *)mp)->v[3])); + break; + + case FSM_STRUCT: + + w = BrFilePrintf(df->h, "%s", ((br_file_struct *)sm->extra)->name); + + /* + * Put member comment before structure + */ + add_comment = 0; + + if (sm->name) + { + for (i = w; i < 40; i++) + BrFilePutChar(' ', df->h); + + BrFilePrintf(df->h, " # %s", sm->name); + } + BrFilePutChar('\n', df->h); + + StructWriteTextSub(df, sm->extra, mp, indent + 2); + break; + + case FSM_ASCIZ: + if (*((char **)mp)) + w = BrFilePrintf(df->h, "\"%s\"", *((char **)mp)); + else + w = BrFilePrintf(df->h, "NULL"); + break; + } + + /* + * Put member comment at end of line (column 60+indent) + */ + if (add_comment && sm->name) + { + for (i = w; i < 40; i++) + BrFilePutChar(' ', df->h); + + BrFilePrintf(df->h, " # %s\n", sm->name); + } + } + + return 1; +} + +static br_uint_32 StructReadTextSub(br_datafile *df, br_file_struct *str, void *base); + +static br_uint_32 DfStructReadText(br_datafile *df, br_file_struct *str, void *base) +{ + char *id, *data; + + /* + * Check input is the correct structure + */ + TextReadLine(df, &id, &data); + + if (strcmp(id, "struct")) + BR_ERROR1("Unknown text identifer \"%s\"", id); + + if (strcmp(data, str->name)) + BR_ERROR1("Incorrect structure name \"%s\"", data); + + StructReadTextSub(df, str, base); + + return 1; +} + +static br_uint_32 StructReadTextSub(br_datafile *df, br_file_struct *str, void *base) +{ + unsigned int m, r, g, b; + int i, n; + void *mp; + br_file_struct_member *sm; + char *id, *data, *ep; + + /* + * Check input is the correct structure + */ + for (m = 0, sm = str->members; m < str->nmembers; m++, sm++) + { + /* + * Get pointer to destination memory + */ + mp = (char *)base + sm->offset; + + /* + * Read next line + */ + if (!TextReadLine(df, &id, &data)) + BR_ERROR0("Unexpected EOF in strructure"); + + if (strcmp(id, member_type_names[sm->type])) + BR_ERROR1("Unknown member identifer \"%s\"", id); + + /* + * Do type specific processing + */ + switch (sm->type) + { + case FSM_INT_8: + *((br_int_8 *)mp) = (br_int_8)strtol(data, 0, 0); + break; + + case FSM_UINT_8: + *((br_uint_8 *)mp) = (br_uint_8)strtoul(data, 0, 0); + break; + + case FSM_INT_16: + *((br_int_16 *)mp) = (br_int_16)strtol(data, 0, 0); + break; + + case FSM_UINT_16: + *((br_uint_16 *)mp) = (br_uint_16)strtoul(data, 0, 0); + break; + + case FSM_COLOUR: + r = strtoul(data, &ep, 0); + if (*ep != ',') + BR_ERROR0("Incorrect colour"); + + g = strtoul(ep + 1, &ep, 0); + if (*ep != ',') + BR_ERROR0("Incorrect colour"); + + b = strtoul(ep + 1, &ep, 0); + + *((br_colour *)mp) = BR_COLOUR_RGB(r, g, b); + + break; + + case FSM_INT_32: + *((br_int_32 *)mp) = (br_int_32)strtol(data, 0, 0); + break; + + case FSM_UINT_32: + *((br_uint_32 *)mp) = (br_uint_32)strtoul(data, 0, 0); + break; + + case FSM_FIXED: + *((br_fixed_ls *)mp) = BrFloatToFixed(atof(data)); + break; + + case FSM_ANGLE: + *((br_angle *)mp) = BrDegreeToAngle(BrFloatToScalar(atof(data))); + break; + + case FSM_FLOAT: + *((float *)mp) = (float)atof(data); + break; + + case FSM_DOUBLE: + *((double *)mp) = atof(data); + break; + + case FSM_SCALAR: + *((br_scalar *)mp) = BrFloatToScalar(atof(data)); + break; + + case FSM_FRACTION: + *((br_fraction *)mp) = BrScalarToFraction(BrFloatToScalar(atof(data))); + break; + + case FSM_UFRACTION: + *((br_ufraction *)mp) = BrScalarToUFraction(BrFloatToScalar(atof(data))); + break; + + case FSM_ENUM_8: + *((br_uint_8 *)mp) = EnumFromString(sm->extra, data); + break; + + case FSM_ENUM_16: + *((br_uint_16 *)mp) = EnumFromString(sm->extra, data); + break; + + case FSM_ENUM_32: + *((br_uint_32 *)mp) = EnumFromString(sm->extra, data); + break; + + case FSM_VECTOR2: + n = 2; + goto get_vector; + + case FSM_VECTOR3: + n = 3; + goto get_vector; + + case FSM_VECTOR4: + n = 4; + get_vector: + for (i = 0; i < n; i++) + { + while (*data == ',' || ISSPACE(*data)) + data++; + + if (*data == '\0') + BR_ERROR0("Incorrect vector"); + + ((br_vector4 *)mp)->v[i] = BrFloatToScalar(atof(data)); + + while (*data != '\0' && *data != ',' && !ISSPACE(*data)) + data++; + } + break; + + case FSM_STRUCT: + if (strcmp(data, ((br_file_struct *)sm->extra)->name)) + BR_ERROR1("Incorrect structure name \"%s\"", data); + + StructReadTextSub(df, sm->extra, mp); + break; + + case FSM_ASCIZ: + if (!strcmp(data, "NULL") || (*data != '"')) + { + *((char **)mp) = NULL; + } + else + { + *((char **)mp) = BrResStrDup(df->res ? df->res : fw.res, data + 1); + }; + } + } + + return 1; +} + +/* + * Find the number of lines a structure would occupy when written to a + * text file + */ +static int DfStructSizeText(br_datafile *df, br_file_struct *str, void *base) +{ + unsigned int m; + br_file_struct_member *sm; + int lines = 1; /* Structure has 1 line header */ + + /* + * Each member occupies one line, except structures, + * for which we recurse + */ + for (m = 0, sm = str->members; m < str->nmembers; m++, sm++) + { + if (sm->type == FSM_STRUCT) + lines += DfStructSizeText(df, sm->extra, (char *)base + sm->offset); + else + lines++; + } + + return lines; +} + +/* + * Write an array of structures to the current file as a chunk + */ +br_uint_32 DfStructWriteArray(br_datafile *df, br_file_struct *str, void *base, int n) +{ + char *cp = base; + int i; + + for (i = 0; i < n; i++, cp += str->mem_size) + df->prims->struct_write(df, str, cp); + + return i; +} + +/* + * Read a number of structures from a file + */ +br_uint_32 DfStructReadArray(br_datafile *df, br_file_struct *str, void *base, int n) +{ + char *cp = base; + int i; + + for (i = 0; i < n; i++, cp += str->mem_size) + if (BrFileEof(df->h)) + break; + else + df->prims->struct_read(df, str, cp); + + return i; +} + +/** + ** Reading and writing chunk headers + **/ +static char *ChunkNames[] = { + "END", + + "IMAGE_PLANE", + "RLE_IMAGE_PLANE", + "PIXELMAP", + + "MATERIAL", + "ADD_MATERIAL", + + "OLD_ACTOR", + "OLD_ADD_SIBLING", + "OLD_ADD_CHILD", + + "OLD_MATERIAL_INDEX", + "OLD_VERTICES", + "OLD_VERTICES_UV", + "OLD_FACES", + "OLD_MODEL", + + "ADD_MODEL", + + "ANIM", + "ANIM_TRANSFORM", + "ANIM_RATE", + "FILE_INFO", + "OLD_LIGHT", + "OLD_CAMERA", + "PIVOT", + + "MATERIAL_INDEX", + "VERTICES", + "VERTEX_UV", + "OLD_FACES_1", + "FACE_MATERIAL", + "OLD_MODEL_1", + + "COLOUR_MAP_REF", + "OPACITY_MAP_REF", + "INDEX_BLEND_REF", + "INDEX_SHADE_REF", + "SCREENDOOR_REF", + + "PIXELS", + "ADD_MAP", + + "ACTOR", + + "ACTOR_MODEL", + "ACTOR_TRANSFORM", + "ACTOR_MATERIAL", + + "ACTOR_LIGHT", + "ACTOR_CAMERA", + "ACTOR_BOUNDS", + + "ACTOR_ADD_CHILD", + + "TRANSFORM_MATRIX34", + "TRANSFORM_MATRIX34_LP", + "TRANSFORM_QUAT", + "TRANSFORM_EULER", + "TRANSFORM_LOOK_UP", + "TRANSFORM_TRANSLATION", + "TRANSFORM_IDENTITY", + + "BOUNDS", + "LIGHT", + "CAMERA", + + "FACES", + "MODEL", + + "ACTOR_CLIP_PLANE", + "PLANE", + + "SATURN_FACES", + "SATURN_MODEL", +}; + +/* + * Write out a chunk header in text format + */ +static int DfChunkWriteText(br_datafile *df, br_uint_32 id, br_uint_32 length) +{ + ASSERT(id < BR_ASIZE(ChunkNames)); + + if (id < BR_ASIZE(ChunkNames)) + BrFilePrintf(df->h, "*%-16s %d\n", ChunkNames[id], length); + else + BrFilePrintf(df->h, "*0x%08x %d\n", id, length); + + return 0; +} + +/* + * Read a chunk header in text format + */ +static int DfChunkReadText(br_datafile *df, br_uint_32 *plength) +{ + int i; + char *id, *data; + + if (!TextReadLine(df, &id, &data)) + return -1; + + if (id[0] != '*') + BR_ERROR0("Chunk ID not found"); + + id++; + + /* + * Convert or look up name + */ + if (id[0] == '0') + { + i = strtoul(id, 0, 0); + } + else + { + for (i = 0; i < BR_ASIZE(ChunkNames); i++) + if (!strcmp(ChunkNames[i], id)) + break; + + if (i >= BR_ASIZE(ChunkNames)) + BR_ERROR1("Chunk ID not known: %s", id); + } + + /* + * Convert length + */ + if (plength) + *plength = strtoul(data, 0, 0); + + return i; +} + +/* + * Write out a chunk header in binary format + */ +static int DfChunkWriteBinary(br_datafile *df, br_uint_32 id, br_uint_32 length) +{ + br_uint_32 l; + + l = BrHtoNL(id); + BrFileWrite(&l, sizeof(l), 1, df->h); + + l = BrHtoNL(length); + BrFileWrite(&l, sizeof(l), 1, df->h); + + return 0; +} + +/* + * Read a chunk header in binary format + */ +static int DfChunkReadBinary(br_datafile *df, br_uint_32 *plength) +{ + br_uint_32 id, l; + + if (BrFileEof(df->h)) + return -1; + + BrFileRead(&id, sizeof(id), 1, df->h); + + if (BrFileEof(df->h)) + return -1; + + id = BrHtoNL(id); + + BrFileRead(&l, sizeof(l), 1, df->h); + + if (BrFileEof(df->h)) + return -1; + + if (plength) + *plength = BrHtoNL(l); + + return id; +} + +static void DfCountWriteText(br_datafile *df, br_uint_32 count) +{ + BrFilePrintf(df->h, " count %d\n", count); +} + +static br_uint_32 DfCountReadText(br_datafile *df) +{ + char *id, *data; + + TextReadLine(df, &id, &data); + + if (strcmp(id, "count")) + BR_ERROR0("no element count for chunk"); + + return strtoul(data, 0, 0); +} + +static void DfCountWriteBinary(br_datafile *df, br_uint_32 count) +{ + br_uint_32 l; + + l = BrHtoNL(count); + BrFileWrite(&l, sizeof(l), 1, df->h); +} + +static br_uint_32 DfCountReadBinary(br_datafile *df) +{ + br_uint_32 l; + + BrFileRead(&l, sizeof(l), 1, df->h); + + return BrHtoNL(l); +} + +int DfCountSizeText(br_datafile *df) +{ + return 1; +} + +static int DfCountSizeBinary(br_datafile *df) +{ + return sizeof(br_uint_32); +} + +static br_uint_8 *BlockWriteSetup(void *base, int block_size, int block_stride, int block_count, int size) +{ + int b; + br_uint_8 *block, *sp, *dp; + +#if 1 + /* + * If blocks are contiguous, merge into 1 block + */ + if (block_stride == block_size) + { + block_size *= block_count; + block_count = 1; + } +#endif + +#if !BR_ENDIAN_BIG + if (size == 1 && block_count == 1) +#else + if (block_count == 1) +#endif + return base; + + block = BrScratchAllocate(block_count * block_size * size); + + sp = base; + dp = block; + + for (b = 0; b < block_count; b++) + { + memcpy(dp, sp, block_size * size); + sp += block_stride; + dp += block_size * size; + } + +#if !BR_ENDIAN_BIG + BrSwapBlock(block, block_size * block_count, size); +#endif + + return block; +} + +/* + * Write out a block of elements in text format + */ +static int DfBlockWriteText(br_datafile *df, void *base, int block_size, int block_stride, int block_count, int size) +{ + int i, b; + br_uint_8 *cp, *block; + int count = block_count * block_size; + + block = BlockWriteSetup(base, block_size, block_stride, block_count, size); + + BrFilePrintf(df->h, " block %d\n", count); + BrFilePrintf(df->h, " size %d\n", size); + + for (i = 0, cp = block; i < size * count; i++, cp++) + { + if ((i % TEXT_BLOCK_LINE) == 0) + BrFilePrintf(df->h, " %08x: %02x", i, *cp); + else + BrFilePrintf(df->h, "%02x", *cp); + + if ((i % TEXT_BLOCK_LINE) == (TEXT_BLOCK_LINE - 1)) + BrFilePutChar('\n', df->h); + } + + if ((i % TEXT_BLOCK_LINE) != 0) + BrFilePutChar('\n', df->h); + + /* + * Release any allocated buffer + */ + if (block != base) + BrScratchFree(block); + + return 0; +} + +/* + * Read a block of bytes in text format + */ +static void *DfBlockReadText(br_datafile *df, void *base, int *count, int size, int mtype) +{ + char *id, *data; + int l, s, a; + char b[3]; + + /* + * Find length of incoming block + */ + TextReadLine(df, &id, &data); + if (strcmp(id, "block")) + BR_ERROR0("no block"); + l = strtoul(data, 0, 0); + + TextReadLine(df, &id, &data); + if (strcmp(id, "size")) + BR_ERROR0("no size"); + s = strtoul(data, 0, 0); + + if (s != size) + BR_ERROR0("block size mismatch"); + + if (base == NULL) + { + /* + * If no existing block, allocate a new one and read data in + */ + base = BrResAllocate(df->res ? df->res : fw.res, (br_size_t)l * size, (br_uint_8)mtype); + } + else + { + /* + * An existing block - limit the amount read + */ + if (*count < l) + BR_ERROR1("DfBlockReadText: block too long: %d", l); + } + + /* + * Return the actual size + */ + *count = l; + + /* + * Read the block + */ + a = 0; + b[2] = '\0'; + while (a < l * size) + { + TextReadLine(df, &id, &data); + + /* + * Check address of line + */ + if (a != strtol(id, 0, 16)) + BR_ERROR0("block address mismatch"); + + /* + * Consume pairs of hex digits + */ + for (; data[0] && data[1]; data += 2, a++) + { + b[0] = data[0]; + b[1] = data[1]; + ((br_uint_8 *)base)[a] = (br_uint_8)strtoul(b, 0, 16); + } + } + + /* + * Byte swap it if necessary + */ +#if !BR_ENDIAN_BIG + BrSwapBlock(base, l, size); +#endif + return base; +} + +/* + * Write out a block of bytes in binary format + */ +static int DfBlockWriteBinary(br_datafile *df, void *base, int block_size, int block_stride, int block_count, int size) +{ + int count = block_size * block_count; + br_uint_32 l = BrHtoNL(count); + br_uint_32 s = BrHtoNL(size); + void *block; + + block = BlockWriteSetup(base, block_size, block_stride, block_count, size); + + BrFileWrite(&l, sizeof(l), 1, df->h); + BrFileWrite(&s, sizeof(s), 1, df->h); + BrFileWrite(block, count, size, df->h); + + /* + * Release any allocated buffer + */ + if (block != base) + BrScratchFree(block); + + return 0; +} + +/* + * Read a block of bytes in binary format + */ +static void *DfBlockReadBinary(br_datafile *df, void *base, int *count, int size, int mtype) +{ + int l, s; + + /* + * Find length of incoming block + */ + BrFileRead(&l, sizeof(l), 1, df->h); + l = BrHtoNL(l); + + BrFileRead(&s, sizeof(s), 1, df->h); + s = BrHtoNL(s); + + if (s != size) + BR_ERROR0("block size mismatch"); + + if (base == NULL) + { + /* + * If no existing block, allocate a new one and read data in + */ + base = BrResAllocate(df->res ? df->res : fw.res, (br_size_t)l * size, (br_uint_8)mtype); + } + else + { + /* + * An existing block - limit the amount read + */ + if (*count < l) + BR_ERROR1("DfBlockReadBinary: block too long: %d", l); + } + + /* + * Return the actual size + */ + *count = l; + + /* + * Read the block + */ + BrFileRead(base, l, size, df->h); + +#if !BR_ENDIAN_BIG + BrSwapBlock(base, l, size); +#endif + + return base; +} + +/* + * Return size of a block of bytes in text format + */ +static int DfBlockSizeText(br_datafile *df, void *base, int block_size, int block_stride, int block_count, int size) +{ + return (size * block_count * block_size + TEXT_BLOCK_LINE - 1) / TEXT_BLOCK_LINE + 2; +} + +/* + * Return size of a block of bytes in binary format + */ +static int DfBlockSizeBinary(br_datafile *df, void *base, int block_size, int block_stride, int block_count, int size) +{ + return size * block_count * block_size + sizeof(br_uint_32) * 2; +} + +/** + ** Names + **/ +static char *DfNameReadText(br_datafile *df, char *name) +{ + char *id, *data; + + TextReadLine(df, &id, &data); + + if (strcmp(id, "name")) + BR_ERROR0("no name"); + if (data == NULL || *data != '\"') + BR_ERROR0("no name string"); + + /* + * Copy name into callers buffer + */ + strncpy(name, data + 1, BR_MAX_NAME - 1); + name[BR_MAX_NAME - 1] = '\0'; + + return name; +} + +static int DfNameWriteText(br_datafile *df, char *name) +{ + BrFilePrintf(df->h, " name \"%s\"\n", name ? name : "NULL"); + + return 0; +} + +static int DfNameSizeText(br_datafile *df, char *name) +{ + return 1; +} + +static char *DfNameReadBinary(br_datafile *df, char *name) +{ + int c; + int i; + + for (i = 0; i < BR_MAX_NAME - 1; i++) + { + c = BrFileGetChar(df->h); + if (c == '\0' || c == BR_EOF) + break; + + name[i] = c; + } + + /* + * Terminate + */ + name[i] = '\0'; + + return name; +} + +static int DfNameWriteBinary(br_datafile *df, char *name) +{ + if (name) + BrFileWrite(name, 1, strlen(name), df->h); + + BrFilePutChar('\0', df->h); + return 0; +} + +static int DfNameSizeBinary(br_datafile *df, char *name) +{ + if (name) + return strlen(name + 1); + else + return 1; +} + +/* + * Skip a given length in text file + */ +static int DfSkipText(br_datafile *df, br_uint_32 length) +{ + char *id, *data; + + while (!BrFileEof(df->h) && length--) + TextReadLine(df, &id, &data); + + return 0; +} + +/* + * Skip a given length in binary file + */ +static int DfSkipBinary(br_datafile *df, br_uint_32 length) +{ + BrFileAdvance(length, df->h); + + return 0; +} + +/* + * Interpret a stream of chunks from a file by calling + * routines looked up from a given table + */ +int DfChunksInterpret(br_datafile *df, br_chunks_table *table) +{ + br_uint_32 length, count; + br_uint_32 id; + int r, i; + +#if CHUNK_LOG + BrLogPrintf("ChunkInterpret\n"); +#endif + /* + * Consume chunks until End Of File or a handler return != 0 + * + * Return 0 at EOF, or handler return + */ + for (;;) + { + + /* + * Read the next chunk header + */ + id = df->prims->chunk_read(df, &length); + + /* + * Catch EOF + */ + if (id == 0xFFFFFFFF) + { +#if CHUNK_LOG + BrLogPrintf("EOF\n"); +#endif + return 0; + } + + /* + * Lookup ID in table + */ + for (i = 0; i < table->nentries; i++) + if (id == table->entries[i].id) + break; + +#if CHUNK_LOG + BrLogPrintf("%s ", ChunkNames[id]); +#endif + + /* + * If handler exists, call it (with count if needed) + */ + if (i < table->nentries) + { +#if CHUNK_LOG + BrLogPrintf("calling\n"); +#endif + if (table->entries[i].has_count) + { + count = df->prims->count_read(df); + } + else + { + count = 0; + } + + r = table->entries[i].handler(df, id, length, count); + if (r) + return r; + } + else + { +#if CHUNK_LOG + BrLogPrintf("skipping\n"); +#endif + df->prims->skip(df, length); + } + } +} + +static void BrNullOther(void) +{ + BR_FATAL0("Invald file primitive call"); +} + +/* + * Handler structures for getting at the above functions + */ +br_file_primitives _BrFilePrimsNull = { + "NULL", /* identifier */ + + (void *)BrNullOther, /* skip */ + + (void *)BrNullOther, /* chunk_write */ + (void *)BrNullOther, /* chunk_read */ + + (void *)BrNullOther, /* count_write */ + (void *)BrNullOther, /* count_read */ + (void *)BrNullOther, /* count_size */ + + (void *)BrNullOther, /* struct_write */ + (void *)BrNullOther, /* struct_read */ + (void *)BrNullOther, /* struct_size */ + + (void *)BrNullOther, /* block_write */ + (void *)BrNullOther, /* block_read */ + (void *)BrNullOther, /* block_size */ + + (void *)BrNullOther, /* name_write */ + (void *)BrNullOther, /* name_read */ + (void *)BrNullOther, /* name_size */ +}; + +static br_file_primitives _BrFilePrimsReadBinary = { + "Read Binary", /* identifier */ + + (void *)DfSkipBinary, /* skip */ + + (void *)BrNullOther, /* chunk_write */ + (void *)DfChunkReadBinary, /* chunk_read */ + + (void *)BrNullOther, /* count_write */ + (void *)DfCountReadBinary, /* count_read */ + (void *)DfCountSizeBinary, /* count_size */ + + (void *)BrNullOther, /* struct_write */ + (void *)DfStructReadBinary, /* struct_read */ + (void *)DfStructSizeBinary, /* struct_size */ + + (void *)BrNullOther, /* block_write */ + (void *)DfBlockReadBinary, /* block_read */ + (void *)DfBlockSizeBinary, /* block_size */ + + (void *)BrNullOther, /* name_write */ + (void *)DfNameReadBinary, /* name_read */ + (void *)DfNameSizeBinary, /* name_size */ +}; + +static br_file_primitives _BrFilePrimsWriteBinary = { + "Write Binary", /* identifier */ + + (void *)DfSkipBinary, /* skip */ + + (void *)DfChunkWriteBinary, /* chunk_write */ + (void *)BrNullOther, /* chunk_read */ + + (void *)DfCountWriteBinary, /* count_write */ + (void *)BrNullOther, /* count_read */ + (void *)DfCountSizeBinary, /* count_size */ + + (void *)DfStructWriteBinary, /* struct_write */ + (void *)BrNullOther, /* struct_read */ + (void *)DfStructSizeBinary, /* struct_size */ + + (void *)DfBlockWriteBinary, /* block_write */ + (void *)BrNullOther, /* block_read */ + (void *)DfBlockSizeBinary, /* block_size */ + + (void *)DfNameWriteBinary, /* name_write */ + (void *)BrNullOther, /* name_read */ + (void *)DfNameSizeBinary, /* name_size */ +}; + +static br_file_primitives _BrFilePrimsReadText = { + "Read Text", /* identifier */ + + (void *)DfSkipText, /* skip */ + + (void *)BrNullOther, /* chunk_write */ + (void *)DfChunkReadText, /* chunk_read */ + + (void *)BrNullOther, /* count_write */ + (void *)DfCountReadText, /* count_read */ + (void *)DfCountSizeText, /* count_size */ + + (void *)BrNullOther, /* struct_write */ + (void *)DfStructReadText, /* struct_read */ + (void *)DfStructSizeText, /* struct_size */ + + (void *)BrNullOther, /* block_write */ + (void *)DfBlockReadText, /* block_read */ + (void *)DfBlockSizeText, /* block_size */ + + (void *)BrNullOther, /* name_write */ + (void *)DfNameReadText, /* name_read */ + (void *)DfNameSizeText, /* name_size */ +}; + +static br_file_primitives _BrFilePrimsWriteText = { + "Write Text", /* identifier */ + + (void *)DfSkipText, /* skip */ + + (void *)DfChunkWriteText, /* chunk_write */ + (void *)BrNullOther, /* chunk_read */ + + (void *)DfCountWriteText, /* count_write */ + (void *)BrNullOther, /* count_read */ + (void *)DfCountSizeText, /* count_size */ + + (void *)DfStructWriteText, /* struct_write */ + (void *)BrNullOther, /* struct_read */ + (void *)DfStructSizeText, /* struct_size */ + + (void *)DfBlockWriteText, /* block_write */ + (void *)BrNullOther, /* block_read */ + (void *)DfBlockSizeText, /* block_size */ + + (void *)DfNameWriteText, /* name_write */ + (void *)BrNullOther, /* name_read */ + (void *)DfNameSizeText, /* name_size */ +}; + +/* + * Identify a file type from it's magic numbers + */ +static int BR_CALLBACK DfFileIdentify(br_uint_8 *magics, br_size_t n_magics) +{ + static char text_magics[8] = "*FILE_IN"; + static char binary_magics[8] = "\0\0\0\022\0\0\0\010"; + + ASSERT(n_magics == BR_ASIZE(text_magics)); + + if (!memcmp(magics, text_magics, BR_ASIZE(text_magics))) + return BR_FS_MODE_TEXT; + + ASSERT(n_magics == BR_ASIZE(binary_magics)); + if (!memcmp(magics, binary_magics, BR_ASIZE(binary_magics))) + return BR_FS_MODE_BINARY; + + return BR_FS_MODE_UNKNOWN; +} + +/* + * Sets up a new current datafile for reading or writing, working out whether it + * is in text mode or not, returns true if open suceeded + */ +br_datafile *DfOpen(char *name, int write) +{ + int mode = fw.open_mode; + br_datafile *df; + void *h; + + /* + * Try and open file + */ + if (write) + h = BrFileOpenWrite(name, mode); + else + h = BrFileOpenRead(name, 2 * sizeof(br_uint_32), DfFileIdentify, &mode); + + /* + * Set up datafile structure + */ + + if (h == NULL) + return NULL; + + df = BrResAllocate(fw.res, sizeof(*df), BR_MEMORY_DATAFILE); + df->h = h; + df->prims = &_BrFilePrimsNull; + + switch (mode) + { + case BR_FS_MODE_TEXT: + df->prims = write ? &_BrFilePrimsWriteText : &_BrFilePrimsReadText; + break; + + case BR_FS_MODE_BINARY: + df->prims = write ? &_BrFilePrimsWriteBinary : &_BrFilePrimsReadBinary; + break; + } + + /* + * Put a mark on stack + */ + DfPush(DFST_MARK, df, 1); + + return df; +} + +/* + * Close the current datafile + */ +void DfClose(br_datafile *df) +{ + br_datafile *dfp; + + UASSERT(df != NULL); + ASSERT(df->h != NULL); + + /* + * Clear back down to mark + */ + while (DfTopType() != DFST_MARK) + DfPop(DfTopType(), NULL); + + /* + * Check for correct mark + */ + dfp = DfPop(DFST_MARK, NULL); + ASSERT(df == dfp); + + BrFileClose(df->h); + + BrResFree(df); +} + +/* + * Set the current output mode + */ +int BR_PUBLIC_ENTRY BrWriteModeSet(int mode) +{ + int old = fw.open_mode; + + fw.open_mode = mode; + + return old; +} diff --git a/bren/FW/datafile.h b/bren/FW/datafile.h new file mode 100644 index 00000000..10735b40 --- /dev/null +++ b/bren/FW/datafile.h @@ -0,0 +1,493 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: datafile.h 1.22 1995/08/31 16:29:22 sam Exp $ + * $Locker: $ + * + * Constants and structures inside a 3d data file + */ + +#ifndef _DATAFILE_H_ +#define _DATAFILE_H_ + +#ifndef _BRHTON_H_ +#include "brhton.h" +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * Version number written into new files + */ +#define BR_FILE_VERSION 2 + +/* + * File open modes + */ +#define DFOPEN_READ 0 +#define DFOPEN_WRITE 1 +#define DFOPEN_BINARY 2 + + /* + * File chunk IDs + */ + enum + { + FID_END, + + FID_IMAGE_PLANE, /* UNUSED */ + FID_RLE_IMAGE_PLANE, /* UNUSED */ + FID_PIXELMAP, + + FID_MATERIAL, + FID_ADD_MATERIAL, /* UNUSED */ + + FID_OLD_ACTOR, /* UNUSED */ + FID_OLD_ADD_SIBLING, /* UNUSED */ + FID_OLD_ADD_CHILD, /* UNUSED */ + + FID_OLD_MATERIAL_INDEX, + FID_OLD_VERTICES, + FID_OLD_VERTICES_UV, + FID_OLD_FACES, + FID_OLD_MODEL, + + FID_ADD_MODEL, + + FID_ANIM, + FID_ANIM_TRANSFORM, + FID_ANIM_RATE, + FID_FILE_INFO, + FID_OLD_LIGHT, /* UNUSED */ + FID_OLD_CAMERA, /* UNUSED */ + FID_PIVOT, + + FID_MATERIAL_INDEX, + FID_VERTICES, + FID_VERTEX_UV, + FID_OLD_FACES_1, + FID_FACE_MATERIAL, + FID_OLD_MODEL_1, + + FID_COLOUR_MAP_REF, + FID_OPACITY_MAP_REF, /* UNUSED */ + FID_INDEX_BLEND_REF, + FID_INDEX_SHADE_REF, + FID_SCREENDOOR_REF, + + FID_PIXELS, + FID_ADD_MAP, + + FID_ACTOR, + + FID_ACTOR_MODEL, + FID_ACTOR_TRANSFORM, + FID_ACTOR_MATERIAL, + + FID_ACTOR_LIGHT, + FID_ACTOR_CAMERA, + FID_ACTOR_BOUNDS, + + FID_ACTOR_ADD_CHILD, + + FID_TRANSFORM_MATRIX34, + FID_TRANSFORM_MATRIX34_LP, + FID_TRANSFORM_QUAT, + FID_TRANSFORM_EULER, + FID_TRANSFORM_LOOK_UP, + FID_TRANSFORM_TRANSLATION, + FID_TRANSFORM_IDENTITY, + + FID_BOUNDS, + FID_LIGHT, + FID_CAMERA, + + FID_FACES, + FID_MODEL, + + FID_ACTOR_CLIP_PLANE, + FID_PLANE, + + FID_SATURN_FACES, + FID_SATURN_MODEL + }; + + /* + * Data Stack types + */ + enum + { + DFST_NONE, + DFST_IMAGE_PLANE, + DFST_PIXELMAP, + DFST_MATERIAL, + DFST_ACTOR, + DFST_MATERIAL_INDEX, + DFST_VERTICES, + DFST_FACES, + DFST_MODEL, + DFST_ANIM, + DFST_ANIM_NAME, + DFST_ANIM_TRANSFORM, + DFST_ANIM_COUNT, + DFST_ANIM_RATE, + DFST_FILE_INFO, + DFST_PIVOT, + DFST_TRANSFORM, + DFST_LIGHT, + DFST_CAMERA, + DFST_BOUNDS, + DFST_PLANE, + DFST_MARK, + + DFST_SATURN_FACES, + DFST_SATURN_MODEL, + + DFST_MAX + }; + + /* + * File info types + */ + enum + { + FILE_TYPE_NONE, + + /* FILE_TYPE_MODEL, */ + FILE_TYPE_ACTORS, + /* FILE_TYPE_ANIMATION, */ + FILE_TYPE_PIXELMAP, + FILE_TYPE_LIGHT, + FILE_TYPE_CAMERA, + FILE_TYPE_MATERIAL, + + /* + * Old Types + */ + FILE_TYPE_MODEL = 0xFACE, + FILE_TYPE_ANIMATION = 0x0A11, + FILE_TYPE_TREE = 0x5EED + }; + + /** + ** General structure reading/writing system + **/ + + /* + * Member types + */ + enum + { + FSM_INT_8, + FSM_UINT_8, + FSM_INT_16, + FSM_UINT_16, + FSM_INT_32, + FSM_UINT_32, + FSM_FIXED, + FSM_ANGLE, + FSM_FLOAT, + FSM_DOUBLE, + FSM_SCALAR, + FSM_FRACTION, + FSM_UFRACTION, + FSM_ENUM_8, + FSM_ENUM_16, + FSM_ENUM_32, + FSM_STRUCT, + FSM_ASCIZ, + FSM_COLOUR, + FSM_VECTOR2, + FSM_VECTOR3, + FSM_VECTOR4 + }; + + typedef struct br_file_struct_member + { + br_uint_16 type; /* Type of member */ + br_uint_32 offset; /* Offset in memory from base of structure */ + char *name; /* text identifier for debug purposes */ + void *extra; /* Any extra type data */ + } br_file_struct_member; + + typedef struct br_file_struct + { + char *name; + br_uint_32 nmembers; + br_file_struct_member *members; + int mem_size; + } br_file_struct; + +/* + * Some nasty macros to make building structure descriptions easier + * Requires that a macro _STRUCT_NAME be defined - the type of the + * structure being referenced + */ +#define _INT_8(m) \ + { \ + FSM_INT_8, offsetof(_STRUCT_NAME, m), #m \ + } +#define _UINT_8(m) \ + { \ + FSM_UINT_8, offsetof(_STRUCT_NAME, m), #m \ + } +#define _INT_16(m) \ + { \ + FSM_INT_16, offsetof(_STRUCT_NAME, m), #m \ + } +#define _UINT_16(m) \ + { \ + FSM_UINT_16, offsetof(_STRUCT_NAME, m), #m \ + } +#define _INT_32(m) \ + { \ + FSM_INT_32, offsetof(_STRUCT_NAME, m), #m \ + } +#define _UINT_32(m) \ + { \ + FSM_UINT_32, offsetof(_STRUCT_NAME, m), #m \ + } +#define _FIXED(m) \ + { \ + FSM_FIXED, offsetof(_STRUCT_NAME, m), #m \ + } +#define _ANGLE(m) \ + { \ + FSM_ANGLE, offsetof(_STRUCT_NAME, m), #m \ + } +#define _FLOAT(m) \ + { \ + FSM_FLOAT, offsetof(_STRUCT_NAME, m), #m \ + } +#define _DOUBLE(m) \ + { \ + FSM_DOUBLE, offsetof(_STRUCT_NAME, m), #m \ + } +#define _SCALAR(m) \ + { \ + FSM_SCALAR, offsetof(_STRUCT_NAME, m), #m \ + } +#define _FRACTION(m) \ + { \ + FSM_FRACTION, offsetof(_STRUCT_NAME, m), #m \ + } +#define _UFRACTION(m) \ + { \ + FSM_UFRACTION, offsetof(_STRUCT_NAME, m), #m \ + } +#define _ENUM_8(m, e) \ + { \ + FSM_ENUM_8, offsetof(_STRUCT_NAME, m), #m, &(e) \ + } +#define _ENUM_16(m, e) \ + { \ + FSM_ENUM_16, offsetof(_STRUCT_NAME, m), #m, &(e) \ + } +#define _ENUM_32(m, e) \ + { \ + FSM_ENUM_32, offsetof(_STRUCT_NAME, m), #m, &(e) \ + } +#define _STRUCT(m, s) \ + { \ + FSM_STRUCT, offsetof(_STRUCT_NAME, m), #m, &(s) \ + } +#define _ASCIZ(m) \ + { \ + FSM_ASCIZ, offsetof(_STRUCT_NAME, m), #m \ + } +#define _COLOUR(m) \ + { \ + FSM_COLOUR, offsetof(_STRUCT_NAME, m), #m \ + } +#define _VECTOR2(m) \ + { \ + FSM_VECTOR2, offsetof(_STRUCT_NAME, m), #m \ + } +#define _VECTOR3(m) \ + { \ + FSM_VECTOR3, offsetof(_STRUCT_NAME, m), #m \ + } +#define _VECTOR4(m) \ + { \ + FSM_VECTOR4, offsetof(_STRUCT_NAME, m), #m \ + } + +#define _FILE_STRUCT(name) \ + br_file_struct name##_F = { \ + #name, \ + BR_ASIZE(name##_FM), \ + name##_FM, \ + sizeof(_STRUCT_NAME), \ + } + + /* + * Structures for describing an enum + */ + typedef struct br_file_enum_member + { + int value; + char *name; + } br_file_enum_member; + + typedef struct br_file_enum + { + br_uint_32 nmembers; + br_file_enum_member *members; + } br_file_enum; + +/* + * Macros for building enums + */ +#define _ENUM_MEMBER(e) \ + { \ + e, #e \ + } + +#define _FILE_ENUM(name) \ + br_file_enum name##_F = { \ + BR_ASIZE(name##_FM), \ + name##_FM, \ + } + +/* + * Constants used to grab bytes out of a byte array mapped onto each type + */ +#if BR_ENDIAN_BIG + +#define BR_HTON_64(b) (b) +#define BR_HTON_32(b) (b) +#define BR_HTON_24(b) (b) +#define BR_HTON_16(b) (b) +#define BR_HTON_8(b) (b) +#define BR_HTON_F(b) (b) +#define BR_HTON_D(b) (b) + +#define BR_NTOH_64(b) (b) +#define BR_NTOH_32(b) (b) +#define BR_NTOH_24(b) (b) +#define BR_NTOH_16(b) (b) +#define BR_NTOH_8(b) (b) +#define BR_NTOH_F(b) (b) +#define BR_NTOH_D(b) (b) + +#endif + +#if BR_ENDIAN_LITTLE + +#define BR_HTON_64(b) (7 - (b)) +#define BR_HTON_32(b) (3 - (b)) +#define BR_HTON_24(b) (2 - (b)) +#define BR_HTON_16(b) (1 - (b)) +#define BR_HTON_8(b) (b) +#define BR_HTON_F(b) (3 - (b)) +#define BR_HTON_D(b) (7 - (b)) + +#define BR_NTOH_64(b) (7 - (b)) +#define BR_NTOH_32(b) (3 - (b)) +#define BR_NTOH_24(b) (2 - (b)) +#define BR_NTOH_16(b) (1 - (b)) +#define BR_NTOH_8(b) (b) +#define BR_NTOH_F(b) (3 - (b)) +#define BR_NTOH_D(b) (7 - (b)) + +#endif + + struct br_file_primitives; + + typedef struct br_datafile + { + /* + * File handle + */ + void *h; + + /* + * Primitives + */ + struct br_file_primitives *prims; + + /* + * Resource that any datafile allocations should be attached to + */ + void *res; + + } br_datafile; + + /* + * Table used to associate chunk ID's with handlers + */ + typedef struct br_chunks_table_entry + { + br_uint_32 id; + br_uint_8 has_count; + int (*handler)(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count); + } br_chunks_table_entry; + + typedef struct br_chunks_table + { + int nentries; + br_chunks_table_entry *entries; + } br_chunks_table; + + /* + * Vector of functions for reading and writing datafile primitives + */ + typedef struct br_file_primitives + { + + char *identifier; + + /* + * High level file operations + */ + + int (*skip)(br_datafile *df, br_uint_32 length); + + int (*chunk_write)(br_datafile *df, br_uint_32 id, br_uint_32 length); + int (*chunk_read)(br_datafile *df, br_uint_32 *plength); + + void (*count_write)(br_datafile *df, br_uint_32 count); + br_uint_32 (*count_read)(br_datafile *df); + int (*count_size)(br_datafile *df); + + br_uint_32 (*struct_write)(br_datafile *df, br_file_struct *str, void *base); + br_uint_32 (*struct_read)(br_datafile *df, br_file_struct *str, void *base); + int (*struct_size)(br_datafile *df, br_file_struct *str, void *base); + + int (*block_write)(br_datafile *df, void *base, int block_size, int block_stride, int block_count, int size); + void *(*block_read)(br_datafile *df, void *base, int *pcount, int size, int mtype); + int (*block_size)(br_datafile *df, void *base, int block_size, int block_stride, int block_count, int size); + + int (*name_write)(br_datafile *df, char *name); + char *(*name_read)(br_datafile *df, char *name); + int (*name_size)(br_datafile *df, char *name); + + } br_file_primitives; + +#ifndef NO_PROTOTYPES + /* + * Datafile prototypes - thse are here so that 'trusted' applications + * can get lower level access to the file IO by including "datafile.h" + * as well as "brender.h" + */ + void *DfPop(int type, int *countp); + void DfPush(int type, void *value, int count); + void *DfTop(int type, int *countp); + int DfTopType(void); + + int DfChunksInterpret(br_datafile *df, struct br_chunks_table *table); + + br_uint_32 DfStructWriteArray(br_datafile *df, struct br_file_struct *str, void *base, int n); + br_uint_32 DfStructReadArray(br_datafile *df, struct br_file_struct *str, void *base, int n); + + br_datafile *DfOpen(char *name, int write); + void DfClose(br_datafile *df); +#endif + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/bren/FW/def_mat.c b/bren/FW/def_mat.c new file mode 100644 index 00000000..3a9dbca2 --- /dev/null +++ b/bren/FW/def_mat.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: def_mat.c 1.4 1995/02/22 21:41:31 sam Exp $ + * $Locker: $ + * + * default material + */ +#include "brender.h" + +static char rscid[] = "$Id: def_mat.c 1.4 1995/02/22 21:41:31 sam Exp $"; + +/* + * Default material - this should really be in the renderer structure + * so that private fields can be per renderer + */ +br_material _BrDefaultMaterial = { + "default", + BR_COLOUR_RGB(255, 255, 255), /* colour */ + 255, /* opacity */ + + BR_UFRACTION(0.10), /* Indexed ka */ + BR_UFRACTION(0.70), /* kd */ + BR_UFRACTION(0.0), /* ks */ + + BR_SCALAR(20), /* power */ + BR_MATF_LIGHT, /* flags */ + {{ + BR_VECTOR2(1, 0), /* map transform */ + BR_VECTOR2(0, 1), + BR_VECTOR2(0, 0), + }}, + 0, + 63, /* index base/range */ +}; diff --git a/bren/FW/def_mdl.c b/bren/FW/def_mdl.c new file mode 100644 index 00000000..dad99ba9 --- /dev/null +++ b/bren/FW/def_mdl.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: def_mdl.c 1.13 1995/03/29 16:40:59 sam Exp $ + * $Locker: $ + * + * default model for when an actor is created - a cube of the default + * material + */ +#include "brender.h" + +static char rscid[] = "$Id: def_mdl.c 1.13 1995/03/29 16:40:59 sam Exp $"; + +/* + * 8 Vertices + */ +static br_vertex default_model_vertices[] = { + {BR_VECTOR3(-1.0, -1.0, 1.0), BR_VECTOR2(0.00, 0.99)}, /* 0 */ + {BR_VECTOR3(1.0, -1.0, 1.0), BR_VECTOR2(0.99, 0.99)}, /* 1 */ + {BR_VECTOR3(1.0, 1.0, 1.0), BR_VECTOR2(0.99, 0.99)}, /* 2 */ + {BR_VECTOR3(-1.0, 1.0, 1.0), BR_VECTOR2(0.00, 0.99)}, /* 3 */ + {BR_VECTOR3(-1.0, -1.0, -1.0), BR_VECTOR2(0.00, 0.00)}, /* 4 */ + {BR_VECTOR3(1.0, -1.0, -1.0), BR_VECTOR2(0.99, 0.00)}, /* 5 */ + {BR_VECTOR3(1.0, 1.0, -1.0), BR_VECTOR2(0.99, 0.00)}, /* 6 */ + {BR_VECTOR3(-1.0, 1.0, -1.0), BR_VECTOR2(0.00, 0.00)}, /* 7 */ +}; + +/* + * 12 Faces + */ +static br_face default_model_faces[] = { + {{0, 1, 2}, {0}, NULL, 1}, /* 0 */ + {{0, 2, 3}, {0}, NULL, 1}, /* 1 */ + {{0, 4, 5}, {0}, NULL, 1}, /* 2 */ + {{0, 5, 1}, {0}, NULL, 1}, /* 3 */ + {{1, 5, 6}, {0}, NULL, 1}, /* 4 */ + {{1, 6, 2}, {0}, NULL, 1}, /* 5 */ + {{2, 6, 7}, {0}, NULL, 1}, /* 6 */ + {{2, 7, 3}, {0}, NULL, 1}, /* 7 */ + {{3, 7, 4}, {0}, NULL, 1}, /* 8 */ + {{3, 4, 0}, {0}, NULL, 1}, /* 9 */ + {{4, 7, 6}, {0}, NULL, 1}, /* 10 */ + {{4, 6, 5}, {0}, NULL, 1}, /* 11 */ +}; + +br_model _BrDefaultModel = { + "default_model", /* identifier */ + default_model_vertices, /* vertices */ + default_model_faces, /* faces */ + 8, /* nvertices */ + 12, /* nfaces */ + BR_VECTOR3(0.0, 0.0, 0.0), /* pivot */ + BR_MODF_KEEP_ORIGINAL, /* Flags */ +}; diff --git a/bren/FW/defdiag.c b/bren/FW/defdiag.c new file mode 100644 index 00000000..0773a849 --- /dev/null +++ b/bren/FW/defdiag.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: defdiag.c 1.1 1995/07/28 19:03:09 sam Exp $ + * $Locker: $ + * + * Default diagnostic handler that does nothing + */ +#include + +static void BrNullWarning(char *message) +{ +} + +static void BrNullFailure(char *message) +{ +} + +/* + * DiagHandler structure + */ +br_errorhandler BrNullDiagHandler = { + "Null DiagHandler", + BrNullWarning, + BrNullFailure, +}; + +/* + * Global variable that can be overridden by linking something first + */ +br_diaghandler *_BrDefaultDiagHandler = &BrNullDiagHandler; diff --git a/bren/FW/deferr.c b/bren/FW/deferr.c new file mode 100644 index 00000000..2a27d05a --- /dev/null +++ b/bren/FW/deferr.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: deferr.c 1.3 1995/07/28 19:01:37 sam Exp $ + * $Locker: $ + * + * Default diagnostic handler that does nothing + */ +#include + +static void BrNullWarning(char *message) +{ +} + +static void BrNullFailure(char *message) +{ +} + +/* + * DiagHandler structure + */ +br_errorhandler BrNullDiagHandler = { + "Null DiagHandler", + BrNullWarning, + BrNullFailure, +}; + +/* + * Global variable that can be overridden by linking something first + */ +br_diaghandler *_BrDefaultDiagHandler = &BrNullDiagHandler; diff --git a/bren/FW/deffile.c b/bren/FW/deffile.c new file mode 100644 index 00000000..3c8b616d --- /dev/null +++ b/bren/FW/deffile.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: deffile.c 1.2 1995/02/22 21:41:34 sam Exp $ + * $Locker: $ + * + * Default file handler that does nothing + */ +#include + +static br_uint_32 BrNullAttributes(void) +{ + return 0; +} + +static void BrNullOther(void) +{ + BR_FATAL0("Invald file system call"); +} + +/* + * Filesystem structure + */ +br_filesystem BrNullFilesystem = { + "Null Filesystem", /* identifier */ + + BrNullAttributes, /* attributes */ + (void *)BrNullOther, /* open_read */ + (void *)BrNullOther, /* openwrite */ + (void *)BrNullOther, /* close */ + (void *)BrNullOther, /* eof */ + + (void *)BrNullOther, /* getchar */ + (void *)BrNullOther, /* putchar */ + + (void *)BrNullOther, /* read */ + (void *)BrNullOther, /* write */ + + (void *)BrNullOther, /* getline */ + (void *)BrNullOther, /* putline */ + + (void *)BrNullOther, /* advance */ +}; + +/* + * Global variable that can be overridden by linking something first + */ +br_filesystem *_BrDefaultFilesystem = &BrNullFilesystem; diff --git a/bren/FW/defmem.c b/bren/FW/defmem.c new file mode 100644 index 00000000..565ff8ec --- /dev/null +++ b/bren/FW/defmem.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: defmem.c 1.3 1995/02/22 21:41:35 sam Exp $ + * $Locker: $ + * + * Default memory handler that does nothing + */ + +#include + +static void *BrNullAllocate(br_size_t size, br_uint_8 type) +{ + return 0; +} + +static void BrNullFree(void *mem) +{ +} + +static br_size_t BrNullInquire(br_uint_8 type) +{ + return 0; +} + +/* + * Allocator structure + */ +br_allocator BrNullAllocator = { + "Null", + BrNullAllocate, + BrNullFree, + BrNullInquire, +}; + +/* + * Global variable that can be overridden by linking something first + */ +br_allocator *_BrDefaultAllocator = &BrNullAllocator; diff --git a/bren/FW/device.h b/bren/FW/device.h new file mode 100644 index 00000000..6e1928da --- /dev/null +++ b/bren/FW/device.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: device.h 1.5 1995/07/28 19:01:38 sam Exp $ + * $Locker: $ + * + * Device structure - a function dispatch table for pixelmap operations + */ + +#ifndef _DEVICE_H_ +#define _DEVICE_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + * function list for pixelmaps->context + */ + struct br_context; + struct br_device; + + typedef void BR_ASM_CALL ctx_fill_cbfn(struct br_context *dev, br_pixelmap *dst, br_uint_32 colour); + + typedef void BR_ASM_CALL ctx_rectangle_cbfn(struct br_context *dev, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, + br_uint_16 w, br_uint_16 h, br_uint_32 colour); + + typedef void BR_ASM_CALL ctx_rectangle2_cbfn(struct br_context *dev, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, + br_uint_16 w, br_uint_16 h, br_uint_32 colour1, br_uint_32 colour2); + + typedef void BR_ASM_CALL ctx_rectangle_copy_cbfn(struct br_context *dev, br_pixelmap *dst, br_uint_16 dx, + br_uint_16 dy, br_pixelmap *src, br_uint_16 sx, br_uint_16 sy, + br_uint_16 w, br_uint_16 h); + + typedef void BR_ASM_CALL ctx_rectangle_fill_cbfn(struct br_context *dev, br_pixelmap *dst, br_uint_16 x, + br_uint_16 y, br_uint_16 w, br_uint_16 h, br_uint_32 colour); + + typedef void BR_ASM_CALL ctx_dirty_rectangle_copy_cbfn(struct br_context *dev, br_pixelmap *dst, br_pixelmap *src, + br_uint_16 x, br_uint_16 y, br_uint_16 w, br_uint_16 h); + + typedef void BR_ASM_CALL ctx_dirty_rectangle_fill_cbfn(struct br_context *dev, br_pixelmap *dst, br_uint_16 x, + br_uint_16 y, br_uint_16 w, br_uint_16 h, br_uint_32 colour); + + typedef void BR_ASM_CALL ctx_pixel_set_cbfn(struct br_context *dev, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, + br_uint_32 colour); + + typedef br_uint_32 BR_ASM_CALL ctx_pixel_get_cbfn(struct br_context *dev, br_pixelmap *dst, br_uint_16 x, + br_uint_16 y); + + typedef void BR_ASM_CALL ctx_copy_cbfn(struct br_context *dev, br_pixelmap *dst, br_pixelmap *src); + typedef void BR_ASM_CALL ctx_line_cbfn(struct br_context *dev, br_pixelmap *dst, br_int_16 x1, br_int_16 y1, + br_int_16 x2, br_int_16 y2, br_uint_32 colour); + typedef void BR_ASM_CALL ctx_copy_bits_cbfn(struct br_context *dev, br_pixelmap *dst, br_int_16 x, br_int_16 y, + br_uint_8 *src, br_uint_16 s_stride, br_uint_16 start_bit, + br_uint_16 end_bit, br_uint_16 nrows, br_uint_32 colour); + + typedef void BR_ASM_CALL ctx_double_buffer_cbfn(struct br_context *dev, br_pixelmap *dest, br_pixelmap *src); + + typedef br_pixelmap *BR_ASM_CALL ctx_match_cbfn(struct br_context *dev, br_pixelmap *src, br_uint_8 match_type); + typedef br_pixelmap *BR_ASM_CALL ctx_clone_cbfn(struct br_context *dev, br_pixelmap *src); + typedef void BR_ASM_CALL ctx_free_cbfn(struct br_context *dev, br_pixelmap *src); + + /* + * Device context structure + */ + typedef struct br_context + { + /* + * General ID for this structure + */ + char *identifier; + + /* + * Pointer to underlying device + */ + struct br_device *device; + + /* + * Font for context + */ + struct br_font *font; + + /** + ** Function pointers for all the context operations + **/ + + /* + * Pixelmap management operations + */ + ctx_free_cbfn *free; + ctx_match_cbfn *match; + ctx_clone_cbfn *clone; + ctx_double_buffer_cbfn *double_buffer; + + /* + * Pixelmap copying + */ + ctx_copy_cbfn *copy; + ctx_copy_cbfn *copy_to; + ctx_copy_cbfn *copy_from; + + /* + * Rendering operations + */ + ctx_fill_cbfn *fill; + ctx_rectangle_cbfn *rectangle; + ctx_rectangle2_cbfn *rectangle2; + ctx_rectangle_copy_cbfn *rectangle_copy; + ctx_rectangle_copy_cbfn *rectangle_copy_to; + ctx_rectangle_copy_cbfn *rectangle_copy_from; + ctx_rectangle_fill_cbfn *rectangle_fill; + ctx_dirty_rectangle_copy_cbfn *dirty_rectangle_copy; + ctx_dirty_rectangle_fill_cbfn *dirty_rectangle_fill; + ctx_pixel_set_cbfn *pixel_set; + ctx_pixel_get_cbfn *pixel_get; + ctx_line_cbfn *line; + ctx_copy_bits_cbfn *copy_bits; + + } br_context; + + /* + * Generic device class structure + */ + typedef void BR_ASM_CALL dev_load_cbfn(struct br_device *dev); + typedef void BR_ASM_CALL dev_unload_cbfn(struct br_device *dev); + typedef void BR_ASM_CALL dev_enquire_cbfn(struct br_device *dev); + typedef void BR_ASM_CALL dev_create_cbfn(struct br_device *dev); + + typedef struct br_device + { + /* + * Loaded devices are linked into a list + */ + br_node node; + + char *identifier; + + dev_enquire_cbfn *enquire; + dev_load_cbfn *load; + dev_unload_cbfn *unload; + dev_create_cbfn *create; + + } br_device; + +/* + * Given a pixelmap, returns the context to use + * + * XXX Handles NULL context pointer, but that should be sorted out in + * PixelmapAllocate + */ +#define CONTEXT(pm) ((br_context *)(pm->context ? pm->context : &_BrMemoryContext)) + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/bren/FW/diag.c b/bren/FW/diag.c new file mode 100644 index 00000000..774b2906 --- /dev/null +++ b/bren/FW/diag.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: diag.c 1.1 1995/07/28 19:03:10 sam Exp $ + * $Locker: $ + * + * Diagnostic handling support + * + * These routines are not called directly, but via macros. This is + * to allow the underlying diagnostic mechanism to be radically changed + * and allow various text scanning methods for message extraction + * + */ + +#include +#include +#include + +#include "fw.h" + +static char rscid[] = "$Id: diag.c 1.1 1995/07/28 19:03:10 sam Exp $"; +static char _diag_scratch[128]; + +void BR_PUBLIC_ENTRY BrFailure(char *s, ...) +{ + va_list args; + static char failure_header[] = "Failure: "; + + strcpy(_diag_scratch, failure_header); + + va_start(args, s); + vsprintf(_diag_scratch + (BR_ASIZE(failure_header) - 1), s, args); + va_end(args); + +#if DEBUG + if (fw.diag->failure == NULL) + { + fprintf(stderr, "FAILURE: NULL DIAGNOSTIC HANDLER: %s\n", _diag_scratch); + } +#endif + + fw.diag->failure(_diag_scratch); +} + +void BR_PUBLIC_ENTRY BrWarning(char *s, ...) +{ + va_list args; + static char warning_header[] = "Warning: "; + + strcpy(_diag_scratch, warning_header); + + va_start(args, s); + vsprintf(_diag_scratch + (BR_ASIZE(warning_header) - 1), s, args); + va_end(args); + +#if DEBUG + if (fw.diag->warning == NULL) + { + fprintf(stderr, "WARNING: NULL DIAGNOSTIC HANDLER: %s\n", _diag_scratch); + } +#endif + + fw.diag->warning(_diag_scratch); +} + +void BR_PUBLIC_ENTRY BrFatal(char *name, int line, char *s, ...) +{ + va_list args; + int n; + + n = sprintf(_diag_scratch, "FATAL %s:%d \n", name, line); + va_start(args, s); + vsprintf(_diag_scratch + n, s, args); + va_end(args); + +#if DEBUG + if (fw.diag->failure == NULL) + { + fprintf(stderr, "FATAL: NULL DIAGNOSTIC HANDLER: %s\n", _diag_scratch); + } +#endif + + fw.diag->failure(_diag_scratch); +} + +#if DEBUG +void BR_PUBLIC_ENTRY _BrAssert(char *condition, char *file, unsigned line) +{ +#if DEBUG + if (fw.diag->failure == NULL) + { + fprintf(stderr, "ASSERT: NULL DIAGNOSTIC HANDLER: %s\n", _diag_scratch); + } +#endif + + sprintf(_diag_scratch, "ASSERTION FAILED %s:%d: \"%s\"\n", file, line, condition); + fw.diag->failure(_diag_scratch); +} +#endif + +#if PARANOID +void BR_PUBLIC_ENTRY _BrUAssert(char *condition, char *file, unsigned line) +{ +#if DEBUG + if (fw.diag->failure == NULL) + { + fprintf(stderr, "UASSERT: NULL DIAGNOSTIC HANDLER: %s\n", _diag_scratch); + } +#endif + sprintf(_diag_scratch, "ASSERTION FAILED %s:%d: \"%s\"\n", file, line, condition); + fw.diag->failure(_diag_scratch); +} +#endif diff --git a/bren/FW/envmap.c b/bren/FW/envmap.c new file mode 100644 index 00000000..bf7f3987 --- /dev/null +++ b/bren/FW/envmap.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: envmap.c 1.11 1995/03/01 15:25:57 sam Exp $ + * $Locker: $ + * + * Bits of the environment mapping support + */ +#include "fw.h" +#include "brassert.h" +#include "shortcut.h" + +static char rscid[] = "$Id: envmap.c 1.11 1995/03/01 15:25:57 sam Exp $"; + +/* + * Sets the new environment anchor + * + * Returns the previous value + */ +br_actor *BR_PUBLIC_ENTRY BrEnvironmentSet(br_actor *a) +{ + br_actor *old_a = fw.enabled_environment; + + fw.enabled_environment = a; + + return old_a; +} + +/* + * Generate U,V for environment assuming infinite eye + */ +void BR_SURFACE_CALL MapEnvironmentInfinite2D(br_vertex *v, br_fvector3 *normal, br_scalar *comp) +{ + br_vector3 r, wr, n; + br_scalar d, cu, cv; + br_angle a; + + /* + * Convert normal to standard vector + */ + n.v[0] = BrFractionToScalar(normal->v[0]); + n.v[1] = BrFractionToScalar(normal->v[1]); + n.v[2] = BrFractionToScalar(normal->v[2]); + + /* + * Generate reflected vector + * + * - - - - - + * R = 2N(N.E)-E + */ + d = BR_CONST_MUL(BrVector3Dot(&fw.eye_m_normalised, &n), 2); + BrVector3Scale(&r, &n, d); + BrVector3Sub(&r, &r, &fw.eye_m_normalised); + + /* + * If there is an environment frame, rotate vector into it + */ + if (fw.enabled_environment) + { + BrMatrix34ApplyV(&wr, &r, &fw.model_to_environment); + BrVector3Normalise(&wr, &wr); + } + else + wr = r; + + /* + * Convert vector to environment coordinates + */ + cu = BrAngleToScalar(BR_ATAN2(wr.v[0], -wr.v[2])); + +#if 0 + a = BR_ASIN(-wr.v[1]/2+BR_SCALAR(0.5)); + cv = BrAngleToScalar(a); +#else + cv = -wr.v[1] / 2 + BR_SCALAR(0.5); +#endif + + APPLY_UV(comp[C_U], comp[C_V], cu, cv); + + /* + * Call next surface function + */ + fw.surface_fn_after_map(v, normal, comp); +} + +/* + * Generate U,V for environment assuming local eye + */ +void BR_SURFACE_CALL MapEnvironmentLocal2D(br_vertex *v, br_fvector3 *normal, br_scalar *comp) +{ + br_vector3 eye; + br_vector3 r, wr, n; + br_scalar d, cu, cv; + br_angle a; + + /* + * Generate eye vector - + */ + BrVector3Sub(&eye, &fw.eye_m, &v->p); + BrVector3Normalise(&eye, &eye); + + /* + * Convert normal to standard vector + */ + n.v[0] = BrFractionToScalar(normal->v[0]); + n.v[1] = BrFractionToScalar(normal->v[1]); + n.v[2] = BrFractionToScalar(normal->v[2]); + + /* + * Generate reflected vector + * + * - - - - - + * R = 2N(N.E)-E + */ + d = BR_CONST_MUL(BrVector3Dot(&eye, &n), 2); + BrVector3Scale(&r, &n, d); + BrVector3Sub(&r, &r, &eye); + + /* + * If there is an environment frame, rotate vector into it + */ + if (fw.enabled_environment) + { + BrMatrix34ApplyV(&wr, &r, &fw.model_to_environment); + BrVector3Normalise(&wr, &wr); + } + else + wr = r; + + /* + * Convert vector to environment coordinates + */ + cu = BrAngleToScalar(BR_ATAN2(wr.v[0], -wr.v[2])); + +#if 0 + a = BR_ASIN(-wr.v[1]/2+BR_SCALAR(0.5)); + cv = BrAngleToScalar(a); +#else + cv = -wr.v[1] / 2 + BR_SCALAR(0.5); +#endif + + APPLY_UV(comp[C_U], comp[C_V], cu, cv); + + /* + * Call next surface function + */ + fw.surface_fn_after_map(v, normal, comp); +} + +/* + * Take U,V from vertex + */ +void BR_SURFACE_CALL MapFromVertex(br_vertex *v, br_fvector3 *normal, br_scalar *comp) +{ + APPLY_UV(comp[C_U], comp[C_V], v->map.v[U], v->map.v[V]); + + /* + * Call next surface function + */ + fw.surface_fn_after_map(v, normal, comp); +} + +void BR_SURFACE_CALL MapFromVertexOnly(br_vertex *v, br_fvector3 *normal, br_scalar *comp) +{ + APPLY_UV(comp[C_U], comp[C_V], v->map.v[U], v->map.v[V]); +} diff --git a/bren/FW/error.c b/bren/FW/error.c new file mode 100644 index 00000000..fbc5661e --- /dev/null +++ b/bren/FW/error.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: error.c 1.5 1995/07/28 19:01:40 sam Exp $ + * $Locker: $ + * + * Error value support + */ + +#include +#include +#include + +#include "fw.h" + +static char rscid[] = "$Id: error.c 1.5 1995/07/28 19:01:40 sam Exp $"; + +static br_error lastErrorType; +static void **lastErrorValue; + +br_error BR_PUBLIC_ENTRY BrGetLastError(void **valuep) +{ + if (valuep) + valuep = lastErrorValue; + + return lastErrorType; +} + +void BrSetLastError(br_error type, void *value) +{ + lastErrorType = type; + lastErrorValue = value; +} diff --git a/bren/FW/ffhooks.c b/bren/FW/ffhooks.c new file mode 100644 index 00000000..f1945267 --- /dev/null +++ b/bren/FW/ffhooks.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. + * + * $Id: ffhooks.c 1.1 1995/02/26 20:08:28 sam Exp $ + * $Locker: $ + * + * FindFailed hooks that load models/materials/maps/tables from the filesystem + */ +#include + +#include "brender.h" + +/* + * Find Failed callbacks to automatically load textures & tables + */ +br_pixelmap *BR_CALLBACK BrMapFindFailedLoad(char *name) +{ + br_pixelmap *pm; + + if ((pm = BrPixelmapLoad(name)) != NULL) + { + pm->identifier = BrMemStrDup(name); + BrMapAdd(pm); + } + + return pm; +} + +br_pixelmap *BR_CALLBACK BrTableFindFailedLoad(char *name) +{ + br_pixelmap *pm; + + if ((pm = BrPixelmapLoad(name)) != NULL) + { + pm->identifier = BrMemStrDup(name); + BrTableAdd(pm); + } + + return pm; +} + +br_model *BR_CALLBACK BrModelFindFailedLoad(char *name) +{ + br_model *m; + + if ((m = BrModelLoad(name)) != NULL) + { + m->identifier = BrMemStrDup(name); + BrModelAdd(m); + } + + return m; +} + +br_material *BR_CALLBACK BrMaterialFindFailedLoad(char *name) +{ + br_material *m; + + if ((m = BrMaterialLoad(name)) != NULL) + { + m->identifier = BrMemStrDup(name); + BrMaterialAdd(m); + } + + return m; +} diff --git a/bren/FW/file.c b/bren/FW/file.c new file mode 100644 index 00000000..d88b140a --- /dev/null +++ b/bren/FW/file.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: file.c 1.6 1995/08/31 16:29:24 sam Exp $ + * $Locker: $ + * + * Low level wrappers for file system access + */ +#include +#include +#include + +#include "fw.h" +#include "brassert.h" + +static char rscid[] = "$Id: file.c 1.6 1995/08/31 16:29:24 sam Exp $"; + +/* + * Resource block used to represent an open file + */ +typedef struct br_file +{ + void *raw_file; + br_boolean writing; + int mode; + char name[1]; +} br_file; + +/* + * Resource destructor for files + */ +void BR_CALLBACK _BrFileFree(void *res, br_uint_8 res_class, br_size_t size) +{ + br_file *file = res; + + /* + * Close low level file + */ + ASSERT(fw.fsys->close != NULL); + + fw.fsys->close(((br_file *)file)->raw_file); +} + +br_uint_32 BR_PUBLIC_ENTRY BrFileAttributes(void) +{ + ASSERT(fw.fsys->attributes != NULL); + + return fw.fsys->attributes(); +} + +void *BR_PUBLIC_ENTRY BrFileOpenRead(char *name, br_size_t n_magics, br_mode_test_cbfn *mode_test, int *mode_result) +{ + void *raw_file; + br_file *file; + + ASSERT(fw.fsys->open_read != NULL); + + /* + * Invoke low level file access + */ + raw_file = fw.fsys->open_read(name, n_magics, mode_test, mode_result); + + /* + * Catch failure + */ + if (raw_file == NULL) + return NULL; + + /* + * Create a file block (which includes the name and mode) + */ + file = BrResAllocate(fw.res, sizeof(br_file) + strlen(name), BR_MEMORY_FILE); + file->writing = BR_FALSE; + file->mode = *mode_result; + file->raw_file = raw_file; + strcpy(file->name, name); + + return file; +} + +void *BR_PUBLIC_ENTRY BrFileOpenWrite(char *name, int mode) +{ + void *raw_file; + br_file *file; + + ASSERT(fw.fsys->open_write != NULL); + + raw_file = fw.fsys->open_write(name, mode); + + /* + * Catch failure + */ + if (raw_file == NULL) + return NULL; + + /* + * Create a file block (which includes the name and mode) + */ + file = BrResAllocate(fw.res, sizeof(br_file) + strlen(name), BR_MEMORY_FILE); + file->writing = BR_TRUE; + file->mode = mode; + file->raw_file = raw_file; + strcpy(file->name, name); + + return file; +} + +void BR_PUBLIC_ENTRY BrFileClose(void *f) +{ + BrResFree(f); +} + +int BR_PUBLIC_ENTRY BrFileEof(void *f) +{ + ASSERT(fw.fsys->eof != NULL); + + return fw.fsys->eof(((br_file *)f)->raw_file); +} + +int BR_PUBLIC_ENTRY BrFileGetChar(void *f) +{ + ASSERT(fw.fsys->getchr != NULL); + + return fw.fsys->getchr(((br_file *)f)->raw_file); +} + +void BR_PUBLIC_ENTRY BrFilePutChar(int c, void *f) +{ + ASSERT(fw.fsys->putchr != NULL); + + fw.fsys->putchr(c, ((br_file *)f)->raw_file); +} + +int BR_PUBLIC_ENTRY BrFileRead(void *buf, int size, int n, void *f) +{ + + ASSERT(fw.fsys->read != NULL); + + return fw.fsys->read(buf, size, n, ((br_file *)f)->raw_file); +} + +int BR_PUBLIC_ENTRY BrFileWrite(void *buf, int size, int n, void *f) +{ + ASSERT(fw.fsys->write != NULL); + + return fw.fsys->write(buf, size, n, ((br_file *)f)->raw_file); +} + +int BR_PUBLIC_ENTRY BrFileGetLine(char *buf, br_size_t buf_len, void *f) +{ + return fw.fsys->getline(buf, buf_len, ((br_file *)f)->raw_file); +} + +void BR_PUBLIC_ENTRY BrFilePutLine(char *buf, void *f) +{ + ASSERT(fw.fsys->putline != NULL); + + fw.fsys->putline(buf, ((br_file *)f)->raw_file); +} + +void BR_PUBLIC_ENTRY BrFileAdvance(long int count, void *f) +{ + ASSERT(fw.fsys->advance != NULL); + + fw.fsys->advance(count, ((br_file *)f)->raw_file); +} + +int BR_PUBLIC_ENTRY BrFilePrintf(void *f, char *fmt, ...) +{ + int n; + va_list args; + + ASSERT(fw.fsys->write != NULL); + + va_start(args, fmt); + n = vsprintf(_br_scratch_string, fmt, args); + va_end(args); + + fw.fsys->write(_br_scratch_string, 1, n, ((br_file *)f)->raw_file); + + return n; +} diff --git a/bren/FW/fileops.c b/bren/FW/fileops.c new file mode 100644 index 00000000..0b3e8932 --- /dev/null +++ b/bren/FW/fileops.c @@ -0,0 +1,2214 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: fileops.c 1.33 1995/08/31 16:29:25 sam Exp $ + * $Locker: $ + * + * Per-chunk file operations + * + */ +#include + +#include "fw.h" +#include "brassert.h" +#include "datafile.h" + +static char rscid[] = "$Id: fileops.c 1.33 1995/08/31 16:29:25 sam Exp $"; + +/* + * For digging around in points etc - makes things slightly easier to read + */ +#define X 0 +#define Y 1 +#define Z 2 +#define W 3 + +#define U 0 +#define V 1 + +/** + ** End Marker + **/ + +static int FopRead_END(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + return 1; +} + +static int FopWrite_END(br_datafile *df) +{ + df->prims->chunk_write(df, FID_END, 0); + + return 0; +} + +/** + ** File Info + **/ +struct file_info +{ + br_uint_32 type; + br_uint_32 version; +}; + +static br_file_enum_member file_type_FM[] = { + _ENUM_MEMBER(FILE_TYPE_NONE), + + _ENUM_MEMBER(FILE_TYPE_ACTORS), _ENUM_MEMBER(FILE_TYPE_PIXELMAP), _ENUM_MEMBER(FILE_TYPE_LIGHT), + _ENUM_MEMBER(FILE_TYPE_CAMERA), _ENUM_MEMBER(FILE_TYPE_MATERIAL), + + _ENUM_MEMBER(FILE_TYPE_MODEL), _ENUM_MEMBER(FILE_TYPE_ANIMATION), _ENUM_MEMBER(FILE_TYPE_TREE), +}; + +static _FILE_ENUM(file_type); + +#define _STRUCT_NAME struct file_info +static br_file_struct_member file_info_FM[] = { + _ENUM_32(type, file_type_F), + _UINT_32(version), +}; +static _FILE_STRUCT(file_info); +#undef _STRUCT_NAME + +#if 0 +static int FopRead_FILE_INFO(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + struct file_info fi; + + df->prims->struct_read(df,&file_info_F, &fi); + + return fi.type; +} +#endif + +static int FopWrite_FILE_INFO(br_datafile *df, br_uint_32 type) +{ + struct file_info fi; + + fi.type = type; + fi.version = BR_FILE_VERSION; + + df->prims->chunk_write(df, FID_FILE_INFO, df->prims->struct_size(df, &file_info_F, &fi)); + df->prims->struct_write(df, &file_info_F, &fi); + + return 0; +} + +/** + ** Vertices + UV + **/ + +#define _STRUCT_NAME struct br_vertex +static br_file_struct_member br_vertex_FM[] = { + _SCALAR(p.v[X]), + _SCALAR(p.v[Y]), + _SCALAR(p.v[Z]), +}; +static _FILE_STRUCT(br_vertex); +#undef _STRUCT_NAME + +/* + * Write out the vertices from a model + */ +static int FopWrite_VERTICES(br_datafile *df, br_vertex *vertices, int nvertices) +{ + df->prims->chunk_write(df, FID_VERTICES, + df->prims->count_size(df) + nvertices * df->prims->struct_size(df, &br_vertex_F, NULL)); + df->prims->count_write(df, nvertices); + DfStructWriteArray(df, &br_vertex_F, vertices, nvertices); + + return 0; +} + +/* + * Adds an array of vertices to a model that is on the stack + * + */ +static int FopRead_VERTICES(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_model *mp = DfTop(DFST_MODEL, 0); + + mp->vertices = BrResAllocate(mp, count * sizeof(br_vertex), BR_MEMORY_VERTICES); + DfStructReadArray(df, &br_vertex_F, mp->vertices, count); + mp->nvertices = (br_uint_16)count; + + return 0; +} + +/* + * Builds an array of vertices and pushes it onto the stack + * + */ +static int FopRead_OLD_VERTICES(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + void *ptr; + + count = length / df->prims->struct_size(df, &br_vertex_F, NULL); + + ptr = BrResAllocate(fw.res, count * sizeof(br_vertex), BR_MEMORY_VERTICES); + + DfStructReadArray(df, &br_vertex_F, ptr, count); + + DfPush(DFST_VERTICES, ptr, count); + + return 0; +} + +/** + ** Per Vertex UV + **/ +#define _STRUCT_NAME struct br_vertex +static br_file_struct_member br_vertex_uv_FM[] = { + _SCALAR(map.v[0]), + _SCALAR(map.v[1]), +}; +static _FILE_STRUCT(br_vertex_uv); +#undef _STRUCT_NAME + +/* + * Write out an array of vertices and their texture coordinates + */ +static int FopWrite_VERTEX_UV(br_datafile *df, br_vertex *vertices, int nvertices) +{ + df->prims->chunk_write(df, FID_VERTEX_UV, + df->prims->count_size(df) + nvertices * df->prims->struct_size(df, &br_vertex_uv_F, NULL)); + df->prims->count_write(df, nvertices); + + DfStructWriteArray(df, &br_vertex_uv_F, vertices, nvertices); + + return 0; +} + +/* + * Read an array of texture components and add it to the model on the stack + * + * The incoming array has to be <= the existing vertex array + */ +static int FopRead_VERTEX_UV(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_model *mp = DfTop(DFST_MODEL, 0); + + if (count > mp->nvertices) + BR_ERROR0("Vertex UV: too many entries"); + + DfStructReadArray(df, &br_vertex_uv_F, mp->vertices, count); + + return 0; +} + +#define _STRUCT_NAME struct br_vertex +static br_file_struct_member br_old_vertex_uv_FM[] = { + _SCALAR(p.v[X]), _SCALAR(p.v[Y]), _SCALAR(p.v[Z]), _SCALAR(map.v[0]), _SCALAR(map.v[1]), +}; +static _FILE_STRUCT(br_old_vertex_uv); +#undef _STRUCT_NAME + +/* + * Read an array of vertices and push it onto the stack + */ +static int FopRead_OLD_VERTICES_UV(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + void *ptr; + + count = length / df->prims->struct_size(df, &br_old_vertex_uv_F, NULL); + + ptr = BrResAllocate(fw.res, count * sizeof(br_vertex), BR_MEMORY_VERTICES); + + DfStructReadArray(df, &br_old_vertex_uv_F, ptr, count); + + DfPush(DFST_VERTICES, ptr, count); + + return 0; +} + +/** + ** Material Index + **/ +/* + * Read a material index and push it onto the stack + */ +static int FopRead_MATERIAL_INDEX(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + char name[BR_MAX_NAME]; + br_material **mip; + br_uint_32 i; + + /* + * Allocate block for pointers to materials. Include a NULL pointer + * at entry 0 + */ + mip = BrResAllocate(fw.res, (count + 1) * sizeof(*mip), BR_MEMORY_MATERIAL_INDEX); + + mip[0] = NULL; + + /* + * Read and lookup each name + */ + for (i = 1; i < count + 1; i++) + mip[i] = BrMaterialFind(df->prims->name_read(df, name)); + + /* + * Push index onto stack + */ + DfPush(DFST_MATERIAL_INDEX, mip, count + 1); + + return 0; +} + +/* + * Write out the material naes from a table of material pointers + * + */ +static int FopWrite_MATERIAL_INDEX(br_datafile *df, br_material **materials, int nmaterials) +{ + int i, s; + + /* + * Work out size of chunk + */ + s = df->prims->count_size(df); + for (i = 0; i < nmaterials; i++) + s += df->prims->name_size(df, materials[i]->identifier); + + df->prims->chunk_write(df, FID_MATERIAL_INDEX, s); + df->prims->count_write(df, nmaterials); + + /* + * Go through materials table writing out identifiers + */ + for (i = 0; i < nmaterials; i++) + df->prims->name_write(df, materials[i]->identifier); + + return 0; +} + +/* + * Read an old-style material index (no count) and push it onto the stack + */ +static int FopRead_OLD_MATERIAL_INDEX(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + char *mblock, *cp; + int i, num_materials; + br_material **mip; + + /* + * Read the index block into temporary buffer + */ + mblock = BrScratchAllocate(length); + + if (BrFileRead(mblock, 1, length, df->h) != (int)length) + BR_ERROR0("could not read material index"); + + /* + * Count the number of 0's in buffer (== number of strings as + * each string is 0 or more chars terminated with 0) + */ + for (i = 0, cp = mblock, num_materials = 0; i < (int)length; i++) + if (*cp++ == '\0') + num_materials++; + + /* + * Allocate block for pointers to materials + */ + mip = BrResAllocate(fw.res, num_materials * sizeof(*mip), BR_MEMORY_MATERIAL_INDEX); + + /* + * Go through table looking up materials + */ + for (i = 0, cp = mblock; i < num_materials; i++) + { + mip[i] = BrMaterialFind(cp); + while (*cp++) + ; + } + + /* + * Free working buffer + */ + BrScratchFree(mblock); + + /* + * Push index onto stack + */ + DfPush(DFST_MATERIAL_INDEX, mip, num_materials); + + return 0; +} + +/** + ** Faces + **/ +#define _STRUCT_NAME struct br_face +static br_file_struct_member br_face_FM[] = { + _UINT_16(vertices[0]), _UINT_16(vertices[1]), _UINT_16(vertices[2]), _UINT_16(smoothing), _UINT_8(flags), +}; +static _FILE_STRUCT(br_face); +#undef _STRUCT_NAME + +/* + * Read an array of triangular faces and add it to model on the stack + */ +static int FopRead_FACES(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + struct br_model *mp; + int i; + + /* + * Get the model and material table + */ + mp = DfTop(DFST_MODEL, 0); + + mp->faces = BrResAllocate(mp, count * sizeof(br_face), BR_MEMORY_FACES); + mp->nfaces = (br_uint_16)count; + + /* + * Read faces + */ + DfStructReadArray(df, &br_face_F, mp->faces, mp->nfaces); + + /* + * make sure each face has at least one smoothing group + */ + for (i = 0; i < mp->nfaces; i++) + if (mp->faces[i].smoothing == 0) + mp->faces[i].smoothing = (br_uint_16)~0; + + return 0; +} + +/* + * Write out an array of faces + */ +static int FopWrite_FACES(br_datafile *df, br_face *faces, int nfaces) +{ + df->prims->chunk_write(df, FID_FACES, + df->prims->count_size(df) + nfaces * df->prims->struct_size(df, &br_face_F, NULL)); + df->prims->count_write(df, nfaces); + + DfStructWriteArray(df, &br_face_F, faces, nfaces); + + return 0; +} + +/** + ** Obselete Faces (before 16 bit smoothing values) + **/ +#define _STRUCT_NAME struct br_face +static br_file_struct_member br_old_face_1_FM[] = { + _UINT_16(vertices[0]), _UINT_16(vertices[1]), _UINT_16(vertices[2]), _UINT_8(smoothing), _UINT_8(flags), +}; +static _FILE_STRUCT(br_old_face_1); +#undef _STRUCT_NAME + +/* + * Read an array of triangular faces and add it to model on the stack + */ +static int FopRead_OLD_FACES_1(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + struct br_model *mp; + int i; + + /* + * Get the model and material table + */ + mp = DfTop(DFST_MODEL, 0); + + mp->faces = BrResAllocate(mp, count * sizeof(br_face), BR_MEMORY_FACES); + mp->nfaces = (br_uint_16)count; + + /* + * Read faces + */ + DfStructReadArray(df, &br_old_face_1_F, mp->faces, mp->nfaces); + + /* + * Convert smoothing groups to bitmask + */ + for (i = 0; i < mp->nfaces; i++) + { + if (mp->faces[i].smoothing == 0) + mp->faces[i].smoothing = (br_uint_16)~0; + else + mp->faces[i].smoothing = 1 << ((mp->faces[i].smoothing - 1) % 16); + } + + return 0; +} + +/* + * Old faces + */ +#define _STRUCT_NAME struct br_face +static br_file_struct_member br_old_face_FM[] = { + _UINT_16(vertices[0]), _UINT_16(vertices[1]), _UINT_16(vertices[2]), + + _UINT_16(material), _UINT_32(smoothing), +}; +static _FILE_STRUCT(br_old_face); +#undef _STRUCT_NAME + +static int FopRead_OLD_FACES(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + struct br_face *fp; + br_material **mip; + int mi_count; + unsigned int i; + void *ptr; + + count = length / df->prims->struct_size(df, &br_old_face_F, NULL); + + /* + * Get the number of vertices and material table + */ + ptr = DfPop(DFST_VERTICES, (int *)&i); + mip = DfPop(DFST_MATERIAL_INDEX, &mi_count); + DfPush(DFST_VERTICES, ptr, i); + + fp = BrResAllocate(fw.res, count * sizeof(br_face), BR_MEMORY_FACES); + + DfStructReadArray(df, &br_old_face_F, fp, count); + + /* + * Go through and convert materials to pointers + */ + for (i = 0; i < count; i++) + { + fp[i].material = mip[*((br_uint_16 *)&fp[i].material)]; + + /* + * make sure each face has at least one smoothing group + */ + if (fp[i].smoothing == 0) + fp[i].smoothing = (br_uint_16)~0; + } + + /* + * Free up material index + */ + BrResFree(mip); + + /* + * Leave allocated block on stack + */ + DfPush(DFST_FACES, fp, count); + + return 0; +} + +/** + ** Per face material indices + **/ + +static int FopWrite_FACE_MATERIAL(br_datafile *df, br_face *faces, int nfaces, br_material **mindex, int nmaterials) +{ + br_uint_16 *block, *ip; + br_face *fp; + int i, j; + + /* + * Make a block in memory for index + */ + block = BrResAllocate(fw.res, nfaces * sizeof(*block), BR_MEMORY_MATERIAL_INDEX); + + /* + * Build index + */ + for (i = 0, fp = faces, ip = block; i < nfaces; i++, fp++, ip++) + { + *ip = 0; + + /* + * Look up material in index if not NULL + */ + if (fp->material) + { + for (j = 0; j < nmaterials; j++) + { + if (mindex[j] == fp->material) + { + *ip = j + 1; /* Index entries start at 1 */ + break; + } + } + } + } + + df->prims->chunk_write(df, FID_FACE_MATERIAL, df->prims->block_size(df, block, nfaces, 0, 1, sizeof(br_uint_16))); + + /* + * Write index as a block + */ + df->prims->block_write(df, block, nfaces, 0, 1, sizeof(br_uint_16)); + + BrResFree(block); + + return 0; +} + +static int FopRead_FACE_MATERIAL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_material **mindex; + int nmaterials; + br_model *mp; + br_face *fp; + br_uint_16 *block, *ip; + int block_count, i; + + /* + * Grab material index of stack + */ + mindex = DfPop(DFST_MATERIAL_INDEX, &nmaterials); + + mp = DfTop(DFST_MODEL, 0); + + /* + * Read block from file + */ + block = BrScratchAllocate(length); + block_count = mp->nfaces; + block = df->prims->block_read(df, block, &block_count, sizeof(br_uint_16), 0); + + if (block_count > mp->nfaces) + BR_ERROR0("Face Materials: too many entries"); + /* + * Go through block looking up material pointers + */ + for (i = 0, fp = mp->faces, ip = block; i < block_count; i++, fp++, ip++) + { + fp->material = (*ip < nmaterials) ? mindex[*ip] : NULL; + } + /* + * Release block + */ + BrScratchFree(block); + + /* + * Release material index + */ + BrResFree(mindex); + + return 0; +} + +/** + ** Model + **/ +#define _STRUCT_NAME struct br_model +static br_file_struct_member br_model_FM[] = { + _UINT_16(flags), + _ASCIZ(identifier), +}; +static _FILE_STRUCT(br_model); +#undef _STRUCT_NAME + +static int FopRead_MODEL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_model *mp; + + /* + * Allocate and read in model structure + */ + mp = BrModelAllocate(NULL, 0, 0); + df->res = mp; + df->prims->struct_read(df, &br_model_F, mp); + df->res = NULL; + + /* + * Make sure CUSTOM flag is _NOT_ set + */ + mp->flags &= ~(BR_MODF_CUSTOM | BR_MODF_PREPREPARED); + + /* + * Leave model on stack + */ + DfPush(DFST_MODEL, mp, 1); + + return 0; +} + +static int FopWrite_MODEL(br_datafile *df, br_model *mp) +{ + br_model temp_model = *mp; + + /* + * Don't save the CUSTOM flag + */ + temp_model.flags &= ~(BR_MODF_CUSTOM | BR_MODF_PREPREPARED); + + df->prims->chunk_write(df, FID_MODEL, df->prims->struct_size(df, &br_model_F, &temp_model)); + df->prims->struct_write(df, &br_model_F, &temp_model); + + return 0; +} + +/** + ** Old model + **/ +#define _STRUCT_NAME struct br_model +static br_file_struct_member br_old_model_1_FM[] = { + _ASCIZ(identifier), +}; +static _FILE_STRUCT(br_old_model_1); +#undef _STRUCT_NAME + +static int FopRead_OLD_MODEL_1(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_model *mp; + + /* + * Allocate and read in model structure + */ + mp = BrModelAllocate(NULL, 0, 0); + df->res = mp; + df->prims->struct_read(df, &br_old_model_1_F, mp); + df->res = NULL; + + /* + * Leave model on stack + */ + DfPush(DFST_MODEL, mp, 1); + + return 0; +} + +static int FopRead_OLD_MODEL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_model *mp; + int i; + + /* + * Allocate and read in model structure + */ + mp = BrModelAllocate(NULL, 0, 0); + + df->res = mp; + df->prims->struct_read(df, &br_model_F, mp); + df->res = NULL; + + /* + * Hook up vertices and faces + */ + mp->faces = DfPop(DFST_FACES, &i); + mp->nfaces = i; + mp->vertices = DfPop(DFST_VERTICES, &i); + mp->nvertices = i; + + BrResAdd(mp, mp->faces); + BrResAdd(mp, mp->vertices); + + /* + * Make sure CUSTOM flag is _NOT_ set + */ + mp->flags &= ~(BR_MODF_CUSTOM | BR_MODF_PREPREPARED); + + /* + * Leave model on stack + */ + DfPush(DFST_MODEL, mp, 1); + + return 0; +} + +/** + ** Pivot + **/ +#define _STRUCT_NAME struct br_model +static br_file_struct_member br_pivot_FM[] = { + _SCALAR(pivot.v[X]), + _SCALAR(pivot.v[Y]), + _SCALAR(pivot.v[Z]), +}; +static _FILE_STRUCT(br_pivot); +#undef _STRUCT_NAME + +static int FopRead_PIVOT(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_model *mp; + + mp = DfPop(DFST_MODEL, 0); + df->res = mp; + df->prims->struct_read(df, &br_pivot_F, mp); + df->res = NULL; + DfPush(DFST_MODEL, mp, 1); + + return 0; +} + +/** + ** Material + **/ +#define _STRUCT_NAME struct br_material +static br_file_struct_member br_material_FM[] = { + _COLOUR(colour), + _UINT_8(opacity), + _UFRACTION(ka), + _UFRACTION(kd), + _UFRACTION(ks), + _SCALAR(power), + _UINT_16(flags), + _VECTOR2(map_transform.m[0]), + _VECTOR2(map_transform.m[1]), + _VECTOR2(map_transform.m[2]), + _UINT_8(index_base), + _UINT_8(index_range), + _ASCIZ(identifier), +}; + +static _FILE_STRUCT(br_material); +#undef _STRUCT_NAME + +static int FopRead_MATERIAL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_material *mp; + + /* + * Allocate and read in material structure + */ + mp = BrMaterialAllocate(NULL); + df->res = mp; + df->prims->struct_read(df, &br_material_F, mp); + df->res = NULL; + + /* + * Leave material on stack + */ + DfPush(DFST_MATERIAL, mp, 1); + + return 0; +} + +static int FopWrite_MATERIAL(br_datafile *df, br_material *mp) +{ + df->prims->chunk_write(df, FID_MATERIAL, df->prims->struct_size(df, &br_material_F, mp)); + df->prims->struct_write(df, &br_material_F, mp); + + return 0; +} + +/* + * Add a reference to a pixelmap to material on the stack + */ + +/* + * Table of chunk id's versus offsets in material structure + */ +static struct +{ + br_uint_32 id; + size_t offset; + int table; +} MaterialMaps[] = { + {FID_COLOUR_MAP_REF, offsetof(struct br_material, colour_map), 0}, + {FID_INDEX_BLEND_REF, offsetof(struct br_material, index_blend), 1}, + {FID_INDEX_SHADE_REF, offsetof(struct br_material, index_shade), 1}, + {FID_SCREENDOOR_REF, offsetof(struct br_material, screendoor), 1}, +}; + +static int FopRead_PIXELMAP_REF(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_pixelmap *pm; + char name[BR_MAX_NAME]; + char *mp; + int i; + + /* + * Lookup ID in table + */ + for (i = 0; i < BR_ASIZE(MaterialMaps); i++) + if (id == MaterialMaps[i].id) + break; + + ASSERT(i < BR_ASIZE(MaterialMaps)); + + /* + * Get material from stack, get name, and look it up + */ + mp = DfTop(DFST_MATERIAL, 0); + + if (MaterialMaps[i].table) + pm = BrTableFind(df->prims->name_read(df, name)); + else + pm = BrMapFind(df->prims->name_read(df, name)); + + *(br_pixelmap **)(mp + MaterialMaps[i].offset) = pm; + + return 0; +} + +/* + * Wrtie out a reference to a pixelmap + */ +static int FopWrite_PIXELMAP_REF(br_datafile *df, int id, br_pixelmap *pixelmap) +{ + ASSERT(pixelmap && pixelmap->identifier); + + df->prims->chunk_write(df, id, df->prims->name_size(df, pixelmap->identifier)); + df->prims->name_write(df, pixelmap->identifier); + return 0; +} + +/** + ** Pixelmap + **/ +static br_file_enum_member pixelmap_type_FM[] = { + _ENUM_MEMBER(BR_PMT_INDEX_1), _ENUM_MEMBER(BR_PMT_INDEX_2), _ENUM_MEMBER(BR_PMT_INDEX_4), + _ENUM_MEMBER(BR_PMT_INDEX_8), _ENUM_MEMBER(BR_PMT_RGB_555), _ENUM_MEMBER(BR_PMT_RGB_565), + _ENUM_MEMBER(BR_PMT_RGB_888), _ENUM_MEMBER(BR_PMT_RGBX_888), _ENUM_MEMBER(BR_PMT_RGBA_8888), + _ENUM_MEMBER(BR_PMT_YUYV_8888), _ENUM_MEMBER(BR_PMT_YUV_888), _ENUM_MEMBER(BR_PMT_DEPTH_16), + _ENUM_MEMBER(BR_PMT_DEPTH_32), _ENUM_MEMBER(BR_PMT_ALPHA_8), _ENUM_MEMBER(BR_PMT_INDEXA_88), +}; + +static _FILE_ENUM(pixelmap_type); + +#define _STRUCT_NAME struct br_pixelmap +static br_file_struct_member br_pixelmap_FM[] = { + _ENUM_8(type, pixelmap_type_F), + _UINT_16(row_bytes), + _UINT_16(width), + _UINT_16(height), + _UINT_16(origin_x), + _UINT_16(origin_y), + _ASCIZ(identifier), +}; + +static _FILE_STRUCT(br_pixelmap); +#undef _STRUCT_NAME + +static int FopWrite_PIXELMAP(br_datafile *df, br_pixelmap *pp) +{ + br_pixelmap pixelmap = *pp; + + pixelmap.row_bytes = pixelmap.width * BrPixelmapPixelSize(&pixelmap) / 8; + + df->prims->chunk_write(df, FID_PIXELMAP, df->prims->struct_size(df, &br_pixelmap_F, &pixelmap)); + df->prims->struct_write(df, &br_pixelmap_F, &pixelmap); + + return 0; +} + +static int FopRead_PIXELMAP(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_pixelmap *pp; + + /* + * Allocate and read in pixelmap structure + */ + pp = BrResAllocate(fw.res, sizeof(*pp), BR_MEMORY_PIXELMAP); + df->res = pp; + df->prims->struct_read(df, &br_pixelmap_F, pp); + df->res = NULL; + + pp->row_bytes = pp->width * BrPixelmapPixelSize(pp) / 8; + + /* + * Leave material on stack + */ + DfPush(DFST_PIXELMAP, pp, 1); + + return 0; +} + +/** + ** Pixel bytes + **/ +static int FopWrite_PIXELS(br_datafile *df, br_pixelmap *pixelmap) +{ + int size = BrPixelmapFileSize(pixelmap); + int bpp = BrPixelmapPixelSize(pixelmap); + int block_count = (pixelmap->width * bpp / 8) / size; + char *pixels; + int y; + + pixels = (char *)(pixelmap->pixels) + pixelmap->base_y * pixelmap->row_bytes + (pixelmap->base_x * bpp) / 8; + + df->prims->chunk_write(df, FID_PIXELS, + df->prims->block_size(df, pixels, block_count, pixelmap->row_bytes, pixelmap->height, size)); + + df->prims->block_write(df, pixels, block_count, pixelmap->row_bytes, pixelmap->height, size); + + return 0; +} + +static int FopRead_PIXELS(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + int icount; + br_pixelmap *pp; + int size; + + pp = DfTop(DFST_PIXELMAP, 0); + size = BrPixelmapFileSize(pp); + + df->res = pp; + pp->pixels = df->prims->block_read(df, NULL, &icount, size, BR_MEMORY_PIXELS); + pp->flags |= BR_PMF_LINEAR; + df->res = NULL; + + return 0; +} + +/** + ** Connecting a map to an indexed pixelmap + **/ +static int FopWrite_ADD_MAP(br_datafile *df) +{ + df->prims->chunk_write(df, FID_ADD_MAP, 0); + + return 0; +} + +static int FopRead_ADD_MAP(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_pixelmap *pp, *map; + + map = DfPop(DFST_PIXELMAP, 0); + pp = DfTop(DFST_PIXELMAP, 0); + + pp->map = map; + + return 0; +} + +/** + ** Actor + **/ + +static br_file_enum_member actor_type_FM[] = { + _ENUM_MEMBER(BR_ACTOR_NONE), _ENUM_MEMBER(BR_ACTOR_MODEL), _ENUM_MEMBER(BR_ACTOR_LIGHT), + _ENUM_MEMBER(BR_ACTOR_CAMERA), _ENUM_MEMBER(_BR_ACTOR_RESERVED), _ENUM_MEMBER(BR_ACTOR_BOUNDS), + _ENUM_MEMBER(BR_ACTOR_BOUNDS_CORRECT), _ENUM_MEMBER(BR_ACTOR_CLIP_PLANE), +}; + +static _FILE_ENUM(actor_type); + +static br_file_enum_member render_style_FM[] = { + _ENUM_MEMBER(BR_RSTYLE_DEFAULT), _ENUM_MEMBER(BR_RSTYLE_NONE), + _ENUM_MEMBER(BR_RSTYLE_POINTS), _ENUM_MEMBER(BR_RSTYLE_EDGES), + _ENUM_MEMBER(BR_RSTYLE_FACES), _ENUM_MEMBER(BR_RSTYLE_BOUNDING_POINTS), + _ENUM_MEMBER(BR_RSTYLE_BOUNDING_EDGES), _ENUM_MEMBER(BR_RSTYLE_BOUNDING_FACES), +}; + +static _FILE_ENUM(render_style); + +#define _STRUCT_NAME struct br_actor +static br_file_struct_member br_actor_FM[] = { + _ENUM_8(type, actor_type_F), + _ENUM_8(render_style, render_style_F), + _ASCIZ(identifier), +}; +static _FILE_STRUCT(br_actor); +#undef _STRUCT_NAME + +static int FopWrite_ACTOR(br_datafile *df, br_actor *ap) +{ + df->prims->chunk_write(df, FID_ACTOR, df->prims->struct_size(df, &br_actor_F, ap)); + df->prims->struct_write(df, &br_actor_F, ap); + + return 0; +} + +static int FopRead_ACTOR(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_actor *ap; + + /* + * Allocate and read in actor structure + */ + ap = BrActorAllocate(BR_ACTOR_NONE, NULL); + df->res = ap; + df->prims->struct_read(df, &br_actor_F, ap); + df->res = NULL; + + ap->t.type = BR_TRANSFORM_IDENTITY; + + /* + * Leave actor on stack + */ + DfPush(DFST_ACTOR, ap, 1); + + return 0; +} + +/** + ** Actor's reference to a model + **/ +static int FopWrite_ACTOR_MODEL(br_datafile *df, br_model *model) +{ + ASSERT(model && model->identifier); + + df->prims->chunk_write(df, FID_ACTOR_MODEL, df->prims->name_size(df, model->identifier)); + df->prims->name_write(df, model->identifier); + return 0; +} + +static int FopRead_ACTOR_MODEL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + char name[BR_MAX_NAME]; + br_actor *a; + + /* + * Get actor from stack + */ + a = DfTop(DFST_ACTOR, 0); + + a->model = BrModelFind(df->prims->name_read(df, name)); + + return 0; +} + +/** + ** Actor's reference to a material + **/ +static int FopWrite_ACTOR_MATERIAL(br_datafile *df, br_material *material) +{ + ASSERT(material && material->identifier); + + df->prims->chunk_write(df, FID_ACTOR_MATERIAL, df->prims->name_size(df, material->identifier)); + df->prims->name_write(df, material->identifier); + return 0; +} + +static int FopRead_ACTOR_MATERIAL(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + char name[BR_MAX_NAME]; + br_actor *a; + + /* + * Get actor from stack + */ + a = DfTop(DFST_ACTOR, 0); + + a->material = BrMaterialFind(df->prims->name_read(df, name)); + + return 0; +} + +/** + ** Actor's transform + **/ +static int FopWrite_ACTOR_TRANSFORM(br_datafile *df) +{ + df->prims->chunk_write(df, FID_ACTOR_TRANSFORM, 0); + + return 0; +} + +static int FopRead_ACTOR_TRANSFORM(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_actor *a; + br_transform *tp; + + /* + * Get transform and actor of the stack + */ + tp = DfPop(DFST_TRANSFORM, 0); + a = DfTop(DFST_ACTOR, 0); + + /* + * Copy transform into actor + */ + a->t = *tp; + + /* + * Free the translation + */ + BrResFree(tp); + + return 0; +} + +/** + ** Add light to actor + **/ + +static int FopWrite_ACTOR_LIGHT(br_datafile *df) +{ + df->prims->chunk_write(df, FID_ACTOR_LIGHT, 0); + + return 0; +} + +static int FopRead_ACTOR_LIGHT(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_actor *a; + br_light *lp; + + /* + * Get light and actor of the stack + */ + lp = DfPop(DFST_LIGHT, 0); + a = DfTop(DFST_ACTOR, 0); + + /* + * Attach light to actor + */ + a->type_data = lp; + + return 0; +} + +/** + ** Add camera to actor + **/ + +static int FopWrite_ACTOR_CAMERA(br_datafile *df) +{ + df->prims->chunk_write(df, FID_ACTOR_CAMERA, 0); + + return 0; +} + +static int FopRead_ACTOR_CAMERA(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_actor *a; + br_light *cp; + + /* + * Get camera and actor of the stack + */ + cp = DfPop(DFST_CAMERA, 0); + a = DfTop(DFST_ACTOR, 0); + + /* + * Attach camera to actor + */ + a->type_data = cp; + + return 0; +} + +/** + ** Add bounds to actor + **/ + +static int FopWrite_ACTOR_BOUNDS(br_datafile *df) +{ + df->prims->chunk_write(df, FID_ACTOR_BOUNDS, 0); + + return 0; +} + +static int FopRead_ACTOR_BOUNDS(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_actor *a; + br_bounds *bp; + + /* + * Get bounds and actor of the stack + */ + bp = DfPop(DFST_BOUNDS, 0); + a = DfTop(DFST_ACTOR, 0); + + /* + * Attach bounds to actor + */ + a->type_data = bp; + + return 0; +} + +/** + ** Add Clip plane to actor + **/ + +static int FopWrite_ACTOR_CLIP_PLANE(br_datafile *df) +{ + df->prims->chunk_write(df, FID_ACTOR_CLIP_PLANE, 0); + + return 0; +} + +static int FopRead_ACTOR_CLIP_PLANE(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_actor *a; + br_vector4 *vp; + + /* + * Get clip vector and actor of the stack + */ + vp = DfPop(DFST_PLANE, 0); + a = DfTop(DFST_ACTOR, 0); + + /* + * Attach bounds to actor + */ + a->type_data = vp; + + return 0; +} + +static int FopWrite_ACTOR_ADD_CHILD(br_datafile *df) +{ + df->prims->chunk_write(df, FID_ACTOR_ADD_CHILD, 0); + + return 0; +} + +/* + * Add actor at top of stack as a child of actor next on stack + */ +static int FopRead_ACTOR_ADD_CHILD(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_actor *a, *p; + + a = DfPop(DFST_ACTOR, 0); + p = DfTop(DFST_ACTOR, 0); + + BrActorAdd(p, a); + + return 0; +} + +/** + ** Transforms + **/ +#define _STRUCT_NAME struct br_transform +static br_file_struct_member br_transform_matrix34_FM[] = { + /* + * XXX Assumes rows of matrix can be cast to vectors + */ + _VECTOR3(t.mat.m[0]), + _VECTOR3(t.mat.m[1]), + _VECTOR3(t.mat.m[2]), + _VECTOR3(t.mat.m[3]), +}; + +static _FILE_STRUCT(br_transform_matrix34); +#undef _STRUCT_NAME + +#define _STRUCT_NAME struct br_transform +static br_file_struct_member br_transform_quat_FM[] = { + _SCALAR(t.quat.q.x), _SCALAR(t.quat.q.y), _SCALAR(t.quat.q.z), _SCALAR(t.quat.q.w), + + _VECTOR3(t.quat.t), +}; + +static _FILE_STRUCT(br_transform_quat); +#undef _STRUCT_NAME + +static br_file_enum_member angle_order_FM[] = { + _ENUM_MEMBER(BR_EULER_XYZ_S), _ENUM_MEMBER(BR_EULER_XYX_S), _ENUM_MEMBER(BR_EULER_XZY_S), + _ENUM_MEMBER(BR_EULER_XZX_S), _ENUM_MEMBER(BR_EULER_YZX_S), _ENUM_MEMBER(BR_EULER_YZY_S), + _ENUM_MEMBER(BR_EULER_YXZ_S), _ENUM_MEMBER(BR_EULER_YXY_S), _ENUM_MEMBER(BR_EULER_ZXY_S), + _ENUM_MEMBER(BR_EULER_ZXZ_S), _ENUM_MEMBER(BR_EULER_ZYX_S), _ENUM_MEMBER(BR_EULER_ZYZ_S), + + _ENUM_MEMBER(BR_EULER_ZYX_R), _ENUM_MEMBER(BR_EULER_XYX_R), _ENUM_MEMBER(BR_EULER_YZX_R), + _ENUM_MEMBER(BR_EULER_XZX_R), _ENUM_MEMBER(BR_EULER_XZY_R), _ENUM_MEMBER(BR_EULER_YZY_R), + _ENUM_MEMBER(BR_EULER_ZXY_R), _ENUM_MEMBER(BR_EULER_YXY_R), _ENUM_MEMBER(BR_EULER_YXZ_R), + _ENUM_MEMBER(BR_EULER_ZXZ_R), _ENUM_MEMBER(BR_EULER_XYZ_R), _ENUM_MEMBER(BR_EULER_ZYZ_R), +}; + +static _FILE_ENUM(angle_order); + +#define _STRUCT_NAME struct br_transform +static br_file_struct_member br_transform_euler_FM[] = { + _ENUM_8(t.euler.e.order, angle_order_F), + _ANGLE(t.euler.e.a), + _ANGLE(t.euler.e.b), + _ANGLE(t.euler.e.c), + + _VECTOR3(t.euler.t), +}; + +static _FILE_STRUCT(br_transform_euler); +#undef _STRUCT_NAME + +#define _STRUCT_NAME struct br_transform +static br_file_struct_member br_transform_look_up_FM[] = { + _VECTOR3(t.look_up.look), + _VECTOR3(t.look_up.up), + _VECTOR3(t.look_up.t), +}; + +static _FILE_STRUCT(br_transform_look_up); +#undef _STRUCT_NAME + +#define _STRUCT_NAME struct br_transform +static br_file_struct_member br_transform_translation_FM[] = { + _VECTOR3(t.translate.t), +}; + +static _FILE_STRUCT(br_transform_translation); +#undef _STRUCT_NAME + +/* + * Index (by transform type), of chunk ID and file struct to use + */ +static struct transform_type +{ + int id; + struct br_file_struct *fs; +} TransformTypes[] = { + {FID_TRANSFORM_MATRIX34, &br_transform_matrix34_F}, + {FID_TRANSFORM_MATRIX34_LP, &br_transform_matrix34_F}, + {FID_TRANSFORM_QUAT, &br_transform_quat_F}, + {FID_TRANSFORM_EULER, &br_transform_euler_F}, + {FID_TRANSFORM_LOOK_UP, &br_transform_look_up_F}, + {FID_TRANSFORM_TRANSLATION, &br_transform_translation_F}, + {FID_TRANSFORM_IDENTITY, NULL}, +}; + +static int FopWrite_TRANSFORM(br_datafile *df, br_transform *t) +{ + struct transform_type *tt; + + ASSERT(t->type < BR_ASIZE(TransformTypes)); + + tt = TransformTypes + t->type; + + if (tt->fs) + { + df->prims->chunk_write(df, tt->id, df->prims->struct_size(df, tt->fs, t)); + df->prims->struct_write(df, tt->fs, t); + } + else + { + df->prims->chunk_write(df, tt->id, 0); + } + + return 0; +} + +static int FopRead_TRANSFORM(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + int t; + br_transform *tp; + + /* + * Look up ID in table + */ + for (t = 0; t < BR_ASIZE(TransformTypes); t++) + if (TransformTypes[t].id == id) + break; + + ASSERT(t < BR_ASIZE(TransformTypes)); + + /* + * Allocate transform and fill in type + */ + tp = BrResAllocate(fw.res, sizeof(*tp), BR_MEMORY_TRANSFORM); + tp->type = t; + + df->res = tp; + + if (TransformTypes[t].fs) + df->prims->struct_read(df, TransformTypes[t].fs, tp); + + df->res = NULL; + + /* + * Leave transform on stack + */ + DfPush(DFST_TRANSFORM, tp, 1); + + return 0; +} + +/** + ** Bounds + **/ + +#define _STRUCT_NAME struct br_bounds3 +static br_file_struct_member br_bounds3_FM[] = { + _VECTOR3(min), + _VECTOR3(max), +}; + +static _FILE_STRUCT(br_bounds3); +#undef _STRUCT_NAME + +static int FopWrite_BOUNDS(br_datafile *df, br_bounds *bp) +{ + df->prims->chunk_write(df, FID_BOUNDS, df->prims->struct_size(df, &br_bounds3_F, bp)); + df->prims->struct_write(df, &br_bounds3_F, bp); + + return 0; +} + +int FopRead_BOUNDS(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_bounds3 *bp; + + /* + * Allocate and read in bounds structure + */ + bp = BrResAllocate(fw.res, sizeof(*bp), BR_MEMORY_BOUNDS); + df->res = bp; + df->prims->struct_read(df, &br_bounds3_F, bp); + df->res = NULL; + + /* + * Leave bounds on stack + */ + DfPush(DFST_BOUNDS, bp, 1); + + return 0; +} + +/** + ** Plane + **/ +struct br_plane +{ + br_vector4 *eqn; +}; + +#define _STRUCT_NAME struct br_plane +static br_file_struct_member br_plane_FM[] = { + _VECTOR4(eqn), +}; + +static _FILE_STRUCT(br_plane); +#undef _STRUCT_NAME + +static int FopWrite_PLANE(br_datafile *df, br_vector4 *pp) +{ + df->prims->chunk_write(df, FID_PLANE, df->prims->struct_size(df, &br_plane_F, pp)); + df->prims->struct_write(df, &br_plane_F, pp); + + return 0; +} + +static int FopRead_PLANE(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_vector4 *pp; + + /* + * Allocate and read in vector + */ + pp = BrResAllocate(fw.res, sizeof(*pp), BR_MEMORY_CLIP_PLANE); + df->res = pp; + df->prims->struct_read(df, &br_plane_F, pp); + df->res = NULL; + + /* + * Leave bounds on stack + */ + DfPush(DFST_PLANE, pp, 1); + + return 0; +} + +/** + ** Light + **/ +static br_file_enum_member light_type_FM[] = { + _ENUM_MEMBER(BR_LIGHT_POINT), + _ENUM_MEMBER(BR_LIGHT_DIRECT), + _ENUM_MEMBER(BR_LIGHT_SPOT), + + _ENUM_MEMBER(BR_LIGHT_VIEW | BR_LIGHT_POINT), + _ENUM_MEMBER(BR_LIGHT_VIEW | BR_LIGHT_DIRECT), + _ENUM_MEMBER(BR_LIGHT_VIEW | BR_LIGHT_SPOT), +}; + +static _FILE_ENUM(light_type); + +#define _STRUCT_NAME struct br_light +static br_file_struct_member br_light_FM[] = { + _ENUM_8(type, light_type_F), + + _COLOUR(colour), + + _SCALAR(attenuation_c), + _SCALAR(attenuation_l), + _SCALAR(attenuation_q), + + _ANGLE(cone_inner), + _ANGLE(cone_outer), + + _ASCIZ(identifier), +}; +static _FILE_STRUCT(br_light); +#undef _STRUCT_NAME + +static int FopWrite_LIGHT(br_datafile *df, br_light *lp) +{ + df->prims->chunk_write(df, FID_LIGHT, df->prims->struct_size(df, &br_light_F, lp)); + df->prims->struct_write(df, &br_light_F, lp); + + return 0; +} + +static int FopRead_LIGHT(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_light *lp; + + /* + * Allocate and read in light structure + */ + lp = BrResAllocate(fw.res, sizeof(*lp), BR_MEMORY_LIGHT); + df->res = lp; + df->prims->struct_read(df, &br_light_F, lp); + df->res = NULL; + + /* + * Leave light on stack + */ + DfPush(DFST_LIGHT, lp, 1); + + return 0; +} + +/** + ** Camera + **/ +static br_file_enum_member camera_type_FM[] = { + _ENUM_MEMBER(BR_CAMERA_PARALLEL), + _ENUM_MEMBER(BR_CAMERA_PERSPECTIVE), +}; + +static _FILE_ENUM(camera_type); + +#define _STRUCT_NAME struct br_camera +static br_file_struct_member br_camera_FM[] = { + _ENUM_8(type, camera_type_F), _ANGLE(field_of_view), _SCALAR(hither_z), _SCALAR(yon_z), _SCALAR(aspect), + _ASCIZ(identifier), +}; +static _FILE_STRUCT(br_camera); +#undef _STRUCT_NAME + +static int FopWrite_CAMERA(br_datafile *df, br_camera *cp) +{ + df->prims->chunk_write(df, FID_CAMERA, df->prims->struct_size(df, &br_camera_F, cp)); + df->prims->struct_write(df, &br_camera_F, cp); + + return 0; +} + +static int FopRead_CAMERA(br_datafile *df, br_uint_32 id, br_uint_32 length, br_uint_32 count) +{ + br_camera *cp; + + /* + * Allocate and read in camera structure + */ + cp = BrResAllocate(fw.res, sizeof(*cp), BR_MEMORY_CAMERA); + df->res = cp; + df->prims->struct_read(df, &br_camera_F, cp); + df->res = NULL; + + /* + * Leave camera on stack + */ + DfPush(DFST_CAMERA, cp, 1); + + return 0; +} + +/** + ** Public file operations + **/ + +/* + * Allocate memory and read the model from the file - bind and material + * references to the current loaded set - or default if the named material + * does not exist. + */ + +static br_chunks_table_entry ModelLoadEntries[] = { + {FID_END, 0, FopRead_END}, + + {FID_OLD_MATERIAL_INDEX, 0, FopRead_OLD_MATERIAL_INDEX}, + {FID_OLD_VERTICES, 0, FopRead_OLD_VERTICES}, + {FID_OLD_VERTICES_UV, 0, FopRead_OLD_VERTICES_UV}, + {FID_OLD_FACES, 0, FopRead_OLD_FACES}, + {FID_OLD_MODEL, 0, FopRead_OLD_MODEL}, + {FID_OLD_FACES_1, 1, FopRead_OLD_FACES_1}, + {FID_OLD_MODEL_1, 0, FopRead_OLD_MODEL_1}, + + {FID_MODEL, 0, FopRead_MODEL}, + {FID_MATERIAL_INDEX, 1, FopRead_MATERIAL_INDEX}, + {FID_VERTICES, 1, FopRead_VERTICES}, + {FID_VERTEX_UV, 1, FopRead_VERTEX_UV}, + {FID_FACES, 1, FopRead_FACES}, + {FID_FACE_MATERIAL, 0, FopRead_FACE_MATERIAL}, + {FID_PIVOT, 0, FopRead_PIVOT}, +}; + +static br_chunks_table ModelLoadTable = { + BR_ASIZE(ModelLoadEntries), + ModelLoadEntries, +}; + +br_uint_32 BR_PUBLIC_ENTRY BrModelLoadMany(char *filename, br_model **models, br_uint_16 num) +{ + int count; + int r; + br_datafile *df; + + df = DfOpen(filename, 0); + + if (df == NULL) + return 0; + + for (count = 0; count < num;) + { + r = DfChunksInterpret(df, &ModelLoadTable); + + if (DfTopType() == DFST_MODEL) + models[count++] = DfPop(DFST_MODEL, 0); + + if (r == 0) + break; + } + + DfClose(df); + + return count; +} + +/* + * Write a complete single model. + * + * Does not know about groups - which would be a quicker way of acquiring + * the material index, but makes this code dependant on the groups code + * staying the same. + */ + +static int BR_CALLBACK PtrCompare(const void *a, const void *b) +{ + return *((char **)b) - *((char **)a); +} + +static br_uint_32 BR_CALLBACK WriteModel(br_model *mp, br_datafile *df) +{ + br_material **mindex; + br_vertex *vp; + int nmaterials; + int i; + int has_uv; + + /* + * Build material index - there will never be more materials than faces + */ + if (mp->faces) + { + mindex = BrResAllocate(fw.res, mp->nfaces * sizeof(*mindex), BR_MEMORY_MATERIAL_INDEX); + + /* + * make table of material pointers + */ + for (i = 0; i < mp->nfaces; i++) + mindex[i] = mp->faces[i].material; + + /* + * sort pointers (reverse by value - NULL should wind up at end) + */ + BrQsort(mindex, mp->nfaces, sizeof(*mindex), PtrCompare); + + /* + * Count how many unique pointers there are and compact + * them to the base of the table + */ + for (i = 1, nmaterials = 1; i < mp->nfaces; i++) + if (mindex[i] != mindex[i - 1]) + mindex[nmaterials++] = mindex[i]; + + /* + * Remove any NULL from end of table + */ + if (mindex[nmaterials - 1] == NULL) + nmaterials--; + } + + /* + * See if model has any non zero U and V components + */ + has_uv = 0; + for (i = 0, vp = mp->vertices; i < mp->nvertices; i++, vp++) + { + if ((vp->map.v[U] != BR_SCALAR(0.0)) || (vp->map.v[V] != BR_SCALAR(0.0))) + { + has_uv = 1; + break; + } + } + + /* + * Write out chunks + */ + FopWrite_MODEL(df, mp); + + if (mp->nvertices) + { + FopWrite_VERTICES(df, mp->vertices, mp->nvertices); + if (has_uv) + FopWrite_VERTEX_UV(df, mp->vertices, mp->nvertices); + } + + if (mp->nfaces) + { + FopWrite_FACES(df, mp->faces, mp->nfaces); + if (nmaterials) + { + FopWrite_MATERIAL_INDEX(df, mindex, nmaterials); + FopWrite_FACE_MATERIAL(df, mp->faces, mp->nfaces, mindex, nmaterials); + } + } + + FopWrite_END(df); + + BrResFree(mindex); + + return 0; +} + +/* + * Save a set of models to the named file. + * + * if models == NULL, then all registered models are saved + */ +br_uint_32 BR_PUBLIC_ENTRY BrModelSaveMany(char *filename, br_model **models, br_uint_16 num) +{ + br_datafile *df; + int i, m = 0; + + /* + * Open file and write header + */ + df = DfOpen(filename, 1); + + if (df == NULL) + return 0; + + FopWrite_FILE_INFO(df, FILE_TYPE_MODEL); + + if (models) + { + for (i = 0; i < num; i++) + WriteModel(models[i], df); + m = num; + } + else + { + BrModelEnum(NULL, (br_model_enum_cbfn *)WriteModel, (void *)df); + m = BrModelCount(NULL); + } + + DfClose(df); + + return m; +} + +/* + * Load a hierachy of 1 or more actors and their transforms described in + * a file + */ +static br_chunks_table_entry ActorLoadEntries[] = { + {FID_END, 0, FopRead_END}, + + {FID_ACTOR, 0, FopRead_ACTOR}, + {FID_ACTOR_MODEL, 0, FopRead_ACTOR_MODEL}, + {FID_ACTOR_TRANSFORM, 0, FopRead_ACTOR_TRANSFORM}, + {FID_ACTOR_MATERIAL, 0, FopRead_ACTOR_MATERIAL}, + {FID_ACTOR_LIGHT, 0, FopRead_ACTOR_LIGHT}, + {FID_ACTOR_CAMERA, 0, FopRead_ACTOR_CAMERA}, + {FID_ACTOR_BOUNDS, 0, FopRead_ACTOR_BOUNDS}, + {FID_ACTOR_CLIP_PLANE, 0, FopRead_ACTOR_CLIP_PLANE}, + {FID_ACTOR_ADD_CHILD, 0, FopRead_ACTOR_ADD_CHILD}, + + {FID_TRANSFORM_MATRIX34, 0, FopRead_TRANSFORM}, + {FID_TRANSFORM_MATRIX34_LP, 0, FopRead_TRANSFORM}, + {FID_TRANSFORM_QUAT, 0, FopRead_TRANSFORM}, + {FID_TRANSFORM_EULER, 0, FopRead_TRANSFORM}, + {FID_TRANSFORM_LOOK_UP, 0, FopRead_TRANSFORM}, + {FID_TRANSFORM_TRANSLATION, 0, FopRead_TRANSFORM}, + {FID_TRANSFORM_IDENTITY, 0, FopRead_TRANSFORM}, + + {FID_BOUNDS, 0, FopRead_BOUNDS}, + {FID_LIGHT, 0, FopRead_LIGHT}, + {FID_CAMERA, 0, FopRead_CAMERA}, + {FID_PLANE, 0, FopRead_PLANE}, +}; + +static br_chunks_table ActorLoadTable = { + BR_ASIZE(ActorLoadEntries), + ActorLoadEntries, +}; + +br_uint_32 BR_PUBLIC_ENTRY BrActorLoadMany(char *filename, br_actor **actors, br_uint_16 num) +{ + br_datafile *df; + int count; + int r; + + df = DfOpen(filename, 0); + + if (df == NULL) + return 0; + + for (count = 0; count < num;) + { + r = DfChunksInterpret(df, &ActorLoadTable); + + if (DfTopType() == DFST_ACTOR) + actors[count++] = DfPop(DFST_ACTOR, 0); + + if (r == 0) + break; + } + + DfClose(df); + + return count; +} + +/* + * Save a hierachy of 1 or more actors and their transforms described in a file + */ +static int WriteActor(br_actor *a, br_datafile *df) +{ + br_actor *ap; + + /* + * Base actor structure + */ + FopWrite_ACTOR(df, a); + + /* + * Transform + */ + if (a->t.type != BR_TRANSFORM_IDENTITY) + { + FopWrite_TRANSFORM(df, &a->t); + FopWrite_ACTOR_TRANSFORM(df); + } + + /* + * Model and material references, if they exist + */ + if (a->material) + FopWrite_ACTOR_MATERIAL(df, a->material); + + if (a->model) + FopWrite_ACTOR_MODEL(df, a->model); + + /* + * Type specific data + */ + if (a->type_data) + { + switch (a->type) + { + case BR_ACTOR_LIGHT: + FopWrite_LIGHT(df, a->type_data); + FopWrite_ACTOR_LIGHT(df); + break; + + case BR_ACTOR_CAMERA: + FopWrite_CAMERA(df, a->type_data); + FopWrite_ACTOR_CAMERA(df); + break; + + case BR_ACTOR_BOUNDS: + FopWrite_BOUNDS(df, a->type_data); + FopWrite_ACTOR_BOUNDS(df); + break; + + case BR_ACTOR_CLIP_PLANE: + FopWrite_PLANE(df, a->type_data); + FopWrite_ACTOR_CLIP_PLANE(df); + break; + } + } + + /* + * Children + */ + BR_FOR_SIMPLELIST(&a->children, ap) + { + WriteActor(ap, df); + FopWrite_ACTOR_ADD_CHILD(df); + } + + return 0; +} + +/* + * Save a set of actors to the named file. + */ +br_uint_32 BR_PUBLIC_ENTRY BrActorSaveMany(char *filename, br_actor **actors, br_uint_16 num) +{ + br_datafile *df; + int i; + + /* + * Open file and write header + */ + df = DfOpen(filename, 1); + + if (df == NULL) + return 0; + + FopWrite_FILE_INFO(df, FILE_TYPE_ACTORS); + + /* + * Write out all the actors + */ + for (i = 0; i < num; i++) + { + WriteActor(actors[i], df); + FopWrite_END(df); + } + + DfClose(df); + + return num; +} + +/* + * Load a group of materials from a file + */ +static br_chunks_table_entry MaterialLoadEntries[] = { + {FID_END, 0, FopRead_END}, + {FID_MATERIAL, 0, FopRead_MATERIAL}, + {FID_COLOUR_MAP_REF, 0, FopRead_PIXELMAP_REF}, + {FID_INDEX_BLEND_REF, 0, FopRead_PIXELMAP_REF}, + {FID_INDEX_SHADE_REF, 0, FopRead_PIXELMAP_REF}, + {FID_SCREENDOOR_REF, 0, FopRead_PIXELMAP_REF}, +}; + +static br_chunks_table MaterialLoadTable = { + BR_ASIZE(MaterialLoadEntries), + MaterialLoadEntries, +}; + +br_uint_32 BR_PUBLIC_ENTRY BrMaterialLoadMany(char *filename, br_material **materials, br_uint_16 num) +{ + br_datafile *df; + int count; + int r; + + df = DfOpen(filename, 0); + + if (df == NULL) + return 0; + + for (count = 0; count < num;) + { + r = DfChunksInterpret(df, &MaterialLoadTable); + + if (DfTopType() == DFST_MATERIAL) + materials[count++] = DfPop(DFST_MATERIAL, 0); + + if (r == 0) + break; + } + + DfClose(df); + + return count; +} + +/* + * Save a set of materials to the named file. + * + * if materials == NULL, then all registered materials are saved + */ +static br_uint_32 BR_CALLBACK WriteMaterial(br_material *mp, br_datafile *df) +{ + /* + * Write base material structure + */ + FopWrite_MATERIAL(df, mp); + + /* + * Write out any references to pixelmaps + */ + + if (mp->colour_map) + FopWrite_PIXELMAP_REF(df, FID_COLOUR_MAP_REF, mp->colour_map); + + if (mp->index_shade) + FopWrite_PIXELMAP_REF(df, FID_INDEX_SHADE_REF, mp->index_shade); + + if (mp->index_blend) + FopWrite_PIXELMAP_REF(df, FID_INDEX_BLEND_REF, mp->index_blend); + + if (mp->screendoor) + FopWrite_PIXELMAP_REF(df, FID_SCREENDOOR_REF, mp->screendoor); + + FopWrite_END(df); + + return 0; +} + +br_uint_32 BR_PUBLIC_ENTRY BrMaterialSaveMany(char *filename, br_material **materials, br_uint_16 num) +{ + br_datafile *df; + int i, count; + + /* + * Open file and write header + */ + df = DfOpen(filename, 1); + + if (df == NULL) + return 0; + + FopWrite_FILE_INFO(df, FILE_TYPE_MATERIAL); + + if (materials) + { + for (i = 0; i < num; i++) + WriteMaterial(materials[i], df); + count = num; + } + else + { + BrMaterialEnum(NULL, (br_material_enum_cbfn *)WriteMaterial, df); + count = BrMaterialCount(NULL); + } + + DfClose(df); + + return count; +} + +/* + * Load a group of pixelmaps from a file + */ +static br_chunks_table_entry PixelmapLoadEntries[] = { + {FID_END, 0, FopRead_END}, + {FID_PIXELMAP, 0, FopRead_PIXELMAP}, + {FID_PIXELS, 0, FopRead_PIXELS}, + {FID_ADD_MAP, 0, FopRead_ADD_MAP}, +}; + +static br_chunks_table PixelmapLoadTable = { + BR_ASIZE(PixelmapLoadEntries), + PixelmapLoadEntries, +}; + +br_uint_32 BR_PUBLIC_ENTRY BrPixelmapLoadMany(char *filename, br_pixelmap **pixelmaps, br_uint_16 num) +{ + br_datafile *df; + int count; + int r; + + df = DfOpen(filename, 0); + + if (df == NULL) + return 0; + + for (count = 0; count < num;) + { + r = DfChunksInterpret(df, &PixelmapLoadTable); + + if (DfTopType() == DFST_PIXELMAP) + pixelmaps[count++] = DfPop(DFST_PIXELMAP, 0); + + if (r == 0) + break; + } + + DfClose(df); + + return count; +} + +/* + * Save a group of pixelmaps to a file + */ +static int WritePixelmap(br_pixelmap *pp, br_datafile *df) +{ + ASSERT(!(pp->flags & BR_PMF_NO_ACCESS)); + + /* + * Write base pixelmap structure + */ + FopWrite_PIXELMAP(df, pp); + + /* + * Write any palette + */ + if (pp->map) + { + WritePixelmap(pp->map, df); + FopWrite_ADD_MAP(df); + } + + /* + * Write pixel data + */ + FopWrite_PIXELS(df, pp); + + return 0; +} + +br_uint_32 BR_PUBLIC_ENTRY BrPixelmapSaveMany(char *filename, br_pixelmap **pixelmaps, br_uint_16 num) +{ + br_datafile *df; + int i; + + ASSERT(filename != NULL); + ASSERT(pixelmaps != NULL); + + /* + * Open file and write header + */ + df = DfOpen(filename, 1); + + if (df == NULL) + return 0; + + FopWrite_FILE_INFO(df, FILE_TYPE_PIXELMAP); + + for (i = 0; i < num; i++) + { + WritePixelmap(pixelmaps[i], df); + FopWrite_END(df); + } + + DfClose(df); + + return num; +} + +br_model *BR_PUBLIC_ENTRY BrModelLoad(char *filename) +{ + br_model *ptr; + + return (BrModelLoadMany(filename, &ptr, 1) != 1) ? NULL : ptr; +} + +br_uint_32 BR_PUBLIC_ENTRY BrModelSave(char *filename, br_model *ptr) +{ + return BrModelSaveMany(filename, &ptr, 1); +} + +br_material *BR_PUBLIC_ENTRY BrMaterialLoad(char *filename) +{ + br_material *ptr; + + return (BrMaterialLoadMany(filename, &ptr, 1) != 1) ? NULL : ptr; +} + +br_uint_32 BR_PUBLIC_ENTRY BrMaterialSave(char *filename, br_material *ptr) +{ + return BrMaterialSaveMany(filename, &ptr, 1); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrPixelmapLoad(char *filename) +{ + br_pixelmap *ptr; + + return (BrPixelmapLoadMany(filename, &ptr, 1) != 1) ? NULL : ptr; +} + +br_uint_32 BR_PUBLIC_ENTRY BrPixelmapSave(char *filename, br_pixelmap *ptr) +{ + return BrPixelmapSaveMany(filename, &ptr, 1); +} + +br_actor *BR_PUBLIC_ENTRY BrActorLoad(char *filename) +{ + br_actor *ptr; + + return (BrActorLoadMany(filename, &ptr, 1) != 1) ? NULL : ptr; +} + +br_uint_32 BR_PUBLIC_ENTRY BrActorSave(char *filename, br_actor *ptr) +{ + return BrActorSaveMany(filename, &ptr, 1); +} diff --git a/bren/FW/fixed.c b/bren/FW/fixed.c new file mode 100644 index 00000000..2fc69db5 --- /dev/null +++ b/bren/FW/fixed.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: fixed.c 1.10 1995/02/22 21:41:42 sam Exp $ + * $Locker: $ + * + * Various fixed point support functions + */ +#include + +#if defined(__WATCOMC__) && defined(__TARGET_MSC__) + +#pragma aux sqrt "_*" parm caller[] modify[eax ecx edx]; +#pragma aux pow "_*" parm caller[] modify[eax ecx edx]; +#endif + +#include "fw.h" + +static char rscid[] = "$Id: fixed.c 1.10 1995/02/22 21:41:42 sam Exp $"; + +br_fixed_ls BR_PUBLIC_ENTRY BrFixedSqrt(br_fixed_ls a) +{ + return BrFloatToFixed(sqrt(BrFixedToFloat(a))); +} + +br_fixed_ls BR_PUBLIC_ENTRY BrFixedPow(br_fixed_ls a, br_fixed_ls b) +{ + return BrFloatToFixed(pow(BrFixedToFloat(a), BrFixedToFloat(b))); +} + +/* + * Reciprocal table + * + * 0x8000000/x from 0 2048 + */ +unsigned long BR_ASM_DATA _reciprocal[2048] = { + 0x00010000, 0x000010000, 0x000008000, 0x000005555, 0x000004000, 0x000003333, 0x000002AAA, 0x000002492, 0x00002000, + 0x000001C71, 0x000001999, 0x000001745, 0x000001555, 0x0000013B1, 0x000001249, 0x000001111, 0x00001000, 0x000000F0F, + 0x000000E38, 0x000000D79, 0x000000CCC, 0x000000C30, 0x000000BA2, 0x000000B21, 0x00000AAA, 0x000000A3D, 0x0000009D8, + 0x00000097B, 0x000000924, 0x0000008D3, 0x000000888, 0x000000842, 0x00000800, 0x0000007C1, 0x000000787, 0x000000750, + 0x00000071C, 0x0000006EB, 0x0000006BC, 0x000000690, 0x00000666, 0x00000063E, 0x000000618, 0x0000005F4, 0x0000005D1, + 0x0000005B0, 0x000000590, 0x000000572, 0x00000555, 0x000000539, 0x00000051E, 0x000000505, 0x0000004EC, 0x0000004D4, + 0x0000004BD, 0x0000004A7, 0x00000492, 0x00000047D, 0x000000469, 0x000000456, 0x000000444, 0x000000432, 0x000000421, + 0x000000410, 0x00000400, 0x0000003F0, 0x0000003E0, 0x0000003D2, 0x0000003C3, 0x0000003B5, 0x0000003A8, 0x00000039B, + 0x0000038E, 0x000000381, 0x000000375, 0x000000369, 0x00000035E, 0x000000353, 0x000000348, 0x00000033D, 0x00000333, + 0x000000329, 0x00000031F, 0x000000315, 0x00000030C, 0x000000303, 0x0000002FA, 0x0000002F1, 0x000002E8, 0x0000002E0, + 0x0000002D8, 0x0000002D0, 0x0000002C8, 0x0000002C0, 0x0000002B9, 0x0000002B1, 0x000002AA, 0x0000002A3, 0x00000029C, + 0x000000295, 0x00000028F, 0x000000288, 0x000000282, 0x00000027C, 0x00000276, 0x000000270, 0x00000026A, 0x000000264, + 0x00000025E, 0x000000259, 0x000000253, 0x00000024E, 0x00000249, 0x000000243, 0x00000023E, 0x000000239, 0x000000234, + 0x000000230, 0x00000022B, 0x000000226, 0x00000222, 0x00000021D, 0x000000219, 0x000000214, 0x000000210, 0x00000020C, + 0x000000208, 0x000000204, 0x00000200, 0x0000001FC, 0x0000001F8, 0x0000001F4, 0x0000001F0, 0x0000001EC, 0x0000001E9, + 0x0000001E5, 0x000001E1, 0x0000001DE, 0x0000001DA, 0x0000001D7, 0x0000001D4, 0x0000001D0, 0x0000001CD, 0x0000001CA, + 0x000001C7, 0x0000001C3, 0x0000001C0, 0x0000001BD, 0x0000001BA, 0x0000001B7, 0x0000001B4, 0x0000001B2, 0x000001AF, + 0x0000001AC, 0x0000001A9, 0x0000001A6, 0x0000001A4, 0x0000001A1, 0x00000019E, 0x00000019C, 0x00000199, 0x000000197, + 0x000000194, 0x000000192, 0x00000018F, 0x00000018D, 0x00000018A, 0x000000188, 0x00000186, 0x000000183, 0x000000181, + 0x00000017F, 0x00000017D, 0x00000017A, 0x000000178, 0x000000176, 0x00000174, 0x000000172, 0x000000170, 0x00000016E, + 0x00000016C, 0x00000016A, 0x000000168, 0x000000166, 0x00000164, 0x000000162, 0x000000160, 0x00000015E, 0x00000015C, + 0x00000015A, 0x000000158, 0x000000157, 0x00000155, 0x000000153, 0x000000151, 0x000000150, 0x00000014E, 0x00000014C, + 0x00000014A, 0x000000149, 0x00000147, 0x000000146, 0x000000144, 0x000000142, 0x000000141, 0x00000013F, 0x00000013E, + 0x00000013C, 0x0000013B, 0x000000139, 0x000000138, 0x000000136, 0x000000135, 0x000000133, 0x000000132, 0x000000130, + 0x0000012F, 0x00000012E, 0x00000012C, 0x00000012B, 0x000000129, 0x000000128, 0x000000127, 0x000000125, 0x00000124, + 0x000000123, 0x000000121, 0x000000120, 0x00000011F, 0x00000011E, 0x00000011C, 0x00000011B, 0x0000011A, 0x000000119, + 0x000000118, 0x000000116, 0x000000115, 0x000000114, 0x000000113, 0x000000112, 0x00000111, 0x00000010F, 0x00000010E, + 0x00000010D, 0x00000010C, 0x00000010B, 0x00000010A, 0x000000109, 0x00000108, 0x000000107, 0x000000106, 0x000000105, + 0x000000104, 0x000000103, 0x000000102, 0x000000101, 0x00000100, 0x0000000FF, 0x0000000FE, 0x0000000FD, 0x0000000FC, + 0x0000000FB, 0x0000000FA, 0x0000000F9, 0x000000F8, 0x0000000F7, 0x0000000F6, 0x0000000F5, 0x0000000F4, 0x0000000F3, + 0x0000000F2, 0x0000000F1, 0x000000F0, 0x0000000F0, 0x0000000EF, 0x0000000EE, 0x0000000ED, 0x0000000EC, 0x0000000EB, + 0x0000000EA, 0x000000EA, 0x0000000E9, 0x0000000E8, 0x0000000E7, 0x0000000E6, 0x0000000E5, 0x0000000E5, 0x0000000E4, + 0x000000E3, 0x0000000E2, 0x0000000E1, 0x0000000E1, 0x0000000E0, 0x0000000DF, 0x0000000DE, 0x0000000DE, 0x000000DD, + 0x0000000DC, 0x0000000DB, 0x0000000DB, 0x0000000DA, 0x0000000D9, 0x0000000D9, 0x0000000D8, 0x000000D7, 0x0000000D6, + 0x0000000D6, 0x0000000D5, 0x0000000D4, 0x0000000D4, 0x0000000D3, 0x0000000D2, 0x000000D2, 0x0000000D1, 0x0000000D0, + 0x0000000D0, 0x0000000CF, 0x0000000CE, 0x0000000CE, 0x0000000CD, 0x000000CC, 0x0000000CC, 0x0000000CB, 0x0000000CA, + 0x0000000CA, 0x0000000C9, 0x0000000C9, 0x0000000C8, 0x000000C7, 0x0000000C7, 0x0000000C6, 0x0000000C5, 0x0000000C5, + 0x0000000C4, 0x0000000C4, 0x0000000C3, 0x000000C3, 0x0000000C2, 0x0000000C1, 0x0000000C1, 0x0000000C0, 0x0000000C0, + 0x0000000BF, 0x0000000BF, 0x000000BE, 0x0000000BD, 0x0000000BD, 0x0000000BC, 0x0000000BC, 0x0000000BB, 0x0000000BB, + 0x0000000BA, 0x000000BA, 0x0000000B9, 0x0000000B9, 0x0000000B8, 0x0000000B8, 0x0000000B7, 0x0000000B7, 0x0000000B6, + 0x000000B6, 0x0000000B5, 0x0000000B5, 0x0000000B4, 0x0000000B4, 0x0000000B3, 0x0000000B3, 0x0000000B2, 0x000000B2, + 0x0000000B1, 0x0000000B1, 0x0000000B0, 0x0000000B0, 0x0000000AF, 0x0000000AF, 0x0000000AE, 0x000000AE, 0x0000000AD, + 0x0000000AD, 0x0000000AC, 0x0000000AC, 0x0000000AC, 0x0000000AB, 0x0000000AB, 0x000000AA, 0x0000000AA, 0x0000000A9, + 0x0000000A9, 0x0000000A8, 0x0000000A8, 0x0000000A8, 0x0000000A7, 0x000000A7, 0x0000000A6, 0x0000000A6, 0x0000000A5, + 0x0000000A5, 0x0000000A5, 0x0000000A4, 0x0000000A4, 0x000000A3, 0x0000000A3, 0x0000000A3, 0x0000000A2, 0x0000000A2, + 0x0000000A1, 0x0000000A1, 0x0000000A1, 0x000000A0, 0x0000000A0, 0x00000009F, 0x00000009F, 0x00000009F, 0x00000009E, + 0x00000009E, 0x00000009D, 0x0000009D, 0x00000009D, 0x00000009C, 0x00000009C, 0x00000009C, 0x00000009B, 0x00000009B, + 0x00000009A, 0x0000009A, 0x00000009A, 0x000000099, 0x000000099, 0x000000099, 0x000000098, 0x000000098, 0x000000098, + 0x00000097, 0x000000097, 0x000000097, 0x000000096, 0x000000096, 0x000000095, 0x000000095, 0x000000095, 0x00000094, + 0x000000094, 0x000000094, 0x000000093, 0x000000093, 0x000000093, 0x000000092, 0x000000092, 0x00000092, 0x000000091, + 0x000000091, 0x000000091, 0x000000090, 0x000000090, 0x000000090, 0x000000090, 0x0000008F, 0x00000008F, 0x00000008F, + 0x00000008E, 0x00000008E, 0x00000008E, 0x00000008D, 0x00000008D, 0x0000008D, 0x00000008C, 0x00000008C, 0x00000008C, + 0x00000008C, 0x00000008B, 0x00000008B, 0x00000008B, 0x0000008A, 0x00000008A, 0x00000008A, 0x000000089, 0x000000089, + 0x000000089, 0x000000089, 0x000000088, 0x00000088, 0x000000088, 0x000000087, 0x000000087, 0x000000087, 0x000000087, + 0x000000086, 0x000000086, 0x00000086, 0x000000086, 0x000000085, 0x000000085, 0x000000085, 0x000000084, 0x000000084, + 0x000000084, 0x00000084, 0x000000083, 0x000000083, 0x000000083, 0x000000083, 0x000000082, 0x000000082, 0x000000082, + 0x00000082, 0x000000081, 0x000000081, 0x000000081, 0x000000081, 0x000000080, 0x000000080, 0x000000080, 0x00000080, + 0x00000007F, 0x00000007F, 0x00000007F, 0x00000007F, 0x00000007E, 0x00000007E, 0x00000007E, 0x0000007E, 0x00000007D, + 0x00000007D, 0x00000007D, 0x00000007D, 0x00000007C, 0x00000007C, 0x00000007C, 0x0000007C, 0x00000007B, 0x00000007B, + 0x00000007B, 0x00000007B, 0x00000007A, 0x00000007A, 0x00000007A, 0x0000007A, 0x00000007A, 0x000000079, 0x000000079, + 0x000000079, 0x000000079, 0x000000078, 0x000000078, 0x00000078, 0x000000078, 0x000000078, 0x000000077, 0x000000077, + 0x000000077, 0x000000077, 0x000000076, 0x00000076, 0x000000076, 0x000000076, 0x000000076, 0x000000075, 0x000000075, + 0x000000075, 0x000000075, 0x00000075, 0x000000074, 0x000000074, 0x000000074, 0x000000074, 0x000000073, 0x000000073, + 0x000000073, 0x00000073, 0x000000073, 0x000000072, 0x000000072, 0x000000072, 0x000000072, 0x000000072, 0x000000071, + 0x00000071, 0x000000071, 0x000000071, 0x000000071, 0x000000070, 0x000000070, 0x000000070, 0x000000070, 0x00000070, + 0x000000070, 0x00000006F, 0x00000006F, 0x00000006F, 0x00000006F, 0x00000006F, 0x00000006E, 0x0000006E, 0x00000006E, + 0x00000006E, 0x00000006E, 0x00000006D, 0x00000006D, 0x00000006D, 0x00000006D, 0x0000006D, 0x00000006D, 0x00000006C, + 0x00000006C, 0x00000006C, 0x00000006C, 0x00000006C, 0x00000006B, 0x0000006B, 0x00000006B, 0x00000006B, 0x00000006B, + 0x00000006B, 0x00000006A, 0x00000006A, 0x00000006A, 0x0000006A, 0x00000006A, 0x00000006A, 0x000000069, 0x000000069, + 0x000000069, 0x000000069, 0x000000069, 0x00000069, 0x000000068, 0x000000068, 0x000000068, 0x000000068, 0x000000068, + 0x000000068, 0x000000067, 0x00000067, 0x000000067, 0x000000067, 0x000000067, 0x000000067, 0x000000066, 0x000000066, + 0x000000066, 0x00000066, 0x000000066, 0x000000066, 0x000000065, 0x000000065, 0x000000065, 0x000000065, 0x000000065, + 0x00000065, 0x000000064, 0x000000064, 0x000000064, 0x000000064, 0x000000064, 0x000000064, 0x000000064, 0x00000063, + 0x000000063, 0x000000063, 0x000000063, 0x000000063, 0x000000063, 0x000000062, 0x000000062, 0x00000062, 0x000000062, + 0x000000062, 0x000000062, 0x000000062, 0x000000061, 0x000000061, 0x000000061, 0x00000061, 0x000000061, 0x000000061, + 0x000000061, 0x000000060, 0x000000060, 0x000000060, 0x000000060, 0x00000060, 0x000000060, 0x000000060, 0x00000005F, + 0x00000005F, 0x00000005F, 0x00000005F, 0x00000005F, 0x0000005F, 0x00000005F, 0x00000005E, 0x00000005E, 0x00000005E, + 0x00000005E, 0x00000005E, 0x00000005E, 0x0000005E, 0x00000005E, 0x00000005D, 0x00000005D, 0x00000005D, 0x00000005D, + 0x00000005D, 0x00000005D, 0x0000005D, 0x00000005C, 0x00000005C, 0x00000005C, 0x00000005C, 0x00000005C, 0x00000005C, + 0x00000005C, 0x0000005C, 0x00000005B, 0x00000005B, 0x00000005B, 0x00000005B, 0x00000005B, 0x00000005B, 0x00000005B, + 0x0000005B, 0x00000005A, 0x00000005A, 0x00000005A, 0x00000005A, 0x00000005A, 0x00000005A, 0x00000005A, 0x0000005A, + 0x000000059, 0x000000059, 0x000000059, 0x000000059, 0x000000059, 0x000000059, 0x000000059, 0x00000059, 0x000000058, + 0x000000058, 0x000000058, 0x000000058, 0x000000058, 0x000000058, 0x000000058, 0x00000058, 0x000000057, 0x000000057, + 0x000000057, 0x000000057, 0x000000057, 0x000000057, 0x000000057, 0x00000057, 0x000000057, 0x000000056, 0x000000056, + 0x000000056, 0x000000056, 0x000000056, 0x000000056, 0x00000056, 0x000000056, 0x000000056, 0x000000055, 0x000000055, + 0x000000055, 0x000000055, 0x000000055, 0x00000055, 0x000000055, 0x000000055, 0x000000055, 0x000000054, 0x000000054, + 0x000000054, 0x000000054, 0x00000054, 0x000000054, 0x000000054, 0x000000054, 0x000000054, 0x000000053, 0x000000053, + 0x000000053, 0x00000053, 0x000000053, 0x000000053, 0x000000053, 0x000000053, 0x000000053, 0x000000052, 0x000000052, + 0x00000052, 0x000000052, 0x000000052, 0x000000052, 0x000000052, 0x000000052, 0x000000052, 0x000000052, 0x00000051, + 0x000000051, 0x000000051, 0x000000051, 0x000000051, 0x000000051, 0x000000051, 0x000000051, 0x00000051, 0x000000051, + 0x000000050, 0x000000050, 0x000000050, 0x000000050, 0x000000050, 0x000000050, 0x00000050, 0x000000050, 0x000000050, + 0x000000050, 0x00000004F, 0x00000004F, 0x00000004F, 0x00000004F, 0x0000004F, 0x00000004F, 0x00000004F, 0x00000004F, + 0x00000004F, 0x00000004F, 0x00000004E, 0x00000004E, 0x0000004E, 0x00000004E, 0x00000004E, 0x00000004E, 0x00000004E, + 0x00000004E, 0x00000004E, 0x00000004E, 0x0000004E, 0x00000004D, 0x00000004D, 0x00000004D, 0x00000004D, 0x00000004D, + 0x00000004D, 0x00000004D, 0x0000004D, 0x00000004D, 0x00000004D, 0x00000004D, 0x00000004C, 0x00000004C, 0x00000004C, + 0x00000004C, 0x0000004C, 0x00000004C, 0x00000004C, 0x00000004C, 0x00000004C, 0x00000004C, 0x00000004C, 0x00000004B, + 0x0000004B, 0x00000004B, 0x00000004B, 0x00000004B, 0x00000004B, 0x00000004B, 0x00000004B, 0x00000004B, 0x0000004B, + 0x00000004B, 0x00000004A, 0x00000004A, 0x00000004A, 0x00000004A, 0x00000004A, 0x00000004A, 0x0000004A, 0x00000004A, + 0x00000004A, 0x00000004A, 0x00000004A, 0x00000004A, 0x000000049, 0x000000049, 0x00000049, 0x000000049, 0x000000049, + 0x000000049, 0x000000049, 0x000000049, 0x000000049, 0x000000049, 0x00000049, 0x000000049, 0x000000048, 0x000000048, + 0x000000048, 0x000000048, 0x000000048, 0x000000048, 0x00000048, 0x000000048, 0x000000048, 0x000000048, 0x000000048, + 0x000000048, 0x000000048, 0x000000047, 0x00000047, 0x000000047, 0x000000047, 0x000000047, 0x000000047, 0x000000047, + 0x000000047, 0x000000047, 0x00000047, 0x000000047, 0x000000047, 0x000000047, 0x000000046, 0x000000046, 0x000000046, + 0x000000046, 0x00000046, 0x000000046, 0x000000046, 0x000000046, 0x000000046, 0x000000046, 0x000000046, 0x000000046, + 0x00000046, 0x000000045, 0x000000045, 0x000000045, 0x000000045, 0x000000045, 0x000000045, 0x000000045, 0x00000045, + 0x000000045, 0x000000045, 0x000000045, 0x000000045, 0x000000045, 0x000000044, 0x000000044, 0x00000044, 0x000000044, + 0x000000044, 0x000000044, 0x000000044, 0x000000044, 0x000000044, 0x000000044, 0x00000044, 0x000000044, 0x000000044, + 0x000000044, 0x000000043, 0x000000043, 0x000000043, 0x000000043, 0x00000043, 0x000000043, 0x000000043, 0x000000043, + 0x000000043, 0x000000043, 0x000000043, 0x000000043, 0x00000043, 0x000000043, 0x000000043, 0x000000042, 0x000000042, + 0x000000042, 0x000000042, 0x000000042, 0x00000042, 0x000000042, 0x000000042, 0x000000042, 0x000000042, 0x000000042, + 0x000000042, 0x000000042, 0x00000042, 0x000000041, 0x000000041, 0x000000041, 0x000000041, 0x000000041, 0x000000041, + 0x000000041, 0x00000041, 0x000000041, 0x000000041, 0x000000041, 0x000000041, 0x000000041, 0x000000041, 0x000000041, + 0x00000041, 0x000000040, 0x000000040, 0x000000040, 0x000000040, 0x000000040, 0x000000040, 0x000000040, 0x00000040, + 0x000000040, 0x000000040, 0x000000040, 0x000000040, 0x000000040, 0x000000040, 0x000000040, 0x00000040, 0x00000003F, + 0x00000003F, 0x00000003F, 0x00000003F, 0x00000003F, 0x00000003F, 0x00000003F, 0x0000003F, 0x00000003F, 0x00000003F, + 0x00000003F, 0x00000003F, 0x00000003F, 0x00000003F, 0x00000003F, 0x0000003F, 0x00000003E, 0x00000003E, 0x00000003E, + 0x00000003E, 0x00000003E, 0x00000003E, 0x00000003E, 0x0000003E, 0x00000003E, 0x00000003E, 0x00000003E, 0x00000003E, + 0x00000003E, 0x00000003E, 0x00000003E, 0x0000003E, 0x00000003E, 0x00000003D, 0x00000003D, 0x00000003D, 0x00000003D, + 0x00000003D, 0x00000003D, 0x0000003D, 0x00000003D, 0x00000003D, 0x00000003D, 0x00000003D, 0x00000003D, 0x00000003D, + 0x00000003D, 0x0000003D, 0x00000003D, 0x00000003D, 0x00000003C, 0x00000003C, 0x00000003C, 0x00000003C, 0x00000003C, + 0x0000003C, 0x00000003C, 0x00000003C, 0x00000003C, 0x00000003C, 0x00000003C, 0x00000003C, 0x00000003C, 0x0000003C, + 0x00000003C, 0x00000003C, 0x00000003C, 0x00000003C, 0x00000003B, 0x00000003B, 0x00000003B, 0x0000003B, 0x00000003B, + 0x00000003B, 0x00000003B, 0x00000003B, 0x00000003B, 0x00000003B, 0x00000003B, 0x0000003B, 0x00000003B, 0x00000003B, + 0x00000003B, 0x00000003B, 0x00000003B, 0x00000003B, 0x00000003A, 0x0000003A, 0x00000003A, 0x00000003A, 0x00000003A, + 0x00000003A, 0x00000003A, 0x00000003A, 0x00000003A, 0x0000003A, 0x00000003A, 0x00000003A, 0x00000003A, 0x00000003A, + 0x00000003A, 0x00000003A, 0x00000003A, 0x0000003A, 0x00000003A, 0x000000039, 0x000000039, 0x000000039, 0x000000039, + 0x000000039, 0x000000039, 0x00000039, 0x000000039, 0x000000039, 0x000000039, 0x000000039, 0x000000039, 0x000000039, + 0x000000039, 0x00000039, 0x000000039, 0x000000039, 0x000000039, 0x000000039, 0x000000039, 0x000000038, 0x000000038, + 0x00000038, 0x000000038, 0x000000038, 0x000000038, 0x000000038, 0x000000038, 0x000000038, 0x000000038, 0x00000038, + 0x000000038, 0x000000038, 0x000000038, 0x000000038, 0x000000038, 0x000000038, 0x000000038, 0x00000038, 0x000000038, + 0x000000038, 0x000000037, 0x000000037, 0x000000037, 0x000000037, 0x000000037, 0x00000037, 0x000000037, 0x000000037, + 0x000000037, 0x000000037, 0x000000037, 0x000000037, 0x000000037, 0x00000037, 0x000000037, 0x000000037, 0x000000037, + 0x000000037, 0x000000037, 0x000000037, 0x000000037, 0x00000036, 0x000000036, 0x000000036, 0x000000036, 0x000000036, + 0x000000036, 0x000000036, 0x000000036, 0x00000036, 0x000000036, 0x000000036, 0x000000036, 0x000000036, 0x000000036, + 0x000000036, 0x000000036, 0x00000036, 0x000000036, 0x000000036, 0x000000036, 0x000000036, 0x000000036, 0x000000035, + 0x000000035, 0x00000035, 0x000000035, 0x000000035, 0x000000035, 0x000000035, 0x000000035, 0x000000035, 0x000000035, + 0x00000035, 0x000000035, 0x000000035, 0x000000035, 0x000000035, 0x000000035, 0x000000035, 0x000000035, 0x00000035, + 0x000000035, 0x000000035, 0x000000035, 0x000000035, 0x000000034, 0x000000034, 0x000000034, 0x00000034, 0x000000034, + 0x000000034, 0x000000034, 0x000000034, 0x000000034, 0x000000034, 0x000000034, 0x00000034, 0x000000034, 0x000000034, + 0x000000034, 0x000000034, 0x000000034, 0x000000034, 0x000000034, 0x00000034, 0x000000034, 0x000000034, 0x000000034, + 0x000000034, 0x000000033, 0x000000033, 0x000000033, 0x00000033, 0x000000033, 0x000000033, 0x000000033, 0x000000033, + 0x000000033, 0x000000033, 0x000000033, 0x00000033, 0x000000033, 0x000000033, 0x000000033, 0x000000033, 0x000000033, + 0x000000033, 0x000000033, 0x00000033, 0x000000033, 0x000000033, 0x000000033, 0x000000033, 0x000000033, 0x000000032, + 0x000000032, 0x00000032, 0x000000032, 0x000000032, 0x000000032, 0x000000032, 0x000000032, 0x000000032, 0x000000032, + 0x00000032, 0x000000032, 0x000000032, 0x000000032, 0x000000032, 0x000000032, 0x000000032, 0x000000032, 0x00000032, + 0x000000032, 0x000000032, 0x000000032, 0x000000032, 0x000000032, 0x000000032, 0x000000031, 0x00000031, 0x000000031, + 0x000000031, 0x000000031, 0x000000031, 0x000000031, 0x000000031, 0x000000031, 0x00000031, 0x000000031, 0x000000031, + 0x000000031, 0x000000031, 0x000000031, 0x000000031, 0x000000031, 0x00000031, 0x000000031, 0x000000031, 0x000000031, + 0x000000031, 0x000000031, 0x000000031, 0x000000031, 0x00000031, 0x000000031, 0x000000030, 0x000000030, 0x000000030, + 0x000000030, 0x000000030, 0x000000030, 0x00000030, 0x000000030, 0x000000030, 0x000000030, 0x000000030, 0x000000030, + 0x000000030, 0x000000030, 0x00000030, 0x000000030, 0x000000030, 0x000000030, 0x000000030, 0x000000030, 0x000000030, + 0x000000030, 0x00000030, 0x000000030, 0x000000030, 0x000000030, 0x000000030, 0x000000030, 0x00000002F, 0x00000002F, + 0x0000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x0000002F, + 0x00000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x0000002F, 0x00000002F, + 0x00000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x00000002F, 0x0000002F, 0x00000002F, 0x00000002F, + 0x00000002E, 0x00000002E, 0x00000002E, 0x00000002E, 0x00000002E, 0x0000002E, 0x00000002E, 0x00000002E, 0x00000002E, + 0x00000002E, 0x00000002E, 0x00000002E, 0x00000002E, 0x0000002E, 0x00000002E, 0x00000002E, 0x00000002E, 0x00000002E, + 0x00000002E, 0x00000002E, 0x00000002E, 0x0000002E, 0x00000002E, 0x00000002E, 0x00000002E, 0x00000002E, 0x00000002E, + 0x00000002E, 0x00000002E, 0x0000002E, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, + 0x00000002D, 0x0000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, + 0x0000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x0000002D, + 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x00000002D, 0x0000002D, 0x00000002C, + 0x00000002C, 0x00000002C, 0x00000002C, 0x00000002C, 0x00000002C, 0x00000002C, 0x0000002C, 0x00000002C, 0x00000002C, + 0x00000002C, 0x00000002C, 0x00000002C, 0x00000002C, 0x00000002C, 0x0000002C, 0x00000002C, 0x00000002C, 0x00000002C, + 0x00000002C, 0x00000002C, 0x00000002C, 0x00000002C, 0x0000002C, 0x00000002C, 0x00000002C, 0x00000002C, 0x00000002C, + 0x00000002C, 0x00000002C, 0x00000002C, 0x0000002C, 0x00000002C, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, + 0x00000002B, 0x00000002B, 0x0000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, + 0x00000002B, 0x0000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, + 0x0000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x0000002B, + 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002B, 0x00000002A, 0x00000002A, 0x00000002A, 0x0000002A, 0x00000002A, + 0x00000002A, 0x00000002A, 0x00000002A, 0x00000002A, 0x00000002A, 0x00000002A, 0x0000002A, 0x00000002A, 0x00000002A, + 0x00000002A, 0x00000002A, 0x00000002A, 0x00000002A, 0x00000002A, 0x0000002A, 0x00000002A, 0x00000002A, 0x00000002A, + 0x00000002A, 0x00000002A, 0x00000002A, 0x00000002A, 0x0000002A, 0x00000002A, 0x00000002A, 0x00000002A, 0x00000002A, + 0x00000002A, 0x00000002A, 0x00000002A, 0x0000002A, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, + 0x000000029, 0x000000029, 0x00000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, + 0x000000029, 0x00000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, + 0x00000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x00000029, + 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000029, 0x000000028, 0x00000028, 0x000000028, + 0x000000028, 0x000000028, 0x000000028, 0x000000028, 0x000000028, 0x000000028, 0x00000028, 0x000000028, 0x000000028, + 0x000000028, 0x000000028, 0x000000028, 0x000000028, 0x000000028, 0x00000028, 0x000000028, 0x000000028, 0x000000028, + 0x000000028, 0x000000028, 0x000000028, 0x000000028, 0x00000028, 0x000000028, 0x000000028, 0x000000028, 0x000000028, + 0x000000028, 0x000000028, 0x000000028, 0x00000028, 0x000000028, 0x000000028, 0x000000028, 0x000000028, 0x000000028, + 0x000000028, 0x000000027, 0x00000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, + 0x000000027, 0x00000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, + 0x00000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x00000027, + 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x00000027, 0x000000027, + 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x000000027, 0x00000027, 0x000000026, 0x000000026, + 0x000000026, 0x000000026, 0x000000026, 0x000000026, 0x000000026, 0x00000026, 0x000000026, 0x000000026, 0x000000026, + 0x000000026, 0x000000026, 0x000000026, 0x000000026, 0x00000026, 0x000000026, 0x000000026, 0x000000026, 0x000000026, + 0x000000026, 0x000000026, 0x000000026, 0x00000026, 0x000000026, 0x000000026, 0x000000026, 0x000000026, 0x000000026, + 0x000000026, 0x000000026, 0x00000026, 0x000000026, 0x000000026, 0x000000026, 0x000000026, 0x000000026, 0x000000026, + 0x000000026, 0x00000026, 0x000000026, 0x000000026, 0x000000026, 0x000000026, 0x000000025, 0x000000025, 0x000000025, + 0x00000025, 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x00000025, + 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x00000025, 0x000000025, + 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x00000025, 0x000000025, 0x000000025, + 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x00000025, 0x000000025, 0x000000025, 0x000000025, + 0x000000025, 0x000000025, 0x000000025, 0x000000025, 0x00000025, 0x000000025, 0x000000025, 0x000000025, 0x000000024, + 0x000000024, 0x000000024, 0x000000024, 0x00000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, + 0x000000024, 0x000000024, 0x00000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, + 0x000000024, 0x00000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, + 0x00000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x00000024, + 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x000000024, 0x00000024, 0x000000024, + 0x000000024, 0x000000024, 0x000000024, 0x000000023, 0x000000023, 0x000000023, 0x00000023, 0x000000023, 0x000000023, + 0x000000023, 0x000000023, 0x000000023, 0x000000023, 0x000000023, 0x00000023, 0x000000023, 0x000000023, 0x000000023, + 0x000000023, 0x000000023, 0x000000023, 0x000000023, 0x00000023, 0x000000023, 0x000000023, 0x000000023, 0x000000023, + 0x000000023, 0x000000023, 0x000000023, 0x00000023, 0x000000023, 0x000000023, 0x000000023, 0x000000023, 0x000000023, + 0x000000023, 0x000000023, 0x00000023, 0x000000023, 0x000000023, 0x000000023, 0x000000023, 0x000000023, 0x000000023, + 0x000000023, 0x00000023, 0x000000023, 0x000000023, 0x000000023, 0x000000023, 0x000000023, 0x000000023, 0x000000023, + 0x00000023, 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x00000022, + 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x00000022, 0x000000022, + 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x00000022, 0x000000022, 0x000000022, + 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x00000022, 0x000000022, 0x000000022, 0x000000022, + 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x00000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, + 0x000000022, 0x000000022, 0x000000022, 0x00000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, 0x000000022, + 0x000000022, 0x000000022, 0x00000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, + 0x000000021, 0x00000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, + 0x00000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x00000021, + 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x00000021, 0x000000021, + 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x00000021, 0x000000021, 0x000000021, + 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x00000021, 0x000000021, 0x000000021, 0x000000021, + 0x000000021, 0x000000021, 0x000000021, 0x000000021, 0x00000021, 0x000000021, 0x000000020, 0x000000020, 0x000000020, + 0x000000020, 0x000000020, 0x000000020, 0x00000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, + 0x000000020, 0x000000020, 0x00000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, + 0x000000020, 0x00000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, + 0x00000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x00000020, + 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x00000020, 0x000000020, + 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x00000020, 0x000000020, 0x000000020, + 0x000000020, 0x000000020, 0x000000020, 0x000000020, 0x000000020, +}; diff --git a/bren/FW/fixed_agnostic.c b/bren/FW/fixed_agnostic.c new file mode 100644 index 00000000..cc0d8ae5 --- /dev/null +++ b/bren/FW/fixed_agnostic.c @@ -0,0 +1,681 @@ +#include +#include +#include + +static br_angle const __sincos_table[] = { + 0x0000, 0x0324, 0x0647, 0x096A, 0x0C8B, 0x0FAB, 0x12C7, 0x15E1, 0x18F8, 0x1C0B, 0x1F19, 0x2223, 0x2527, 0x2826, + 0x2B1E, 0x2E10, 0x30FB, 0x33DE, 0x36B9, 0x398C, 0x3C56, 0x3F16, 0x41CD, 0x447A, 0x471C, 0x49B3, 0x4C3F, 0x4EBF, + 0x5133, 0x539A, 0x55F4, 0x5842, 0x5A81, 0x5CB3, 0x5ED6, 0x60EB, 0x62F1, 0x64E7, 0x66CE, 0x68A5, 0x6A6C, 0x6C23, + 0x6DC9, 0x6F5E, 0x70E1, 0x7254, 0x73B5, 0x7503, 0x7640, 0x776B, 0x7883, 0x7989, 0x7A7C, 0x7B5C, 0x7C29, 0x7CE2, + 0x7D89, 0x7E1C, 0x7E9C, 0x7F08, 0x7F61, 0x7FA6, 0x7FD7, 0x7FF5, + + 0x7FFF, 0x7FF5, 0x7FD7, 0x7FA6, 0x7F61, 0x7F08, 0x7E9C, 0x7E1C, 0x7D89, 0x7CE2, 0x7C29, 0x7B5C, 0x7A7C, 0x7989, + 0x7883, 0x776B, 0x7640, 0x7503, 0x73B5, 0x7254, 0x70E1, 0x6F5E, 0x6DC9, 0x6C23, 0x6A6C, 0x68A5, 0x66CE, 0x64E7, + 0x62F1, 0x60EB, 0x5ED6, 0x5CB3, 0x5A81, 0x5842, 0x55F4, 0x539A, 0x5133, 0x4EBF, 0x4C3F, 0x49B3, 0x471C, 0x447A, + 0x41CD, 0x3F16, 0x3C56, 0x398C, 0x36B9, 0x33DE, 0x30FB, 0x2E10, 0x2B1E, 0x2826, 0x2527, 0x2223, 0x1F19, 0x1C0B, + 0x18F8, 0x15E1, 0x12C7, 0x0FAB, 0x0C8B, 0x096A, 0x0647, 0x0324, 0x0000, 0xFCDC, 0xF9B9, 0xF696, 0xF375, 0xF055, + 0xED39, 0xEA1F, 0xE708, 0xE3F5, 0xE0E7, 0xDDDD, 0xDAD9, 0xD7DA, 0xD4E2, 0xD1F0, 0xCF05, 0xCC22, 0xC947, 0xC674, + 0xC3AA, 0xC0EA, 0xBE33, 0xBB86, 0xB8E4, 0xB64D, 0xB3C1, 0xB141, 0xAECD, 0xAC66, 0xAA0C, 0xA7BE, 0xA57F, 0xA34D, + 0xA12A, 0x9F15, 0x9D0F, 0x9B19, 0x9932, 0x975B, 0x9594, 0x93DD, 0x9237, 0x90A2, 0x8F1F, 0x8DAC, 0x8C4B, 0x8AFD, + 0x89C0, 0x8895, 0x877D, 0x8677, 0x8584, 0x84A4, 0x83D7, 0x831E, 0x8277, 0x81E4, 0x8164, 0x80F8, 0x809F, 0x805A, + 0x8029, 0x800B, 0x8001, 0x800B, 0x8029, 0x805A, 0x809F, 0x80F8, 0x8164, 0x81E4, 0x8277, 0x831E, 0x83D7, 0x84A4, + 0x8584, 0x8677, 0x877D, 0x8895, 0x89C0, 0x8AFD, 0x8C4B, 0x8DAC, 0x8F1F, 0x90A2, 0x9237, 0x93DD, 0x9594, 0x975B, + 0x9932, 0x9B19, 0x9D0F, 0x9F15, 0xA12A, 0xA34D, 0xA57F, 0xA7BE, 0xAA0C, 0xAC66, 0xAECD, 0xB141, 0xB3C1, 0xB64D, + 0xB8E4, 0xBB86, 0xBE33, 0xC0EA, 0xC3AA, 0xC674, 0xC947, 0xCC22, 0xCF05, 0xD1F0, 0xD4E2, 0xD7DA, 0xDAD9, 0xDDDD, + 0xE0E7, 0xE3F5, 0xE708, 0xEA1F, 0xED39, 0xF055, 0xF375, 0xF696, 0xF9B9, 0xFCDC, 0x0000, 0x0324, 0x0647, 0x096A, + 0x0C8B, 0x0FAB, 0x12C7, 0x15E1, 0x18F8, 0x1C0B, 0x1F19, 0x2223, 0x2527, 0x2826, 0x2B1E, 0x2E10, 0x30FB, 0x33DE, + 0x36B9, 0x398C, 0x3C56, 0x3F16, 0x41CD, 0x447A, 0x471C, 0x49B3, 0x4C3F, 0x4EBF, 0x5133, 0x539A, 0x55F4, 0x5842, + 0x5A81, 0x5CB3, 0x5ED6, 0x60EB, 0x62F1, 0x64E7, 0x66CE, 0x68A5, 0x6A6C, 0x6C23, 0x6DC9, 0x6F5E, 0x70E1, 0x7254, + 0x73B5, 0x7503, 0x7640, 0x776B, 0x7883, 0x7989, 0x7A7C, 0x7B5C, 0x7C29, 0x7CE2, 0x7D89, 0x7E1C, 0x7E9C, 0x7F08, + 0x7F61, 0x7FA6, 0x7FD7, 0x7FF5, 0x7FFF, 0x7FFF}; + +static br_angle const __arcsin_table[] = { + 0xC001, 0xC519, 0xC737, 0xC8D7, 0xCA37, 0xCB6D, 0xCC87, 0xCD8A, 0xCE7C, 0xCF5F, 0xD037, 0xD104, 0xD1C9, 0xD286, + 0xD33C, 0xD3ED, 0xD498, 0xD53E, 0xD5DF, 0xD67C, 0xD716, 0xD7AC, 0xD83F, 0xD8CF, 0xD95C, 0xD9E7, 0xDA6F, 0xDAF4, + 0xDB78, 0xDBF9, 0xDC79, 0xDCF7, 0xDD73, 0xDDED, 0xDE66, 0xDEDD, 0xDF53, 0xDFC8, 0xE03B, 0xE0AD, 0xE11E, 0xE18D, + 0xE1FC, 0xE26A, 0xE2D6, 0xE342, 0xE3AC, 0xE416, 0xE47F, 0xE4E7, 0xE54E, 0xE5B4, 0xE61A, 0xE67F, 0xE6E3, 0xE746, + 0xE7A9, 0xE80C, 0xE86D, 0xE8CE, 0xE92F, 0xE98F, 0xE9EE, 0xEA4D, 0xEAAB, 0xEB09, 0xEB66, 0xEBC3, 0xEC20, 0xEC7C, + 0xECD7, 0xED33, 0xED8D, 0xEDE8, 0xEE42, 0xEE9C, 0xEEF5, 0xEF4E, 0xEFA7, 0xEFFF, 0xF057, 0xF0AF, 0xF106, 0xF15D, + 0xF1B4, 0xF20B, 0xF261, 0xF2B8, 0xF30D, 0xF363, 0xF3B9, 0xF40E, 0xF463, 0xF4B8, 0xF50C, 0xF561, 0xF5B5, 0xF609, + 0xF65D, 0xF6B1, 0xF704, 0xF758, 0xF7AB, 0xF7FE, 0xF851, 0xF8A4, 0xF8F7, 0xF949, 0xF99C, 0xF9EE, 0xFA41, 0xFA93, + 0xFAE5, 0xFB37, 0xFB89, 0xFBDB, 0xFC2D, 0xFC7F, 0xFCD1, 0xFD23, 0xFD74, 0xFDC6, 0xFE17, 0xFE69, 0xFEBA, 0xFF0C, + 0xFF5E, 0xFFAF, 0x0000, 0x0051, 0x00A2, 0x00F4, 0x0146, 0x0197, 0x01E9, 0x023A, 0x028C, 0x02DD, 0x032F, 0x0381, + 0x03D3, 0x0425, 0x0477, 0x04C9, 0x051B, 0x056D, 0x05BF, 0x0612, 0x0664, 0x06B7, 0x0709, 0x075C, 0x07AF, 0x0802, + 0x0855, 0x08A8, 0x08FC, 0x094F, 0x09A3, 0x09F7, 0x0A4B, 0x0A9F, 0x0AF4, 0x0B48, 0x0B9D, 0x0BF2, 0x0C47, 0x0C9D, + 0x0CF3, 0x0D48, 0x0D9F, 0x0DF5, 0x0E4C, 0x0EA3, 0x0EFA, 0x0F51, 0x0FA9, 0x1001, 0x1059, 0x10B2, 0x110B, 0x1164, + 0x11BE, 0x1218, 0x1273, 0x12CD, 0x1329, 0x1384, 0x13E0, 0x143D, 0x149A, 0x14F7, 0x1555, 0x15B3, 0x1612, 0x1671, + 0x16D1, 0x1732, 0x1793, 0x17F4, 0x1857, 0x18BA, 0x191D, 0x1981, 0x19E6, 0x1A4C, 0x1AB2, 0x1B19, 0x1B81, 0x1BEA, + 0x1C54, 0x1CBE, 0x1D2A, 0x1D96, 0x1E04, 0x1E73, 0x1EE2, 0x1F53, 0x1FC5, 0x2038, 0x20AD, 0x2123, 0x219A, 0x2213, + 0x228D, 0x2309, 0x2387, 0x2407, 0x2488, 0x250C, 0x2591, 0x2619, 0x26A4, 0x2731, 0x27C1, 0x2854, 0x28EA, 0x2984, + 0x2A21, 0x2AC2, 0x2B68, 0x2C13, 0x2CC4, 0x2D7A, 0x2E37, 0x2EFC, 0x2FC9, 0x30A1, 0x3184, 0x3276, 0x3379, 0x3493, + 0x35C9, 0x3729, 0x38C9, 0x3AE7, 0x4000}; + +static br_angle const __arccos_table[] = { + 0x7FFF, 0x7AE7, 0x78C9, 0x7729, 0x75C9, 0x7493, 0x7379, 0x7276, 0x7184, 0x70A1, 0x6FC9, 0x6EFC, 0x6E37, 0x6D7A, + 0x6CC4, 0x6C13, 0x6B68, 0x6AC2, 0x6A21, 0x6984, 0x68EA, 0x6854, 0x67C1, 0x6731, 0x66A4, 0x6619, 0x6591, 0x650C, + 0x6488, 0x6407, 0x6387, 0x6309, 0x628D, 0x6213, 0x619A, 0x6123, 0x60AD, 0x6038, 0x5FC5, 0x5F53, 0x5EE2, 0x5E73, + 0x5E04, 0x5D96, 0x5D2A, 0x5CBE, 0x5C54, 0x5BEA, 0x5B81, 0x5B19, 0x5AB2, 0x5A4C, 0x59E6, 0x5981, 0x591D, 0x58BA, + 0x5857, 0x57F4, 0x5793, 0x5732, 0x56D1, 0x5671, 0x5612, 0x55B3, 0x5555, 0x54F7, 0x549A, 0x543D, 0x53E0, 0x5384, + 0x5329, 0x52CD, 0x5273, 0x5218, 0x51BE, 0x5164, 0x510B, 0x50B2, 0x5059, 0x5001, 0x4FA9, 0x4F51, 0x4EFA, 0x4EA3, + 0x4E4C, 0x4DF5, 0x4D9F, 0x4D48, 0x4CF3, 0x4C9D, 0x4C47, 0x4BF2, 0x4B9D, 0x4B48, 0x4AF4, 0x4A9F, 0x4A4B, 0x49F7, + 0x49A3, 0x494F, 0x48FC, 0x48A8, 0x4855, 0x4802, 0x47AF, 0x475C, 0x4709, 0x46B7, 0x4664, 0x4612, 0x45BF, 0x456D, + 0x451B, 0x44C9, 0x4477, 0x4425, 0x43D3, 0x4381, 0x432F, 0x42DD, 0x428C, 0x423A, 0x41E9, 0x4197, 0x4146, 0x40F4, + 0x40A2, 0x4051, 0x3FFF, 0x3FAE, 0x3F5D, 0x3F0B, 0x3EB9, 0x3E68, 0x3E16, 0x3DC5, 0x3D73, 0x3D22, 0x3CD0, 0x3C7E, + 0x3C2C, 0x3BDA, 0x3B88, 0x3B36, 0x3AE4, 0x3A92, 0x3A40, 0x39ED, 0x399B, 0x3948, 0x38F6, 0x38A3, 0x3850, 0x37FD, + 0x37AA, 0x3757, 0x3703, 0x36B0, 0x365C, 0x3608, 0x35B4, 0x3560, 0x350B, 0x34B7, 0x3462, 0x340D, 0x33B8, 0x3362, + 0x330C, 0x32B7, 0x3260, 0x320A, 0x31B3, 0x315C, 0x3105, 0x30AE, 0x3056, 0x2FFE, 0x2FA6, 0x2F4D, 0x2EF4, 0x2E9B, + 0x2E41, 0x2DE7, 0x2D8C, 0x2D32, 0x2CD6, 0x2C7B, 0x2C1F, 0x2BC2, 0x2B65, 0x2B08, 0x2AAA, 0x2A4C, 0x29ED, 0x298E, + 0x292E, 0x28CD, 0x286C, 0x280B, 0x27A8, 0x2745, 0x26E2, 0x267E, 0x2619, 0x25B3, 0x254D, 0x24E6, 0x247E, 0x2415, + 0x23AB, 0x2341, 0x22D5, 0x2269, 0x21FB, 0x218C, 0x211D, 0x20AC, 0x203A, 0x1FC7, 0x1F52, 0x1EDC, 0x1E65, 0x1DEC, + 0x1D72, 0x1CF6, 0x1C78, 0x1BF8, 0x1B77, 0x1AF3, 0x1A6E, 0x19E6, 0x195B, 0x18CE, 0x183E, 0x17AB, 0x1715, 0x167B, + 0x15DE, 0x153D, 0x1497, 0x13EC, 0x133B, 0x1285, 0x11C8, 0x1103, 0x1036, 0x0F5E, 0x0E7B, 0x0D89, 0x0C86, 0x0B6C, + 0x0A36, 0x08D6, 0x0736, 0x0518, 0x0000}; + +static br_angle const __arctan_table[] = { + 0x0000, 0x0028, 0x0051, 0x007A, 0x00A2, 0x00CB, 0x00F4, 0x011D, 0x0145, 0x016E, 0x0197, 0x01BF, 0x01E8, 0x0211, + 0x0239, 0x0262, 0x028B, 0x02B3, 0x02DC, 0x0304, 0x032D, 0x0355, 0x037E, 0x03A6, 0x03CE, 0x03F7, 0x041F, 0x0448, + 0x0470, 0x0498, 0x04C0, 0x04E8, 0x0511, 0x0539, 0x0561, 0x0589, 0x05B1, 0x05D9, 0x0601, 0x0628, 0x0650, 0x0678, + 0x06A0, 0x06C7, 0x06EF, 0x0716, 0x073E, 0x0765, 0x078D, 0x07B4, 0x07DB, 0x0803, 0x082A, 0x0851, 0x0878, 0x089F, + 0x08C6, 0x08ED, 0x0913, 0x093A, 0x0961, 0x0987, 0x09AE, 0x09D4, 0x09FB, 0x0A21, 0x0A47, 0x0A6D, 0x0A94, 0x0ABA, + 0x0AE0, 0x0B05, 0x0B2B, 0x0B51, 0x0B77, 0x0B9C, 0x0BC2, 0x0BE7, 0x0C0C, 0x0C32, 0x0C57, 0x0C7C, 0x0CA1, 0x0CC6, + 0x0CEB, 0x0D0F, 0x0D34, 0x0D58, 0x0D7D, 0x0DA1, 0x0DC6, 0x0DEA, 0x0E0E, 0x0E32, 0x0E56, 0x0E7A, 0x0E9E, 0x0EC1, + 0x0EE5, 0x0F08, 0x0F2C, 0x0F4F, 0x0F72, 0x0F95, 0x0FB8, 0x0FDB, 0x0FFE, 0x1021, 0x1044, 0x1066, 0x1089, 0x10AB, + 0x10CD, 0x10EF, 0x1111, 0x1133, 0x1155, 0x1177, 0x1199, 0x11BA, 0x11DC, 0x11FD, 0x121E, 0x123F, 0x1260, 0x1281, + 0x12A2, 0x12C3, 0x12E4, 0x1304, 0x1325, 0x1345, 0x1365, 0x1385, 0x13A5, 0x13C5, 0x13E5, 0x1405, 0x1424, 0x1444, + 0x1463, 0x1483, 0x14A2, 0x14C1, 0x14E0, 0x14FF, 0x151E, 0x153C, 0x155B, 0x1579, 0x1598, 0x15B6, 0x15D4, 0x15F2, + 0x1610, 0x162E, 0x164C, 0x166A, 0x1687, 0x16A5, 0x16C2, 0x16DF, 0x16FC, 0x1719, 0x1736, 0x1753, 0x1770, 0x178C, + 0x17A9, 0x17C5, 0x17E2, 0x17FE, 0x181A, 0x1836, 0x1852, 0x186E, 0x188A, 0x18A5, 0x18C1, 0x18DC, 0x18F7, 0x1913, + 0x192E, 0x1949, 0x1964, 0x197F, 0x1999, 0x19B4, 0x19CE, 0x19E9, 0x1A03, 0x1A1D, 0x1A37, 0x1A51, 0x1A6B, 0x1A85, + 0x1A9F, 0x1AB9, 0x1AD2, 0x1AEC, 0x1B05, 0x1B1E, 0x1B37, 0x1B50, 0x1B69, 0x1B82, 0x1B9B, 0x1BB4, 0x1BCC, 0x1BE5, + 0x1BFD, 0x1C16, 0x1C2E, 0x1C46, 0x1C5E, 0x1C76, 0x1C8E, 0x1CA5, 0x1CBD, 0x1CD5, 0x1CEC, 0x1D04, 0x1D1B, 0x1D32, + 0x1D49, 0x1D60, 0x1D77, 0x1D8E, 0x1DA5, 0x1DBB, 0x1DD2, 0x1DE9, 0x1DFF, 0x1E15, 0x1E2C, 0x1E42, 0x1E58, 0x1E6E, + 0x1E84, 0x1E99, 0x1EAF, 0x1EC5, 0x1EDA, 0x1EF0, 0x1F05, 0x1F1B, 0x1F30, 0x1F45, 0x1F5A, 0x1F6F, 0x1F84, 0x1F99, + 0x1FAD, 0x1FC2, 0x1FD7, 0x1FEB, 0x2000}; + +static br_angle const __sqrt_table[] = { + 0x8000, 0x80FF, 0x81FC, 0x82F7, 0x83F0, 0x84E7, 0x85DD, 0x86D1, 0x87C3, 0x88B4, 0x89A3, 0x8A90, 0x8B7C, 0x8C66, + 0x8D4E, 0x8E36, 0x8F1B, 0x9000, 0x90E2, 0x91C4, 0x92A4, 0x9383, 0x9460, 0x953C, 0x9617, 0x96F1, 0x97CA, 0x98A1, + 0x9977, 0x9A4C, 0x9B20, 0x9BF2, 0x9CC4, 0x9D94, 0x9E64, 0x9F32, 0xA000, 0xA0CC, 0xA197, 0xA261, 0xA32B, 0xA3F3, + 0xA4BA, 0xA581, 0xA646, 0xA70B, 0xA7CF, 0xA892, 0xA953, 0xAA15, 0xAAD5, 0xAB94, 0xAC53, 0xAD11, 0xADCD, 0xAE8A, + 0xAF45, 0xB000, 0xB0B9, 0xB172, 0xB22B, 0xB2E2, 0xB399, 0xB44F, 0xB504, 0xB5B9, 0xB66D, 0xB720, 0xB7D3, 0xB885, + 0xB936, 0xB9E7, 0xBA97, 0xBB46, 0xBBF5, 0xBCA3, 0xBD50, 0xBDFD, 0xBEA9, 0xBF55, 0xC000, 0xC0AA, 0xC154, 0xC1FD, + 0xC2A5, 0xC34E, 0xC3F5, 0xC49C, 0xC542, 0xC5E8, 0xC68E, 0xC732, 0xC7D7, 0xC87A, 0xC91D, 0xC9C0, 0xCA62, 0xCB04, + 0xCBA5, 0xCC46, 0xCCE6, 0xCD86, 0xCE25, 0xCEC3, 0xCF62, 0xD000, 0xD09D, 0xD13A, 0xD1D6, 0xD272, 0xD30D, 0xD3A8, + 0xD443, 0xD4DD, 0xD577, 0xD610, 0xD6A9, 0xD742, 0xD7DA, 0xD871, 0xD908, 0xD99F, 0xDA35, 0xDACB, 0xDB61, 0xDBF6, + 0xDC8B, 0xDD1F, 0xDDB3, 0xDE47, 0xDEDA, 0xDF6D, 0xE000, 0xE092, 0xE123, 0xE1B5, 0xE246, 0xE2D6, 0xE367, 0xE3F7, + 0xE486, 0xE515, 0xE5A4, 0xE633, 0xE6C1, 0xE74F, 0xE7DC, 0xE869, 0xE8F6, 0xE983, 0xEA0F, 0xEA9B, 0xEB26, 0xEBB1, + 0xEC3C, 0xECC7, 0xED51, 0xEDDB, 0xEE65, 0xEEEE, 0xEF77, 0xF000, 0xF088, 0xF110, 0xF198, 0xF21F, 0xF2A6, 0xF32D, + 0xF3B4, 0xF43A, 0xF4C0, 0xF546, 0xF5CB, 0xF651, 0xF6D6, 0xF75A, 0xF7DE, 0xF863, 0xF8E6, 0xF96A, 0xF9ED, 0xFA70, + 0xFAF3, 0xFB75, 0xFBF7, 0xFC79, 0xFCFB, 0xFD7C, 0xFDFD, 0xFE7E, 0xFEFF, 0xFF7F, + + 0xFFFF, 0xFE05, 0xFC17, 0xFA33, 0xF85B, 0xF68C, 0xF4C8, 0xF30D, 0xF15B, 0xEFB3, 0xEE13, 0xEC7B, 0xEAEB, 0xE964, + 0xE7E3, 0xE66B, 0xE4F9, 0xE38E, 0xE229, 0xE0CC, 0xDF74, 0xDE23, 0xDCD7, 0xDB91, 0xDA51, 0xD916, 0xD7E0, 0xD6B0, + 0xD584, 0xD45E, 0xD33C, 0xD21E, 0xD105, 0xCFF1, 0xCEE1, 0xCDD4, 0xCCCC, 0xCBC8, 0xCAC8, 0xC9CB, 0xC8D2, 0xC7DD, + 0xC6EB, 0xC5FC, 0xC511, 0xC429, 0xC344, 0xC263, 0xC184, 0xC0A8, 0xBFD0, 0xBEFA, 0xBE26, 0xBD56, 0xBC88, 0xBBBD, + 0xBAF4, 0xBA2E, 0xB96A, 0xB8A9, 0xB7EA, 0xB72D, 0xB673, 0xB5BB, 0xB504, 0xB450, 0xB39F, 0xB2EF, 0xB241, 0xB195, + 0xB0EB, 0xB043, 0xAF9D, 0xAEF8, 0xAE56, 0xADB5, 0xAD16, 0xAC79, 0xABDD, 0xAB43, 0xAAAA, 0xAA13, 0xA97E, 0xA8EA, + 0xA858, 0xA7C7, 0xA737, 0xA6A9, 0xA61D, 0xA592, 0xA508, 0xA47F, 0xA3F8, 0xA372, 0xA2EE, 0xA26A, 0xA1E8, 0xA167, + 0xA0E7, 0xA069, 0x9FEC, 0x9F6F, 0x9EF4, 0x9E7A, 0x9E01, 0x9D89, 0x9D13, 0x9C9D, 0x9C28, 0x9BB4, 0x9B42, 0x9AD0, + 0x9A5F, 0x99EF, 0x9981, 0x9913, 0x98A6, 0x983A, 0x97CE, 0x9764, 0x96FB, 0x9692, 0x962A, 0x95C3, 0x955D, 0x94F8, + 0x9493, 0x9430, 0x93CD, 0x936B, 0x9309, 0x92A9, 0x9249, 0x91E9, 0x918B, 0x912D, 0x90D0, 0x9074, 0x9018, 0x8FBD, + 0x8F63, 0x8F09, 0x8EB0, 0x8E58, 0x8E00, 0x8DA9, 0x8D53, 0x8CFD, 0x8CA8, 0x8C53, 0x8BFF, 0x8BAC, 0x8B59, 0x8B06, + 0x8AB5, 0x8A64, 0x8A13, 0x89C3, 0x8973, 0x8924, 0x88D6, 0x8888, 0x883B, 0x87EE, 0x87A1, 0x8755, 0x870A, 0x86BF, + 0x8675, 0x862B, 0x85E1, 0x8598, 0x8550, 0x8508, 0x84C0, 0x8479, 0x8432, 0x83EC, 0x83A6, 0x8361, 0x831C, 0x82D7, + 0x8293, 0x824F, 0x820C, 0x81C9, 0x8186, 0x8144, 0x8103, 0x80C1, 0x8080, 0x8040, +}; + +static br_angle const *__sin_table = &__sincos_table[0]; +static br_angle const *__cos_table = &__sincos_table[64]; +static br_angle const *__sqrt_nr_table = &__sqrt_table[0]; +static br_angle const *__sqrt_r_table = &__sqrt_table[64]; + +static inline br_fixed_lsf __BrInterpTable(br_angle const *table, br_angle const i) +{ + br_uint_8 lo = (i & 0x00FF); + br_uint_8 hi = (i & 0xFF00) >> 8; + + br_fixed_lsf val0 = table[hi]; + br_fixed_lsf val1 = table[hi + 1]; + + br_int_32 lerp = (val1 - val0) * lo; + return (lerp >> 8) + val0; +} + +static inline br_uint_32 __BrSqrt64(br_uint_64 a) +{ + br_int_32 error = 0; + br_int_32 estimate = 0; + br_int_32 estimate_mul2 = 0; + + br_uint_32 hi = a >> 32; + br_uint_32 lo = a; + + for (int i = 0; i < 16; i++) + { + error <<= 2; + error |= hi >> (32 - 2); + hi <<= 2; + + estimate *= 2; + estimate_mul2 *= 2; + + if (estimate_mul2 < error) + { + error -= estimate_mul2 + 1; + estimate += 1; + estimate_mul2 += 2; + } + } + + for (int i = 0; i < 16; i++) + { + error <<= 2; + error |= lo >> (32 - 2); + lo <<= 2; + + estimate *= 2; + estimate_mul2 *= 2; + + if (estimate_mul2 < error) + { + error -= estimate_mul2 + 1; + estimate += 1; + estimate_mul2 += 2; + } + } + + return estimate; +} + +static inline br_uint_32 __BrFastRSqrt(br_uint_64 a) +{ + unsigned char clz = __BrBuiltinCLZ(a); + if (clz == 0) + { + return 0; + } + + clz |= 1; + a = __BrBuiltinROR(a, clz); + a = __BrBuiltinROR(a, 1); + a >>= 24; + + br_uint_32 result = __sqrt_r_table[a * 2]; + + clz >>= 1; + result >>= clz; + + return result; +} + +static inline br_uint_32 __BrFastRSqrt64(br_uint_64 a) +{ + if ((a >> 32) != 0) + { + return __BrFastRSqrt(a >> 32); + } + else + { + return __BrFastRSqrt(a); + } +} + +br_fixed_ls BR_ASM_CALL BrFixedAbs(br_fixed_ls a) +{ + if (a >= 0) + { + return a; + } + else + { + return -a; + } +} + +br_fixed_ls BR_ASM_CALL BrFixedMul(br_fixed_ls a, br_fixed_ls b) +{ + br_int_64 mul = (br_int_64)a * (br_int_64)b; + return mul >> 16; +} + +br_fixed_ls BR_ASM_CALL BrFixedDiv(br_fixed_ls a, br_fixed_ls b) +{ + br_int_64 __a = (br_int_64)a << 16; + return __BrBuiltinDivI64I32(__a, b); +} + +br_fixed_ls BR_ASM_CALL BrFixedDivF(br_fixed_ls a, br_fixed_ls b) +{ + br_int_64 __a = (br_int_64)a << 31; + return __BrBuiltinDivI64I32(__a, b); +} + +br_fixed_ls BR_ASM_CALL BrFixedDivR(br_fixed_ls a, br_fixed_ls b) +{ + // NOTE(bjrkk): this isn't really how it originally was done but + // it still ends up giving extremely close results. + return BrFixedDiv(a, b) & 0x0000FFFF; +} + +br_fixed_ls BR_ASM_CALL BrFixedMulDiv(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c) +{ + br_int_64 mul = (br_int_64)a * (br_int_64)b; + return __BrBuiltinDivI64I32(mul, c); +} + +br_fixed_ls BR_ASM_CALL BrFixedMac2(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c, br_fixed_ls d) +{ + br_int_64 ab = (br_int_64)a * (br_int_64)b; + br_int_64 cd = (br_int_64)c * (br_int_64)d; + return (br_uint_64)(ab + cd) >> 16; +} + +br_fixed_ls BR_ASM_CALL BrFixedMac3(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c, br_fixed_ls d, br_fixed_ls e, + br_fixed_ls f) +{ + br_int_64 ab = (br_int_64)a * (br_int_64)b; + br_int_64 cd = (br_int_64)c * (br_int_64)d; + br_int_64 ef = (br_int_64)e * (br_int_64)f; + return (br_uint_64)(ab + cd + ef) >> 16; +} + +br_fixed_ls BR_ASM_CALL BrFixedMac4(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c, br_fixed_ls d, br_fixed_ls e, + br_fixed_ls f, br_fixed_ls g, br_fixed_ls h) +{ + br_int_64 ab = (br_int_64)a * (br_int_64)b; + br_int_64 cd = (br_int_64)c * (br_int_64)d; + br_int_64 ef = (br_int_64)e * (br_int_64)f; + br_int_64 gh = (br_int_64)g * (br_int_64)h; + return (br_uint_64)(ab + cd + ef + gh) >> 16; +} + +br_fixed_ls BR_ASM_CALL BrFixedMac2Div(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c, br_fixed_ls d, br_fixed_ls e) +{ + br_int_64 ab = (br_int_64)a * (br_int_64)b; + br_int_64 cd = (br_int_64)c * (br_int_64)d; + return __BrBuiltinDivI64I32(ab + cd, e); +} + +br_fixed_ls BR_ASM_CALL BrFixedMac3Div(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c, br_fixed_ls d, br_fixed_ls e, + br_fixed_ls f, br_fixed_ls g) +{ + br_int_64 ab = (br_int_64)a * (br_int_64)b; + br_int_64 cd = (br_int_64)c * (br_int_64)d; + br_int_64 ef = (br_int_64)e * (br_int_64)f; + return __BrBuiltinDivI64I32(ab + cd + ef, g); +} + +/* result = (a*b + c*d + e*f + g*h)/i + */ +br_fixed_ls BR_ASM_CALL BrFixedMac4Div(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c, br_fixed_ls d, br_fixed_ls e, + br_fixed_ls f, br_fixed_ls g, br_fixed_ls h, br_fixed_ls i) +{ + br_int_64 ab = (br_int_64)a * (br_int_64)b; + br_int_64 cd = (br_int_64)c * (br_int_64)d; + br_int_64 ef = (br_int_64)e * (br_int_64)f; + br_int_64 gh = (br_int_64)g * (br_int_64)h; + return __BrBuiltinDivI64I32(ab + cd + ef + gh, i); +} + +br_fixed_ls BR_ASM_CALL BrFixedFMac2(br_fixed_lsf a, br_fixed_ls b, br_fixed_lsf c, br_fixed_ls d) +{ + br_int_64 ab = (br_int_64)a * (br_int_64)b; + br_int_64 cd = (br_int_64)c * (br_int_64)d; + return (br_uint_64)(ab + cd) >> 15; +} + +/* result = a*b + c*d + e*f - a,c & e are fractions + */ +br_fixed_ls BR_ASM_CALL BrFixedFMac3(br_fixed_lsf a, br_fixed_ls b, br_fixed_lsf c, br_fixed_ls d, br_fixed_lsf e, + br_fixed_ls f) +{ + br_int_64 ab = (br_int_64)a * (br_int_64)b; + br_int_64 cd = (br_int_64)c * (br_int_64)d; + br_int_64 ef = (br_int_64)e * (br_int_64)f; + return (br_uint_64)(ab + cd + ef) >> 15; +} + +/* result = a*b + c*d + e*f + g*h (a,c,e,g are fractions) + */ +br_fixed_ls BR_ASM_CALL BrFixedFMac4(br_fixed_lsf a, br_fixed_ls b, br_fixed_lsf c, br_fixed_ls d, br_fixed_lsf e, + br_fixed_ls f, br_fixed_lsf g, br_fixed_ls h) +{ + br_int_64 ab = (br_int_64)a * (br_int_64)b; + br_int_64 cd = (br_int_64)c * (br_int_64)d; + br_int_64 ef = (br_int_64)e * (br_int_64)f; + br_int_64 gh = (br_int_64)g * (br_int_64)h; + return (br_uint_64)(ab + cd + ef + gh) >> 15; +} + +br_fixed_ls BR_ASM_CALL BrFixedRcp(br_fixed_ls a) +{ + return BrFixedDiv(BR_SCALAR(1), a); +} + +br_fixed_ls BR_ASM_CALL BrFixedSqr(br_fixed_ls a) +{ + return BrFixedMul(a, a); +} + +br_fixed_ls BR_ASM_CALL BrFixedSqr2(br_fixed_ls a, br_fixed_ls b) +{ + br_int_64 aa = (br_int_64)a * (br_int_64)a; + br_int_64 bb = (br_int_64)b * (br_int_64)b; + return (aa + bb) >> 16; +} + +br_fixed_ls BR_ASM_CALL BrFixedSqr3(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c) +{ + br_int_64 aa = (br_int_64)a * (br_int_64)a; + br_int_64 bb = (br_int_64)b * (br_int_64)b; + br_int_64 cc = (br_int_64)c * (br_int_64)c; + return (aa + bb + cc) >> 16; +} + +br_fixed_ls BR_ASM_CALL BrFixedSqr4(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c, br_fixed_ls d) +{ + br_int_64 aa = (br_int_64)a * (br_int_64)a; + br_int_64 bb = (br_int_64)b * (br_int_64)b; + br_int_64 cc = (br_int_64)c * (br_int_64)c; + br_int_64 dd = (br_int_64)d * (br_int_64)d; + return (aa + bb + cc + dd) >> 16; +} + +br_fixed_ls BR_ASM_CALL BrFixedLength2(br_fixed_ls a, br_fixed_ls b) +{ + br_int_64 aa = (br_int_64)a * (br_int_64)a; + br_int_64 bb = (br_int_64)b * (br_int_64)b; + return __BrSqrt64(aa + bb); +} + +br_fixed_ls BR_ASM_CALL BrFixedLength3(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c) +{ + br_int_64 aa = (br_int_64)a * (br_int_64)a; + br_int_64 bb = (br_int_64)b * (br_int_64)b; + br_int_64 cc = (br_int_64)c * (br_int_64)c; + return __BrSqrt64(aa + bb + cc); +} + +br_fixed_ls BR_ASM_CALL BrFixedLength4(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c, br_fixed_ls d) +{ + br_int_64 aa = (br_int_64)a * (br_int_64)a; + br_int_64 bb = (br_int_64)b * (br_int_64)b; + br_int_64 cc = (br_int_64)c * (br_int_64)c; + br_int_64 dd = (br_int_64)d * (br_int_64)d; + return __BrSqrt64(aa + bb + cc + dd); +} + +br_fixed_ls BR_ASM_CALL BrFixedRLength2(br_fixed_ls a, br_fixed_ls b) +{ + br_int_64 aa = (br_int_64)a * (br_int_64)a; + br_int_64 bb = (br_int_64)b * (br_int_64)b; + return __BrFastRSqrt64(aa + bb); +} + +br_fixed_ls BR_ASM_CALL BrFixedRLength3(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c) +{ + br_int_64 aa = (br_int_64)a * (br_int_64)a; + br_int_64 bb = (br_int_64)b * (br_int_64)b; + br_int_64 cc = (br_int_64)c * (br_int_64)c; + return __BrFastRSqrt64(aa + bb + cc); +} + +br_fixed_ls BR_ASM_CALL BrFixedRLength4(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c, br_fixed_ls d) +{ + br_int_64 aa = (br_int_64)a * (br_int_64)a; + br_int_64 bb = (br_int_64)b * (br_int_64)b; + br_int_64 cc = (br_int_64)c * (br_int_64)c; + br_int_64 dd = (br_int_64)d * (br_int_64)d; + return __BrFastRSqrt64(aa + bb + cc + dd); +} + +br_fixed_ls BR_ASM_CALL BrFixedSin(br_angle a) +{ + br_fixed_ls value = __BrInterpTable(__sin_table, a); + return value + value; +} + +br_fixed_ls BR_ASM_CALL BrFixedCos(br_angle a) +{ + br_fixed_ls value = __BrInterpTable(__cos_table, a); + return value + value; +} + +br_angle BR_ASM_CALL BrFixedASin(br_fixed_ls a) +{ + a += (1 << 16); + a >>= 1; + return __BrInterpTable(__arcsin_table, a); +} + +br_angle BR_ASM_CALL BrFixedACos(br_fixed_ls a) +{ + a += (1 << 16); + a >>= 1; + return __BrInterpTable(__arccos_table, a); +} + +br_angle BR_ASM_CALL BrFixedATan2(br_fixed_ls x, br_fixed_ls y) +{ + // TODO(bjrkk): Get this out of goto hell + + if (x < 0) + { + goto octant_4567; + } + else if (x == 0) + { + goto y_zero; + } + +octant_0123: + if (y < 0) + { + goto octant_23; + } + +octant_01: + if (y < x) + { + goto octant_1; + } + else if (y == x) + { + goto boundary_01; + } + +octant_0: + return __BrInterpTable(__arctan_table, BrFixedDiv(x, y)); + +boundary_01: + return 0x2000; + +octant_1: + return 0x4000 - __BrInterpTable(__arctan_table, BrFixedDiv(y, x)); + +octant_23: + y = -y; + if (y > x) + { + goto octant_3; + } + else if (y == x) + { + goto boundary_23; + } + +octant_2: + return 0x4000 + __BrInterpTable(__arctan_table, BrFixedDiv(y, x)); + +boundary_23: + return 0x6000; + +octant_3: + return 0x8000 - __BrInterpTable(__arctan_table, BrFixedDiv(x, y)); + +octant_4567: + x = -x; + if (y > 0) + { + goto octant_67; + } + +octant_45: + y = -y; + if (y < x) + { + goto octant_5; + } + else if (y == x) + { + goto boundary_45; + } + +octant_4: + return 0x8000 + __BrInterpTable(__arctan_table, BrFixedDiv(x, y)); + +boundary_45: + return 0xA000; + +octant_5: + return 0xC000 - __BrInterpTable(__arctan_table, BrFixedDiv(y, x)); + +octant_67: + if (y > x) + { + goto octant_7; + } + else if (y == x) + { + goto boundary_67; + } + +octant_6: + return 0xC000 + __BrInterpTable(__arctan_table, BrFixedDiv(y, x)); + +boundary_67: + return 0xE000; + +octant_7: + return -__BrInterpTable(__arctan_table, BrFixedDiv(x, y)); + +y_zero: + if (y < 0) + { + return 0x8000; + } + return 0; +} + +br_angle BR_ASM_CALL BrFixedATan2Fast(br_fixed_ls x, br_fixed_ls y) +{ + // TODO(bjrkk): Get this out of goto hell + + if (x < 0) + { + goto octant_4567; + } + else if (x == 0) + { + goto x_zero; + } + +octant_0123: + if (y < 0) + { + goto octant_23; + } + +octant_01: + if (y < x) + { + goto octant_1; + } + else if (y == x) + { + goto boundary_01; + } + +octant_0: + return ((x / y) >> 19); + +octant_1: + return 0x4000 + -((y / x) >> 19); + +boundary_01: + return 0x2000; + +octant_23: + y = -y; + if (y > x) + { + goto octant_3; + } + else if (y == x) + { + goto boundary_23; + } + +octant_2: + return 0x4000 + ((y / x) >> 19); + +boundary_23: + return 0x6000; + +octant_3: + return 0x8000 + -((x / y) >> 19); + +octant_4567: + x = -x; + if (y > 0) + { + goto octant_67; + } + else if (y == 0) + { + goto boundary_45; + } + +octant_45: + y = -y; + if (y < x) + { + goto octant_5; + } + +octant_4: + return 0x8000 + ((x / y) >> 19); + +boundary_45: + return 0xA000; + +octant_5: + return 0xC000 + -((y / x) >> 19); + +octant_67: + if (y > x) + { + goto octant_7; + } + else if (y == x) + { + goto boundary_67; + } + +octant_6: + return 0xC000 + ((y / x) >> 19); + +boundary_67: + return 0xE000; + +octant_7: + return -((x / y) >> 19); + +x_zero: + if (y < 0) + { + return 0x8000; + } + + return 0; +} \ No newline at end of file diff --git a/bren/FW/font_f_3x5.c b/bren/FW/font_f_3x5.c new file mode 100644 index 00000000..ce36b8f1 --- /dev/null +++ b/bren/FW/font_f_3x5.c @@ -0,0 +1,1457 @@ +#include +#include + +#define FONT_WIDTH 3 +#define FONT_HEIGHT 5 + +#pragma pack(push, 1) +typedef struct +{ + br_uint_8 glyph_space[FONT_HEIGHT]; + br_uint_8 glyph_exclam[FONT_HEIGHT]; + br_uint_8 glyph_dquote[FONT_HEIGHT]; + br_uint_8 glyph_pound[FONT_HEIGHT]; + br_uint_8 glyph_hash[FONT_HEIGHT]; + br_uint_8 glyph_percent[FONT_HEIGHT]; + br_uint_8 glyph_ampersand[FONT_HEIGHT]; + br_uint_8 glyph_quote[FONT_HEIGHT]; + br_uint_8 glyph_lparen[FONT_HEIGHT]; + br_uint_8 glyph_rparen[FONT_HEIGHT]; + br_uint_8 glyph_asterisk[FONT_HEIGHT]; + br_uint_8 glyph_plus[FONT_HEIGHT]; + br_uint_8 glyph_comma[FONT_HEIGHT]; + br_uint_8 glyph_minus[FONT_HEIGHT]; + br_uint_8 glyph_period[FONT_HEIGHT]; + br_uint_8 glyph_slash[FONT_HEIGHT]; + br_uint_8 glyph_0[FONT_HEIGHT]; + br_uint_8 glyph_1[FONT_HEIGHT]; + br_uint_8 glyph_2[FONT_HEIGHT]; + br_uint_8 glyph_3[FONT_HEIGHT]; + br_uint_8 glyph_4[FONT_HEIGHT]; + br_uint_8 glyph_5[FONT_HEIGHT]; + br_uint_8 glyph_6[FONT_HEIGHT]; + br_uint_8 glyph_7[FONT_HEIGHT]; + br_uint_8 glyph_8[FONT_HEIGHT]; + br_uint_8 glyph_9[FONT_HEIGHT]; + br_uint_8 glyph_colon[FONT_HEIGHT]; + br_uint_8 glyph_semicolon[FONT_HEIGHT]; + br_uint_8 glyph_langle[FONT_HEIGHT]; + br_uint_8 glyph_equal[FONT_HEIGHT]; + br_uint_8 glyph_rangle[FONT_HEIGHT]; + br_uint_8 glyph_query[FONT_HEIGHT]; + br_uint_8 glyph_comat[FONT_HEIGHT]; + br_uint_8 glyph_A[FONT_HEIGHT]; + br_uint_8 glyph_B[FONT_HEIGHT]; + br_uint_8 glyph_C[FONT_HEIGHT]; + br_uint_8 glyph_D[FONT_HEIGHT]; + br_uint_8 glyph_E[FONT_HEIGHT]; + br_uint_8 glyph_F[FONT_HEIGHT]; + br_uint_8 glyph_G[FONT_HEIGHT]; + br_uint_8 glyph_H[FONT_HEIGHT]; + br_uint_8 glyph_I[FONT_HEIGHT]; + br_uint_8 glyph_J[FONT_HEIGHT]; + br_uint_8 glyph_K[FONT_HEIGHT]; + br_uint_8 glyph_L[FONT_HEIGHT]; + br_uint_8 glyph_M[FONT_HEIGHT]; + br_uint_8 glyph_N[FONT_HEIGHT]; + br_uint_8 glyph_O[FONT_HEIGHT]; + br_uint_8 glyph_P[FONT_HEIGHT]; + br_uint_8 glyph_Q[FONT_HEIGHT]; + br_uint_8 glyph_R[FONT_HEIGHT]; + br_uint_8 glyph_S[FONT_HEIGHT]; + br_uint_8 glyph_T[FONT_HEIGHT]; + br_uint_8 glyph_U[FONT_HEIGHT]; + br_uint_8 glyph_V[FONT_HEIGHT]; + br_uint_8 glyph_W[FONT_HEIGHT]; + br_uint_8 glyph_X[FONT_HEIGHT]; + br_uint_8 glyph_Y[FONT_HEIGHT]; + br_uint_8 glyph_Z[FONT_HEIGHT]; + br_uint_8 glyph_lsquare[FONT_HEIGHT]; + br_uint_8 glyph_bslash[FONT_HEIGHT]; + br_uint_8 glyph_rsquare[FONT_HEIGHT]; + br_uint_8 glyph_caret[FONT_HEIGHT]; + br_uint_8 glyph_underbar[FONT_HEIGHT]; + br_uint_8 glyph_bquote[FONT_HEIGHT]; + br_uint_8 glyph_lbrace[FONT_HEIGHT]; + br_uint_8 glyph_vbar[FONT_HEIGHT]; + br_uint_8 glyph_rbrace[FONT_HEIGHT]; + br_uint_8 glyph_tilde[FONT_HEIGHT]; + br_uint_8 glyph_openbox[FONT_HEIGHT]; + br_uint_8 glyph_alpha[FONT_HEIGHT]; + br_uint_8 glyph_sup2[FONT_HEIGHT]; + br_uint_8 glyph_degree[FONT_HEIGHT]; + br_uint_8 glyph_a[FONT_HEIGHT]; + br_uint_8 glyph_b[FONT_HEIGHT]; + br_uint_8 glyph_c[FONT_HEIGHT]; + br_uint_8 glyph_d[FONT_HEIGHT]; + br_uint_8 glyph_e[FONT_HEIGHT]; + br_uint_8 glyph_f[FONT_HEIGHT]; + br_uint_8 glyph_g[FONT_HEIGHT]; + br_uint_8 glyph_h[FONT_HEIGHT]; + br_uint_8 glyph_i[FONT_HEIGHT]; + br_uint_8 glyph_j[FONT_HEIGHT]; + br_uint_8 glyph_k[FONT_HEIGHT]; + br_uint_8 glyph_l[FONT_HEIGHT]; + br_uint_8 glyph_m[FONT_HEIGHT]; + br_uint_8 glyph_n[FONT_HEIGHT]; + br_uint_8 glyph_o[FONT_HEIGHT]; + br_uint_8 glyph_p[FONT_HEIGHT]; + br_uint_8 glyph_q[FONT_HEIGHT]; + br_uint_8 glyph_r[FONT_HEIGHT]; + br_uint_8 glyph_s[FONT_HEIGHT]; + br_uint_8 glyph_t[FONT_HEIGHT]; + br_uint_8 glyph_u[FONT_HEIGHT]; + br_uint_8 glyph_v[FONT_HEIGHT]; + br_uint_8 glyph_w[FONT_HEIGHT]; + br_uint_8 glyph_x[FONT_HEIGHT]; + br_uint_8 glyph_y[FONT_HEIGHT]; + br_uint_8 glyph_z[FONT_HEIGHT]; + br_uint_8 glyph_ld_tb[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbl[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBl[FONT_HEIGHT]; + br_uint_8 glyph_ld_Bl[FONT_HEIGHT]; + br_uint_8 glyph_ld_bL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TB[FONT_HEIGHT]; + br_uint_8 glyph_ld_BL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TL[FONT_HEIGHT]; + br_uint_8 glyph_ld_Tl[FONT_HEIGHT]; + br_uint_8 glyph_ld_tL[FONT_HEIGHT]; + br_uint_8 glyph_ld_bl[FONT_HEIGHT]; + br_uint_8 glyph_ld_tr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tlr[FONT_HEIGHT]; + br_uint_8 glyph_ld_blr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbr[FONT_HEIGHT]; + br_uint_8 glyph_ld_lr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tblr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBr[FONT_HEIGHT]; + br_uint_8 glyph_ld_TR[FONT_HEIGHT]; + br_uint_8 glyph_ld_BR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_BLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBR[FONT_HEIGHT]; + br_uint_8 glyph_ld_LR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_tLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_Tlr[FONT_HEIGHT]; + br_uint_8 glyph_ld_bLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_Blr[FONT_HEIGHT]; + br_uint_8 glyph_ld_Tr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tR[FONT_HEIGHT]; + br_uint_8 glyph_ld_bR[FONT_HEIGHT]; + br_uint_8 glyph_ld_Br[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBlr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_tl[FONT_HEIGHT]; + br_uint_8 glyph_ld_br[FONT_HEIGHT]; + br_uint_8 glyph_arrow[FONT_HEIGHT]; + br_uint_8 glyph_uparrow[FONT_HEIGHT]; + br_uint_8 glyph_downarrow[FONT_HEIGHT]; + br_uint_8 glyph_leftarrow[FONT_HEIGHT]; + br_uint_8 glyph_rightarrow[FONT_HEIGHT]; + br_uint_8 glyph_tick[FONT_HEIGHT]; + br_uint_8 glyph_bullet[FONT_HEIGHT]; +} __font_glyphs; +#pragma pack(pop) + +__font_glyphs _FontFixed3x5_Glyphs = {.glyph_space = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_dquote = + { + 0b10100000, + 0b10100000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_pound = + { + 0b01100000, + 0b01000000, + 0b11100000, + 0b01000000, + 0b11100000, + }, + .glyph_hash = + { + 0b01000000, + 0b11100000, + 0b01000000, + 0b11100000, + 0b01000000, + }, + .glyph_percent = + { + 0b10100000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b10100000, + }, + .glyph_ampersand = + { + 0b01000000, + 0b10100000, + 0b10100000, + 0b01000000, + 0b10100000, + }, + .glyph_quote = + { + 0b01000000, + 0b10000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_lparen = + { + 0b00100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b00100000, + }, + .glyph_rparen = + { + 0b10000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b10000000, + }, + .glyph_asterisk = + { + 0b00000000, + 0b10100000, + 0b01000000, + 0b10100000, + 0b00000000, + }, + .glyph_plus = + { + 0b00000000, + 0b01000000, + 0b11100000, + 0b01000000, + 0b00000000, + }, + .glyph_comma = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b01000000, + 0b10000000, + }, + .glyph_minus = + { + 0b00000000, + 0b00000000, + 0b11100000, + 0b00000000, + 0b00000000, + }, + .glyph_period = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01000000, + }, + .glyph_slash = + { + 0b00100000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b10000000, + }, + .glyph_0 = + { + 0b11100000, + 0b10100000, + 0b10100000, + 0b10100000, + 0b11100000, + }, + .glyph_1 = + { + 0b11000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b11100000, + }, + .glyph_2 = + { + 0b11100000, + 0b00100000, + 0b11100000, + 0b10000000, + 0b11100000, + }, + .glyph_3 = + { + 0b11100000, + 0b00100000, + 0b01100000, + 0b00100000, + 0b11100000, + }, + .glyph_4 = + { + 0b10000000, + 0b10000000, + 0b10100000, + 0b11100000, + 0b00100000, + }, + .glyph_5 = + { + 0b11100000, + 0b10000000, + 0b11100000, + 0b00100000, + 0b11100000, + }, + .glyph_6 = + { + 0b11100000, + 0b10000000, + 0b11100000, + 0b10100000, + 0b11100000, + }, + .glyph_7 = + { + 0b11100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + }, + .glyph_8 = + { + 0b11100000, + 0b10100000, + 0b11100000, + 0b10100000, + 0b11100000, + }, + .glyph_9 = + { + 0b11100000, + 0b10100000, + 0b11100000, + 0b00100000, + 0b11100000, + }, + .glyph_colon = + { + 0b00000000, + 0b01000000, + 0b00000000, + 0b01000000, + 0b00000000, + }, + .glyph_semicolon = + { + 0b00000000, + 0b01000000, + 0b00000000, + 0b01000000, + 0b10000000, + }, + .glyph_langle = + { + 0b00100000, + 0b01000000, + 0b10000000, + 0b01000000, + 0b00100000, + }, + .glyph_equal = + { + 0b00000000, + 0b11100000, + 0b00000000, + 0b11100000, + 0b00000000, + }, + .glyph_rangle = + { + 0b10000000, + 0b01000000, + 0b00100000, + 0b01000000, + 0b10000000, + }, + .glyph_query = + { + 0b11100000, + 0b00100000, + 0b01100000, + 0b00000000, + 0b01000000, + }, + .glyph_comat = + { + 0b11100000, + 0b10100000, + 0b10100000, + 0b10000000, + 0b11100000, + }, + .glyph_A = + { + 0b01000000, + 0b10100000, + 0b10100000, + 0b11100000, + 0b10100000, + }, + .glyph_B = + { + 0b11000000, + 0b10100000, + 0b11000000, + 0b10100000, + 0b11000000, + }, + .glyph_C = + { + 0b01100000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b01100000, + }, + .glyph_D = + { + 0b11000000, + 0b10100000, + 0b10100000, + 0b10100000, + 0b11000000, + }, + .glyph_E = + { + 0b11100000, + 0b10000000, + 0b11000000, + 0b10000000, + 0b11100000, + }, + .glyph_F = + { + 0b11100000, + 0b10000000, + 0b11000000, + 0b10000000, + 0b10000000, + }, + .glyph_G = + { + 0b01100000, + 0b10000000, + 0b10100000, + 0b10100000, + 0b01100000, + }, + .glyph_H = + { + 0b10100000, + 0b10100000, + 0b11100000, + 0b10100000, + 0b10100000, + }, + .glyph_I = + { + 0b11100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b11100000, + }, + .glyph_J = + { + 0b11100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b11000000, + }, + .glyph_K = + { + 0b10100000, + 0b11100000, + 0b11000000, + 0b11100000, + 0b10100000, + }, + .glyph_L = + { + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b11100000, + }, + .glyph_M = + { + 0b10100000, + 0b11100000, + 0b11100000, + 0b10100000, + 0b10100000, + }, + .glyph_N = + { + 0b10100000, + 0b11100000, + 0b11100000, + 0b11100000, + 0b10100000, + }, + .glyph_O = + { + 0b01000000, + 0b10100000, + 0b10100000, + 0b10100000, + 0b01000000, + }, + .glyph_P = + { + 0b11000000, + 0b10100000, + 0b11000000, + 0b10000000, + 0b10000000, + }, + .glyph_Q = + { + 0b01000000, + 0b10100000, + 0b10100000, + 0b10100000, + 0b01100000, + }, + .glyph_R = + { + 0b11000000, + 0b10100000, + 0b11000000, + 0b10100000, + 0b10100000, + }, + .glyph_S = + { + 0b01100000, + 0b10000000, + 0b01000000, + 0b00100000, + 0b11000000, + }, + .glyph_T = + { + 0b11100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + }, + .glyph_U = + { + 0b10100000, + 0b10100000, + 0b10100000, + 0b10100000, + 0b11100000, + }, + .glyph_V = + { + 0b10100000, + 0b10100000, + 0b10100000, + 0b10100000, + 0b01000000, + }, + .glyph_W = + { + 0b10100000, + 0b10100000, + 0b11100000, + 0b11100000, + 0b10100000, + }, + .glyph_X = + { + 0b10100000, + 0b10100000, + 0b01000000, + 0b10100000, + 0b10100000, + }, + .glyph_Y = + { + 0b10100000, + 0b10100000, + 0b11100000, + 0b01000000, + 0b01000000, + }, + .glyph_Z = + { + 0b11100000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b11100000, + }, + .glyph_lsquare = + { + 0b11100000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b11100000, + }, + .glyph_bslash = + { + 0b10000000, + 0b10000000, + 0b01000000, + 0b00100000, + 0b00100000, + }, + .glyph_rsquare = + { + 0b11100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b11100000, + }, + .glyph_caret = + { + 0b01000000, + 0b10100000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_underbar = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11100000, + }, + .glyph_bquote = + { + 0b01000000, + 0b00100000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_lbrace = + { + 0b01100000, + 0b01000000, + 0b11000000, + 0b01000000, + 0b01100000, + }, + .glyph_vbar = + { + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + }, + .glyph_rbrace = + { + 0b11000000, + 0b01000000, + 0b01100000, + 0b01000000, + 0b11000000, + }, + .glyph_tilde = + { + 0b01010000, + 0b10100000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_openbox = + { + 0b11110000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b11110000, + }, + .glyph_alpha = + { + 0b00000000, + 0b01010000, + 0b10100000, + 0b10100000, + 0b01010000, + }, + .glyph_sup2 = + { + 0b11000000, + 0b00100000, + 0b01000000, + 0b11100000, + 0b00000000, + }, + .glyph_degree = + { + 0b11100000, + 0b10100000, + 0b11100000, + 0b00000000, + 0b00000000, + }, + .glyph_a = + { + 0b00000000, + 0b01000000, + 0b10100000, + 0b11100000, + 0b10100000, + }, + .glyph_b = + { + 0b00000000, + 0b11000000, + 0b11000000, + 0b10100000, + 0b11000000, + }, + .glyph_c = + { + 0b00000000, + 0b01100000, + 0b10000000, + 0b10000000, + 0b01100000, + }, + .glyph_d = + { + 0b00000000, + 0b11000000, + 0b10100000, + 0b10100000, + 0b11000000, + }, + .glyph_e = + { + 0b00000000, + 0b11100000, + 0b11000000, + 0b10000000, + 0b11100000, + }, + .glyph_f = + { + 0b00000000, + 0b11100000, + 0b10000000, + 0b11000000, + 0b10000000, + }, + .glyph_g = + { + 0b00000000, + 0b01100000, + 0b10000000, + 0b10100000, + 0b01100000, + }, + .glyph_h = + { + 0b00000000, + 0b10100000, + 0b10100000, + 0b11100000, + 0b10100000, + }, + .glyph_i = + { + 0b00000000, + 0b11100000, + 0b01000000, + 0b01000000, + 0b11100000, + }, + .glyph_j = + { + 0b00000000, + 0b11100000, + 0b01000000, + 0b01000000, + 0b11000000, + }, + .glyph_k = + { + 0b00000000, + 0b10100000, + 0b11000000, + 0b11000000, + 0b10100000, + }, + .glyph_l = + { + 0b00000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b11100000, + }, + .glyph_m = + { + 0b00000000, + 0b10100000, + 0b11100000, + 0b10100000, + 0b10100000, + }, + .glyph_n = + { + 0b00000000, + 0b10100000, + 0b11100000, + 0b11100000, + 0b10100000, + }, + .glyph_o = + { + 0b00000000, + 0b01000000, + 0b10100000, + 0b10100000, + 0b01000000, + }, + .glyph_p = + { + 0b00000000, + 0b11000000, + 0b10100000, + 0b11000000, + 0b10000000, + }, + .glyph_q = + { + 0b00000000, + 0b01000000, + 0b10100000, + 0b10100000, + 0b01100000, + }, + .glyph_r = + { + 0b00000000, + 0b11000000, + 0b10100000, + 0b11000000, + 0b10100000, + }, + .glyph_s = + { + 0b00000000, + 0b01100000, + 0b10000000, + 0b00100000, + 0b11000000, + }, + .glyph_t = + { + 0b00000000, + 0b11100000, + 0b01000000, + 0b01000000, + 0b01000000, + }, + .glyph_u = + { + 0b00000000, + 0b10100000, + 0b10100000, + 0b10100000, + 0b11100000, + }, + .glyph_v = + { + 0b00000000, + 0b10100000, + 0b10100000, + 0b10100000, + 0b01000000, + }, + .glyph_w = + { + 0b00000000, + 0b10100000, + 0b10100000, + 0b11100000, + 0b10100000, + }, + .glyph_x = + { + 0b00000000, + 0b10100000, + 0b01000000, + 0b01000000, + 0b10100000, + }, + .glyph_y = + { + 0b00000000, + 0b10100000, + 0b10100000, + 0b01000000, + 0b01000000, + }, + .glyph_z = + { + 0b00000000, + 0b11100000, + 0b00100000, + 0b11000000, + 0b11100000, + }, + .glyph_ld_tb = + { + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + }, + .glyph_ld_tbl = + { + 0b01000000, + 0b01000000, + 0b11000000, + 0b01000000, + 0b01000000, + }, + .glyph_ld_tbL = + { + 0b01000000, + 0b11000000, + 0b01000000, + 0b11000000, + 0b01000000, + }, + .glyph_ld_TBl = + { + 0b01100000, + 0b01100000, + 0b11100000, + 0b01100000, + 0b01100000, + }, + .glyph_ld_Bl = + { + 0b00000000, + 0b00000000, + 0b11100000, + 0b01100000, + 0b01100000, + }, + .glyph_ld_bL = + { + 0b00000000, + 0b11100000, + 0b00100000, + 0b11100000, + 0b00100000, + }, + .glyph_ld_TBL = + { + 0b01100000, + 0b11100000, + 0b01100000, + 0b11100000, + 0b01100000, + }, + .glyph_ld_TB = + { + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100000, + }, + .glyph_ld_BL = + { + 0b00000000, + 0b01110000, + 0b01100000, + 0b01110000, + 0b01100000, + }, + .glyph_ld_TL = + { + 0b01100000, + 0b01110000, + 0b01100000, + 0b01110000, + 0b00000000, + }, + .glyph_ld_Tl = + { + 0b01100000, + 0b01100000, + 0b11100000, + 0b00000000, + 0b00000000, + }, + .glyph_ld_tL = + { + 0b01000000, + 0b11000000, + 0b01000000, + 0b11000000, + 0b00000000, + }, + .glyph_ld_bl = + { + 0b00000000, + 0b00000000, + 0b11000000, + 0b01000000, + 0b01000000, + }, + .glyph_ld_tr = + { + 0b01000000, + 0b01000000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_ld_tlr = + { + 0b01000000, + 0b01000000, + 0b11110000, + 0b00000000, + 0b00000000, + }, + .glyph_ld_blr = + { + 0b00000000, + 0b00000000, + 0b11110000, + 0b01000000, + 0b01000000, + }, + .glyph_ld_tbr = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_ld_lr = + { + 0b00000000, + 0b00000000, + 0b11110000, + 0b00000000, + 0b00000000, + }, + .glyph_ld_tblr = + { + 0b01000000, + 0b01000000, + 0b11110000, + 0b01000000, + 0b01000000, + }, + .glyph_ld_tbR = + { + 0b01000000, + 0b01110000, + 0b01000000, + 0b01110000, + 0b01000000, + }, + .glyph_ld_TBr = + { + 0b01100000, + 0b01100000, + 0b01110000, + 0b01100000, + 0b01100000, + }, + .glyph_ld_TR = + { + 0b01100000, + 0b01110000, + 0b01100000, + 0b01110000, + 0b00000000, + }, + .glyph_ld_BR = + { + 0b00000000, + 0b01110000, + 0b01100000, + 0b01110000, + 0b01100000, + }, + .glyph_ld_TLR = + { + 0b01100000, + 0b11110000, + 0b01100000, + 0b11110000, + 0b00000000, + }, + .glyph_ld_BLR = + { + 0b00000000, + 0b11110000, + 0b01100000, + 0b11110000, + 0b01100000, + }, + .glyph_ld_TBR = + { + 0b01100000, + 0b01110000, + 0b01100000, + 0b01110000, + 0b01100000, + }, + .glyph_ld_LR = + { + 0b00000000, + 0b11110000, + 0b00000000, + 0b11110000, + 0b00000000, + }, + .glyph_ld_TBLR = + { + 0b01100000, + 0b11110000, + 0b01100000, + 0b11110000, + 0b01100000, + }, + .glyph_ld_tLR = + { + 0b01000000, + 0b11110000, + 0b01000000, + 0b11110000, + 0b00000000, + }, + .glyph_ld_Tlr = + { + 0b01100000, + 0b01100000, + 0b11110000, + 0b00000000, + 0b00000000, + }, + .glyph_ld_bLR = + { + 0b00000000, + 0b11110000, + 0b01000000, + 0b11110000, + 0b01000000, + }, + .glyph_ld_Blr = + { + 0b00000000, + 0b00000000, + 0b11110000, + 0b01100000, + 0b01100000, + }, + .glyph_ld_Tr = + { + 0b01100000, + 0b01100000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_ld_tR = + { + 0b01000000, + 0b01110000, + 0b01000000, + 0b01110000, + 0b00000000, + }, + .glyph_ld_bR = + { + 0b00000000, + 0b01110000, + 0b01000000, + 0b01110000, + 0b01000000, + }, + .glyph_ld_Br = + { + 0b00000000, + 0b00000000, + 0b01110000, + 0b01100000, + 0b01100000, + }, + .glyph_ld_TBlr = + { + 0b01100000, + 0b01100000, + 0b11110000, + 0b01100000, + 0b01100000, + }, + .glyph_ld_tbLR = + { + 0b01000000, + 0b11110000, + 0b01000000, + 0b11110000, + 0b01000000, + }, + .glyph_ld_tl = + { + 0b01000000, + 0b01000000, + 0b11000000, + 0b00000000, + 0b00000000, + }, + .glyph_ld_br = + { + 0b00000000, + 0b00000000, + 0b01110000, + 0b01000000, + 0b01000000, + }, + .glyph_arrow = + { + 0b11111000, + 0b11110000, + 0b11110000, + 0b11001000, + 0b10000100, + }, + .glyph_uparrow = + { + 0b01000000, + 0b11100000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_downarrow = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b11100000, + 0b01000000, + }, + .glyph_leftarrow = + { + 0b00000000, + 0b01000000, + 0b11000000, + 0b01000000, + 0b00000000, + }, + .glyph_rightarrow = + { + 0b00000000, + 0b01000000, + 0b01100000, + 0b01000000, + 0b00000000, + }, + .glyph_tick = + { + 0b00000000, + 0b01100000, + 0b01000000, + 0b11000000, + 0b01000000, + }, + .glyph_bullet = { + 0b00000000, + 0b00000000, + 0b01000000, + 0b00000000, + 0b00000000, + }}; + +br_uint_16 _FontFixed3x5_Encoding[] = { + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_bullet), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_uparrow), offsetof(__font_glyphs, glyph_downarrow), + offsetof(__font_glyphs, glyph_rightarrow), offsetof(__font_glyphs, glyph_leftarrow), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_uparrow), offsetof(__font_glyphs, glyph_downarrow), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_exclam), + offsetof(__font_glyphs, glyph_dquote), offsetof(__font_glyphs, glyph_hash), + offsetof(__font_glyphs, glyph_pound), offsetof(__font_glyphs, glyph_percent), + offsetof(__font_glyphs, glyph_ampersand), offsetof(__font_glyphs, glyph_quote), + offsetof(__font_glyphs, glyph_lparen), offsetof(__font_glyphs, glyph_rparen), + offsetof(__font_glyphs, glyph_asterisk), offsetof(__font_glyphs, glyph_plus), + offsetof(__font_glyphs, glyph_comma), offsetof(__font_glyphs, glyph_minus), + offsetof(__font_glyphs, glyph_period), offsetof(__font_glyphs, glyph_slash), + offsetof(__font_glyphs, glyph_0), offsetof(__font_glyphs, glyph_1), + offsetof(__font_glyphs, glyph_2), offsetof(__font_glyphs, glyph_3), + offsetof(__font_glyphs, glyph_4), offsetof(__font_glyphs, glyph_5), + offsetof(__font_glyphs, glyph_6), offsetof(__font_glyphs, glyph_7), + offsetof(__font_glyphs, glyph_8), offsetof(__font_glyphs, glyph_9), + offsetof(__font_glyphs, glyph_colon), offsetof(__font_glyphs, glyph_semicolon), + offsetof(__font_glyphs, glyph_langle), offsetof(__font_glyphs, glyph_equal), + offsetof(__font_glyphs, glyph_rangle), offsetof(__font_glyphs, glyph_query), + offsetof(__font_glyphs, glyph_comat), offsetof(__font_glyphs, glyph_A), + offsetof(__font_glyphs, glyph_B), offsetof(__font_glyphs, glyph_C), + offsetof(__font_glyphs, glyph_D), offsetof(__font_glyphs, glyph_E), + offsetof(__font_glyphs, glyph_F), offsetof(__font_glyphs, glyph_G), + offsetof(__font_glyphs, glyph_H), offsetof(__font_glyphs, glyph_I), + offsetof(__font_glyphs, glyph_J), offsetof(__font_glyphs, glyph_K), + offsetof(__font_glyphs, glyph_L), offsetof(__font_glyphs, glyph_M), + offsetof(__font_glyphs, glyph_N), offsetof(__font_glyphs, glyph_O), + offsetof(__font_glyphs, glyph_P), offsetof(__font_glyphs, glyph_Q), + offsetof(__font_glyphs, glyph_R), offsetof(__font_glyphs, glyph_S), + offsetof(__font_glyphs, glyph_T), offsetof(__font_glyphs, glyph_U), + offsetof(__font_glyphs, glyph_V), offsetof(__font_glyphs, glyph_W), + offsetof(__font_glyphs, glyph_X), offsetof(__font_glyphs, glyph_Y), + offsetof(__font_glyphs, glyph_Z), offsetof(__font_glyphs, glyph_lsquare), + offsetof(__font_glyphs, glyph_bslash), offsetof(__font_glyphs, glyph_rsquare), + offsetof(__font_glyphs, glyph_caret), offsetof(__font_glyphs, glyph_underbar), + offsetof(__font_glyphs, glyph_bquote), offsetof(__font_glyphs, glyph_a), + offsetof(__font_glyphs, glyph_b), offsetof(__font_glyphs, glyph_c), + offsetof(__font_glyphs, glyph_d), offsetof(__font_glyphs, glyph_e), + offsetof(__font_glyphs, glyph_f), offsetof(__font_glyphs, glyph_g), + offsetof(__font_glyphs, glyph_h), offsetof(__font_glyphs, glyph_i), + offsetof(__font_glyphs, glyph_j), offsetof(__font_glyphs, glyph_k), + offsetof(__font_glyphs, glyph_l), offsetof(__font_glyphs, glyph_m), + offsetof(__font_glyphs, glyph_n), offsetof(__font_glyphs, glyph_o), + offsetof(__font_glyphs, glyph_p), offsetof(__font_glyphs, glyph_q), + offsetof(__font_glyphs, glyph_r), offsetof(__font_glyphs, glyph_s), + offsetof(__font_glyphs, glyph_t), offsetof(__font_glyphs, glyph_u), + offsetof(__font_glyphs, glyph_v), offsetof(__font_glyphs, glyph_w), + offsetof(__font_glyphs, glyph_x), offsetof(__font_glyphs, glyph_y), + offsetof(__font_glyphs, glyph_z), offsetof(__font_glyphs, glyph_lbrace), + offsetof(__font_glyphs, glyph_vbar), offsetof(__font_glyphs, glyph_rbrace), + offsetof(__font_glyphs, glyph_tilde), offsetof(__font_glyphs, glyph_arrow), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_ld_tb), + offsetof(__font_glyphs, glyph_ld_tbl), offsetof(__font_glyphs, glyph_ld_tbL), + offsetof(__font_glyphs, glyph_ld_TBl), offsetof(__font_glyphs, glyph_ld_Bl), + offsetof(__font_glyphs, glyph_ld_bL), offsetof(__font_glyphs, glyph_ld_TBL), + offsetof(__font_glyphs, glyph_ld_TB), offsetof(__font_glyphs, glyph_ld_BL), + offsetof(__font_glyphs, glyph_ld_TL), offsetof(__font_glyphs, glyph_ld_Tl), + offsetof(__font_glyphs, glyph_ld_tL), offsetof(__font_glyphs, glyph_ld_bl), + offsetof(__font_glyphs, glyph_ld_tr), offsetof(__font_glyphs, glyph_ld_tlr), + offsetof(__font_glyphs, glyph_ld_blr), offsetof(__font_glyphs, glyph_ld_tbr), + offsetof(__font_glyphs, glyph_ld_lr), offsetof(__font_glyphs, glyph_ld_tblr), + offsetof(__font_glyphs, glyph_ld_tbR), offsetof(__font_glyphs, glyph_ld_TBr), + offsetof(__font_glyphs, glyph_ld_TR), offsetof(__font_glyphs, glyph_ld_BR), + offsetof(__font_glyphs, glyph_ld_TLR), offsetof(__font_glyphs, glyph_ld_BLR), + offsetof(__font_glyphs, glyph_ld_TBR), offsetof(__font_glyphs, glyph_ld_LR), + offsetof(__font_glyphs, glyph_ld_TBLR), offsetof(__font_glyphs, glyph_ld_tLR), + offsetof(__font_glyphs, glyph_ld_Tlr), offsetof(__font_glyphs, glyph_ld_bLR), + offsetof(__font_glyphs, glyph_ld_Blr), offsetof(__font_glyphs, glyph_ld_Tr), + offsetof(__font_glyphs, glyph_ld_tR), offsetof(__font_glyphs, glyph_ld_bR), + offsetof(__font_glyphs, glyph_ld_Br), offsetof(__font_glyphs, glyph_ld_TBlr), + offsetof(__font_glyphs, glyph_ld_tbLR), offsetof(__font_glyphs, glyph_ld_tl), + offsetof(__font_glyphs, glyph_ld_br), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_alpha), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_degree), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_tick), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_sup2), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), +}; + +struct br_font _FontFixed3x5 = {.flags = 0, + .glyph_x = FONT_WIDTH, + .glyph_y = FONT_HEIGHT, + .spacing_x = 4, + .spacing_y = 6, + .width = NULL, + .encoding = _FontFixed3x5_Encoding, + .glyphs = (br_uint_8 *)&_FontFixed3x5_Glyphs}; \ No newline at end of file diff --git a/bren/FW/font_p_4x6.c b/bren/FW/font_p_4x6.c new file mode 100644 index 00000000..550c0d7e --- /dev/null +++ b/bren/FW/font_p_4x6.c @@ -0,0 +1,1495 @@ +#include +#include + +#define FONT_WIDTH 4 +#define FONT_HEIGHT 6 + +#pragma pack(push, 1) +typedef struct +{ + br_uint_8 glyph_space[FONT_HEIGHT]; + br_uint_8 glyph_exclam[FONT_HEIGHT]; + br_uint_8 glyph_dquote[FONT_HEIGHT]; + br_uint_8 glyph_pound[FONT_HEIGHT]; + br_uint_8 glyph_hash[FONT_HEIGHT]; + br_uint_8 glyph_percent[FONT_HEIGHT]; + br_uint_8 glyph_ampersand[FONT_HEIGHT]; + br_uint_8 glyph_quote[FONT_HEIGHT]; + br_uint_8 glyph_lparen[FONT_HEIGHT]; + br_uint_8 glyph_rparen[FONT_HEIGHT]; + br_uint_8 glyph_asterisk[FONT_HEIGHT]; + br_uint_8 glyph_plus[FONT_HEIGHT]; + br_uint_8 glyph_comma[FONT_HEIGHT]; + br_uint_8 glyph_minus[FONT_HEIGHT]; + br_uint_8 glyph_period[FONT_HEIGHT]; + br_uint_8 glyph_slash[FONT_HEIGHT]; + br_uint_8 glyph_0[FONT_HEIGHT]; + br_uint_8 glyph_1[FONT_HEIGHT]; + br_uint_8 glyph_2[FONT_HEIGHT]; + br_uint_8 glyph_3[FONT_HEIGHT]; + br_uint_8 glyph_4[FONT_HEIGHT]; + br_uint_8 glyph_5[FONT_HEIGHT]; + br_uint_8 glyph_6[FONT_HEIGHT]; + br_uint_8 glyph_7[FONT_HEIGHT]; + br_uint_8 glyph_8[FONT_HEIGHT]; + br_uint_8 glyph_9[FONT_HEIGHT]; + br_uint_8 glyph_colon[FONT_HEIGHT]; + br_uint_8 glyph_semicolon[FONT_HEIGHT]; + br_uint_8 glyph_langle[FONT_HEIGHT]; + br_uint_8 glyph_equal[FONT_HEIGHT]; + br_uint_8 glyph_rangle[FONT_HEIGHT]; + br_uint_8 glyph_query[FONT_HEIGHT]; + br_uint_8 glyph_comat[FONT_HEIGHT]; + br_uint_8 glyph_A[FONT_HEIGHT]; + br_uint_8 glyph_B[FONT_HEIGHT]; + br_uint_8 glyph_C[FONT_HEIGHT]; + br_uint_8 glyph_D[FONT_HEIGHT]; + br_uint_8 glyph_E[FONT_HEIGHT]; + br_uint_8 glyph_F[FONT_HEIGHT]; + br_uint_8 glyph_G[FONT_HEIGHT]; + br_uint_8 glyph_H[FONT_HEIGHT]; + br_uint_8 glyph_I[FONT_HEIGHT]; + br_uint_8 glyph_J[FONT_HEIGHT]; + br_uint_8 glyph_K[FONT_HEIGHT]; + br_uint_8 glyph_L[FONT_HEIGHT]; + br_uint_8 glyph_M[FONT_HEIGHT]; + br_uint_8 glyph_N[FONT_HEIGHT]; + br_uint_8 glyph_O[FONT_HEIGHT]; + br_uint_8 glyph_P[FONT_HEIGHT]; + br_uint_8 glyph_Q[FONT_HEIGHT]; + br_uint_8 glyph_R[FONT_HEIGHT]; + br_uint_8 glyph_S[FONT_HEIGHT]; + br_uint_8 glyph_T[FONT_HEIGHT]; + br_uint_8 glyph_U[FONT_HEIGHT]; + br_uint_8 glyph_V[FONT_HEIGHT]; + br_uint_8 glyph_W[FONT_HEIGHT]; + br_uint_8 glyph_X[FONT_HEIGHT]; + br_uint_8 glyph_Y[FONT_HEIGHT]; + br_uint_8 glyph_Z[FONT_HEIGHT]; + br_uint_8 glyph_lsquare[FONT_HEIGHT]; + br_uint_8 glyph_bslash[FONT_HEIGHT]; + br_uint_8 glyph_rsquare[FONT_HEIGHT]; + br_uint_8 glyph_caret[FONT_HEIGHT]; + br_uint_8 glyph_underbar[FONT_HEIGHT]; + br_uint_8 glyph_bquote[FONT_HEIGHT]; + br_uint_8 glyph_lbrace[FONT_HEIGHT]; + br_uint_8 glyph_vbar[FONT_HEIGHT]; + br_uint_8 glyph_rbrace[FONT_HEIGHT]; + br_uint_8 glyph_tilde[FONT_HEIGHT]; + br_uint_8 glyph_openbox[FONT_HEIGHT]; + br_uint_8 glyph_alpha[FONT_HEIGHT]; + br_uint_8 glyph_sup2[FONT_HEIGHT]; + br_uint_8 glyph_degree[FONT_HEIGHT]; + br_uint_8 glyph_a[FONT_HEIGHT]; + br_uint_8 glyph_b[FONT_HEIGHT]; + br_uint_8 glyph_c[FONT_HEIGHT]; + br_uint_8 glyph_d[FONT_HEIGHT]; + br_uint_8 glyph_e[FONT_HEIGHT]; + br_uint_8 glyph_f[FONT_HEIGHT]; + br_uint_8 glyph_g[FONT_HEIGHT]; + br_uint_8 glyph_h[FONT_HEIGHT]; + br_uint_8 glyph_i[FONT_HEIGHT]; + br_uint_8 glyph_j[FONT_HEIGHT]; + br_uint_8 glyph_k[FONT_HEIGHT]; + br_uint_8 glyph_l[FONT_HEIGHT]; + br_uint_8 glyph_m[FONT_HEIGHT]; + br_uint_8 glyph_n[FONT_HEIGHT]; + br_uint_8 glyph_o[FONT_HEIGHT]; + br_uint_8 glyph_p[FONT_HEIGHT]; + br_uint_8 glyph_q[FONT_HEIGHT]; + br_uint_8 glyph_r[FONT_HEIGHT]; + br_uint_8 glyph_s[FONT_HEIGHT]; + br_uint_8 glyph_t[FONT_HEIGHT]; + br_uint_8 glyph_u[FONT_HEIGHT]; + br_uint_8 glyph_v[FONT_HEIGHT]; + br_uint_8 glyph_w[FONT_HEIGHT]; + br_uint_8 glyph_x[FONT_HEIGHT]; + br_uint_8 glyph_y[FONT_HEIGHT]; + br_uint_8 glyph_z[FONT_HEIGHT]; + br_uint_8 glyph_ld_tb[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbl[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBl[FONT_HEIGHT]; + br_uint_8 glyph_ld_Bl[FONT_HEIGHT]; + br_uint_8 glyph_ld_bL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TB[FONT_HEIGHT]; + br_uint_8 glyph_ld_BL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TL[FONT_HEIGHT]; + br_uint_8 glyph_ld_Tl[FONT_HEIGHT]; + br_uint_8 glyph_ld_tL[FONT_HEIGHT]; + br_uint_8 glyph_ld_bl[FONT_HEIGHT]; + br_uint_8 glyph_ld_tr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tlr[FONT_HEIGHT]; + br_uint_8 glyph_ld_blr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbr[FONT_HEIGHT]; + br_uint_8 glyph_ld_lr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tblr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBr[FONT_HEIGHT]; + br_uint_8 glyph_ld_TR[FONT_HEIGHT]; + br_uint_8 glyph_ld_BR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_BLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBR[FONT_HEIGHT]; + br_uint_8 glyph_ld_LR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_tLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_Tlr[FONT_HEIGHT]; + br_uint_8 glyph_ld_bLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_Blr[FONT_HEIGHT]; + br_uint_8 glyph_ld_Tr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tR[FONT_HEIGHT]; + br_uint_8 glyph_ld_bR[FONT_HEIGHT]; + br_uint_8 glyph_ld_Br[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBlr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_tl[FONT_HEIGHT]; + br_uint_8 glyph_ld_br[FONT_HEIGHT]; + br_uint_8 glyph_arrow[FONT_HEIGHT]; + br_uint_8 glyph_uparrow[FONT_HEIGHT]; + br_uint_8 glyph_downarrow[FONT_HEIGHT]; + br_uint_8 glyph_leftarrow[FONT_HEIGHT]; + br_uint_8 glyph_rightarrow[FONT_HEIGHT]; + br_uint_8 glyph_tick[FONT_HEIGHT]; + br_uint_8 glyph_bullet[FONT_HEIGHT]; + br_uint_8 glyph_cross[FONT_HEIGHT]; + br_uint_8 glyph_solidbox[FONT_HEIGHT]; + br_uint_8 glyph_cursor[FONT_HEIGHT]; +} __font_glyphs; +#pragma pack(pop) + +__font_glyphs _FontProp4x6_Glyphs = {.glyph_space = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_exclam = + { + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + 0b10000000, + 0b00000000, + }, + .glyph_dquote = + { + 0b10100000, + 0b10100000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_hash = + { + 0b01010000, + 0b11111000, + 0b01010000, + 0b11111000, + 0b01010000, + 0b00000000, + }, + .glyph_pound = + { + 0b01000000, + 0b01100000, + 0b11000000, + 0b00100000, + 0b11000000, + 0b01000000, + }, + .glyph_percent = + { + 0b11001000, + 0b11010000, + 0b00100000, + 0b01011000, + 0b10011000, + 0b00000000, + }, + .glyph_ampersand = + { + 0b01000000, + 0b10100000, + 0b10100000, + 0b01000000, + 0b10100000, + 0b00000000, + }, + .glyph_quote = + { + 0b01000000, + 0b10000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_lparen = + { + 0b01000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b01000000, + 0b00000000, + }, + .glyph_rparen = + { + 0b10000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b10000000, + 0b00000000, + }, + .glyph_asterisk = + { + 0b00000000, + 0b10100000, + 0b01000000, + 0b10100000, + 0b00000000, + 0b00000000, + }, + .glyph_plus = + { + 0b00000000, + 0b01000000, + 0b11100000, + 0b01000000, + 0b00000000, + 0b00000000, + }, + .glyph_comma = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01000000, + 0b10000000, + }, + .glyph_minus = + { + 0b00000000, + 0b00000000, + 0b11100000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_period = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b10000000, + 0b00000000, + }, + .glyph_slash = + { + 0b00001000, + 0b00010000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b00000000, + }, + .glyph_0 = + { + 0b01100000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b01100000, + 0b00000000, + }, + .glyph_1 = + { + 0b00100000, + 0b01100000, + 0b00100000, + 0b00100000, + 0b01110000, + 0b00000000, + }, + .glyph_2 = + { + 0b11100000, + 0b00010000, + 0b01100000, + 0b10000000, + 0b11110000, + 0b00000000, + }, + .glyph_3 = + { + 0b11100000, + 0b00010000, + 0b01100000, + 0b00010000, + 0b11100000, + 0b00000000, + }, + .glyph_4 = + { + 0b10000000, + 0b10000000, + 0b10100000, + 0b11110000, + 0b00100000, + 0b00000000, + }, + .glyph_5 = + { + 0b11110000, + 0b10000000, + 0b11100000, + 0b00010000, + 0b11100000, + 0b00000000, + }, + .glyph_6 = + { + 0b01100000, + 0b10000000, + 0b11100000, + 0b10010000, + 0b01100000, + 0b00000000, + }, + .glyph_7 = + { + 0b11110000, + 0b00010000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b00000000, + }, + .glyph_8 = + { + 0b01100000, + 0b10010000, + 0b01100000, + 0b10010000, + 0b01100000, + 0b00000000, + }, + .glyph_9 = + { + 0b01100000, + 0b10010000, + 0b01110000, + 0b00010000, + 0b01100000, + 0b00000000, + }, + .glyph_colon = + { + 0b00000000, + 0b10000000, + 0b00000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_semicolon = + { + 0b00000000, + 0b01000000, + 0b00000000, + 0b01000000, + 0b10000000, + 0b00000000, + }, + .glyph_langle = + { + 0b00100000, + 0b01000000, + 0b10000000, + 0b01000000, + 0b00100000, + 0b00000000, + }, + .glyph_equal = + { + 0b00000000, + 0b11100000, + 0b00000000, + 0b11100000, + 0b00000000, + 0b00000000, + }, + .glyph_rangle = + { + 0b10000000, + 0b01000000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b00000000, + }, + .glyph_query = + { + 0b11000000, + 0b00100000, + 0b01000000, + 0b00000000, + 0b01000000, + 0b00000000, + }, + .glyph_comat = + { + 0b01100000, + 0b10110000, + 0b10110000, + 0b10000000, + 0b01100000, + 0b00000000, + }, + .glyph_A = + { + 0b01100000, + 0b10010000, + 0b11110000, + 0b10010000, + 0b10010000, + 0b00000000, + }, + .glyph_B = + { + 0b11100000, + 0b10010000, + 0b11100000, + 0b10010000, + 0b11100000, + 0b00000000, + }, + .glyph_C = + { + 0b01100000, + 0b10010000, + 0b10000000, + 0b10010000, + 0b01100000, + 0b00000000, + }, + .glyph_D = + { + 0b11100000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b11100000, + 0b00000000, + }, + .glyph_E = + { + 0b11110000, + 0b10000000, + 0b11100000, + 0b10000000, + 0b11110000, + 0b00000000, + }, + .glyph_F = + { + 0b11110000, + 0b10000000, + 0b11100000, + 0b10000000, + 0b10000000, + 0b00000000, + }, + .glyph_G = + { + 0b01100000, + 0b10000000, + 0b10110000, + 0b10010000, + 0b01100000, + 0b00000000, + }, + .glyph_H = + { + 0b10010000, + 0b10010000, + 0b11110000, + 0b10010000, + 0b10010000, + 0b00000000, + }, + .glyph_I = + { + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + }, + .glyph_J = + { + 0b00010000, + 0b00010000, + 0b00010000, + 0b10010000, + 0b01100000, + 0b00000000, + }, + .glyph_K = + { + 0b10010000, + 0b10100000, + 0b11000000, + 0b10100000, + 0b10010000, + 0b00000000, + }, + .glyph_L = + { + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b11110000, + 0b00000000, + }, + .glyph_M = + { + 0b10001000, + 0b11011000, + 0b10101000, + 0b10001000, + 0b10001000, + 0b00000000, + }, + .glyph_N = + { + 0b10010000, + 0b11010000, + 0b10110000, + 0b10010000, + 0b10010000, + 0b00000000, + }, + .glyph_O = + { + 0b01100000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b01100000, + 0b00000000, + }, + .glyph_P = + { + 0b11100000, + 0b10010000, + 0b11100000, + 0b10000000, + 0b10000000, + 0b00000000, + }, + .glyph_Q = + { + 0b01100000, + 0b10010000, + 0b10010000, + 0b10110000, + 0b01110000, + 0b00000000, + }, + .glyph_R = + { + 0b11100000, + 0b10010000, + 0b11100000, + 0b10010000, + 0b10010000, + 0b00000000, + }, + .glyph_S = + { + 0b01110000, + 0b10000000, + 0b01100000, + 0b00010000, + 0b11100000, + 0b00000000, + }, + .glyph_T = + { + 0b11100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b00000000, + }, + .glyph_U = + { + 0b10010000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b01100000, + 0b00000000, + }, + .glyph_V = + { + 0b10001000, + 0b10001000, + 0b01010000, + 0b01010000, + 0b00100000, + 0b00000000, + }, + .glyph_W = + { + 0b10001000, + 0b10001000, + 0b10101000, + 0b10101000, + 0b01010000, + 0b00000000, + }, + .glyph_X = + { + 0b10001000, + 0b01010000, + 0b00100000, + 0b01010000, + 0b10001000, + 0b00000000, + }, + .glyph_Y = + { + 0b10001000, + 0b01010000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00000000, + }, + .glyph_Z = + { + 0b11111000, + 0b00010000, + 0b00100000, + 0b01000000, + 0b11111000, + 0b00000000, + }, + .glyph_lsquare = + { + 0b11000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b11000000, + 0b00000000, + }, + .glyph_bslash = + { + 0b10000000, + 0b01000000, + 0b00100000, + 0b00010000, + 0b00001000, + 0b00000000, + }, + .glyph_rsquare = + { + 0b11000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b11000000, + 0b00000000, + }, + .glyph_caret = + { + 0b01000000, + 0b10100000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_underbar = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11110000, + }, + .glyph_bquote = + { + 0b10000000, + 0b01000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_a = + { + 0b00000000, + 0b01100000, + 0b10100000, + 0b10100000, + 0b01100000, + 0b00000000, + }, + .glyph_b = + { + 0b10000000, + 0b11000000, + 0b10100000, + 0b10100000, + 0b11000000, + 0b00000000, + }, + .glyph_c = + { + 0b00000000, + 0b01100000, + 0b10000000, + 0b10000000, + 0b01100000, + 0b00000000, + }, + .glyph_d = + { + 0b00100000, + 0b01100000, + 0b10100000, + 0b10100000, + 0b01100000, + 0b00000000, + }, + .glyph_e = + { + 0b00000000, + 0b01000000, + 0b10100000, + 0b11000000, + 0b01100000, + 0b00000000, + }, + .glyph_f = + { + 0b01000000, + 0b10000000, + 0b11000000, + 0b10000000, + 0b10000000, + 0b00000000, + }, + .glyph_g = + { + 0b00000000, + 0b01100000, + 0b10100000, + 0b01100000, + 0b00100000, + 0b01000000, + }, + .glyph_h = + { + 0b10000000, + 0b11000000, + 0b10100000, + 0b10100000, + 0b10100000, + 0b00000000, + }, + .glyph_i = + { + 0b10000000, + 0b00000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + }, + .glyph_j = + { + 0b01000000, + 0b00000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b10000000, + }, + .glyph_k = + { + 0b10000000, + 0b10100000, + 0b11000000, + 0b11000000, + 0b10100000, + 0b00000000, + }, + .glyph_l = + { + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + }, + .glyph_m = + { + 0b00000000, + 0b11010000, + 0b10101000, + 0b10101000, + 0b10101000, + 0b00000000, + }, + .glyph_n = + { + 0b00000000, + 0b11000000, + 0b10100000, + 0b10100000, + 0b10100000, + 0b00000000, + }, + .glyph_o = + { + 0b00000000, + 0b01000000, + 0b10100000, + 0b10100000, + 0b01000000, + 0b00000000, + }, + .glyph_p = + { + 0b00000000, + 0b11000000, + 0b10100000, + 0b10100000, + 0b11000000, + 0b10000000, + }, + .glyph_q = + { + 0b00000000, + 0b01100000, + 0b10100000, + 0b10100000, + 0b01100000, + 0b00100000, + }, + .glyph_r = + { + 0b00000000, + 0b01100000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + }, + .glyph_s = + { + 0b00000000, + 0b01100000, + 0b11000000, + 0b00100000, + 0b11000000, + 0b00000000, + }, + .glyph_t = + { + 0b01000000, + 0b11100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b00000000, + }, + .glyph_u = + { + 0b00000000, + 0b10100000, + 0b10100000, + 0b10100000, + 0b01100000, + 0b00000000, + }, + .glyph_v = + { + 0b00000000, + 0b10100000, + 0b10100000, + 0b01000000, + 0b01000000, + 0b00000000, + }, + .glyph_w = + { + 0b00000000, + 0b10101000, + 0b10101000, + 0b10101000, + 0b01010000, + 0b00000000, + }, + .glyph_x = + { + 0b00000000, + 0b10100000, + 0b01000000, + 0b01000000, + 0b10100000, + 0b00000000, + }, + .glyph_y = + { + 0b00000000, + 0b10100000, + 0b10100000, + 0b01100000, + 0b00100000, + 0b01000000, + }, + .glyph_z = + { + 0b00000000, + 0b11100000, + 0b00100000, + 0b11000000, + 0b11100000, + 0b00000000, + }, + .glyph_lbrace = + { + 0b00100000, + 0b01000000, + 0b11000000, + 0b01000000, + 0b00100000, + 0b00000000, + }, + .glyph_vbar = + { + 0b10000000, + 0b10000000, + 0b00000000, + 0b10000000, + 0b10000000, + 0b00000000, + }, + .glyph_rbrace = + { + 0b10000000, + 0b01000000, + 0b01100000, + 0b01000000, + 0b10000000, + 0b00000000, + }, + .glyph_tilde = + { + 0b01010000, + 0b10100000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_bullet = + { + 0b00000000, + 0b11100000, + 0b11100000, + 0b11100000, + 0b00000000, + 0b00000000, + }, + .glyph_cross = + { + 0b00000000, + 0b10100000, + 0b01000000, + 0b10100000, + 0b00000000, + 0b00000000, + }, + .glyph_tick = + { + 0b00000000, + 0b00001000, + 0b00010000, + 0b10100000, + 0b01000000, + 0b00000000, + }, + .glyph_uparrow = + { + 0b00000000, + 0b01000000, + 0b11100000, + 0b01000000, + 0b01000000, + 0b00000000, + }, + .glyph_downarrow = + { + 0b00000000, + 0b01000000, + 0b01000000, + 0b11100000, + 0b01000000, + 0b00000000, + }, + .glyph_rightarrow = + { + 0b00000000, + 0b00100000, + 0b11110000, + 0b00100000, + 0b00000000, + 0b00000000, + }, + .glyph_leftarrow = + { + 0b00000000, + 0b01000000, + 0b11110000, + 0b01000000, + 0b00000000, + 0b00000000, + }, + .glyph_solidbox = + { + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + }, + .glyph_cursor = { + 0b10100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b10100000, + }}; + +br_uint_16 _FontProp4x6_Encoding[] = { + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_bullet), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_uparrow), offsetof(__font_glyphs, glyph_downarrow), + offsetof(__font_glyphs, glyph_rightarrow), offsetof(__font_glyphs, glyph_leftarrow), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_uparrow), offsetof(__font_glyphs, glyph_downarrow), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_exclam), + offsetof(__font_glyphs, glyph_dquote), offsetof(__font_glyphs, glyph_hash), + offsetof(__font_glyphs, glyph_pound), offsetof(__font_glyphs, glyph_percent), + offsetof(__font_glyphs, glyph_ampersand), offsetof(__font_glyphs, glyph_quote), + offsetof(__font_glyphs, glyph_lparen), offsetof(__font_glyphs, glyph_rparen), + offsetof(__font_glyphs, glyph_asterisk), offsetof(__font_glyphs, glyph_plus), + offsetof(__font_glyphs, glyph_comma), offsetof(__font_glyphs, glyph_minus), + offsetof(__font_glyphs, glyph_period), offsetof(__font_glyphs, glyph_slash), + offsetof(__font_glyphs, glyph_0), offsetof(__font_glyphs, glyph_1), + offsetof(__font_glyphs, glyph_2), offsetof(__font_glyphs, glyph_3), + offsetof(__font_glyphs, glyph_4), offsetof(__font_glyphs, glyph_5), + offsetof(__font_glyphs, glyph_6), offsetof(__font_glyphs, glyph_7), + offsetof(__font_glyphs, glyph_8), offsetof(__font_glyphs, glyph_9), + offsetof(__font_glyphs, glyph_colon), offsetof(__font_glyphs, glyph_semicolon), + offsetof(__font_glyphs, glyph_langle), offsetof(__font_glyphs, glyph_equal), + offsetof(__font_glyphs, glyph_rangle), offsetof(__font_glyphs, glyph_query), + offsetof(__font_glyphs, glyph_comat), offsetof(__font_glyphs, glyph_A), + offsetof(__font_glyphs, glyph_B), offsetof(__font_glyphs, glyph_C), + offsetof(__font_glyphs, glyph_D), offsetof(__font_glyphs, glyph_E), + offsetof(__font_glyphs, glyph_F), offsetof(__font_glyphs, glyph_G), + offsetof(__font_glyphs, glyph_H), offsetof(__font_glyphs, glyph_I), + offsetof(__font_glyphs, glyph_J), offsetof(__font_glyphs, glyph_K), + offsetof(__font_glyphs, glyph_L), offsetof(__font_glyphs, glyph_M), + offsetof(__font_glyphs, glyph_N), offsetof(__font_glyphs, glyph_O), + offsetof(__font_glyphs, glyph_P), offsetof(__font_glyphs, glyph_Q), + offsetof(__font_glyphs, glyph_R), offsetof(__font_glyphs, glyph_S), + offsetof(__font_glyphs, glyph_T), offsetof(__font_glyphs, glyph_U), + offsetof(__font_glyphs, glyph_V), offsetof(__font_glyphs, glyph_W), + offsetof(__font_glyphs, glyph_X), offsetof(__font_glyphs, glyph_Y), + offsetof(__font_glyphs, glyph_Z), offsetof(__font_glyphs, glyph_lsquare), + offsetof(__font_glyphs, glyph_bslash), offsetof(__font_glyphs, glyph_rsquare), + offsetof(__font_glyphs, glyph_caret), offsetof(__font_glyphs, glyph_underbar), + offsetof(__font_glyphs, glyph_bquote), offsetof(__font_glyphs, glyph_a), + offsetof(__font_glyphs, glyph_b), offsetof(__font_glyphs, glyph_c), + offsetof(__font_glyphs, glyph_d), offsetof(__font_glyphs, glyph_e), + offsetof(__font_glyphs, glyph_f), offsetof(__font_glyphs, glyph_g), + offsetof(__font_glyphs, glyph_h), offsetof(__font_glyphs, glyph_i), + offsetof(__font_glyphs, glyph_j), offsetof(__font_glyphs, glyph_k), + offsetof(__font_glyphs, glyph_l), offsetof(__font_glyphs, glyph_m), + offsetof(__font_glyphs, glyph_n), offsetof(__font_glyphs, glyph_o), + offsetof(__font_glyphs, glyph_p), offsetof(__font_glyphs, glyph_q), + offsetof(__font_glyphs, glyph_r), offsetof(__font_glyphs, glyph_s), + offsetof(__font_glyphs, glyph_t), offsetof(__font_glyphs, glyph_u), + offsetof(__font_glyphs, glyph_v), offsetof(__font_glyphs, glyph_w), + offsetof(__font_glyphs, glyph_x), offsetof(__font_glyphs, glyph_y), + offsetof(__font_glyphs, glyph_z), offsetof(__font_glyphs, glyph_lbrace), + offsetof(__font_glyphs, glyph_vbar), offsetof(__font_glyphs, glyph_rbrace), + offsetof(__font_glyphs, glyph_tilde), offsetof(__font_glyphs, glyph_arrow), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_ld_tb), + offsetof(__font_glyphs, glyph_ld_tbl), offsetof(__font_glyphs, glyph_ld_tbL), + offsetof(__font_glyphs, glyph_ld_TBl), offsetof(__font_glyphs, glyph_ld_Bl), + offsetof(__font_glyphs, glyph_ld_bL), offsetof(__font_glyphs, glyph_ld_TBL), + offsetof(__font_glyphs, glyph_ld_TB), offsetof(__font_glyphs, glyph_ld_BL), + offsetof(__font_glyphs, glyph_ld_TL), offsetof(__font_glyphs, glyph_ld_Tl), + offsetof(__font_glyphs, glyph_ld_tL), offsetof(__font_glyphs, glyph_ld_bl), + offsetof(__font_glyphs, glyph_ld_tr), offsetof(__font_glyphs, glyph_ld_tlr), + offsetof(__font_glyphs, glyph_ld_blr), offsetof(__font_glyphs, glyph_ld_tbr), + offsetof(__font_glyphs, glyph_ld_lr), offsetof(__font_glyphs, glyph_ld_tblr), + offsetof(__font_glyphs, glyph_ld_tbR), offsetof(__font_glyphs, glyph_ld_TBr), + offsetof(__font_glyphs, glyph_ld_TR), offsetof(__font_glyphs, glyph_ld_BR), + offsetof(__font_glyphs, glyph_ld_TLR), offsetof(__font_glyphs, glyph_ld_BLR), + offsetof(__font_glyphs, glyph_ld_TBR), offsetof(__font_glyphs, glyph_ld_LR), + offsetof(__font_glyphs, glyph_ld_TBLR), offsetof(__font_glyphs, glyph_ld_tLR), + offsetof(__font_glyphs, glyph_ld_Tlr), offsetof(__font_glyphs, glyph_ld_bLR), + offsetof(__font_glyphs, glyph_ld_Blr), offsetof(__font_glyphs, glyph_ld_Tr), + offsetof(__font_glyphs, glyph_ld_tR), offsetof(__font_glyphs, glyph_ld_bR), + offsetof(__font_glyphs, glyph_ld_Br), offsetof(__font_glyphs, glyph_ld_TBlr), + offsetof(__font_glyphs, glyph_ld_tbLR), offsetof(__font_glyphs, glyph_ld_tl), + offsetof(__font_glyphs, glyph_ld_br), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_alpha), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_degree), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_tick), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_sup2), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), +}; + +br_int_8 _FontProp4x6_Widths[] = { + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 3, /* glyph_bullet */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 3, /* glyph_uparrow */ + 3, /* glyph_downarrow */ + 3, /* glyph_rightarrow */ + 3, /* glyph_leftarrow */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_uparrow */ + 2, /* glyph_downarrow */ + 2, /* glyph_space */ + 1, /* glyph_exclam */ + 3, /* glyph_dquote */ + 5, /* glyph_hash */ + 3, /* glyph_pound */ + 5, /* glyph_percent */ + 3, /* glyph_ampersand */ + 2, /* glyph_quote */ + 2, /* glyph_lparen */ + 2, /* glyph_rparen */ + 3, /* glyph_asterisk */ + 3, /* glyph_plus */ + 2, /* glyph_comma */ + 3, /* glyph_minus */ + 2, /* glyph_period */ + 5, /* glyph_slash */ + 4, /* glyph_0 */ + 4, /* glyph_1 */ + 4, /* glyph_2 */ + 4, /* glyph_3 */ + 4, /* glyph_4 */ + 4, /* glyph_5 */ + 4, /* glyph_6 */ + 4, /* glyph_7 */ + 4, /* glyph_8 */ + 4, /* glyph_9 */ + 1, /* glyph_colon */ + 2, /* glyph_semicolon */ + 3, /* glyph_langle */ + 3, /* glyph_equal */ + 3, /* glyph_rangle */ + 3, /* glyph_query */ + 4, /* glyph_comat */ + 4, /* glyph_A */ + 4, /* glyph_B */ + 4, /* glyph_C */ + 4, /* glyph_D */ + 4, /* glyph_E */ + 4, /* glyph_F */ + 4, /* glyph_G */ + 4, /* glyph_H */ + 1, /* glyph_I */ + 4, /* glyph_J */ + 4, /* glyph_K */ + 4, /* glyph_L */ + 5, /* glyph_M */ + 4, /* glyph_N */ + 4, /* glyph_O */ + 4, /* glyph_P */ + 4, /* glyph_Q */ + 4, /* glyph_R */ + 4, /* glyph_S */ + 3, /* glyph_T */ + 4, /* glyph_U */ + 5, /* glyph_V */ + 5, /* glyph_W */ + 5, /* glyph_X */ + 5, /* glyph_Y */ + 5, /* glyph_Z */ + 2, /* glyph_lsquare */ + 5, /* glyph_bslash */ + 2, /* glyph_rsquare */ + 3, /* glyph_caret */ + 4, /* glyph_underbar */ + 2, /* glyph_bquote */ + 3, /* glyph_a */ + 3, /* glyph_b */ + 3, /* glyph_c */ + 3, /* glyph_d */ + 3, /* glyph_e */ + 2, /* glyph_f */ + 3, /* glyph_g */ + 3, /* glyph_h */ + 1, /* glyph_i */ + 2, /* glyph_j */ + 3, /* glyph_k */ + 1, /* glyph_l */ + 5, /* glyph_m */ + 3, /* glyph_n */ + 3, /* glyph_o */ + 3, /* glyph_p */ + 3, /* glyph_q */ + 3, /* glyph_r */ + 3, /* glyph_s */ + 3, /* glyph_t */ + 3, /* glyph_u */ + 3, /* glyph_v */ + 5, /* glyph_w */ + 3, /* glyph_x */ + 3, /* glyph_y */ + 3, /* glyph_z */ + 3, /* glyph_lbrace */ + 1, /* glyph_vbar */ + 3, /* glyph_rbrace */ + 4, /* glyph_tilde */ + 2, /* glyph_arrow */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 3, /* glyph_ld_tb */ + 2, /* glyph_ld_tbl */ + 2, /* glyph_ld_tbL */ + 2, /* glyph_ld_TBl */ + 2, /* glyph_ld_Bl */ + 2, /* glyph_ld_bL */ + 2, /* glyph_ld_TBL */ + 2, /* glyph_ld_TB */ + 2, /* glyph_ld_BL */ + 2, /* glyph_ld_TL */ + 2, /* glyph_ld_Tl */ + 2, /* glyph_ld_tL */ + 2, /* glyph_ld_bl */ + 2, /* glyph_ld_tr */ + 2, /* glyph_ld_tlr */ + 2, /* glyph_ld_blr */ + 2, /* glyph_ld_tbr */ + 2, /* glyph_ld_lr */ + 2, /* glyph_ld_tblr */ + 2, /* glyph_ld_tbR */ + 2, /* glyph_ld_TBr */ + 2, /* glyph_ld_TR */ + 2, /* glyph_ld_BR */ + 2, /* glyph_ld_TLR */ + 2, /* glyph_ld_BLR */ + 2, /* glyph_ld_TBR */ + 2, /* glyph_ld_LR */ + 2, /* glyph_ld_TBLR */ + 2, /* glyph_ld_tLR */ + 2, /* glyph_ld_Tlr */ + 2, /* glyph_ld_bLR */ + 2, /* glyph_ld_Blr */ + 2, /* glyph_ld_Tr */ + 2, /* glyph_ld_tR */ + 2, /* glyph_ld_bR */ + 2, /* glyph_ld_Br */ + 2, /* glyph_ld_TBlr */ + 2, /* glyph_ld_tbLR */ + 2, /* glyph_ld_tl */ + 2, /* glyph_ld_br */ + 4, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_alpha */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 2, /* glyph_degree */ + 2, /* glyph_space */ + 2, /* glyph_space */ + 5, /* glyph_tick */ + 2, /* glyph_space */ + 2, /* glyph_sup2 */ + 2, /* glyph_space */ + 2, /* glyph_space */ +}; + +struct br_font _FontProp4x6 = {.flags = BR_FONTF_PROPORTIONAL, + .glyph_x = FONT_WIDTH, + .glyph_y = FONT_HEIGHT, + .spacing_x = 4, + .spacing_y = 6, + .width = _FontProp4x6_Widths, + .encoding = _FontProp4x6_Encoding, + .glyphs = (br_uint_8 *)&_FontProp4x6_Glyphs}; \ No newline at end of file diff --git a/bren/FW/font_p_7x9.c b/bren/FW/font_p_7x9.c new file mode 100644 index 00000000..0539b83a --- /dev/null +++ b/bren/FW/font_p_7x9.c @@ -0,0 +1,1809 @@ +#include +#include + +#define FONT_WIDTH 7 +#define FONT_HEIGHT 9 + +#pragma pack(push, 1) +typedef struct +{ + br_uint_8 glyph_space[FONT_HEIGHT]; + br_uint_8 glyph_exclam[FONT_HEIGHT]; + br_uint_8 glyph_dquote[FONT_HEIGHT]; + br_uint_8 glyph_pound[FONT_HEIGHT]; + br_uint_8 glyph_hash[FONT_HEIGHT]; + br_uint_8 glyph_percent[FONT_HEIGHT]; + br_uint_8 glyph_ampersand[FONT_HEIGHT]; + br_uint_8 glyph_quote[FONT_HEIGHT]; + br_uint_8 glyph_lparen[FONT_HEIGHT]; + br_uint_8 glyph_rparen[FONT_HEIGHT]; + br_uint_8 glyph_asterisk[FONT_HEIGHT]; + br_uint_8 glyph_plus[FONT_HEIGHT]; + br_uint_8 glyph_comma[FONT_HEIGHT]; + br_uint_8 glyph_minus[FONT_HEIGHT]; + br_uint_8 glyph_period[FONT_HEIGHT]; + br_uint_8 glyph_slash[FONT_HEIGHT]; + br_uint_8 glyph_0[FONT_HEIGHT]; + br_uint_8 glyph_1[FONT_HEIGHT]; + br_uint_8 glyph_2[FONT_HEIGHT]; + br_uint_8 glyph_3[FONT_HEIGHT]; + br_uint_8 glyph_4[FONT_HEIGHT]; + br_uint_8 glyph_5[FONT_HEIGHT]; + br_uint_8 glyph_6[FONT_HEIGHT]; + br_uint_8 glyph_7[FONT_HEIGHT]; + br_uint_8 glyph_8[FONT_HEIGHT]; + br_uint_8 glyph_9[FONT_HEIGHT]; + br_uint_8 glyph_colon[FONT_HEIGHT]; + br_uint_8 glyph_semicolon[FONT_HEIGHT]; + br_uint_8 glyph_langle[FONT_HEIGHT]; + br_uint_8 glyph_equal[FONT_HEIGHT]; + br_uint_8 glyph_rangle[FONT_HEIGHT]; + br_uint_8 glyph_query[FONT_HEIGHT]; + br_uint_8 glyph_comat[FONT_HEIGHT]; + br_uint_8 glyph_A[FONT_HEIGHT]; + br_uint_8 glyph_B[FONT_HEIGHT]; + br_uint_8 glyph_C[FONT_HEIGHT]; + br_uint_8 glyph_D[FONT_HEIGHT]; + br_uint_8 glyph_E[FONT_HEIGHT]; + br_uint_8 glyph_F[FONT_HEIGHT]; + br_uint_8 glyph_G[FONT_HEIGHT]; + br_uint_8 glyph_H[FONT_HEIGHT]; + br_uint_8 glyph_I[FONT_HEIGHT]; + br_uint_8 glyph_J[FONT_HEIGHT]; + br_uint_8 glyph_K[FONT_HEIGHT]; + br_uint_8 glyph_L[FONT_HEIGHT]; + br_uint_8 glyph_M[FONT_HEIGHT]; + br_uint_8 glyph_N[FONT_HEIGHT]; + br_uint_8 glyph_O[FONT_HEIGHT]; + br_uint_8 glyph_P[FONT_HEIGHT]; + br_uint_8 glyph_Q[FONT_HEIGHT]; + br_uint_8 glyph_R[FONT_HEIGHT]; + br_uint_8 glyph_S[FONT_HEIGHT]; + br_uint_8 glyph_T[FONT_HEIGHT]; + br_uint_8 glyph_U[FONT_HEIGHT]; + br_uint_8 glyph_V[FONT_HEIGHT]; + br_uint_8 glyph_W[FONT_HEIGHT * 2]; + br_uint_8 glyph_X[FONT_HEIGHT]; + br_uint_8 glyph_Y[FONT_HEIGHT]; + br_uint_8 glyph_Z[FONT_HEIGHT]; + br_uint_8 glyph_lsquare[FONT_HEIGHT]; + br_uint_8 glyph_bslash[FONT_HEIGHT]; + br_uint_8 glyph_rsquare[FONT_HEIGHT]; + br_uint_8 glyph_caret[FONT_HEIGHT]; + br_uint_8 glyph_underbar[FONT_HEIGHT]; + br_uint_8 glyph_bquote[FONT_HEIGHT]; + br_uint_8 glyph_lbrace[FONT_HEIGHT]; + br_uint_8 glyph_vbar[FONT_HEIGHT]; + br_uint_8 glyph_rbrace[FONT_HEIGHT]; + br_uint_8 glyph_tilde[FONT_HEIGHT]; + br_uint_8 glyph_openbox[FONT_HEIGHT]; + br_uint_8 glyph_alpha[FONT_HEIGHT]; + br_uint_8 glyph_sup2[FONT_HEIGHT]; + br_uint_8 glyph_degree[FONT_HEIGHT]; + br_uint_8 glyph_a[FONT_HEIGHT]; + br_uint_8 glyph_b[FONT_HEIGHT]; + br_uint_8 glyph_c[FONT_HEIGHT]; + br_uint_8 glyph_d[FONT_HEIGHT]; + br_uint_8 glyph_e[FONT_HEIGHT]; + br_uint_8 glyph_f[FONT_HEIGHT]; + br_uint_8 glyph_g[FONT_HEIGHT]; + br_uint_8 glyph_h[FONT_HEIGHT]; + br_uint_8 glyph_i[FONT_HEIGHT]; + br_uint_8 glyph_j[FONT_HEIGHT]; + br_uint_8 glyph_k[FONT_HEIGHT]; + br_uint_8 glyph_l[FONT_HEIGHT]; + br_uint_8 glyph_m[FONT_HEIGHT]; + br_uint_8 glyph_n[FONT_HEIGHT]; + br_uint_8 glyph_o[FONT_HEIGHT]; + br_uint_8 glyph_p[FONT_HEIGHT]; + br_uint_8 glyph_q[FONT_HEIGHT]; + br_uint_8 glyph_r[FONT_HEIGHT]; + br_uint_8 glyph_s[FONT_HEIGHT]; + br_uint_8 glyph_t[FONT_HEIGHT]; + br_uint_8 glyph_u[FONT_HEIGHT]; + br_uint_8 glyph_v[FONT_HEIGHT]; + br_uint_8 glyph_w[FONT_HEIGHT]; + br_uint_8 glyph_x[FONT_HEIGHT]; + br_uint_8 glyph_y[FONT_HEIGHT]; + br_uint_8 glyph_z[FONT_HEIGHT]; + br_uint_8 glyph_ld_tb[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbl[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBl[FONT_HEIGHT]; + br_uint_8 glyph_ld_Bl[FONT_HEIGHT]; + br_uint_8 glyph_ld_bL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TB[FONT_HEIGHT]; + br_uint_8 glyph_ld_BL[FONT_HEIGHT]; + br_uint_8 glyph_ld_TL[FONT_HEIGHT]; + br_uint_8 glyph_ld_Tl[FONT_HEIGHT]; + br_uint_8 glyph_ld_tL[FONT_HEIGHT]; + br_uint_8 glyph_ld_bl[FONT_HEIGHT]; + br_uint_8 glyph_ld_tr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tlr[FONT_HEIGHT]; + br_uint_8 glyph_ld_blr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbr[FONT_HEIGHT]; + br_uint_8 glyph_ld_lr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tblr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBr[FONT_HEIGHT]; + br_uint_8 glyph_ld_TR[FONT_HEIGHT]; + br_uint_8 glyph_ld_BR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_BLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBR[FONT_HEIGHT]; + br_uint_8 glyph_ld_LR[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_tLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_Tlr[FONT_HEIGHT]; + br_uint_8 glyph_ld_bLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_Blr[FONT_HEIGHT]; + br_uint_8 glyph_ld_Tr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tR[FONT_HEIGHT]; + br_uint_8 glyph_ld_bR[FONT_HEIGHT]; + br_uint_8 glyph_ld_Br[FONT_HEIGHT]; + br_uint_8 glyph_ld_TBlr[FONT_HEIGHT]; + br_uint_8 glyph_ld_tbLR[FONT_HEIGHT]; + br_uint_8 glyph_ld_tl[FONT_HEIGHT]; + br_uint_8 glyph_ld_br[FONT_HEIGHT]; + br_uint_8 glyph_arrow[FONT_HEIGHT]; + br_uint_8 glyph_uparrow[FONT_HEIGHT]; + br_uint_8 glyph_downarrow[FONT_HEIGHT]; + br_uint_8 glyph_leftarrow[FONT_HEIGHT]; + br_uint_8 glyph_rightarrow[FONT_HEIGHT]; + br_uint_8 glyph_tick[FONT_HEIGHT]; + br_uint_8 glyph_bullet[FONT_HEIGHT]; + br_uint_8 glyph_cross[FONT_HEIGHT]; + br_uint_8 glyph_solidbox[FONT_HEIGHT]; + br_uint_8 glyph_cursor[FONT_HEIGHT]; +} __font_glyphs; +#pragma pack(pop) + +__font_glyphs _FontProp7x9_Glyphs = { + .glyph_space = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_exclam = + { + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_dquote = + { + 0b10100000, + 0b10100000, + 0b10100000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_hash = + { + 0b01010000, + 0b01010000, + 0b11111000, + 0b01010000, + 0b11111000, + 0b01010000, + 0b01010000, + 0b00000000, + 0b00000000, + }, + .glyph_pound = + { + 0b00100000, + 0b01110000, + 0b10000000, + 0b01110000, + 0b00001000, + 0b01110000, + 0b00100000, + 0b00000000, + 0b00000000, + }, + .glyph_percent = + { + 0b01000010, + 0b10100100, + 0b01001000, + 0b00010000, + 0b00100100, + 0b01001010, + 0b10000100, + 0b00000000, + 0b00000000, + }, + .glyph_ampersand = + { + 0b00100000, + 0b01010000, + 0b00100000, + 0b01100000, + 0b10011000, + 0b10010000, + 0b01101000, + 0b00000000, + 0b00000000, + }, + .glyph_quote = + { + 0b01000000, + 0b10000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_lparen = + { + 0b00100000, + 0b01000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b01000000, + 0b00100000, + 0b00000000, + 0b00000000, + }, + .glyph_rparen = + { + 0b10000000, + 0b01000000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_asterisk = + { + 0b01010000, + 0b00100000, + 0b11111000, + 0b00100000, + 0b01010000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_plus = + { + 0b00000000, + 0b00100000, + 0b00100000, + 0b11111000, + 0b00100000, + 0b00100000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_comma = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01000000, + 0b10000000, + 0b00000000, + }, + .glyph_minus = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_period = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01000000, + 0b00000000, + 0b00000000, + }, + .glyph_slash = + { + 0b00000010, + 0b00000100, + 0b00001000, + 0b00010000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_0 = + { + 0b01110000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_1 = + { + 0b00100000, + 0b01100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_2 = + { + 0b01110000, + 0b10001000, + 0b00001000, + 0b00010000, + 0b00100000, + 0b01000000, + 0b11111000, + 0b00000000, + 0b00000000, + }, + .glyph_3 = + { + 0b01110000, + 0b10001000, + 0b00001000, + 0b00110000, + 0b00001000, + 0b10001000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_4 = + { + 0b00010000, + 0b00110000, + 0b01010000, + 0b10010000, + 0b11111000, + 0b00010000, + 0b00010000, + 0b00000000, + 0b00000000, + }, + .glyph_5 = + { + 0b11111000, + 0b10000000, + 0b11110000, + 0b00001000, + 0b00001000, + 0b10001000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_6 = + { + 0b00110000, + 0b01000000, + 0b10000000, + 0b11110000, + 0b10001000, + 0b10001000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_7 = + { + 0b11111000, + 0b00001000, + 0b00001000, + 0b00010000, + 0b00010000, + 0b00100000, + 0b00100000, + 0b00000000, + 0b00000000, + }, + .glyph_8 = + { + 0b01110000, + 0b10001000, + 0b10001000, + 0b01110000, + 0b10001000, + 0b10001000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_9 = + { + 0b01110000, + 0b10001000, + 0b10001000, + 0b01111000, + 0b00001000, + 0b00010000, + 0b01100000, + 0b00000000, + 0b00000000, + }, + .glyph_colon = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b01000000, + 0b00000000, + 0b00000000, + 0b01000000, + 0b00000000, + 0b00000000, + }, + .glyph_semicolon = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b01000000, + 0b00000000, + 0b00000000, + 0b01000000, + 0b10000000, + 0b00000000, + }, + .glyph_langle = + { + 0b00010000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b01000000, + 0b00100000, + 0b00010000, + 0b00000000, + 0b00000000, + }, + .glyph_equal = + { + 0b00000000, + 0b00000000, + 0b11111000, + 0b00000000, + 0b00000000, + 0b11111000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_rangle = + { + 0b10000000, + 0b01000000, + 0b00100000, + 0b00010000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_query = + { + 0b01110000, + 0b10001000, + 0b00001000, + 0b00010000, + 0b00100000, + 0b00000000, + 0b00100000, + 0b00000000, + 0b00000000, + }, + .glyph_comat = + { + 0b01111000, + 0b10000100, + 0b10100100, + 0b10100100, + 0b10111000, + 0b10000000, + 0b01111000, + 0b00000000, + 0b00000000, + }, + .glyph_A = + { + 0b00100000, + 0b01010000, + 0b10001000, + 0b10001000, + 0b11111000, + 0b10001000, + 0b10001000, + 0b00000000, + 0b00000000, + }, + .glyph_B = + { + 0b11110000, + 0b10001000, + 0b10001000, + 0b11110000, + 0b10001000, + 0b10001000, + 0b11110000, + 0b00000000, + 0b00000000, + }, + .glyph_C = + { + 0b00111000, + 0b01000100, + 0b10000000, + 0b10000000, + 0b10000000, + 0b01000100, + 0b00111000, + 0b00000000, + 0b00000000, + }, + .glyph_D = + { + 0b11110000, + 0b10001000, + 0b10000100, + 0b10000100, + 0b10000100, + 0b10001000, + 0b11110000, + 0b00000000, + 0b00000000, + }, + .glyph_E = + { + 0b11111000, + 0b10000000, + 0b10000000, + 0b11100000, + 0b10000000, + 0b10000000, + 0b11111000, + 0b00000000, + 0b00000000, + }, + .glyph_F = + { + 0b11111000, + 0b10000000, + 0b10000000, + 0b11100000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_G = + { + 0b00111000, + 0b01000100, + 0b10000000, + 0b10000000, + 0b10001100, + 0b01000100, + 0b00111100, + 0b00000000, + 0b00000000, + }, + .glyph_H = + { + 0b10000100, + 0b10000100, + 0b10000100, + 0b11111100, + 0b10000100, + 0b10000100, + 0b10000100, + 0b00000000, + 0b00000000, + }, + .glyph_I = + { + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_J = + { + 0b00001000, + 0b00001000, + 0b00001000, + 0b00001000, + 0b00001000, + 0b10001000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_K = + { + 0b10001000, + 0b10010000, + 0b10100000, + 0b11000000, + 0b10100000, + 0b10010000, + 0b10001000, + 0b00000000, + 0b00000000, + }, + .glyph_L = + { + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b11111000, + 0b00000000, + 0b00000000, + }, + .glyph_M = + { + 0b10000010, + 0b11000110, + 0b10101010, + 0b10010010, + 0b10000010, + 0b10000010, + 0b10000010, + 0b00000000, + 0b00000000, + }, + .glyph_N = + { + 0b10000010, + 0b11000010, + 0b10100010, + 0b10010010, + 0b10001010, + 0b10000110, + 0b10000010, + 0b00000000, + 0b00000000, + }, + .glyph_O = + { + 0b00111000, + 0b01000100, + 0b10000010, + 0b10000010, + 0b10000010, + 0b01000100, + 0b00111000, + 0b00000000, + 0b00000000, + }, + .glyph_P = + { + 0b11110000, + 0b10001000, + 0b10001000, + 0b11110000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_Q = {0b00111000, 0b01000100, 0b10000010, 0b10000010, 0b10000010, 0b01000100, 0b00111000, 0b00001110, + 0b00000000}, + .glyph_R = + { + 0b11110000, + 0b10001000, + 0b10001000, + 0b11110000, + 0b10100000, + 0b10010000, + 0b10001000, + 0b00000000, + 0b00000000, + }, + .glyph_S = + { + 0b01110000, + 0b10001000, + 0b10000000, + 0b01110000, + 0b00001000, + 0b10001000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_T = + { + 0b11111110, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00000000, + 0b00000000, + }, + .glyph_U = + { + 0b10001000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_V = + { + 0b10001000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b01010000, + 0b00100000, + 0b00000000, + 0b00000000, + }, + .glyph_W = + { + 0b10001000, + 0b10000000, + 0b10001000, + 0b10000000, + 0b10001000, + 0b10000000, + 0b10001000, + 0b10000000, + 0b10001000, + 0b10000000, + 0b01010101, + 0b00000000, + 0b00100010, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_X = + { + 0b10000010, + 0b01000100, + 0b00101000, + 0b00010000, + 0b00101000, + 0b01000100, + 0b10000010, + 0b00000000, + 0b00000000, + }, + .glyph_Y = + { + 0b10000010, + 0b01000100, + 0b00101000, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00000000, + 0b00000000, + }, + .glyph_Z = + { + 0b11111100, + 0b00000100, + 0b00001000, + 0b00010000, + 0b00100000, + 0b01000000, + 0b11111100, + 0b00000000, + 0b00000000, + }, + .glyph_lsquare = + { + 0b11100000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b11100000, + 0b00000000, + 0b00000000, + }, + .glyph_bslash = + { + 0b10000000, + 0b01000000, + 0b00100000, + 0b00010000, + 0b00001000, + 0b00000100, + 0b00000010, + 0b00000000, + 0b00000000, + }, + .glyph_rsquare = + { + 0b11100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b11100000, + 0b00000000, + 0b00000000, + }, + .glyph_caret = + { + 0b00100000, + 0b01010000, + 0b10001000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_underbar = + { + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111100, + }, + .glyph_bquote = + { + 0b10000000, + 0b01000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_a = + { + 0b00000000, + 0b00000000, + 0b01110000, + 0b00001000, + 0b01111000, + 0b10001000, + 0b01111000, + 0b00000000, + 0b00000000, + }, + .glyph_b = + { + 0b10000000, + 0b10000000, + 0b11110000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_c = + { + 0b00000000, + 0b00000000, + 0b01110000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_d = + { + 0b00001000, + 0b00001000, + 0b01111000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b01111000, + 0b00000000, + 0b00000000, + }, + .glyph_e = + { + 0b00000000, + 0b00000000, + 0b01110000, + 0b10001000, + 0b11111000, + 0b10000000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_f = + { + 0b00110000, + 0b01000000, + 0b11100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b00000000, + 0b00000000, + }, + .glyph_g = + { + 0b00000000, + 0b00000000, + 0b01110000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b01111000, + 0b00001000, + 0b01110000, + }, + .glyph_h = + { + 0b10000000, + 0b10000000, + 0b11110000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b00000000, + 0b00000000, + }, + .glyph_i = + { + 0b10000000, + 0b00000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_j = + { + 0b01000000, + 0b00000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b10000000, + }, + .glyph_k = + { + 0b10000000, + 0b10000000, + 0b10010000, + 0b10100000, + 0b11000000, + 0b10100000, + 0b10010000, + 0b00000000, + 0b00000000, + }, + .glyph_l = + { + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_m = + { + 0b00000000, + 0b00000000, + 0b11101100, + 0b10010010, + 0b10010010, + 0b10010010, + 0b10010010, + 0b00000000, + 0b00000000, + }, + .glyph_n = + { + 0b00000000, + 0b00000000, + 0b10110000, + 0b11001000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b00000000, + 0b00000000, + }, + .glyph_o = + { + 0b00000000, + 0b00000000, + 0b01110000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_p = + { + 0b00000000, + 0b00000000, + 0b11110000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b11110000, + 0b10000000, + 0b10000000, + }, + .glyph_q = + { + 0b00000000, + 0b00000000, + 0b01111000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b01111000, + 0b00001000, + 0b00001000, + }, + .glyph_r = + { + 0b00000000, + 0b00000000, + 0b10110000, + 0b11000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_s = + { + 0b00000000, + 0b00000000, + 0b01110000, + 0b10000000, + 0b01110000, + 0b00001000, + 0b01110000, + 0b00000000, + 0b00000000, + }, + .glyph_t = + { + 0b00000000, + 0b01000000, + 0b11100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b00110000, + 0b00000000, + 0b00000000, + }, + .glyph_u = + { + 0b00000000, + 0b00000000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b10011000, + 0b01101000, + 0b00000000, + 0b00000000, + }, + .glyph_v = + { + 0b00000000, + 0b00000000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b01010000, + 0b00100000, + 0b00000000, + 0b00000000, + }, + .glyph_w = + { + 0b00000000, + 0b00000000, + 0b10010010, + 0b10010010, + 0b10010010, + 0b10010010, + 0b01101100, + 0b00000000, + 0b00000000, + }, + .glyph_x = + { + 0b00000000, + 0b00000000, + 0b10001000, + 0b01010000, + 0b00100000, + 0b01010000, + 0b10001000, + 0b00000000, + 0b00000000, + }, + .glyph_y = + { + 0b00000000, + 0b00000000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b01111000, + 0b00001000, + 0b01110000, + }, + .glyph_z = + { + 0b00000000, + 0b00000000, + 0b11111000, + 0b00010000, + 0b00100000, + 0b01000000, + 0b11111000, + 0b00000000, + 0b00000000, + }, + .glyph_lbrace = + { + 0b00110000, + 0b01000000, + 0b01000000, + 0b10000000, + 0b01000000, + 0b01000000, + 0b00110000, + 0b00000000, + 0b00000000, + }, + .glyph_vbar = + { + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b00000000, + 0b00000000, + }, + .glyph_rbrace = + { + 0b11000000, + 0b00100000, + 0b00100000, + 0b00010000, + 0b00100000, + 0b00100000, + 0b11000000, + 0b00000000, + 0b00000000, + }, + .glyph_tilde = + { + 0b01110110, + 0b11011100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_bullet = + { + 0b00000000, + 0b01111000, + 0b11111100, + 0b11111100, + 0b11111100, + 0b01111000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_cross = + { + 0b00000000, + 0b01000100, + 0b00101000, + 0b00010000, + 0b00101000, + 0b01000100, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_tick = + { + 0b00000000, + 0b00000010, + 0b00000100, + 0b10001000, + 0b01010000, + 0b00100000, + 0b00000000, + 0b00000000, + 0b00000000, + }, + .glyph_uparrow = + { + 0b00010000, + 0b00111000, + 0b01111100, + 0b11111110, + 0b00111000, + 0b00111000, + 0b00111000, + 0b00000000, + 0b00000000, + }, + .glyph_downarrow = + { + 0b00111000, + 0b00111000, + 0b00111000, + 0b11111110, + 0b01111100, + 0b00111000, + 0b00010000, + 0b00000000, + 0b00000000, + }, + .glyph_rightarrow = + { + 0b00010000, + 0b00011000, + 0b11111100, + 0b11111110, + 0b11111100, + 0b00011000, + 0b00010000, + 0b00000000, + 0b00000000, + }, + .glyph_leftarrow = + { + 0b00010000, + 0b00110000, + 0b01111110, + 0b11111110, + 0b01111110, + 0b00110000, + 0b00010000, + 0b00000000, + 0b00000000, + }, + .glyph_solidbox = + { + 0b11111110, + 0b11111110, + 0b11111110, + 0b11111110, + 0b11111110, + 0b11111110, + 0b11111110, + 0b00000000, + 0b00000000, + }, + .glyph_cursor = + { + 0b10100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b10100000, + }, +}; + +br_uint_16 _FontProp7x9_Encoding[] = { + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_bullet), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_uparrow), offsetof(__font_glyphs, glyph_downarrow), + offsetof(__font_glyphs, glyph_rightarrow), offsetof(__font_glyphs, glyph_leftarrow), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_uparrow), offsetof(__font_glyphs, glyph_downarrow), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_exclam), + offsetof(__font_glyphs, glyph_dquote), offsetof(__font_glyphs, glyph_hash), + offsetof(__font_glyphs, glyph_pound), offsetof(__font_glyphs, glyph_percent), + offsetof(__font_glyphs, glyph_ampersand), offsetof(__font_glyphs, glyph_quote), + offsetof(__font_glyphs, glyph_lparen), offsetof(__font_glyphs, glyph_rparen), + offsetof(__font_glyphs, glyph_asterisk), offsetof(__font_glyphs, glyph_plus), + offsetof(__font_glyphs, glyph_comma), offsetof(__font_glyphs, glyph_minus), + offsetof(__font_glyphs, glyph_period), offsetof(__font_glyphs, glyph_slash), + offsetof(__font_glyphs, glyph_0), offsetof(__font_glyphs, glyph_1), + offsetof(__font_glyphs, glyph_2), offsetof(__font_glyphs, glyph_3), + offsetof(__font_glyphs, glyph_4), offsetof(__font_glyphs, glyph_5), + offsetof(__font_glyphs, glyph_6), offsetof(__font_glyphs, glyph_7), + offsetof(__font_glyphs, glyph_8), offsetof(__font_glyphs, glyph_9), + offsetof(__font_glyphs, glyph_colon), offsetof(__font_glyphs, glyph_semicolon), + offsetof(__font_glyphs, glyph_langle), offsetof(__font_glyphs, glyph_equal), + offsetof(__font_glyphs, glyph_rangle), offsetof(__font_glyphs, glyph_query), + offsetof(__font_glyphs, glyph_comat), offsetof(__font_glyphs, glyph_A), + offsetof(__font_glyphs, glyph_B), offsetof(__font_glyphs, glyph_C), + offsetof(__font_glyphs, glyph_D), offsetof(__font_glyphs, glyph_E), + offsetof(__font_glyphs, glyph_F), offsetof(__font_glyphs, glyph_G), + offsetof(__font_glyphs, glyph_H), offsetof(__font_glyphs, glyph_I), + offsetof(__font_glyphs, glyph_J), offsetof(__font_glyphs, glyph_K), + offsetof(__font_glyphs, glyph_L), offsetof(__font_glyphs, glyph_M), + offsetof(__font_glyphs, glyph_N), offsetof(__font_glyphs, glyph_O), + offsetof(__font_glyphs, glyph_P), offsetof(__font_glyphs, glyph_Q), + offsetof(__font_glyphs, glyph_R), offsetof(__font_glyphs, glyph_S), + offsetof(__font_glyphs, glyph_T), offsetof(__font_glyphs, glyph_U), + offsetof(__font_glyphs, glyph_V), offsetof(__font_glyphs, glyph_W), + offsetof(__font_glyphs, glyph_X), offsetof(__font_glyphs, glyph_Y), + offsetof(__font_glyphs, glyph_Z), offsetof(__font_glyphs, glyph_lsquare), + offsetof(__font_glyphs, glyph_bslash), offsetof(__font_glyphs, glyph_rsquare), + offsetof(__font_glyphs, glyph_caret), offsetof(__font_glyphs, glyph_underbar), + offsetof(__font_glyphs, glyph_bquote), offsetof(__font_glyphs, glyph_a), + offsetof(__font_glyphs, glyph_b), offsetof(__font_glyphs, glyph_c), + offsetof(__font_glyphs, glyph_d), offsetof(__font_glyphs, glyph_e), + offsetof(__font_glyphs, glyph_f), offsetof(__font_glyphs, glyph_g), + offsetof(__font_glyphs, glyph_h), offsetof(__font_glyphs, glyph_i), + offsetof(__font_glyphs, glyph_j), offsetof(__font_glyphs, glyph_k), + offsetof(__font_glyphs, glyph_l), offsetof(__font_glyphs, glyph_m), + offsetof(__font_glyphs, glyph_n), offsetof(__font_glyphs, glyph_o), + offsetof(__font_glyphs, glyph_p), offsetof(__font_glyphs, glyph_q), + offsetof(__font_glyphs, glyph_r), offsetof(__font_glyphs, glyph_s), + offsetof(__font_glyphs, glyph_t), offsetof(__font_glyphs, glyph_u), + offsetof(__font_glyphs, glyph_v), offsetof(__font_glyphs, glyph_w), + offsetof(__font_glyphs, glyph_x), offsetof(__font_glyphs, glyph_y), + offsetof(__font_glyphs, glyph_z), offsetof(__font_glyphs, glyph_lbrace), + offsetof(__font_glyphs, glyph_vbar), offsetof(__font_glyphs, glyph_rbrace), + offsetof(__font_glyphs, glyph_tilde), offsetof(__font_glyphs, glyph_arrow), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_ld_tb), + offsetof(__font_glyphs, glyph_ld_tbl), offsetof(__font_glyphs, glyph_ld_tbL), + offsetof(__font_glyphs, glyph_ld_TBl), offsetof(__font_glyphs, glyph_ld_Bl), + offsetof(__font_glyphs, glyph_ld_bL), offsetof(__font_glyphs, glyph_ld_TBL), + offsetof(__font_glyphs, glyph_ld_TB), offsetof(__font_glyphs, glyph_ld_BL), + offsetof(__font_glyphs, glyph_ld_TL), offsetof(__font_glyphs, glyph_ld_Tl), + offsetof(__font_glyphs, glyph_ld_tL), offsetof(__font_glyphs, glyph_ld_bl), + offsetof(__font_glyphs, glyph_ld_tr), offsetof(__font_glyphs, glyph_ld_tlr), + offsetof(__font_glyphs, glyph_ld_blr), offsetof(__font_glyphs, glyph_ld_tbr), + offsetof(__font_glyphs, glyph_ld_lr), offsetof(__font_glyphs, glyph_ld_tblr), + offsetof(__font_glyphs, glyph_ld_tbR), offsetof(__font_glyphs, glyph_ld_TBr), + offsetof(__font_glyphs, glyph_ld_TR), offsetof(__font_glyphs, glyph_ld_BR), + offsetof(__font_glyphs, glyph_ld_TLR), offsetof(__font_glyphs, glyph_ld_BLR), + offsetof(__font_glyphs, glyph_ld_TBR), offsetof(__font_glyphs, glyph_ld_LR), + offsetof(__font_glyphs, glyph_ld_TBLR), offsetof(__font_glyphs, glyph_ld_tLR), + offsetof(__font_glyphs, glyph_ld_Tlr), offsetof(__font_glyphs, glyph_ld_bLR), + offsetof(__font_glyphs, glyph_ld_Blr), offsetof(__font_glyphs, glyph_ld_Tr), + offsetof(__font_glyphs, glyph_ld_tR), offsetof(__font_glyphs, glyph_ld_bR), + offsetof(__font_glyphs, glyph_ld_Br), offsetof(__font_glyphs, glyph_ld_TBlr), + offsetof(__font_glyphs, glyph_ld_tbLR), offsetof(__font_glyphs, glyph_ld_tl), + offsetof(__font_glyphs, glyph_ld_br), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_alpha), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_degree), offsetof(__font_glyphs, glyph_space), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_tick), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_sup2), + offsetof(__font_glyphs, glyph_space), offsetof(__font_glyphs, glyph_space), +}; + +br_int_8 _FontProp7x9_Widths[] = { + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 6, /* glyph_bullet */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 7, /* glyph_uparrow */ + 7, /* glyph_downarrow */ + 7, /* glyph_rightarrow */ + 7, /* glyph_leftarrow */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_uparrow */ + 3, /* glyph_downarrow */ + 3, /* glyph_space */ + 1, /* glyph_exclam */ + 3, /* glyph_dquote */ + 5, /* glyph_hash */ + 5, /* glyph_pound */ + 7, /* glyph_percent */ + 5, /* glyph_ampersand */ + 2, /* glyph_quote */ + 3, /* glyph_lparen */ + 3, /* glyph_rparen */ + 5, /* glyph_asterisk */ + 5, /* glyph_plus */ + 2, /* glyph_comma */ + 5, /* glyph_minus */ + 2, /* glyph_period */ + 7, /* glyph_slash */ + 5, /* glyph_0 */ + 5, /* glyph_1 */ + 5, /* glyph_2 */ + 5, /* glyph_3 */ + 5, /* glyph_4 */ + 5, /* glyph_5 */ + 5, /* glyph_6 */ + 5, /* glyph_7 */ + 5, /* glyph_8 */ + 5, /* glyph_9 */ + 2, /* glyph_colon */ + 2, /* glyph_semicolon */ + 4, /* glyph_langle */ + 5, /* glyph_equal */ + 4, /* glyph_rangle */ + 5, /* glyph_query */ + 6, /* glyph_comat */ + 5, /* glyph_A */ + 5, /* glyph_B */ + 6, /* glyph_C */ + 6, /* glyph_D */ + 5, /* glyph_E */ + 5, /* glyph_F */ + 6, /* glyph_G */ + 6, /* glyph_H */ + 1, /* glyph_I */ + 5, /* glyph_J */ + 5, /* glyph_K */ + 5, /* glyph_L */ + 7, /* glyph_M */ + 7, /* glyph_N */ + 7, /* glyph_O */ + 5, /* glyph_P */ + 7, /* glyph_Q */ + 5, /* glyph_R */ + 5, /* glyph_S */ + 7, /* glyph_T */ + 5, /* glyph_U */ + 5, /* glyph_V */ + 9, /* glyph_W */ + 7, /* glyph_X */ + 7, /* glyph_Y */ + 7, /* glyph_Z */ + 3, /* glyph_lsquare */ + 7, /* glyph_bslash */ + 3, /* glyph_rsquare */ + 5, /* glyph_caret */ + 6, /* glyph_underbar */ + 2, /* glyph_bquote */ + 5, /* glyph_a */ + 5, /* glyph_b */ + 4, /* glyph_c */ + 5, /* glyph_d */ + 5, /* glyph_e */ + 4, /* glyph_f */ + 5, /* glyph_g */ + 5, /* glyph_h */ + 1, /* glyph_i */ + 2, /* glyph_j */ + 4, /* glyph_k */ + 1, /* glyph_l */ + 7, /* glyph_m */ + 5, /* glyph_n */ + 5, /* glyph_o */ + 5, /* glyph_p */ + 5, /* glyph_q */ + 4, /* glyph_r */ + 5, /* glyph_s */ + 4, /* glyph_t */ + 5, /* glyph_u */ + 5, /* glyph_v */ + 7, /* glyph_w */ + 5, /* glyph_x */ + 5, /* glyph_y */ + 5, /* glyph_z */ + 4, /* glyph_lbrace */ + 1, /* glyph_vbar */ + 4, /* glyph_rbrace */ + 7, /* glyph_tilde */ + 3, /* glyph_arrow */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_ld_tb */ + 3, /* glyph_ld_tbl */ + 3, /* glyph_ld_tbL */ + 3, /* glyph_ld_TBl */ + 3, /* glyph_ld_Bl */ + 3, /* glyph_ld_bL */ + 3, /* glyph_ld_TBL */ + 3, /* glyph_ld_TB */ + 3, /* glyph_ld_BL */ + 3, /* glyph_ld_TL */ + 3, /* glyph_ld_Tl */ + 3, /* glyph_ld_tL */ + 3, /* glyph_ld_bl */ + 3, /* glyph_ld_tr */ + 3, /* glyph_ld_tlr */ + 3, /* glyph_ld_blr */ + 3, /* glyph_ld_tbr */ + 3, /* glyph_ld_lr */ + 3, /* glyph_ld_tblr */ + 3, /* glyph_ld_tbR */ + 3, /* glyph_ld_TBr */ + 3, /* glyph_ld_TR */ + 3, /* glyph_ld_BR */ + 3, /* glyph_ld_TLR */ + 3, /* glyph_ld_BLR */ + 3, /* glyph_ld_TBR */ + 3, /* glyph_ld_LR */ + 3, /* glyph_ld_TBLR */ + 3, /* glyph_ld_tLR */ + 3, /* glyph_ld_Tlr */ + 3, /* glyph_ld_bLR */ + 3, /* glyph_ld_Blr */ + 3, /* glyph_ld_Tr */ + 3, /* glyph_ld_tR */ + 3, /* glyph_ld_bR */ + 3, /* glyph_ld_Br */ + 3, /* glyph_ld_TBlr */ + 3, /* glyph_ld_tbLR */ + 3, /* glyph_ld_tl */ + 3, /* glyph_ld_br */ + 7, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_alpha */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 3, /* glyph_degree */ + 3, /* glyph_space */ + 3, /* glyph_space */ + 7, /* glyph_tick */ + 3, /* glyph_space */ + 3, /* glyph_sup2 */ + 3, /* glyph_space */ + 3, /* glyph_space */ +}; + +struct br_font _FontProp7x9 = {.flags = BR_FONTF_PROPORTIONAL, + .glyph_x = FONT_WIDTH, + .glyph_y = FONT_HEIGHT, + .spacing_x = 4, + .spacing_y = 6, + .width = _FontProp7x9_Widths, + .encoding = _FontProp7x9_Encoding, + .glyphs = (br_uint_8 *)&_FontProp7x9_Glyphs}; \ No newline at end of file diff --git a/bren/FW/fontptrs.c b/bren/FW/fontptrs.c new file mode 100644 index 00000000..de1fc50b --- /dev/null +++ b/bren/FW/fontptrs.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: fontptrs.c 1.2 1995/05/25 13:23:52 sam Exp $ + * $Locker: $ + * + * Public pointers to standard fonts + */ + +#include "fw.h" + +static char rscid[] = "$Id: fontptrs.c 1.2 1995/05/25 13:23:52 sam Exp $"; + +extern struct br_font BR_ASM_DATA _FontFixed3x5; +extern struct br_font BR_ASM_DATA _FontProp4x6; +extern struct br_font BR_ASM_DATA _FontProp7x9; + +struct br_font *BrFontFixed3x5 = &_FontFixed3x5; +struct br_font *BrFontProp4x6 = &_FontProp4x6; +struct br_font *BrFontProp7x9 = &_FontProp7x9; diff --git a/bren/FW/fw.h b/bren/FW/fw.h new file mode 100644 index 00000000..5fea62bd --- /dev/null +++ b/bren/FW/fw.h @@ -0,0 +1,553 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: fw.h 1.39 1995/07/28 19:01:47 sam Exp $ + * $Locker: sam $ + * + * Internal types and structures for framework + */ +#ifndef _FW_H_ +#define _FW_H_ + +/* + * Pull in all the public definitions/declarations + */ +#ifndef _BRENDER_H_ +#include "brender.h" +#endif + +#ifndef _POOL_H_ +#include "pool.h" +#endif + +#ifndef _BRLISTS_H_ +#include "brlists.h" +#endif + +#ifndef _BREXCEPT_H_ +#include "brexcept.h" +#endif + +#ifndef _BRIMAGE_H_ +#include "brimage.h" +#endif +#ifndef _REGISTER_H_ +#include "register.h" +#endif + +#ifndef _DEVICE_H_ +#include "device.h" +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + * Per vertex components + */ + enum + { + C_X, + C_Y, + C_Z, + C_W, + C_U, + C_V, + C_I, + C_R, + C_G, + C_B, + C_Q, + NUM_COMPONENTS + }; + + /* + * Mask bits for selecting which components take part in various operations + */ + enum + { + CM_X = (1 << C_X), + CM_Y = (1 << C_Y), + CM_Z = (1 << C_Z), + CM_W = (1 << C_W), + CM_U = (1 << C_U), + CM_V = (1 << C_V), + CM_I = (1 << C_I), + CM_R = (1 << C_R), + CM_G = (1 << C_G), + CM_B = (1 << C_B), + CM_Q = (1 << C_Q) + }; + + /* + * Limited set of components used for lighting sub functions + */ + enum + { + L_I, + L_R, + L_G, + L_B, + NUM_L_COMPONENTS + }; + + /* + * Private information about a light as it applies to the current model + */ + typedef struct br_active_light + { + + /* + * Light intensity + */ + br_scalar intensity; + + /* + * position and direction of light in view space + */ + br_vector3 view_position; + br_vector3 view_direction; + + /* + * Position and direction of light in final space, view or model + */ + br_vector3 position; + br_vector3 direction; + + /* + * Half vector for specular effects + */ + br_vector3 half; + + /* + * Cosine of spot angles + */ + br_scalar spot_cosine_outer; + br_scalar spot_cosine_inner; + + /* + * Function to evaluate this light + */ + void (*light_sub_function)(br_vector3 *p, br_fvector3 *n, struct br_active_light *alp, br_scalar *lcomp); + + /* + * Copy of light's type - may vary from original if a model's relationship + * to light allows optimisation, eg: + * very far point light -> directional light + * model compeletely within spot cone -> point light + */ + int type; + + br_light *light; + + } br_active_light; + + /* + * Private information about an active clip plane + */ + typedef struct br_active_clip_plane + { + /* + * Planer eqn. in screen space + */ + br_vector4 screen_plane; + } br_active_clip_plane; + +/* + * Framework has a table of functions used for lighting - this + * will be initialised according to what sort of output is required + * (eg: indexed or RGB) + */ +#ifdef __WATCOMCX__ +#define BR_SURFACE_CALL +#else +#define BR_SURFACE_CALL BR_ASM_CALL +#endif + + typedef void BR_SURFACE_CALL br_surface_fn(br_vertex *v, br_fvector3 *n, br_scalar *comp); + typedef br_uint_32 BR_SURFACE_CALL br_face_surface_fn(br_vertex *v, br_face *fp, int reversed); + + typedef void br_light_sub_fn(br_vector3 *p, br_fvector3 *n, struct br_active_light *alp, br_scalar *lcomp); + + typedef void br_model_update_cbfn(br_model *model, br_uint_16 flags); + typedef void br_material_update_cbfn(br_material *mat, br_uint_16 flags); + typedef void br_table_update_cbfn(br_pixelmap *table, br_uint_16 flags); + typedef void br_map_update_cbfn(br_pixelmap *map, br_uint_16 flags); + + struct fw_fn_table + { + + /* + * Top level surface functions + */ + br_surface_fn *light; /* Evauluate lighting */ + br_surface_fn *light_material; /* Copy material */ + br_surface_fn *light_vertex; /* Copy vertex */ + + br_surface_fn *light_texture; /* simple light plus simple texture mapping */ + + br_face_surface_fn *face_light; /* Evauluate surface for a face */ + + /* + * Lighting + */ + br_light_sub_fn *direct; + br_light_sub_fn *point; + br_light_sub_fn *point_attn; + br_light_sub_fn *spot; + br_light_sub_fn *spot_attn; + }; + + /* + * Private state of framework + */ + typedef struct br_framework_state + { + + /* + * Main surface properties function + */ + br_surface_fn *surface_fn; + + /* + * Called after U,V generation + */ + br_surface_fn *surface_fn_after_map; + + /* + * Called after component copying + */ + br_surface_fn *surface_fn_after_copy; + + /* + * Lighting a face - usually calls vertex function and converts result for faces + */ + br_face_surface_fn *face_surface_fn; + + /* + * Current mapping coordinate transform + */ + br_matrix23 map_transform; + + /* + * Base and scale for indexes + */ + br_scalar index_base; + br_scalar index_range; + + /* + * Current Transforms + */ + br_matrix4 model_to_screen; + br_matrix4 view_to_screen; + + br_matrix34 model_to_view; + br_matrix34 view_to_model; + br_matrix34 model_to_environment; + + /* + * List of transforms from camera to root with associated actor address + */ + struct + { + br_matrix34 m; + br_actor *a; + } camera_path[MAX_CAMERA_DEPTH]; + + /* + * Type of view to screen transform + */ + int vtos_type; + + /* + * COP in model space + */ + br_vector3 eye_m; + br_vector3 eye_m_normalised; + + /* + * Material curently in use - used for lighting calcs. + */ + br_material *material; + + /* + * Information about each active light, the lights that need to be + * processed in model space are first, followed by those processed + * in view space + */ + br_active_light active_lights_model[BR_MAX_LIGHTS]; + br_active_light active_lights_view[BR_MAX_LIGHTS]; + + /* + * numbers of active lights of each type + */ + br_uint_16 nactive_lights_model; + br_uint_16 nactive_lights_view; + + /* + * Flag that is set if there is only 1 direct light in model space + */ + int light_is_1md; + + /* + * Eye vector to use for lighting, either in model or view space + */ + br_vector3 eye_l; + + /* + * A table of active clip planes + */ + br_active_clip_plane active_clip_planes[BR_MAX_CLIP_PLANES]; + br_uint_16 nactive_clip_planes; + + /* + * A table of pointers to enabled lights + * + * If an entry is not NULL then the referenced actor is an enabled light + */ + br_actor *enabled_lights[BR_MAX_LIGHTS]; + + /* + * A table of pointers to enabled clip planes + * + * If an entry is not NULL then the referenced actor is a clip plane + */ + br_actor *enabled_clip_planes[BR_MAX_CLIP_PLANES]; + + /* + * A pointer to the current environment - if NULL, then the model's + * local frame will be used + */ + br_actor *enabled_environment; + + /* + * Output pixelmap + */ + br_pixelmap *output; + + /* + * Viewport parameters + */ + br_scalar vp_width, vp_height, vp_ox, vp_oy; + + /* + * Flag that is true if rendering is going on + */ + int rendering; + + /* + * Various lists of registered items + */ + br_registry reg_models; + br_registry reg_materials; + br_registry reg_textures; + br_registry reg_tables; + br_registry reg_resource_classes; + + /* + * An index of registered resources by class + */ + br_resource_class *resource_class_index[BR_MAX_RESOURCE_CLASSES]; + + /* + * Renderer functions for item preperation & update + */ + br_model_update_cbfn *model_update; + br_material_update_cbfn *material_update; + br_table_update_cbfn *table_update; + br_map_update_cbfn *map_update; + + /* + * Current filesystem, memory, and error handlers + */ + br_filesystem *fsys; + br_allocator *mem; + br_diaghandler *diag; + + /* + * File write mode + */ + int open_mode; + + /* + * Base resource of which everything else is + * a descendant + */ + void *res; + + /* + * Default model + */ + br_model *default_model; + + /* + * Default material + */ + br_material *default_material; + + /* + * Function pointers to current lighting ops. + */ + struct fw_fn_table fn_table; + + /* + * Global scratch space + */ + void *scratch_ptr; + br_size_t scratch_size; + br_size_t scratch_last; + int scratch_inuse; + + } br_framework_state; + + /* + * Global renderer state + */ + extern br_framework_state fw; + +/* + * Minimum scratch space to allocate for render temps. + */ +#define MIN_WORKSPACE 8192 + +/* + * Make sure NULL is defined + */ +#ifndef NULL +#define NULL 0 +#endif + + /* + * Class of view->screen transform + */ + enum view_to_screen_type + { + BR_VTOS_PARALLEL, + BR_VTOS_PERSPECTIVE, + BR_VTOS_4X4 + }; + +/* + * Magic value for vertex->r to say that this vertex does not reuse a previous x,y,z + */ +#define NO_REUSE 0xffff + +/* + * The level below which the fixed specular power function is zero + */ +#define SPECULARPOW_CUTOFF BR_SCALAR(0.6172) + +/* + * Material flags generated during MaterialUpdate() + */ +#define MATUF_SURFACE_FACES 0x0001 +#define MATUF_SURFACE_VERTICES 0x0002 +#define MATUF_REGISTERED 0x0004 + +/* + * Model flags generated during ModelUpdate() + */ +#define MODUF_SIMPLE_GROUPS 0x0001 /* Smoothing group is the same for the whole model */ +#define MODUF_VERTEX_GROUPS_MATCH 0x0002 /* There are the same number of vertex groups, using the same materials */ +#define MODUF_REGISTERED 0x0004 +#define MODUF_HAS_PIVOT 0x0008 /* Model has non-zero pivot point */ + +/* + * Perspective dive for Z component of vertices + */ +#if BASED_FIXED +#define PERSP_DIV_Z(a, b) (BrFixedDivF(-a, b)) +#endif + +#if BASED_FLOAT +#define PERSP_DIV_Z(a, b) (-32767.0 * (a) / (b)) +#endif + +/* + * Generates outcodes for a homogenous point + */ +#define OUTCODE_POINT(outcode, screen) \ + { \ + int c; \ + \ + (outcode) = OUTCODES_NOT; \ + /* \ + * The 6 planes of the view volume... \ + */ \ + if ((screen)->v[X] > (screen)->v[W]) \ + (outcode) ^= (OUTCODE_LEFT | OUTCODE_N_LEFT); \ + \ + if ((screen)->v[X] < -(screen)->v[W]) \ + (outcode) ^= (OUTCODE_RIGHT | OUTCODE_N_RIGHT); \ + \ + if ((screen)->v[Y] > (screen)->v[W]) \ + (outcode) ^= (OUTCODE_TOP | OUTCODE_N_TOP); \ + if ((screen)->v[Y] < -(screen)->v[W]) \ + (outcode) ^= (OUTCODE_BOTTOM | OUTCODE_N_BOTTOM); \ + \ + if (-(screen)->v[Z] > (screen)->v[W]) \ + (outcode) ^= (OUTCODE_YON | OUTCODE_N_YON); \ + if ((screen)->v[Z] > 0) \ + (outcode) ^= (OUTCODE_HITHER | OUTCODE_N_HITHER); \ + \ + /* \ + * Any user defined clip planes... \ + */ \ + for (c = 0; c < fw.nactive_clip_planes; c++) \ + if (BrVector4Dot((screen), &fw.active_clip_planes[c].screen_plane) < S0) \ + outcode ^= (OUTCODE_USER | OUTCODE_N_USER) << c; \ + } + +#if 1 +#define APPLY_UV(du, dv, su, sv) \ + { \ + du = BR_ADD(BR_MAC2(fw.map_transform.m[0][0], su, fw.map_transform.m[1][0], sv), fw.map_transform.m[2][0]); \ + dv = BR_ADD(BR_MAC2(fw.map_transform.m[0][1], su, fw.map_transform.m[1][1], sv), fw.map_transform.m[2][1]); \ + } +#else +#define APPLY_UV(du, dv, su, sv) \ + { \ + du = BR_ADD(BR_MUL(fw.map_transform.m[0][0], su), fw.map_transform.m[2][0]); \ + dv = BR_ADD(BR_MUL(fw.map_transform.m[1][1], sv), fw.map_transform.m[2][1]); \ + } +#endif + +#if DEBUG +/* + * Controls whether the source file/line of each + * resource allocation is tracked + */ +#define BR_RES_TRACKING 1 + +/* + * True if resources are tagged with a magic number + */ +#define BR_RES_TAGGING 1 +#else +#define BR_RES_TRACKING 1 +#define BR_RES_TAGGING 1 +#endif + +/* + * Pull in private prototypes + */ +#ifndef _NO_PROTOTYPES + +#ifndef _FWIPROTO_H_ +#include "fwiproto.h" +#endif + +#ifndef _NO_VECTOR_MACROS +#ifndef _VECIFNS_H_ +#include "vecifns.h" +#endif +#endif + +#endif + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/bren/FW/fwiproto.h b/bren/FW/fwiproto.h new file mode 100644 index 00000000..6db96f36 --- /dev/null +++ b/bren/FW/fwiproto.h @@ -0,0 +1,271 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: fwiproto.h 1.29 1995/08/31 16:29:28 sam Exp $ + * $Locker: $ + * + * Prototypes for functions internal to framework + */ +#ifndef _FWIPROTO_H_ +#define _FWIPROTO_H_ +#ifndef NO_PROTOTYPES + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + * surface.c + */ + void SurfacePerScene(br_actor *world, int true_colour); + void SurfacePerModel(void); + void SurfacePerMaterial(br_material *mat); + void BR_SURFACE_CALL CopyComponents(br_vertex *v, br_fvector3 *normal, br_scalar *comp); + + /* + * light8.c + */ + br_uint_32 BR_SURFACE_CALL LightingFaceIndex(br_vertex *v, br_face *fp, int reversed); + void BR_SURFACE_CALL LightingIndex(br_vertex *v, br_fvector3 *n, br_scalar *comp); + void BR_SURFACE_CALL LightingIndexCopyVertex(br_vertex *v, br_fvector3 *n, br_scalar *comp); + void BR_SURFACE_CALL LightingIndexCopyMaterial(br_vertex *v, br_fvector3 *n, br_scalar *comp); + + void LightingIndex_Dirn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp); + void LightingIndex_Point(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp); + void LightingIndex_PointAttn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp); + void LightingIndex_Spot(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp); + void LightingIndex_SpotAttn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp); + + void BR_SURFACE_CALL LightingIndex_1MD(br_vertex *v, br_fvector3 *n, br_scalar *comp); + void BR_SURFACE_CALL LightingIndex_1MDT(br_vertex *v, br_fvector3 *n, br_scalar *comp); + + /* + * light24.c + */ + br_uint_32 BR_SURFACE_CALL LightingFaceColour(br_vertex *v, br_face *fp, int reversed); + void BR_SURFACE_CALL LightingColour(br_vertex *v, br_fvector3 *n, br_scalar *comp); + void BR_SURFACE_CALL LightingColourCopyVertex(br_vertex *v, br_fvector3 *n, br_scalar *comp); + void BR_SURFACE_CALL LightingColourCopyMaterial(br_vertex *v, br_fvector3 *n, br_scalar *comp); + + void LightingColour_Dirn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp); + void LightingColour_Point(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp); + void LightingColour_PointAttn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp); + void LightingColour_Spot(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp); + void LightingColour_SpotAttn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp); + + void BR_SURFACE_CALL LightingColour_1MD(br_vertex *v, br_fvector3 *n, br_scalar *comp); + void BR_SURFACE_CALL LightingColour_1MDT(br_vertex *v, br_fvector3 *n, br_scalar *comp); + + /* + * envmap.c + */ + void BR_SURFACE_CALL MapEnvironmentInfinite2D(br_vertex *v, br_fvector3 *normal, br_scalar *comp); + void BR_SURFACE_CALL MapEnvironmentLocal2D(br_vertex *v, br_fvector3 *normal, br_scalar *comp); + void BR_SURFACE_CALL MapFromVertex(br_vertex *v, br_fvector3 *normal, br_scalar *comp); + void BR_SURFACE_CALL MapFromVertexOnly(br_vertex *v, br_fvector3 *normal, br_scalar *comp); + + /* + * rendsupt.c + */ + extern br_material default_material; + + /* + * actsupt.c + */ + int BrActorToRoot(br_actor *a, br_actor *root, br_matrix34 *m); + void BrVector3EyeInModel(br_vector3 *eye_m); + int BrCameraToScreenMatrix4(br_matrix4 *mat, br_actor *camera); + + /* + * vector.c - private vector functions + */ + br_scalar BrFVector2Dot(br_fvector2 *v1, br_vector2 *v2); + void BrVector3CopyF(br_vector3 *v1, br_fvector3 *v2); + void BrVector3ScaleF(br_vector3 *v1, br_fvector3 *v2, br_scalar s); + br_scalar BrFVector3Dot(br_fvector3 *v1, br_vector3 *v2); + void BrFVector3Normalise(br_fvector3 *v1, br_vector3 *v2); + void BrFVector3NormaliseQuick(br_fvector3 *v1, br_vector3 *v2); + void BrFVector3NormaliseLP(br_fvector3 *v1, br_vector3 *v2); + + /* + * matrix.c - private matrix functions + */ + void BrMatrix34TApplyFV(br_vector3 *A, br_fvector3 *B, br_matrix34 *C); + + /* + * register.c + */ + int NamePatternMatch(char *p, char *s); + void *RegistryNew(br_registry *reg); + void *RegistryClear(br_registry *reg); + void *RegistryAdd(br_registry *reg, void *item); + int RegistryAddMany(br_registry *reg, void **item, int n); + void *RegistryRemove(br_registry *reg, void *item); + int RegistryRemoveMany(br_registry *reg, void **item, int n); + void *RegistryFind(br_registry *reg, char *pattern); + int RegistryFindMany(br_registry *reg, char *pattern, void **item, int n); + int RegistryCount(br_registry *reg, char *pattern); + int RegistryEnum(br_registry *reg, char *pattern, br_enum_cbfn *callback, void *arg); + + /* + * scrstr.c + */ + extern char _br_scratch_string[]; + + /* + * pool.c + */ + void BR_ASM_CALLBACK BrPoolAddChunk(br_pool *pool); + + /* + * fixed386.asm + */ + +#if 1 /* DEBUG */ + /* + * Debugging printf + */ + int BrLogPrintf(char *fmt, ...); +#endif + + /* + * fixed.c + */ + extern unsigned long BR_ASM_DATA _reciprocal[2048]; + + /* + * transform.c + */ + extern br_uint_8 _CombineTransforms[BR_TRANSFORM_MAX][BR_TRANSFORM_MAX]; + +#define COMBINE_TRANSFORMS(a, b) (_CombineTransforms[(a)][(b)]) +#define IS_LP(a) ((a) != BR_TRANSFORM_MATRIX34) + + /* + * pmmemops.c + */ + extern br_context _BrMemoryContext; + extern br_device _BrMemoryDevice; + + void BR_ASM_CALL _BrPmMemFill(br_context *ctx, br_pixelmap *dst, br_uint_32 colour); + void BR_ASM_CALL _BrPmMemRectangleCopyTo(br_context *ctx, br_pixelmap *dst, br_uint_16 dx, br_uint_16 dy, + br_pixelmap *src, br_uint_16 sx, br_uint_16 sy, br_uint_16 w, + br_uint_16 h); + void BR_ASM_CALL _BrPmMemRectangleCopyFrom(br_context *ctx, br_pixelmap *dst, br_uint_16 dx, br_uint_16 dy, + br_pixelmap *src, br_uint_16 sx, br_uint_16 sy, br_uint_16 w, + br_uint_16 h); + void BR_ASM_CALL _BrPmMemRectangleFill(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, br_uint_16 w, + br_uint_16 h, br_uint_32 colour); + void BR_ASM_CALL _BrPmMemDirtyRectangleCopy(br_context *ctx, br_pixelmap *dst, br_pixelmap *src, br_uint_16 x, + br_uint_16 y, br_uint_16 w, br_uint_16 h); + void BR_ASM_CALL _BrPmMemDirtyRectangleFill(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, + br_uint_16 w, br_uint_16 h, br_uint_32 colour); + void BR_ASM_CALL _BrPmMemPixelSet(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, br_uint_32 colour); + br_uint_32 BR_ASM_CALL _BrPmMemPixelGet(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y); + void BR_ASM_CALL _BrPmMemCopy(br_context *ctx, br_pixelmap *dst, br_pixelmap *src); + void BR_ASM_CALL _BrPmMemLine(br_context *ctx, br_pixelmap *dst, br_int_16 x1, br_int_16 y1, br_int_16 x2, + br_int_16 y2, br_uint_32 colour); + void BR_ASM_CALL _BrPmMemCopyBits(br_context *ctx, br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_8 *src, + br_uint_16 s_stride, br_uint_16 start_bit, br_uint_16 end_bit, br_uint_16 nrows, + br_uint_32 colour); + void BR_ASM_CALL _BrPmMemDoubleBuffer(br_context *ctx, br_pixelmap *dest, br_pixelmap *src); + br_pixelmap *BR_ASM_CALL _BrPmMemMatch(br_context *ctx, br_pixelmap *src, br_uint_8 match_type); + br_pixelmap *BR_ASM_CALL _BrPmMemClone(br_context *ctx, br_pixelmap *dest, br_pixelmap *src); + void BR_ASM_CALL _BrPmMemFree(br_context *ctx, br_pixelmap *src); + + /* + * pmgenops.c + */ + void BR_ASM_CALL _BrGenericLine(br_context *ctx, br_pixelmap *dst, br_int_16 x1, br_int_16 y1, br_int_16 x2, + br_int_16 y2, br_uint_32 colour); + void BR_ASM_CALL _BrGenericDoubleBuffer(br_context *ctx, br_pixelmap *dest, br_pixelmap *src); + br_pixelmap *BR_ASM_CALL _BrGenericMatch(br_context *ctx, br_pixelmap *src, br_uint_8 match_type); + br_pixelmap *BR_ASM_CALL _BrGenericClone(br_context *ctx, br_pixelmap *src); + void BR_ASM_CALL _BrGenericFree(br_context *ctx, br_pixelmap *src); + void BR_ASM_CALL _BrGenericDirtyRectangleCopy(br_context *ctx, br_pixelmap *dst, br_pixelmap *src, br_uint_16 x, + br_uint_16 y, br_uint_16 w, br_uint_16 h); + void BR_ASM_CALL _BrGenericDirtyRectangleFill(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, + br_uint_16 w, br_uint_16 h, br_uint_32 colour); + + void BR_ASM_CALL _BrGenericRectangle(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, br_uint_16 w, + br_uint_16 h, br_uint_32 colour); + void BR_ASM_CALL _BrGenericRectangle2(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, br_uint_16 w, + br_uint_16 h, br_uint_32 colour1, br_uint_32 colour2); + + void BR_ASM_CALL _BrGenericRectangleCopy(br_context *ctx, br_pixelmap *dst, br_uint_16 dx, br_uint_16 dy, + br_pixelmap *src, br_uint_16 sx, br_uint_16 sy, br_uint_16 w, + br_uint_16 h); + + void BR_ASM_CALL _BrGenericCopy(br_context *ctx, br_pixelmap *dst, br_pixelmap *src); + + /* + * fonts + */ + extern struct br_font BR_ASM_DATA _FontFixed3x5; + extern struct br_font BR_ASM_DATA _FontProp4x6; + extern struct br_font BR_ASM_DATA _FontProp7x9; + + /* + * memloops.asm + */ + void BR_ASM_CALL _MemCopyBits_A(char *dest, br_int_32 d_stride, br_uint_8 *src, br_uint_32 s_stride, + br_uint_32 start_bit, br_uint_32 end_bit, br_uint_32 nrows, br_uint_32 bpp, + br_uint_32 colour); + + void BR_ASM_CALL _MemFill_A(char *dest, br_uint_32 pixels, br_uint_32 bpp, br_uint_32 colour); + void BR_ASM_CALL _MemRectFill_A(char *dest, br_uint_32 pwidth, br_uint_32 pheight, br_int_32 d_stride, + br_uint_32 bpp, br_uint_32 colour); + + void BR_ASM_CALL _MemRectCopy_A(char *dest, char *src, br_uint_32 pwidth, br_uint_32 pheight, br_int_32 d_stride, + br_int_32 s_stride, br_uint_32 bpp); + + void BR_ASM_CALL _MemCopy_A(char *dest, char *src, br_uint_32 pixels, br_uint_32 bpp); + void BR_ASM_CALL _MemPixelSet(char *dest, br_uint_32 bytes, br_uint_32 colour); + + br_uint_32 BR_ASM_CALL _MemPixelGet(char *dest, br_uint_32 bytes); + + /* + * resource.c + */ + br_uint_32 BR_PUBLIC_ENTRY BrResCheck(void *vres, int no_tag); + void BR_PUBLIC_ENTRY BrResDump(void *vres, void (*putline)(char *str, void *arg), void *arg); + + /* + * pixelmap.c + */ + br_uint_16 BR_PUBLIC_ENTRY BrPixelmapFileSize(br_pixelmap *pm); + + /* + * brexcept.c + */ + struct br_exception_handler *_BrCatch(void); + void _BrThrow(br_int_32 value); + void *_BrExceptionResource(void); + extern br_exception_handler *_BrCurrentHandler; + + /* + * loader.c + */ + br_image *BR_PUBLIC_ENTRY BrImageReference(char *name); + void BR_PUBLIC_ENTRY BrImageDereference(br_image *image); + void *BR_PUBLIC_ENTRY BrImageLookupName(br_image *img, char *name, br_uint_32 hint); + void *BR_PUBLIC_ENTRY BrImageLookupOrdinal(br_image *img, br_uint_32 ordinal); + + void BR_CALLBACK _BrImageFree(void *res, br_uint_8 res_class, br_size_t size); + + /* + * file.c + */ + void BR_CALLBACK _BrFileFree(void *res, br_uint_8 res_class, br_size_t size); + + /* + * error.c + */ + void BrSetLastError(br_error type, void *value); + +#ifdef __cplusplus +}; +#endif +#endif +#endif diff --git a/bren/FW/fwsetup.c b/bren/FW/fwsetup.c new file mode 100644 index 00000000..5ab112ac --- /dev/null +++ b/bren/FW/fwsetup.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: fwsetup.c 1.23 1995/08/31 16:29:30 sam Exp $ + * $Locker: $ + * + */ +#include "fw.h" +#include "datafile.h" +#include + +static char rscid[] = "$Id: fwsetup.c 1.23 1995/08/31 16:29:30 sam Exp $"; + +/* + * Global renderer state + */ +br_framework_state BR_ASM_DATA fw; + +/* + * Various bits of default data + */ +extern br_model _BrDefaultModel; +extern br_material _BrDefaultMaterial; + +extern br_diaghandler *_BrDefaultDiagHandler; +extern br_filesystem *_BrDefaultFilesystem; +extern br_allocator *_BrDefaultAllocator; +extern br_file_primitives _BrFilePrimsNull; + +/* + * System resource classes + */ +static br_resource_class SystemResourceClasses[] = { + /* + * These two classes have to be initialised by hand + */ + {"REGISTRY", BR_MEMORY_REGISTRY, NULL}, + {"ANCHOR", BR_MEMORY_ANCHOR, NULL}, + + {"RESOURCE_CLASS", BR_MEMORY_RESOURCE_CLASS, NULL}, + {"SCRATCH,", BR_MEMORY_SCRATCH, NULL}, + {"PIXELMAP", BR_MEMORY_PIXELMAP, NULL}, + {"PIXELS", BR_MEMORY_PIXELS, NULL}, + {"VERTICES", BR_MEMORY_VERTICES, NULL}, + {"FACES", BR_MEMORY_FACES, NULL}, + {"GROUPS", BR_MEMORY_GROUPS, NULL}, + {"MODEL", BR_MEMORY_MODEL, NULL}, + {"MATERIAL", BR_MEMORY_MATERIAL, NULL}, + {"MATERIAL_INDEX", BR_MEMORY_MATERIAL_INDEX, NULL}, + {"ACTOR", BR_MEMORY_ACTOR, NULL}, + {"PREPARED_VERTICES", BR_MEMORY_PREPARED_VERTICES, NULL}, + {"PREPARED_FACES", BR_MEMORY_PREPARED_FACES, NULL}, + {"LIGHT", BR_MEMORY_LIGHT, NULL}, + {"CAMERA", BR_MEMORY_CAMERA, NULL}, + {"BOUNDS", BR_MEMORY_BOUNDS, NULL}, + {"CLIP_PLANE", BR_MEMORY_CLIP_PLANE, NULL}, + {"STRING", BR_MEMORY_STRING, NULL}, + {"TRANSFORM", BR_MEMORY_TRANSFORM, NULL}, + {"FILE", BR_MEMORY_FILE, _BrFileFree}, + {"POOL", BR_MEMORY_POOL, NULL}, + {"RENDER_MATERIAL", BR_MEMORY_RENDER_MATERIAL, NULL}, + {"DATAFILE", BR_MEMORY_DATAFILE, NULL}, +#if 0 + {"IMAGE", BR_MEMORY_IMAGE, _BrImageFree }, + {"IMAGE_ARENA", BR_MEMORY_IMAGE_ARENA, NULL }, + {"IMAGE_SECTIONS", BR_MEMORY_IMAGE_SECTIONS, NULL }, + {"IMAGE_NAMES", BR_MEMORY_IMAGE_NAMES, NULL }, + {"EXCEPTION_HANDLER",BR_MEMORY_EXCEPTION_HANDLER,NULL }, +#endif + {"RENDER_DATA", BR_MEMORY_RENDER_DATA, NULL}, + {"APPLICATION", BR_MEMORY_APPLICATION, NULL}, +}; + +void BR_PUBLIC_ENTRY BrBegin(void) +{ + int i; + + /* + * Set handlers to use defaults + */ + if (fw.diag == NULL) + { + fw.diag = _BrDefaultDiagHandler; + } + if (fw.fsys == NULL) + { + fw.fsys = _BrDefaultFilesystem; + } + if (fw.mem == NULL) + { + fw.mem = _BrDefaultAllocator; + } + + /* + * Set up initial state of file writing + */ + fw.open_mode = BR_FS_MODE_BINARY; + + /* + * Initialse all registries + */ + RegistryNew(&fw.reg_models); + RegistryNew(&fw.reg_materials); + RegistryNew(&fw.reg_textures); + RegistryNew(&fw.reg_tables); + RegistryNew(&fw.reg_resource_classes); + + /* + * Fake the resource classes that are required to + * support the registry + */ + fw.resource_class_index[BR_MEMORY_REGISTRY] = SystemResourceClasses + 0; + + fw.resource_class_index[BR_MEMORY_ANCHOR] = SystemResourceClasses + 1; + + /* + * Allocate the zero sized base resource instance for + * the framework + */ + fw.res = BrResAllocate(NULL, 0, BR_MEMORY_ANCHOR); + + /* + * Register all the system resource classes + */ + for (i = 0; i < BR_ASIZE(SystemResourceClasses); i++) + BrResClassAdd(SystemResourceClasses + i); + + /* + * Create default model + */ + fw.default_model = BrResAllocate(fw.res, sizeof(br_model), BR_MEMORY_MODEL); + + *fw.default_model = _BrDefaultModel; + fw.default_model->prep_flags |= MODUF_REGISTERED; + + /* + * Create default material + */ + fw.default_material = &_BrDefaultMaterial; + fw.default_material->prep_flags |= MATUF_REGISTERED; +} + +void BR_PUBLIC_ENTRY BrEnd(void) +{ + /* + * Free all resources ... + */ +#if 1 + BrResFree(fw.res); +#endif + + /* + * Clear out fw structure + */ + memset(&fw, 0, sizeof(fw)); +} + +/* + * User functions for setting new errorhandler, filesystem, or allocator + */ +br_diaghandler *BR_PUBLIC_ENTRY BrDiagHandlerSet(br_diaghandler *newdh) +{ + br_diaghandler *old = fw.diag; + + if (newdh == NULL) + fw.diag = _BrDefaultDiagHandler; + else + fw.diag = newdh; + + return old; +} + +br_filesystem *BR_PUBLIC_ENTRY BrFilesystemSet(br_filesystem *newfs) +{ + br_filesystem *old = fw.fsys; + + if (newfs == NULL) + fw.fsys = _BrDefaultFilesystem; + else + fw.fsys = newfs; + + return old; +} + +br_allocator *BR_PUBLIC_ENTRY BrAllocatorSet(br_allocator *newal) +{ + br_allocator *old = fw.mem; + + if (newal == NULL) + { + fw.mem = _BrDefaultAllocator; + } + else + { + fw.mem = newal; + } + + return old; +} diff --git a/bren/FW/ifile.h b/bren/FW/ifile.h new file mode 100644 index 00000000..6976473a --- /dev/null +++ b/bren/FW/ifile.h @@ -0,0 +1,8 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: ifile.h 1.3 1995/07/28 19:01:55 sam Exp $ + * $Locker: $ + * + * #defines to shortcut file operations + */ diff --git a/bren/FW/light24.c b/bren/FW/light24.c new file mode 100644 index 00000000..bb3f8385 --- /dev/null +++ b/bren/FW/light24.c @@ -0,0 +1,566 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: light24.c 1.5 1995/03/01 15:26:08 sam Exp $ + * $Locker: $ + * + * Bits of the lighting model for true colour pixels + */ + +#include "fw.h" +#include "shortcut.h" +#include "brassert.h" + +static char rscid[] = "$Id: light24.c 1.5 1995/03/01 15:26:08 sam Exp $"; + +/* + * Evaluate the vertex lighting function, and return a value + * for uniform face rendering + */ +br_uint_32 BR_SURFACE_CALL LightingFaceColour(br_vertex *v, br_face *fp, int reversed) +{ + br_scalar comp[NUM_COMPONENTS]; + br_fvector3 rev_normal; + + if (!reversed) + { + fw.surface_fn(v, &fp->n, comp); + } + else + { + + BrFVector3Negate(&rev_normal, &fp->n); + fw.surface_fn(v, &rev_normal, comp); + } + + return BR_COLOUR_RGB(BrScalarToInt(comp[C_R]), BrScalarToInt(comp[C_G]), BrScalarToInt(comp[C_B])); +} + +/* + * Lighting function for unlit colour + */ +void BR_SURFACE_CALL LightingColourCopyMaterial(br_vertex *v, br_fvector3 *n, br_scalar *comp) +{ + comp[C_R] = BrIntToScalar(BR_RED(fw.material->colour)); + comp[C_G] = BrIntToScalar(BR_GRN(fw.material->colour)); + comp[C_B] = BrIntToScalar(BR_BLU(fw.material->colour)); +} + +/* + * Lighting function for prelit colour + */ +void BR_SURFACE_CALL LightingColourCopyVertex(br_vertex *v, br_fvector3 *n, br_scalar *comp) +{ + comp[C_R] = BrIntToScalar(v->red); + comp[C_G] = BrIntToScalar(v->grn); + comp[C_B] = BrIntToScalar(v->blu); +} + +/* + * Work out 3 component lighting given: + * A point + * A normal + * A material + * + * Examines all active lights and accumulates lighting from each light + * + * Writes results into + * comp[C_R] + * comp[C_G] + * comp[C_B] + */ +void BR_SURFACE_CALL LightingColour(br_vertex *v, br_fvector3 *n, br_scalar *comp) +{ + br_active_light *alp; + int i; + br_vector3 vp; + br_vector3 vn; + br_fvector3 fvn; + + br_scalar lcomp[NUM_L_COMPONENTS]; + br_scalar r, g, b; + + r = g = b = BR_SCALAR(0.0); + + fw.eye_l = fw.eye_m_normalised; + alp = fw.active_lights_model; + + /* + * Ambient component + */ + r = BR_MUL(fw.material->ka, BrFixedToScalar(BR_RED(fw.material->colour) << 8)); + g = BR_MUL(fw.material->ka, BrFixedToScalar(BR_GRN(fw.material->colour) << 8)); + b = BR_MUL(fw.material->ka, BrFixedToScalar(BR_BLU(fw.material->colour) << 8)); + + /* + * Accumulate intensities for each active light in model space + */ + alp = fw.active_lights_model; + for (i = 0; i < fw.nactive_lights_model; i++, alp++) + { + alp->light_sub_function(&v->p, n, alp, lcomp); + + r += lcomp[L_R]; + g += lcomp[L_G]; + b += lcomp[L_B]; + } + + /* + * See if any lights are to be calculated in view space + */ + if (fw.nactive_lights_view) + { + BrMatrix34ApplyP(&vp, &v->p, &fw.model_to_view); + BrMatrix34TApplyFV(&vn, n, &fw.view_to_model); + BrFVector3Normalise(&fvn, &vn); + + fw.eye_l.v[0] = BR_SCALAR(0); + fw.eye_l.v[1] = BR_SCALAR(0); + fw.eye_l.v[2] = BR_SCALAR(1); + + /* + * ... and accumulate + */ + alp = fw.active_lights_view; + for (i = 0; i < fw.nactive_lights_view; i++, alp++) + { + alp->light_sub_function(&vp, &fvn, alp, lcomp); + r += lcomp[L_R]; + g += lcomp[L_G]; + b += lcomp[L_B]; + } + } + + /* + * Scale and clamp to final range + */ + comp[C_R] = BR_MUL(r, BR_SCALAR(256)); + comp[C_G] = BR_MUL(g, BR_SCALAR(256)); + comp[C_B] = BR_MUL(b, BR_SCALAR(256)); + +#define RGB_MAX BR_SCALAR(254.0) +#define RGB_MIN BR_SCALAR(1.0) + + if (comp[C_R] >= RGB_MAX) + comp[C_R] = RGB_MAX; + else if (comp[C_R] < RGB_MIN) + comp[C_R] = RGB_MIN; + + if (comp[C_G] >= RGB_MAX) + comp[C_G] = RGB_MAX; + else if (comp[C_G] < RGB_MIN) + comp[C_G] = RGB_MIN; + + if (comp[C_B] >= RGB_MAX) + comp[C_B] = RGB_MAX; + else if (comp[C_B] < RGB_MIN) + comp[C_B] = RGB_MIN; +} + +/* + * Lighting function that returns 0.0 + * True colour + */ +void LightingColour_Null(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + lcomp[L_R] = lcomp[L_G] = lcomp[L_B] = BR_SCALAR(1.0); +} + +/* + * Lighting for directional light source in model space + * True colour + */ +void LightingColour_Dirn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + br_scalar c, l, d; + + /* + * Accumulate diffuse and specular components + * + */ + + /* + * Diffuse (alp->direction already has alp->intensitt factored into it) + */ + c = BrFVector3Dot(n, &alp->direction); + + if (c > BR_SCALAR(0.0)) + { + + c = BR_MUL(c, fw.material->kd); + + lcomp[L_R] = BR_MUL(c, BrFixedToScalar(BR_RED(fw.material->colour) << 8)); + lcomp[L_G] = BR_MUL(c, BrFixedToScalar(BR_GRN(fw.material->colour) << 8)); + lcomp[L_B] = BR_MUL(c, BrFixedToScalar(BR_BLU(fw.material->colour) << 8)); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + + c = BrFVector3Dot(n, &alp->half); + + if (c > SPECULARPOW_CUTOFF) + { + l = BR_MUL(fw.material->ks, alp->intensity); + d = BR_MULDIV(c, l, fw.material->power - BR_MUL(fw.material->power, c) + c); + + lcomp[L_R] += d; + lcomp[L_G] += d; + lcomp[L_B] += d; + } + } + + lcomp[L_R] = BR_MUL(lcomp[L_R], BrFixedToScalar(BR_RED(alp->light->colour) << 8)); + lcomp[L_G] = BR_MUL(lcomp[L_G], BrFixedToScalar(BR_GRN(alp->light->colour) << 8)); + lcomp[L_B] = BR_MUL(lcomp[L_B], BrFixedToScalar(BR_BLU(alp->light->colour) << 8)); + } + else + lcomp[L_R] = lcomp[L_G] = lcomp[L_B] = BR_SCALAR(0.0); +} + +/* + * Lighting for point light source with attenuation + * True colour + */ +void LightingColour_Point(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + br_scalar c, rd, l, d; + br_vector3 dirn, dirn_norm, r, sn; + + /* + * Work out vector between point and light source + */ + BrVector3Sub(&dirn, &alp->position, p); + BrVector3Normalise(&dirn_norm, &dirn); + + /* + * Diffuse + */ + + c = BrFVector3Dot(n, &dirn_norm); + + if (c > BR_SCALAR(0.0)) + { + + c = BR_MUL(alp->intensity, BR_MUL(c, fw.material->kd)); + + lcomp[L_R] = BR_MUL(c, BrFixedToScalar(BR_RED(fw.material->colour) << 8)); + lcomp[L_G] = BR_MUL(c, BrFixedToScalar(BR_GRN(fw.material->colour) << 8)); + lcomp[L_B] = BR_MUL(c, BrFixedToScalar(BR_BLU(fw.material->colour) << 8)); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + /* + * Specular + */ + BrVector3CopyF(&sn, n); + rd = BR_CONST_MUL(BrVector3Dot(&dirn_norm, &sn), 2); + BrVector3Scale(&r, &sn, rd); + BrVector3Sub(&r, &r, &dirn_norm); + + c = BrVector3Dot(&fw.eye_l, &r); + + /* + * Phong lighting approximation from Gems IV pg. 385 + */ + if (c > SPECULARPOW_CUTOFF) + { + l = BR_MUL(fw.material->ks, alp->intensity); + d = BR_MULDIV(c, l, fw.material->power - BR_MUL(fw.material->power, c) + c); + + lcomp[L_R] += d; + lcomp[L_G] += d; + lcomp[L_B] += d; + } + } + + lcomp[L_R] = BR_MUL(lcomp[L_R], BrFixedToScalar(BR_RED(alp->light->colour) << 8)); + lcomp[L_G] = BR_MUL(lcomp[L_G], BrFixedToScalar(BR_GRN(alp->light->colour) << 8)); + lcomp[L_B] = BR_MUL(lcomp[L_B], BrFixedToScalar(BR_BLU(alp->light->colour) << 8)); + } + else + lcomp[L_R] = lcomp[L_G] = lcomp[L_B] = BR_SCALAR(0.0); +} + +/* + * Lighting for point light source with attenuation + * Colour + */ +void LightingColour_PointAttn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + br_scalar c, d, d2, rd, i, power, l; + br_vector3 dirn, dirn_norm, r, sn; + + /* + * Work out vector between point and light source + */ + BrVector3Sub(&dirn, &alp->position, p); + + /* + * Work out attenuation with distance and distance^2 + */ + d = BrVector3Length(&dirn); + + if (d == BR_SCALAR(0.0)) + { + lcomp[L_R] = lcomp[L_G] = lcomp[L_B] = BR_SCALAR(0.0); + return; + } + + if (d >= BR_SCALAR(180.0)) + d2 = BR_SCALAR(32767.0); + else + d2 = BR_MUL(d, d); + + i = alp->light->attenuation_c + BR_MUL(d, alp->light->attenuation_l) + BR_MUL(d2, alp->light->attenuation_q); + + d = BR_RCP(d); + + BrVector3Scale(&dirn_norm, &dirn, d); + + /* + * Diffuse + */ + + c = BrFVector3Dot(n, &dirn_norm); + + if (c > BR_SCALAR(0.0)) + { + + c = BR_MUL(alp->intensity, BR_MUL(c, fw.material->kd)); + + lcomp[L_R] = BR_MUL(c, BrFixedToScalar(BR_RED(fw.material->colour) << 8)); + lcomp[L_G] = BR_MUL(c, BrFixedToScalar(BR_GRN(fw.material->colour) << 8)); + lcomp[L_B] = BR_MUL(c, BrFixedToScalar(BR_BLU(fw.material->colour) << 8)); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + /* + * Specular + */ + BrVector3CopyF(&sn, n); + rd = BR_CONST_MUL(BrVector3Dot(&dirn_norm, &sn), 2); + BrVector3Scale(&r, &sn, rd); + BrVector3Sub(&r, &r, &dirn_norm); + + c = BrVector3Dot(&fw.eye_l, &r); + + /* + * Phong lighting approximation from Gems IV pg. 385 + */ + if (c > SPECULARPOW_CUTOFF) + { + l = BR_MUL(fw.material->ks, alp->intensity); + d = BR_MULDIV(c, l, fw.material->power - BR_MUL(fw.material->power, c) + c); + + lcomp[L_R] += d; + lcomp[L_G] += d; + lcomp[L_B] += d; + } + } + + lcomp[L_R] = BR_MULDIV(lcomp[L_R], BrFixedToScalar(BR_RED(alp->light->colour) << 8), i); + lcomp[L_G] = BR_MULDIV(lcomp[L_G], BrFixedToScalar(BR_GRN(alp->light->colour) << 8), i); + lcomp[L_B] = BR_MULDIV(lcomp[L_B], BrFixedToScalar(BR_BLU(alp->light->colour) << 8), i); + } + else + lcomp[L_R] = lcomp[L_G] = lcomp[L_B] = BR_SCALAR(0.0); +} + +/* + * Lighting for spot light source + * True colour + */ +void LightingColour_Spot(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + br_scalar c, rd, i = alp->intensity, power, l, d; + br_vector3 dirn, dirn_norm, r, sn; + + /* + * Work out vector between point and light source + */ + BrVector3Sub(&dirn, &alp->position, p); + BrVector3Normalise(&dirn_norm, &dirn); + + /* + * Check cutoff + */ + c = BrVector3Dot(&dirn_norm, &alp->direction); + + if (c < alp->spot_cosine_outer) + { + lcomp[L_R] = lcomp[L_G] = lcomp[L_B] = BR_SCALAR(0.0); + return; + } + + /* + * Falloff between inner and outer cones + */ + if (c < alp->spot_cosine_inner) + i = BR_MULDIV(i, alp->spot_cosine_outer - c, alp->spot_cosine_outer - alp->spot_cosine_inner); + + /* + * Diffuse + */ + + c = BrFVector3Dot(n, &dirn_norm); + + if (c > BR_SCALAR(0.0)) + { + + c = BR_MUL(alp->intensity, BR_MUL(c, fw.material->kd)); + + lcomp[L_R] = BR_MUL(c, BrFixedToScalar(BR_RED(fw.material->colour) << 8)); + lcomp[L_G] = BR_MUL(c, BrFixedToScalar(BR_GRN(fw.material->colour) << 8)); + lcomp[L_B] = BR_MUL(c, BrFixedToScalar(BR_BLU(fw.material->colour) << 8)); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + /* + * Specular + */ + BrVector3CopyF(&sn, n); + rd = BR_CONST_MUL(BrVector3Dot(&dirn_norm, &sn), 2); + BrVector3Scale(&r, &sn, rd); + BrVector3Sub(&r, &r, &dirn_norm); + + c = BrVector3Dot(&fw.eye_l, &r); + + /* + * Phong lighting approximation from Gems IV pg. 385 + */ + if (c > SPECULARPOW_CUTOFF) + { + l = BR_MUL(fw.material->ks, alp->intensity); + d = BR_MULDIV(c, l, fw.material->power - BR_MUL(fw.material->power, c) + c); + + lcomp[L_R] += d; + lcomp[L_G] += d; + lcomp[L_B] += d; + } + } + + lcomp[L_R] = BR_MUL(lcomp[L_R], BrFixedToScalar(BR_RED(alp->light->colour) << 8)); + lcomp[L_G] = BR_MUL(lcomp[L_G], BrFixedToScalar(BR_GRN(alp->light->colour) << 8)); + lcomp[L_B] = BR_MUL(lcomp[L_B], BrFixedToScalar(BR_BLU(alp->light->colour) << 8)); + + lcomp[L_R] = BR_MUL(lcomp[L_R], i); + lcomp[L_G] = BR_MUL(lcomp[L_G], i); + lcomp[L_B] = BR_MUL(lcomp[L_B], i); + } + else + lcomp[L_R] = lcomp[L_G] = lcomp[L_B] = BR_SCALAR(0.0); +} + +/* + * Lighting for spot light source with attenuation + * True colour + */ +void LightingColour_SpotAttn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + br_scalar c, d, d2, rd, i, power, l; + br_vector3 dirn, dirn_norm, r, sn; + + /* + * Work out vector between point and light source + */ + BrVector3Sub(&dirn, &alp->position, p); + + d = BrVector3Length(&dirn); + + if (d == BR_SCALAR(0.0)) + { + lcomp[L_R] = lcomp[L_G] = lcomp[L_B] = BR_SCALAR(0.0); + return; + } + + d2 = BR_RCP(d); + BrVector3Scale(&dirn_norm, &dirn, d2); + + /* + * Check cutoff + */ + c = BrVector3Dot(&dirn_norm, &alp->direction); + + if (c < alp->spot_cosine_outer) + { + lcomp[L_R] = lcomp[L_G] = lcomp[L_B] = BR_SCALAR(0.0); + return; + } + + /* + * Work out attenuation with distance and distance^2 + */ + + if (d == BR_SCALAR(0.0)) + { + lcomp[L_R] = lcomp[L_G] = lcomp[L_B] = BR_SCALAR(0.0); + return; + } + + if (d >= BR_SCALAR(180.0)) + d2 = BR_SCALAR(32767.0); + else + d2 = BR_MUL(d, d); + + i = alp->light->attenuation_c + BR_MUL(d, alp->light->attenuation_l) + BR_MUL(d2, alp->light->attenuation_q); + + i = BR_RCP(i); + + /* + * Falloff between inner and outer cones + */ + if (c < alp->spot_cosine_inner) + i = BR_MULDIV(i, alp->spot_cosine_outer - c, alp->spot_cosine_outer - alp->spot_cosine_inner); + + /* + * Diffuse + */ + + c = BrFVector3Dot(n, &dirn_norm); + + if (c > BR_SCALAR(0.0)) + { + + c = BR_MUL(alp->intensity, BR_MUL(c, fw.material->kd)); + + lcomp[L_R] = BR_MUL(c, BrFixedToScalar(BR_RED(fw.material->colour) << 8)); + lcomp[L_G] = BR_MUL(c, BrFixedToScalar(BR_GRN(fw.material->colour) << 8)); + lcomp[L_B] = BR_MUL(c, BrFixedToScalar(BR_BLU(fw.material->colour) << 8)); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + /* + * Specular + */ + BrVector3CopyF(&sn, n); + rd = BR_CONST_MUL(BrVector3Dot(&dirn_norm, &sn), 2); + BrVector3Scale(&r, &sn, rd); + BrVector3Sub(&r, &r, &dirn_norm); + + c = BrVector3Dot(&fw.eye_l, &r); + + /* + * Phong lighting approximation from Gems IV pg. 385 + */ + if (c > SPECULARPOW_CUTOFF) + { + l = BR_MUL(fw.material->ks, alp->intensity); + d = BR_MULDIV(c, l, fw.material->power - BR_MUL(fw.material->power, c) + c); + + lcomp[L_R] += d; + lcomp[L_G] += d; + lcomp[L_B] += d; + } + } + + lcomp[L_R] = BR_MUL(lcomp[L_R], BrFixedToScalar(BR_RED(alp->light->colour) << 8)); + lcomp[L_G] = BR_MUL(lcomp[L_G], BrFixedToScalar(BR_GRN(alp->light->colour) << 8)); + lcomp[L_B] = BR_MUL(lcomp[L_B], BrFixedToScalar(BR_BLU(alp->light->colour) << 8)); + + lcomp[L_R] = BR_MUL(lcomp[L_R], i); + lcomp[L_G] = BR_MUL(lcomp[L_G], i); + lcomp[L_B] = BR_MUL(lcomp[L_B], i); + } + else + lcomp[L_R] = lcomp[L_G] = lcomp[L_B] = BR_SCALAR(0.0); +} diff --git a/bren/FW/light24o.c b/bren/FW/light24o.c new file mode 100644 index 00000000..166a8c36 --- /dev/null +++ b/bren/FW/light24o.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: light24o.c 1.5 1995/02/22 21:41:59 sam Exp $ + * $Locker: $ + * + * Special case lighting models for true colour pixels + */ + +#include "fw.h" +#include "shortcut.h" +#include "brassert.h" + +static char rscid[] = "$Id: light24o.c 1.5 1995/02/22 21:41:59 sam Exp $"; + +/* + * Special case surface function for when there is a single directional + * light source in model space + */ +void BR_SURFACE_CALL LightingColour_1MD(br_vertex *v, br_fvector3 *n, br_scalar *comp) +{ + LightingColour(v, n, comp); +} + +void BR_SURFACE_CALL LightingColour_1MDT(br_vertex *v, br_fvector3 *n, br_scalar *comp) +{ + LightingColour(v, n, comp); + + APPLY_UV(comp[C_U], comp[C_V], v->map.v[U], v->map.v[V]); +} diff --git a/bren/FW/light8.c b/bren/FW/light8.c new file mode 100644 index 00000000..8a079ef5 --- /dev/null +++ b/bren/FW/light8.c @@ -0,0 +1,453 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: light8.c 1.7 1995/03/29 16:41:16 sam Exp $ + * $Locker: sam $ + * + * Bits of the lighting model for indexed pixels + */ + +#include "fw.h" +#include "shortcut.h" +#include "brassert.h" + +static char rscid[] = "$Id: light8.c 1.7 1995/03/29 16:41:16 sam Exp $"; + +/* + * Evaluate the vertex lighting function, and return a value + * for uniform face rendering + */ +br_uint_32 BR_SURFACE_CALL LightingFaceIndex(br_vertex *v, br_face *fp, int reversed) +{ + br_scalar comp[NUM_COMPONENTS]; + br_fvector3 rev_normal; + + if (!reversed) + { + fw.surface_fn(v, &fp->n, comp); + } + else + { + + BrFVector3Negate(&rev_normal, &fp->n); + fw.surface_fn(v, &rev_normal, comp); + } + + return BrScalarToInt(comp[C_I]); +} + +/* + * Lighting function for unlit indexed + */ +void BR_SURFACE_CALL LightingIndexCopyMaterial(br_vertex *v, br_fvector3 *n, br_scalar *comp) +{ + comp[C_I] = BrIntToScalar(fw.material->index_base); +} + +/* + * Lighting function for prelit indexed + */ +void BR_SURFACE_CALL LightingIndexCopyVertex(br_vertex *v, br_fvector3 *n, br_scalar *comp) +{ +#if 0 + comp[C_I] = BrIntToScalar(v->index); +#else + comp[C_I] = BR_MUL(fw.index_range, BR_CONST_DIV(BrIntToScalar(v->index), 256)) + fw.index_base; +#endif +} + +/* + * Accumulate lighting for multiple active lights by calling the + * appropriate sub-function for each light + * + * Write the results into comp[C_I] + */ +void BR_SURFACE_CALL LightingIndex(br_vertex *v, br_fvector3 *n, br_scalar *comp) +{ + int i; + br_active_light *alp; + br_vector3 vp; + br_vector3 vn; + br_fvector3 fvn; + + br_scalar lcomp[NUM_L_COMPONENTS]; + br_scalar l; + + /* + * Ambient component + */ + l = fw.material->ka; + + /* + * Accumulate intensities for each active light in model space + */ + fw.eye_l = fw.eye_m_normalised; + alp = fw.active_lights_model; + for (i = 0; i < fw.nactive_lights_model; i++, alp++) + { + alp->light_sub_function(&v->p, n, alp, lcomp); + l += lcomp[L_I]; + } + + /* + * See if any lights are to be calculated in view space + */ + if (fw.nactive_lights_view) + { + /* + * Transform point and normal into view space ... + */ + BrMatrix34ApplyP(&vp, &v->p, &fw.model_to_view); + BrMatrix34TApplyFV(&vn, n, &fw.view_to_model); + BrFVector3Normalise(&fvn, &vn); + + fw.eye_l.v[0] = BR_SCALAR(0); + fw.eye_l.v[1] = BR_SCALAR(0); + fw.eye_l.v[2] = BR_SCALAR(1); + + /* + * ... and accumulate + */ + alp = fw.active_lights_view; + for (i = 0; i < fw.nactive_lights_view; i++, alp++) + { + alp->light_sub_function(&vp, &fvn, alp, lcomp); + l += lcomp[L_I]; + } + } + + /* + * Scale final intensity to range of indices + * + * XXX Could make the scale be shifts (only ^2 ranges) + */ + if (l >= BR_SCALAR(1.0)) + comp[C_I] = fw.index_base + fw.index_range - BR_SCALAR_EPSILON; + else if (l <= BR_SCALAR(0.0)) + comp[C_I] = fw.index_base; + else + comp[C_I] = BR_MUL(fw.index_range, l) + fw.index_base; +} + +/* + * Lighting function that returns 0.0 + * Index + */ +void LightingIndex_Null(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + lcomp[L_I] = BR_SCALAR(0.0); +} + +/* + * Lighting for directional light source in model space + * Index + */ +void LightingIndex_Dirn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + br_scalar c, l, d; + + /* + * Accumulate diffuse and specular components + * + */ + + /* + * Diffuse + */ + c = BrFVector3Dot(n, &alp->direction); + + if (c > BR_SCALAR(0.0)) + { + + d = BR_MUL(c, fw.material->kd); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + /* + * Specular + */ + c = BrFVector3Dot(n, &alp->half); + + /* + * Phong lighting approximation from Gems IV pg. 385 + */ + if (c > SPECULARPOW_CUTOFF) + { + l = BR_MUL(fw.material->ks, alp->intensity); + d += BR_MULDIV(c, l, fw.material->power - BR_MUL(fw.material->power, c) + c); + } + } + lcomp[L_I] = d; + } + else + lcomp[L_I] = BR_SCALAR(0.0); +} + +/* + * Lighting for point light source with attenuation + * Index + */ +void LightingIndex_Point(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + br_scalar c, rd, d; + br_vector3 dirn, dirn_norm, r, sn; + + /* + * Work out vector between point and light source + */ + BrVector3Sub(&dirn, &alp->position, p); + BrVector3Normalise(&dirn_norm, &dirn); + + /* + * Diffuse + */ + + c = BrFVector3Dot(n, &dirn_norm); + + if (c > BR_SCALAR(0.0)) + { + d = BR_MUL(c, fw.material->kd); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + /* + * Specular + */ + BrVector3CopyF(&sn, n); + rd = BR_CONST_MUL(BrVector3Dot(&dirn_norm, &sn), 2); + BrVector3Scale(&r, &sn, rd); + BrVector3Sub(&r, &r, &dirn_norm); + + c = BrVector3Dot(&fw.eye_l, &r); + + /* + * Phong lighting approximation from Gems IV pg. 385 + */ + if (c > SPECULARPOW_CUTOFF) + d += BR_MULDIV(c, fw.material->ks, fw.material->power - BR_MUL(fw.material->power, c) + c); + } + lcomp[L_I] = BR_MUL(d, alp->intensity); + } + else + lcomp[L_I] = BR_SCALAR(0.0); +} + +/* + * Lighting for point light source with attenuation + * Index + */ +void LightingIndex_PointAttn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + br_scalar c, d2, rd, i; + br_vector3 dirn, dirn_norm, r, sn; + + /* + * Work out vector between point and light source + */ + BrVector3Sub(&dirn, &alp->position, p); + + /* + * Work out attenuation with distance and distance^2 + */ + lcomp[L_I] = BrVector3Length(&dirn); + + if (lcomp[L_I] == BR_SCALAR(0.0)) + return; + + if (lcomp[L_I] >= BR_SCALAR(180.0)) + d2 = BR_SCALAR(32767.0); + else + d2 = BR_MUL(lcomp[L_I], lcomp[L_I]); + + i = alp->light->attenuation_c + BR_MUL(lcomp[L_I], alp->light->attenuation_l) + + BR_MUL(d2, alp->light->attenuation_q); + + lcomp[L_I] = BR_RCP(lcomp[L_I]); + + BrVector3Scale(&dirn_norm, &dirn, lcomp[L_I]); + + /* + * Diffuse + */ + + c = BrFVector3Dot(n, &dirn_norm); + + if (c > BR_SCALAR(0.0)) + { + lcomp[L_I] = BR_MUL(c, fw.material->kd); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + /* + * Specular + */ + BrVector3CopyF(&sn, n); + rd = BR_CONST_MUL(BrVector3Dot(&dirn_norm, &sn), 2); + BrVector3Scale(&r, &sn, rd); + BrVector3Sub(&r, &r, &dirn_norm); + + c = BrVector3Dot(&fw.eye_l, &r); + + /* + * Phong lighting approximation from Gems IV pg. 385 + */ + if (c > SPECULARPOW_CUTOFF) + lcomp[L_I] += BR_MULDIV(c, fw.material->ks, fw.material->power - BR_MUL(fw.material->power, c) + c); + } + lcomp[L_I] = BR_DIV(lcomp[L_I], i); + } + else + lcomp[L_I] = BR_SCALAR(0.0); +} + +/* + * Lighting for spot light source + * Index + */ +void LightingIndex_Spot(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + br_scalar c, rd, i = alp->intensity; + br_vector3 dirn, dirn_norm, r, sn; + + /* + * Work out vector between point and light source + */ + BrVector3Sub(&dirn, &alp->position, p); + BrVector3Normalise(&dirn_norm, &dirn); + + /* + * Check cutoff + */ + c = BrVector3Dot(&dirn_norm, &alp->direction); + + if (c < alp->spot_cosine_outer) + { + lcomp[L_I] = BR_SCALAR(0.0); + return; + } + + /* + * Falloff between inner and outer cones + */ + if (c < alp->spot_cosine_inner) + i = BR_MULDIV(i, alp->spot_cosine_outer - c, alp->spot_cosine_outer - alp->spot_cosine_inner); + /* + * Diffuse + */ + c = BrFVector3Dot(n, &dirn_norm); + + if (c > BR_SCALAR(0.0)) + { + lcomp[L_I] = BR_MUL(c, fw.material->kd); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + /* + * Specular + */ + BrVector3CopyF(&sn, n); + rd = BR_CONST_MUL(BrVector3Dot(&dirn_norm, &sn), 2); + BrVector3Scale(&r, &sn, rd); + BrVector3Sub(&r, &r, &dirn_norm); + + c = BrVector3Dot(&fw.eye_l, &r); + + /* + * Phong lighting approximation from Gems IV pg. 385 + */ + if (c > SPECULARPOW_CUTOFF) + lcomp[L_I] += BR_MULDIV(c, fw.material->ks, fw.material->power - BR_MUL(fw.material->power, c) + c); + } + lcomp[L_I] = BR_MUL(lcomp[L_I], i); + } + else + lcomp[L_I] = BR_SCALAR(0.0); +} + +/* + * Lighting for spot light source with attenuation + * Index + */ +void LightingIndex_SpotAttn(br_vector3 *p, br_fvector3 *n, br_active_light *alp, br_scalar *lcomp) +{ + br_scalar c, d2, rd, i; + br_vector3 dirn, dirn_norm, r, sn; + + /* + * Work out vector between point and light source + */ + BrVector3Sub(&dirn, &alp->position, p); + + lcomp[L_I] = BrVector3Length(&dirn); + + if (lcomp[L_I] == BR_SCALAR(0.0)) + return; + + d2 = BR_RCP(lcomp[L_I]); + BrVector3Scale(&dirn_norm, &dirn, d2); + + /* + * Check cutoff + */ + c = BrVector3Dot(&dirn_norm, &alp->direction); + + if (c < alp->spot_cosine_outer) + { + lcomp[L_I] = BR_SCALAR(0.0); + return; + } + + /* + * Work out attenuation with distance and distance^2 + */ + + if (lcomp[L_I] == BR_SCALAR(0.0)) + return; + + if (lcomp[L_I] >= BR_SCALAR(180.0)) + d2 = BR_SCALAR(32767.0); + else + d2 = BR_MUL(lcomp[L_I], lcomp[L_I]); + + i = alp->light->attenuation_c + +BR_MUL(lcomp[L_I], alp->light->attenuation_l) + + BR_MUL(d2, alp->light->attenuation_q); + + i = BR_RCP(i); + + /* + * Falloff between inner and outer cones + */ + if (c < alp->spot_cosine_inner) + i = BR_MULDIV(i, alp->spot_cosine_outer - c, alp->spot_cosine_outer - alp->spot_cosine_inner); + /* + * Diffuse + */ + c = BrFVector3Dot(n, &dirn_norm); + + if (c > BR_SCALAR(0.0)) + { + lcomp[L_I] = BR_MUL(c, fw.material->kd); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + /* + * Specular + */ + BrVector3CopyF(&sn, n); + rd = BR_CONST_MUL(BrVector3Dot(&dirn_norm, &sn), 2); + BrVector3Scale(&r, &sn, rd); + BrVector3Sub(&r, &r, &dirn_norm); + + c = BrVector3Dot(&fw.eye_l, &r); + + /* + * Phong lighting approximation from Gems IV pg. 385 + */ + if (c > SPECULARPOW_CUTOFF) + lcomp[L_I] += BR_MULDIV(c, fw.material->ks, fw.material->power - BR_MUL(fw.material->power, c) + c); + } + lcomp[L_I] = BR_MUL(lcomp[L_I], i); + } + else + lcomp[L_I] = BR_SCALAR(0.0); +} diff --git a/bren/FW/light8o.c b/bren/FW/light8o.c new file mode 100644 index 00000000..ce81d1ad --- /dev/null +++ b/bren/FW/light8o.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: light8o.c 1.6 1995/03/01 15:26:09 sam Exp $ + * $Locker: $ + * + * Special case lighting models for indexed pixels + */ + +#include "fw.h" +#include "shortcut.h" +#include "brassert.h" + +static char rscid[] = "$Id: light8o.c 1.6 1995/03/01 15:26:09 sam Exp $"; + +/* + * Special case surface function for when there is a single directional + * light source in model space + */ +void BR_SURFACE_CALL LightingIndex_1MD(br_vertex *v, br_fvector3 *n, br_scalar *comp) +{ + int i; + br_active_light *alp; + br_vector3 vp; + br_vector3 vn; + br_fvector3 fvn; + br_scalar l, s, c, d; + + /* + * Diffuse + */ + c = BrFVector3Dot(n, &fw.active_lights_model[0].direction); + + if (c > BR_SCALAR(0.0)) + { + + d = BR_MUL(c, fw.material->kd); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + + /* + * Specular + */ + c = BrFVector3Dot(n, &fw.active_lights_model[0].half); + + /* + * Phong lighting approximation from Gems IV pg. 385 + */ + if (c > SPECULARPOW_CUTOFF) + { + s = BR_MUL(fw.material->ks, fw.active_lights_model[0].intensity); + d += BR_MULDIV(c, s, fw.material->power - BR_MUL(fw.material->power, c) + c); + } + } + l = fw.material->ka + d; + + /* + * Scale final intensity to range of indices + * + * XXX Could make the scale be shifts (only ^2 ranges) + */ + + if (l >= BR_SCALAR(1.0)) + comp[C_I] = fw.index_base + fw.index_range - BR_SCALAR_EPSILON; + else if (l <= BR_SCALAR(0.0)) + comp[C_I] = fw.index_base; + else + comp[C_I] = BR_MUL(fw.index_range, l) + fw.index_base; + } + else + { + comp[C_I] = BR_MUL(fw.index_range, fw.material->ka) + fw.index_base; + } +} + +/* + * Special case surface function for when there is a single directional + * light source in model space and texture mapping + */ +void BR_SURFACE_CALL LightingIndex_1MDT(br_vertex *v, br_fvector3 *n, br_scalar *comp) +{ + int i; + br_active_light *alp; + br_vector3 vp; + br_vector3 vn; + br_fvector3 fvn; + br_scalar l, s, c, d; + + /* + * Diffuse + */ + c = BrFVector3Dot(n, &fw.active_lights_model[0].direction); + + if (c > BR_SCALAR(0.0)) + { + + d = BR_MUL(c, fw.material->kd); + + if (fw.material->ks != BR_SCALAR(0.0)) + { + + /* + * Specular + */ + c = BrFVector3Dot(n, &fw.active_lights_model[0].half); + + /* + * Phong lighting approximation from Gems IV pg. 385 + */ + if (c > SPECULARPOW_CUTOFF) + { + s = BR_MUL(fw.material->ks, fw.active_lights_model[0].intensity); + d += BR_MULDIV(c, s, fw.material->power - BR_MUL(fw.material->power, c) + c); + } + } + l = fw.material->ka + d; + + /* + * Scale final intensity to range of indices + * + * XXX Could make the scale be shifts (only ^2 ranges) + */ + + if (l >= BR_SCALAR(1.0)) + comp[C_I] = fw.index_base + fw.index_range - BR_SCALAR_EPSILON; + else if (l <= BR_SCALAR(0.0)) + comp[C_I] = fw.index_base; + else + comp[C_I] = BR_MUL(fw.index_range, l) + fw.index_base; + } + else + { + comp[C_I] = BR_MUL(fw.index_range, fw.material->ka) + fw.index_base; + } + + APPLY_UV(comp[C_U], comp[C_V], v->map.v[U], v->map.v[V]); +} diff --git a/bren/FW/loader.c b/bren/FW/loader.c new file mode 100644 index 00000000..e5283f28 --- /dev/null +++ b/bren/FW/loader.c @@ -0,0 +1,538 @@ +/* + * Copyright (c) 1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: loader.c 1.1 1995/07/28 19:03:07 sam Exp $ + * $Locker: $ + * + * Win32 Image Loader - Can load EXEs and DLLs + */ +#include +#include +#include + +#include "fw.h" +#include "wincoff.h" + +#define READ_BLOCK(var, fh) \ + do \ + { \ + if (BrFileRead(&(var), 1, sizeof(var), (fh)) != sizeof(var)) \ + return NULL; \ + } while (0) + +/* + * List of currently loaded images + */ +br_simple_list _BrLoadedImages; + +/* + * Attempts to load an image file into memory + */ +static br_image *ImageLoad(char *name) +{ + void *fh; + int mode = BR_FS_MODE_BINARY; + struct msdos_header dos_header; + struct coff_header coff_header; + struct nt_optional_header nt_header; + struct section_header section_header; + br_uint_32 pe; + br_image *img; + br_uint_8 *arena_base; + int arena_size; + int i; + int offset; + + /* + * Try name as is. + */ + fh = BrFileOpenRead(name, 0, NULL, &mode); + + /* + * Try appending ".DLL" + */ + if (fh == NULL) + { + strcpy(_br_scratch_string, name); + strcat(_br_scratch_string, ".DLL"); + fh = BrFileOpenRead(_br_scratch_string, 0, NULL, &mode); + + /* + * Try appending ".BDD" + */ + if (fh == NULL) + { + strcpy(_br_scratch_string, name); + strcat(_br_scratch_string, ".BDD"); + fh = BrFileOpenRead(_br_scratch_string, 0, NULL, &mode); + + if (fh == NULL) + return NULL; + } + } + + /* + * Read MSDOS header + */ + READ_BLOCK(dos_header, fh); + + /* + * Validate MSDOS header + */ + if (dos_header.magic != 0x5A4D) + return NULL; + + /* + * Read PE signature + */ + if (dos_header.new_header_offset < sizeof(dos_header)) + return NULL; + + BrFileAdvance(dos_header.new_header_offset - sizeof(dos_header), fh); + + READ_BLOCK(pe, fh); + + if (pe != 0x00004550) + return NULL; + + /* + * Read base COFF header + */ + READ_BLOCK(coff_header, fh); + + /* + * Check machine type + */ + if (coff_header.machine != IMAGE_FILE_MACHINE_I386) + return NULL; /* Wrong processor type */ + + if (coff_header.flags & IMAGE_FILE_RELOCS_STRIPPED) + return NULL; /* No base relocation */ + + if (!(coff_header.flags & IMAGE_FILE_EXECUTABLE_IMAGE)) + return NULL; /* Not executable file */ + + if (!(coff_header.flags & IMAGE_FILE_32BIT_MACHINE)) + return NULL; /* Not 32 bit machine */ + + if (coff_header.opt_header_size != sizeof(nt_header)) + return NULL; /* Expecting NT coff file */ + + /* + * Read optional header + */ + READ_BLOCK(nt_header, fh); + + img = BrResAllocate(NULL, sizeof(*img), BR_MEMORY_IMAGE); + + img->sections = BrResAllocate(img, sizeof(br_image_section) * coff_header.n_sections, BR_MEMORY_IMAGE_SECTIONS); + + /* + * Read each section header + */ + for (i = 0; i < coff_header.n_sections; i++) + { + READ_BLOCK(section_header, fh); + + /* + * Make copies of the parts of the header that + * are needed + */ + img->sections[i].name = BrMemStrDup(section_header.section_name); + img->sections[i].mem_offset = section_header.rva; + img->sections[i].mem_size = section_header.virtual_size; + img->sections[i].data_size = section_header.data_size; + img->sections[i].data_offset = section_header.data_offset; + } + + /* + * Allocate image arena (aligned) + */ + arena_size = nt_header.image_size; + arena_base = BrResAllocate(img, arena_size, BR_MEMORY_IMAGE_ARENA); + + /* + * Remember current offset into file + */ + offset = dos_header.new_header_offset + sizeof(pe) + sizeof(coff_header) + sizeof(nt_header) + + coff_header.n_sections * sizeof(section_header); + + /* + * Read each section into image arena + */ + for (i = 0; i < coff_header.n_sections; i++) + { + + /* + * Ignore sections that have no raw data + */ + if ((img->sections[i].data_offset == 0) || (img->sections[i].data_size == 0)) + continue; + + /* + * make sure we only ever go forwards in file + */ + if (offset > img->sections[i].data_offset) + return NULL; /* Section data not in order */ + + /* + * XXX Check that block is within arena + */ + + /* + * Advance to start of section in file + */ + BrFileAdvance(img->sections[i].data_offset - offset, fh); + + /* + * Record pointer to start of section + */ + img->sections[i].base = arena_base + img->sections[i].mem_offset; + + /* + * Read the section into memory + */ + if (BrFileRead(img->sections[i].base, 1, img->sections[i].data_size, fh) != img->sections[i].data_size) + return NULL; + + offset = img->sections[i].data_offset + img->sections[i].data_size; + } + + /* + * Close file + */ + BrFileClose(fh); + + /* + * Exports + */ + if (nt_header.directories[DIRECTORY_EXPORT].size != 0) + { + struct export_directory *ed; + + ed = (export_directory *)(arena_base + nt_header.directories[DIRECTORY_EXPORT].rva); + + /* + * Fill in image structure with info from export directory + */ + img->identifier = (char *)(arena_base + ed->name); + img->ordinal_base = ed->ordinal_base; + img->n_functions = ed->n_entries; + img->functions = (void **)(arena_base + ed->export_table); + img->n_names = ed->n_names; + img->names = (char **)(arena_base + ed->name_table); + img->name_ordinals = (br_uint_16 *)(arena_base + ed->ordinal_table); + + /* + * Relocate the tables of pointers + */ + for (i = 0; i < img->n_functions; i++) + img->functions[i] = (void *)((br_uint_32)(img->functions[i]) + arena_base); + + for (i = 0; i < img->n_names; i++) + img->names[i] = (char *)((br_uint_32)(img->names[i]) + arena_base); + } + + /* + * Imports + */ + if (nt_header.directories[DIRECTORY_IMPORT].size != 0) + { + struct import_directory *id; + void **at; + br_uint_32 *lt; + br_image *import_img; + int n, i; + + /* + * Count number of import DLLs + */ + n = 0; + for (id = (import_directory *)(arena_base + nt_header.directories[DIRECTORY_IMPORT].rva); id->lookup_table; + id++) + n++; + + /* + * Allocate a table of pointers to imported DLL names + */ + img->imports = BrResAllocate(img, sizeof(*img->imports), BR_MEMORY_IMAGE_NAMES); + img->n_imports = n; + +#if 1 + /* + * For each entry in the directory table... + */ + for (n = 0, id = (import_directory *)(arena_base + nt_header.directories[DIRECTORY_IMPORT].rva); + id->lookup_table; id++, n++) + { + + /* + * Get a handle onto referenced DLL + */ + import_img = BrImageReference((char *)(id->name + arena_base)); + if (import_img == NULL) + return NULL; /* could not find DLL */ + + img->imports[n] = import_img; + + /* + * For each entry in lookup table + */ + at = (void **)(arena_base + id->address_table); + + for (lt = (br_uint_32 *)(arena_base + id->lookup_table); *lt; lt++, at++) + { + if (*lt & 0x80000000) + *at = BrImageLookupOrdinal(import_img, *lt & 0x7fffffff); + else + *at = BrImageLookupName(import_img, (char *)(*lt + arena_base + 2), + *((br_uint_16 *)(*lt + arena_base))); + + if (*at == NULL) + return NULL; /* Could not resolve symbol */ + } + } +#endif + } + + /* + * Base Relocation (only if the base needs to be moved) + */ + if (((br_int_32)arena_base != nt_header.image_base) && (nt_header.directories[DIRECTORY_BASERELOC].size != 0)) + { + + basereloc_header *header; + br_uint_16 *entry; + br_uint_8 *fixup; + br_int_32 delta; + br_int_16 delta_h, delta_l; + + offset = 0; + delta = (br_int_32)arena_base - nt_header.image_base; + delta_h = delta >> 16; + delta_l = delta & 0xFFFF; + + /* + * Loop for each block in section + */ + while (offset < nt_header.directories[DIRECTORY_BASERELOC].size) + { + header = (basereloc_header *)(nt_header.directories[DIRECTORY_BASERELOC].rva + arena_base + offset); + offset += header->size; + + /* + * Loop for each entry in block + */ + for (i = 0, entry = (br_uint_16 *)(header + 1); + i < (header->size - sizeof(basereloc_header)) / sizeof(br_uint_16); i++, entry++) + { + + fixup = ENTRY_OFFSET(*entry) + header->rva + arena_base; + + /* + * Check fixup is within arena + */ + if (fixup >= arena_base + arena_size) + return NULL; /* Fixup overrun */ + + /* + * Apply delta + */ + switch (ENTRY_TYPE(*entry)) + { + case IMAGE_REL_BASED_ABSOLUTE: + /* Do nothing */ + break; + + case IMAGE_REL_BASED_HIGH: + *(br_int_16 *)fixup += delta_h; + break; + + case IMAGE_REL_BASED_LOW: + *(br_int_16 *)fixup += delta_l; + break; + + case IMAGE_REL_BASED_HIGHLOW: + *(br_int_32 *)fixup += delta; + break; + + case IMAGE_REL_BASED_HIGHADJ: + + case IMAGE_REL_BASED_MIPS_JMPADDR: + + default: + return NULL; /* Unknown fixup type */ + } + } + } + } + + return img; +} + +/* + * Looks for an image in the currently loaded set + */ +br_image *BR_PUBLIC_ENTRY BrImageFind(char *pattern) +{ + br_image *img; + + /* + * Look for image in currently loaded set + */ + BR_FOR_SIMPLELIST(&_BrLoadedImages, img) + if (NamePatternMatch(pattern, img->identifier)) + return img; + + return NULL; +} + +br_image *BR_PUBLIC_ENTRY BrImageReference(char *name) +{ + br_image *img; + char tmp[256]; + +#if 0 + br_exception ex_type; + void *ex_value; + + if(ex_type = BrExceptionCatch(&ex_value)) { + SET_ERROR(ex_type, ex_value); + return NULL; + } +#endif + + img = BrImageFind(name); + + /* + * See if image is already loaded... + */ + if (img) + { + img->ref_count++; + return img; + } + + img = ImageLoad(name); + + /* + * Add image to current list + */ + BR_SIMPLEADDHEAD(&_BrLoadedImages, img); + + return img; +} + +/* + * Find a symbol in an image file + */ +void *BR_PUBLIC_ENTRY BrImageLookupName(br_image *img, char *name, br_uint_32 hint) +{ + int c, limit, base; + + /* + * See if 'hint' matches + */ + if (hint < img->n_names && !strcmp(name, img->names[hint])) + return img->functions[img->name_ordinals[hint]]; + + /* + * Binary search on name table + */ + limit = img->n_names; + base = 0; + + while (limit) + { + /* + * Compare with halfway point + */ + c = strcmp(name, img->names[base + limit / 2]); + + if (c < 0) + { + /* + * Lower + */ + limit = limit / 2; + } + else if (c > 0) + { + /* + * Higher + */ + base += limit / 2 + 1; + limit = limit - (limit / 2 + 1); + } + else + { + /* + * Hit + */ + return img->functions[img->name_ordinals[base + limit / 2]]; + } + } + + /* + * No match + */ + return NULL; +} + +void *BR_PUBLIC_ENTRY BrImageLookupOrdinal(br_image *img, br_uint_32 ordinal) +{ + ordinal -= img->ordinal_base; + + /* + * Check that ordinal exists + */ + if (ordinal > img->n_functions) + return NULL; + + return img->functions[ordinal]; +} + +void BR_PUBLIC_ENTRY BrImageDereference(br_image *image) +{ + image->ref_count--; + + if (image->ref_count > 0) + return; + + /* + * Resident images are locked in memory + * because they contain pointers into the + * program + */ + if (image->resident) + return; + + /* + * Unlink image + */ + BR_SIMPLEREMOVE(image); + + /* + * Free resource + */ + BrResFree(image); +} + +void BR_PUBLIC_ENTRY BrImageFree(br_image *image) +{ + int i; + + /* + * Dereference all referenced DLLs + */ + for (i = 0; i < image->n_imports; i++) + BrImageDereference(image->imports[i]); +} + +/* + * Resource destructor + */ +void BR_CALLBACK _BrImageFree(void *res, br_uint_8 res_class, br_size_t size) +{ + BrImageFree(res); +} diff --git a/bren/FW/logprint.c b/bren/FW/logprint.c new file mode 100644 index 00000000..4c2ec239 --- /dev/null +++ b/bren/FW/logprint.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: logprint.c 1.5 1995/03/01 15:26:10 sam Exp $ + * $Locker: $ + * + * Low level wrappers for file system access + */ + +#include +#include + +#include "fw.h" +#include "shortcut.h" + +#if DEBUG + +static char rscid[] = "$Id: logprint.c 1.5 1995/03/01 15:26:10 sam Exp $"; + +int BrLogPrintf(char *fmt, ...) +{ + int n; + va_list args; + + va_start(args, fmt); + n = vsprintf(_br_scratch_string, fmt, args); + va_end(args); + + fwrite(_br_scratch_string, 1, n, stderr); + + return n; +} +#endif diff --git a/bren/FW/matrix23.c b/bren/FW/matrix23.c new file mode 100644 index 00000000..14a19fa7 --- /dev/null +++ b/bren/FW/matrix23.c @@ -0,0 +1,345 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: matrix23.c 1.2 1995/08/31 16:29:32 sam Exp $ + * $Locker: $ + * + * A very unoptimised set of transforms - these should each + * be re-done for the sparse multiplication. + * + * 3x4 Matrices + * + */ + +#include "fw.h" +#include "shortcut.h" + +static char rscid[] = "$Id: matrix23.c 1.2 1995/08/31 16:29:32 sam Exp $"; + +static br_matrix23 mattmp1, mattmp2; + +/* + * A = B + */ +void BR_PUBLIC_ENTRY BrMatrix23Copy(br_matrix23 *A, br_matrix23 *B) +{ + A(0, 0) = B(0, 0); + A(0, 1) = B(0, 1); + + A(1, 0) = B(1, 0); + A(1, 1) = B(1, 1); + + A(2, 0) = B(2, 0); + A(2, 1) = B(2, 1); +} + +/* + * A = B*C + */ +void BR_PUBLIC_ENTRY BrMatrix23Mul(br_matrix23 *A, br_matrix23 *B, br_matrix23 *C) +{ + A(0, 0) = BR_MAC2(B(0, 0), C(0, 0), B(0, 1), C(1, 0)); + A(0, 1) = BR_MAC2(B(0, 0), C(0, 1), B(0, 1), C(1, 1)); + + A(1, 0) = BR_MAC2(B(1, 0), C(0, 0), B(1, 1), C(1, 0)); + A(1, 1) = BR_MAC2(B(1, 0), C(0, 1), B(1, 1), C(1, 1)); + + A(2, 0) = BR_MAC2(B(2, 0), C(0, 0), B(2, 1), C(1, 0)) + C(2, 0); + A(2, 1) = BR_MAC2(B(2, 0), C(0, 1), B(2, 1), C(1, 1)) + C(2, 1); +} + +void BR_PUBLIC_ENTRY BrMatrix23Identity(br_matrix23 *mat) +{ + M(0, 0) = S1; + M(0, 1) = S0; + M(1, 0) = S0; + M(1, 1) = S1; + M(2, 0) = S0; + M(2, 1) = S0; +} + +/* + * Ú ¿ + * ³ cosé siné 0 ³ + * ³ ³ + * ³ -siné cosé 0 ³ + * R(é) = ³ ³ + * ³ 0 0 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix23Rotate(br_matrix23 *mat, br_angle rz) +{ + br_scalar s = BR_SIN(rz); + br_scalar c = BR_COS(rz); + + M(0, 0) = c; + M(0, 1) = s; + M(1, 0) = -s; + M(1, 1) = c; + M(2, 0) = S0; + M(2, 1) = S0; +} + +/* + * Ú ¿ + * ³ 1 0 0 ³ + * ³ ³ + * ³ 0 1 0 ³ + * T(dx,dy) = ³ ³ + * ³ dx dy 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix23Translate(br_matrix23 *mat, br_scalar dx, br_scalar dy) +{ + M(0, 0) = S1; + M(0, 1) = S0; + M(1, 0) = S0; + M(1, 1) = S1; + M(2, 0) = dx; + M(2, 1) = dy; +} + +/* + * Ú ¿ + * ³ sx 0 0 ³ + * ³ ³ + * ³ 0 sy 0 ³ + * S(sx,sy) = ³ ³ + * ³ 0 0 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix23Scale(br_matrix23 *mat, br_scalar sx, br_scalar sy) +{ + M(0, 0) = sx; + M(0, 1) = S0; + M(1, 0) = S0; + M(1, 1) = sy; + M(2, 0) = S0; + M(2, 1) = S0; +} + +/* + * Ú ¿ + * ³ 1 sy 0 ³ + * ³ ³ + * ³ 0 1 0 ³ + * ShearX(sy) = ³ ³ + * ³ 0 0 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix23ShearX(br_matrix23 *mat, br_scalar sy) +{ + M(0, 0) = S1; + M(0, 1) = sy; + M(1, 0) = S0; + M(1, 1) = S1; + M(2, 0) = S0; + M(2, 1) = S0; +} + +/* + * Ú ¿ + * ³ 1 0 0 ³ + * ³ ³ + * ³ sx 1 0 ³ + * ShearY(sx) = ³ ³ + * ³ 0 0 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix23ShearY(br_matrix23 *mat, br_scalar sx) +{ + M(0, 0) = S1; + M(0, 1) = S0; + M(1, 0) = sx; + M(1, 1) = S1; + M(2, 0) = S0; + M(2, 1) = S0; +} + +/* + * Computes the inverse of a 2D affine matrix; + */ + +#define PRECISION_LIMIT BR_SCALAR(1e-15) + +br_scalar BR_PUBLIC_ENTRY BrMatrix23Inverse(br_matrix23 *B, br_matrix23 *A) +{ + br_scalar det, idet, pos = 0, neg = 0; + + det = BR_MUL(A(0, 0), A(1, 1)); + if (det >= 0) + pos += det; + else + neg += det; + + det = BR_MUL(-A(1, 0), A(0, 1)); + if (det >= 0) + pos += det; + else + neg += det; + + det = pos + neg; + + if (BR_ABS(det) <= BR_SCALAR_EPSILON * 2) + return S0; + + if (BR_DIV(det, pos - neg) < PRECISION_LIMIT) + return S0; + + idet = BR_RCP(det); + + B(0, 0) = BR_MUL(A(1, 1), idet); + B(0, 1) = -BR_MUL(A(0, 1), idet); + B(1, 0) = -BR_MUL(A(1, 0), idet); + B(1, 1) = BR_MUL(A(0, 0), idet); + B(2, 0) = BR_MUL(BR_MUL(A(1, 0), A(2, 1)) - BR_MUL(A(1, 1), A(2, 0)), idet); + B(2, 1) = BR_MUL(BR_MUL(A(0, 1), A(2, 0)) - BR_MUL(A(0, 0), A(2, 1)), idet); + + return det; +} + +/* + * Invert a length preserving matrix + */ + +void BR_PUBLIC_ENTRY BrMatrix23LPInverse(br_matrix23 *B, br_matrix23 *A) +{ + B(0, 0) = A(1, 1); + B(0, 1) = -A(0, 1); + B(1, 0) = -A(1, 0); + B(1, 1) = A(0, 0); + B(2, 0) = BR_MUL(A(1, 0), A(2, 1)) - BR_MUL(A(1, 1), A(2, 0)); + B(2, 1) = BR_MUL(A(0, 1), A(2, 0)) - BR_MUL(A(0, 0), A(2, 1)); +} + +void BR_PUBLIC_ENTRY BrMatrix23LPNormalise(br_matrix23 *A, br_matrix23 *B) +{ + BrVector2Normalise((br_vector2 *)A->m[Y], (br_vector2 *)B->m[Y]); + A(0, 0) = A(1, 1); + A(0, 1) = -A(1, 0); + + A(2, 0) = B(2, 0); + A(2, 1) = B(2, 1); +} + +/* + * [a b ] = [ e f ] . M + */ +void BR_PUBLIC_ENTRY BrMatrix23ApplyP(br_vector2 *A, br_vector2 *B, br_matrix23 *C) +{ + A->v[0] = BR_MAC2(B->v[0], C(0, 0), B->v[1], C(1, 0)) + C(2, 0); + A->v[1] = BR_MAC2(B->v[0], C(0, 1), B->v[1], C(1, 1)) + C(2, 1); +} + +/* + * [a b c] = [ e f 0 ] . M + */ +void BR_PUBLIC_ENTRY BrMatrix23ApplyV(br_vector2 *A, br_vector2 *B, br_matrix23 *C) +{ + A->v[0] = BR_MAC2(B->v[0], C(0, 0), B->v[1], C(1, 0)); + A->v[1] = BR_MAC2(B->v[0], C(0, 1), B->v[1], C(1, 1)); +} + +/* + * [a b] = [ e f] . transpose(M) + */ +void BR_PUBLIC_ENTRY BrMatrix23TApplyP(br_vector2 *A, br_vector2 *B, br_matrix23 *C) +{ + A->v[0] = BR_MAC2(B->v[0], C(0, 0), B->v[1], C(0, 1)); + A->v[1] = BR_MAC2(B->v[0], C(1, 0), B->v[1], C(1, 1)); +} + +/* + * [a b c] = [ e f 0 ] . transpose(M) + */ +void BR_PUBLIC_ENTRY BrMatrix23TApplyV(br_vector2 *A, br_vector2 *B, br_matrix23 *C) +{ + A->v[0] = BR_MAC2(B->v[0], C(0, 0), B->v[1], C(0, 1)); + A->v[1] = BR_MAC2(B->v[0], C(1, 0), B->v[1], C(1, 1)); +} + +/* + * Composite matrix operations - + * pre and post-multiply with an existing matrix + */ + +void BR_PUBLIC_ENTRY BrMatrix23Pre(br_matrix23 *mat, br_matrix23 *A) +{ + BrMatrix23Mul(&mattmp2, A, mat); + BrMatrix23Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix23Post(br_matrix23 *mat, br_matrix23 *A) +{ + BrMatrix23Mul(&mattmp2, mat, A); + BrMatrix23Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix23PreRotate(br_matrix23 *mat, br_angle rz) +{ + BrMatrix23Rotate(&mattmp1, rz); + BrMatrix23Mul(&mattmp2, &mattmp1, mat); + BrMatrix23Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix23PostRotate(br_matrix23 *mat, br_angle rz) +{ + BrMatrix23Rotate(&mattmp1, rz); + BrMatrix23Mul(&mattmp2, mat, &mattmp1); + BrMatrix23Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix23PreTranslate(br_matrix23 *mat, br_scalar x, br_scalar y) +{ + BrMatrix23Translate(&mattmp1, x, y); + BrMatrix23Mul(&mattmp2, &mattmp1, mat); + BrMatrix23Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix23PostTranslate(br_matrix23 *A, br_scalar x, br_scalar y) +{ + A(2, 0) += x; + A(2, 1) += y; +} + +void BR_PUBLIC_ENTRY BrMatrix23PreScale(br_matrix23 *mat, br_scalar sx, br_scalar sy) +{ + BrMatrix23Scale(&mattmp1, sx, sy); + BrMatrix23Mul(&mattmp2, &mattmp1, mat); + BrMatrix23Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix23PostScale(br_matrix23 *mat, br_scalar sx, br_scalar sy) +{ + BrMatrix23Scale(&mattmp1, sx, sy); + BrMatrix23Mul(&mattmp2, mat, &mattmp1); + BrMatrix23Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix23PreShearX(br_matrix23 *mat, br_scalar sy) +{ + BrMatrix23ShearX(&mattmp1, sy); + BrMatrix23Mul(&mattmp2, &mattmp1, mat); + BrMatrix23Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix23PostShearX(br_matrix23 *mat, br_scalar sy) +{ + BrMatrix23ShearX(&mattmp1, sy); + BrMatrix23Mul(&mattmp2, mat, &mattmp1); + BrMatrix23Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix23PreShearY(br_matrix23 *mat, br_scalar sx) +{ + BrMatrix23ShearY(&mattmp1, sx); + BrMatrix23Mul(&mattmp2, &mattmp1, mat); + BrMatrix23Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix23PostShearY(br_matrix23 *mat, br_scalar sx) +{ + BrMatrix23ShearY(&mattmp1, sx); + BrMatrix23Mul(&mattmp2, mat, &mattmp1); + BrMatrix23Copy(mat, &mattmp2); +} diff --git a/bren/FW/matrix34.c b/bren/FW/matrix34.c new file mode 100644 index 00000000..c297d7b8 --- /dev/null +++ b/bren/FW/matrix34.c @@ -0,0 +1,902 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: matrix34.c 1.4 1995/03/01 15:26:13 sam Exp $ + * $Locker: $ + * + * A very unoptimised set of transforms - these should each + * be re-done for the sparse multiplication. + * + * 3x4 Matrices + * + */ + +#include "fw.h" +#include "shortcut.h" + +static char rscid[] = "$Id: matrix34.c 1.4 1995/03/01 15:26:13 sam Exp $"; + +static br_matrix34 mattmp1, mattmp2; + +/* + * A = B + */ +void BR_PUBLIC_ENTRY BrMatrix34Copy(br_matrix34 *A, br_matrix34 *B) +{ + A(0, 0) = B(0, 0); + A(0, 1) = B(0, 1); + A(0, 2) = B(0, 2); + + A(1, 0) = B(1, 0); + A(1, 1) = B(1, 1); + A(1, 2) = B(1, 2); + + A(2, 0) = B(2, 0); + A(2, 1) = B(2, 1); + A(2, 2) = B(2, 2); + + A(3, 0) = B(3, 0); + A(3, 1) = B(3, 1); + A(3, 2) = B(3, 2); +} + +/* + * A = B*C + */ +void BR_PUBLIC_ENTRY BrMatrix34Mul(br_matrix34 *A, br_matrix34 *B, br_matrix34 *C) +{ + A(0, 0) = BR_MAC3(B(0, 0), C(0, 0), B(0, 1), C(1, 0), B(0, 2), C(2, 0)); + A(0, 1) = BR_MAC3(B(0, 0), C(0, 1), B(0, 1), C(1, 1), B(0, 2), C(2, 1)); + A(0, 2) = BR_MAC3(B(0, 0), C(0, 2), B(0, 1), C(1, 2), B(0, 2), C(2, 2)); + + A(1, 0) = BR_MAC3(B(1, 0), C(0, 0), B(1, 1), C(1, 0), B(1, 2), C(2, 0)); + A(1, 1) = BR_MAC3(B(1, 0), C(0, 1), B(1, 1), C(1, 1), B(1, 2), C(2, 1)); + A(1, 2) = BR_MAC3(B(1, 0), C(0, 2), B(1, 1), C(1, 2), B(1, 2), C(2, 2)); + + A(2, 0) = BR_MAC3(B(2, 0), C(0, 0), B(2, 1), C(1, 0), B(2, 2), C(2, 0)); + A(2, 1) = BR_MAC3(B(2, 0), C(0, 1), B(2, 1), C(1, 1), B(2, 2), C(2, 1)); + A(2, 2) = BR_MAC3(B(2, 0), C(0, 2), B(2, 1), C(1, 2), B(2, 2), C(2, 2)); + + A(3, 0) = BR_MAC3(B(3, 0), C(0, 0), B(3, 1), C(1, 0), B(3, 2), C(2, 0)) + C(3, 0); + A(3, 1) = BR_MAC3(B(3, 0), C(0, 1), B(3, 1), C(1, 1), B(3, 2), C(2, 1)) + C(3, 1); + A(3, 2) = BR_MAC3(B(3, 0), C(0, 2), B(3, 1), C(1, 2), B(3, 2), C(2, 2)) + C(3, 2); +} + +void BR_PUBLIC_ENTRY BrMatrix34Identity(br_matrix34 *mat) +{ + M(0, 0) = S1; + M(0, 1) = S0; + M(0, 2) = S0; + M(1, 0) = S0; + M(1, 1) = S1; + M(1, 2) = S0; + M(2, 0) = S0; + M(2, 1) = S0; + M(2, 2) = S1; + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; +} + +/* + * Ú ¿ + * ³ 1 0 0 0 ³ + * ³ ³ + * ³ 0 cosé siné 0 ³ + * Rx(é) = ³ ³ + * ³ 0 -siné cosé 0 ³ + * ³ ³ + * ³ 0 0 0 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix34RotateX(br_matrix34 *mat, br_angle rx) +{ + br_scalar s = BR_SIN(rx); + br_scalar c = BR_COS(rx); + + M(0, 0) = S1; + M(0, 1) = S0; + M(0, 2) = S0; + M(1, 0) = S0; + M(1, 1) = c; + M(1, 2) = s; + M(2, 0) = S0; + M(2, 1) = -s; + M(2, 2) = c; + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; +} + +/* + * Ú ¿ + * ³ cosé 0 -siné 0 ³ + * ³ ³ + * ³ 0 1 0 0 ³ + * Ry(é) = ³ ³ + * ³ siné 0 cosé 0 ³ + * ³ ³ + * ³ 0 0 0 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix34RotateY(br_matrix34 *mat, br_angle ry) +{ + br_scalar s = BR_SIN(ry); + br_scalar c = BR_COS(ry); + + M(0, 0) = c; + M(0, 1) = S0; + M(0, 2) = -s; + M(1, 0) = S0; + M(1, 1) = S1; + M(1, 2) = S0; + M(2, 0) = s; + M(2, 1) = S0; + M(2, 2) = c; + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; +} + +/* + * Ú ¿ + * ³ cosé siné 0 0 ³ + * ³ ³ + * ³ -siné cosé 0 0 ³ + * Ry(é) = ³ ³ + * ³ 0 0 1 0 ³ + * ³ ³ + * ³ 0 0 0 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix34RotateZ(br_matrix34 *mat, br_angle rz) +{ + br_scalar s = BR_SIN(rz); + br_scalar c = BR_COS(rz); + + M(0, 0) = c; + M(0, 1) = s; + M(0, 2) = S0; + M(1, 0) = -s; + M(1, 1) = c; + M(1, 2) = S0; + M(2, 0) = S0; + M(2, 1) = S0; + M(2, 2) = S1; + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; +} + +/* + * Rotation about an arbitary (normalised) axis + */ +void BR_PUBLIC_ENTRY BrMatrix34Rotate(br_matrix34 *mat, br_angle r, br_vector3 *a) +{ + br_scalar t, s, c; + br_scalar txy, txz, tyz, sx, sy, sz; + + s = BR_SIN(r); + c = BR_COS(r); + t = S1 - c; + + txy = BR_MUL(t, a->v[X]); + txz = BR_MUL(txy, a->v[Z]); + txy = BR_MUL(txy, a->v[Y]); + tyz = BR_MUL(t, BR_MUL(a->v[Y], a->v[Z])); + + sx = BR_MUL(s, a->v[X]); + sy = BR_MUL(s, a->v[Y]); + sz = BR_MUL(s, a->v[Z]); + + M(0, 0) = BR_MUL(t, BR_SQR(a->v[X])) + c; + M(0, 1) = txy + sz; + M(0, 2) = txz - sy; + M(1, 0) = txy - sz; + M(1, 1) = BR_MUL(t, BR_SQR(a->v[Y])) + c; + M(1, 2) = tyz + sx; + M(2, 0) = txz + sy; + M(2, 1) = tyz - sx; + M(2, 2) = BR_MUL(t, BR_SQR(a->v[Z])) + c; + + M(3, 0) = M(3, 1) = M(3, 2) = S0; +} + +/* + * Ú ¿ + * ³ 1 0 0 0 ³ + * ³ ³ + * ³ 0 1 0 0 ³ + * T(dx,dy,dz) = ³ ³ + * ³ 0 0 1 0 ³ + * ³ ³ + * ³ dx dy dz 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix34Translate(br_matrix34 *mat, br_scalar dx, br_scalar dy, br_scalar dz) +{ + M(0, 0) = S1; + M(0, 1) = S0; + M(0, 2) = S0; + M(1, 0) = S0; + M(1, 1) = S1; + M(1, 2) = S0; + M(2, 0) = S0; + M(2, 1) = S0; + M(2, 2) = S1; + M(3, 0) = dx; + M(3, 1) = dy; + M(3, 2) = dz; +} + +/* + * Ú ¿ + * ³ sx 0 0 0 ³ + * ³ ³ + * ³ 0 sy 0 0 ³ + * S(sx,sy,sz) = ³ ³ + * ³ 0 0 sz 0 ³ + * ³ ³ + * ³ 0 0 0 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix34Scale(br_matrix34 *mat, br_scalar sx, br_scalar sy, br_scalar sz) +{ + M(0, 0) = sx; + M(0, 1) = S0; + M(0, 2) = S0; + M(1, 0) = S0; + M(1, 1) = sy; + M(1, 2) = S0; + M(2, 0) = S0; + M(2, 1) = S0; + M(2, 2) = sz; + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; +} + +/* + * Ú ¿ + * ³ 1 sy sz 0 ³ + * ³ ³ + * ³ 0 1 0 0 ³ + * ShearX(sy,sz) = ³ ³ + * ³ 0 0 1 0 ³ + * ³ ³ + * ³ 0 0 0 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix34ShearX(br_matrix34 *mat, br_scalar sy, br_scalar sz) +{ + M(0, 0) = S1; + M(0, 1) = sy; + M(0, 2) = sz; + M(1, 0) = S0; + M(1, 1) = S1; + M(1, 2) = S0; + M(2, 0) = S0; + M(2, 1) = S0; + M(2, 2) = S1; + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; +} + +/* + * Ú ¿ + * ³ 1 0 0 0 ³ + * ³ ³ + * ³ sx 1 sz 0 ³ + * ShearY(sx,sz) = ³ ³ + * ³ 0 0 1 0 ³ + * ³ ³ + * ³ 0 0 0 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix34ShearY(br_matrix34 *mat, br_scalar sx, br_scalar sz) +{ + M(0, 0) = S1; + M(0, 1) = S0; + M(0, 2) = S0; + M(1, 0) = sx; + M(1, 1) = S1; + M(1, 2) = sz; + M(2, 0) = S0; + M(2, 1) = S0; + M(2, 2) = S1; + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; +} + +/* + * Ú ¿ + * ³ 1 0 0 0 ³ + * ³ ³ + * ³ 0 1 0 0 ³ + * ShearZ(sx,sy) = ³ ³ + * ³ sx sy 1 0 ³ + * ³ ³ + * ³ 0 0 0 1 ³ + * À Ù + */ +void BR_PUBLIC_ENTRY BrMatrix34ShearZ(br_matrix34 *mat, br_scalar sx, br_scalar sy) +{ + M(0, 0) = S1; + M(0, 1) = S0; + M(0, 2) = S0; + M(1, 0) = S0; + M(1, 1) = S1; + M(1, 2) = S0; + M(2, 0) = sx; + M(2, 1) = sy; + M(2, 2) = S1; + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; +} + +/* + * From Graphics Gems II - Fast Matrix Inversion by Kevin Wu (pp. 342) + * + * This should be extended to work with flags asociated with each transform. + * + * + * Computes the inverse of a 3D affine matrix; i.e. a matrix with a dimen- + * sionality of 4 where the right column has the entries (0, 0, 0, 1). + * + * This procedure treats the 4 by 4 matrix as a block matrix and + * calculates the inverse of one submatrix for a significant perform- + * ance improvement over a general procedure that can invert any non- + * singular matrix: + * -- -- -- -- + * | | -1 | -1 | + * | A 0 | | A 0 | + * -1 | | | | + * M = | | = | -1 | + * | C 1 | | -C A 1 | + * | | | | + * -- -- -- -- + * + * where M is a 4 by 4 matrix, + * A is the 3 by 3 ur left submatrix of M, + * C is the 1 by 3 lower left submatrix of M. + * + * Input: + * A - 3D affine matrix + * + * Output: + * B - inverse of 3D affine matrix + * + * Returned value: + * determinant of matrix + */ +#if 1 + +br_scalar BR_PUBLIC_ENTRY BrMatrix34Inverse(br_matrix34 *B, br_matrix34 *A) +{ + br_scalar idet, det; + br_scalar pos, neg, temp; + +#define ACCUMULATE \ + if (temp >= S0) \ + pos += temp; \ + else \ + neg += temp; + +#define PRECISION_LIMIT BR_SCALAR(1.0e-15) + +#define ABS(a) (((a) < 0) ? -(a) : (a)) + + /* + * Calculate the determinant of submatrix A and determine if the + * the matrix is singular as limited by the double precision + * floating-point data representation. + */ + pos = neg = S0; + temp = BR_MUL(BR_MUL(A(0, 0), A(1, 1)), A(2, 2)); + ACCUMULATE + temp = BR_MUL(BR_MUL(A(0, 1), A(1, 2)), A(2, 0)); + ACCUMULATE + temp = BR_MUL(BR_MUL(A(0, 2), A(1, 0)), A(2, 1)); + ACCUMULATE + temp = -BR_MUL(BR_MUL(A(0, 2), A(1, 1)), A(2, 0)); + ACCUMULATE + temp = -BR_MUL(BR_MUL(A(0, 1), A(1, 0)), A(2, 2)); + ACCUMULATE + temp = -BR_MUL(BR_MUL(A(0, 0), A(1, 2)), A(2, 1)); + ACCUMULATE + det = pos + neg; + + /* + * Is the submatrix A singular? + */ + if (ABS(det) <= BR_SCALAR_EPSILON * 2) + return S0; + + if ((ABS(BR_DIV(det, (pos - neg))) < PRECISION_LIMIT)) + { + /* + * Matrix M has no inverse + */ + return S0; + } + + /* + * Calculate inverse(A) = adj(A) / det(A) + */ + idet = BR_DIV(S1, det); + + B(0, 0) = BR_MUL(BR_MAC2(A(1, 1), A(2, 2), -A(1, 2), A(2, 1)), idet); + B(1, 0) = -BR_MUL(BR_MAC2(A(1, 0), A(2, 2), -A(1, 2), A(2, 0)), idet); + B(2, 0) = BR_MUL(BR_MAC2(A(1, 0), A(2, 1), -A(1, 1), A(2, 0)), idet); + B(0, 1) = -BR_MUL(BR_MAC2(A(0, 1), A(2, 2), -A(0, 2), A(2, 1)), idet); + B(1, 1) = BR_MUL(BR_MAC2(A(0, 0), A(2, 2), -A(0, 2), A(2, 0)), idet); + B(2, 1) = -BR_MUL(BR_MAC2(A(0, 0), A(2, 1), -A(0, 1), A(2, 0)), idet); + B(0, 2) = BR_MUL(BR_MAC2(A(0, 1), A(1, 2), -A(0, 2), A(1, 1)), idet); + B(1, 2) = -BR_MUL(BR_MAC2(A(0, 0), A(1, 2), -A(0, 2), A(1, 0)), idet); + B(2, 2) = BR_MUL(BR_MAC2(A(0, 0), A(1, 1), -A(0, 1), A(1, 0)), idet); + + /* + * Calculate -C * inverse(A) + */ + B(3, 0) = -BR_MAC3(A(3, 0), B(0, 0), A(3, 1), B(1, 0), A(3, 2), B(2, 0)); + B(3, 1) = -BR_MAC3(A(3, 0), B(0, 1), A(3, 1), B(1, 1), A(3, 2), B(2, 1)); + B(3, 2) = -BR_MAC3(A(3, 0), B(0, 2), A(3, 1), B(1, 2), A(3, 2), B(2, 2)); + + return det; +} +#endif + +#if 0 + +#define AF(x, y) (AF[x][y]) +#define BF(x, y) (BF[x][y]) + +#define BR_FLOAT_EPSILON 1.192092896e-7f + +/* + * Use float intermediates for invertion + */ +br_scalar BR_PUBLIC_ENTRY BrMatrix34Inverse(br_matrix34 *B, br_matrix34 *A) +{ + float idet,det; + float pos, neg, temp; + float AF[4][3], BF[4][3]; + int i; + +#define ACCUMULATE \ + if (temp >= 0.0) \ + pos += temp; \ + else \ + neg += temp; +#define PRECISION_LIMIT BR_SCALAR(1.0e-15) +#define ABS(a) (((a) < 0) ? -(a) : (a)) + + /* + * Convert input to floats + */ + for(i=0; i < 4; i++) { + AF(i,0) = BrScalarToFloat(A(i,0)); + AF(i,1) = BrScalarToFloat(A(i,1)); + AF(i,2) = BrScalarToFloat(A(i,2)); + } + + /* + * Calculate the determinant of submatrix A and determine if the + * the matrix is singular as limited by the double precision + * floating-point data representation. + */ + pos = neg = 0.0; + temp = AF(0,0) * AF(1,1) * AF(2,2); + ACCUMULATE + temp = AF(0,1) * AF(1,2) * AF(2,0); + ACCUMULATE + temp = AF(0,2) * AF(1,0) * AF(2,1); + ACCUMULATE + temp = -AF(0,2) * AF(1,1) * AF(2,0); + ACCUMULATE + temp = -AF(0,1) * AF(1,0) * AF(2,2); + ACCUMULATE + temp = -AF(0,0) * AF(1,2) * AF(2,1); + ACCUMULATE + det = pos + neg; + + /* + * Is the submatrix A singular? + */ + if(ABS(det) <= BR_FLOAT_EPSILON) + return S0; + + if((ABS(det/(pos - neg)) < PRECISION_LIMIT)) { + /* + * Matrix M has no inverse + */ + return S0; + } + + /* + * Calculate inverse(A) = adj(A) / det(A) + */ + idet = 1.0/det; + + BF(0,0) = (AF(1,1) * AF(2,2) - AF(1,2) * AF(2,1)) * idet; + BF(1,0) = -(AF(1,0) * AF(2,2) - AF(1,2) * AF(2,0)) * idet; + BF(2,0) = (AF(1,0) * AF(2,1) - AF(1,1) * AF(2,0)) * idet; + BF(0,1) = -(AF(0,1) * AF(2,2) - AF(0,2) * AF(2,1)) * idet; + BF(1,1) = (AF(0,0) * AF(2,2) - AF(0,2) * AF(2,0)) * idet; + BF(2,1) = -(AF(0,0) * AF(2,1) - AF(0,1) * AF(2,0)) * idet; + BF(0,2) = (AF(0,1) * AF(1,2) - AF(0,2) * AF(1,1)) * idet; + BF(1,2) = -(AF(0,0) * AF(1,2) - AF(0,2) * AF(1,0)) * idet; + BF(2,2) = (AF(0,0) * AF(1,1) - AF(0,1) * AF(1,0)) * idet; + + /* + * Calculate -C * inverse(A) + */ + BF(3,0) = -(AF(3,0) * BF(0,0) + AF(3,1) * BF(1,0) + AF(3,2) * BF(2,0)); + BF(3,1) = -(AF(3,0) * BF(0,1) + AF(3,1) * BF(1,1) + AF(3,2) * BF(2,1)); + BF(3,2) = -(AF(3,0) * BF(0,2) + AF(3,1) * BF(1,2) + AF(3,2) * BF(2,2)); + + /* + * Convert output back to scalars + */ + for(i=0; i < 4; i++) { + B(i,0) = BrFloatToScalar(BF(i,0)); + B(i,1) = BrFloatToScalar(BF(i,1)); + B(i,2) = BrFloatToScalar(BF(i,2)); + } + + return BrFloatToScalar(det); +} +#endif + +/* + * Invert a length preserving matrix + * + * Given: + * + * A 0 + * + * C 1 + * + * Produce - + * + * T + * A 0 + * T + * -C A 1 + * + */ +void BR_PUBLIC_ENTRY BrMatrix34LPInverse(br_matrix34 *A, br_matrix34 *B) +{ + A(0, 0) = B(0, 0); + A(0, 1) = B(1, 0); + A(0, 2) = B(2, 0); + + A(1, 0) = B(0, 1); + A(1, 1) = B(1, 1); + A(1, 2) = B(2, 1); + + A(2, 0) = B(0, 2); + A(2, 1) = B(1, 2); + A(2, 2) = B(2, 2); + + /* + * Calculate -C * inverse(A) + */ + A(3, 0) = -BR_MAC3(B(3, 0), A(0, 0), B(3, 1), A(1, 0), B(3, 2), A(2, 0)); + A(3, 1) = -BR_MAC3(B(3, 0), A(0, 1), B(3, 1), A(1, 1), B(3, 2), A(2, 1)); + A(3, 2) = -BR_MAC3(B(3, 0), A(0, 2), B(3, 1), A(1, 2), B(3, 2), A(2, 2)); +} + +void BR_PUBLIC_ENTRY BrMatrix34LPNormalise(br_matrix34 *A, br_matrix34 *B) +{ + BrVector3Normalise((br_vector3 *)A->m[Z], (br_vector3 *)B->m[Z]); + BrVector3Cross((br_vector3 *)A->m[X], (br_vector3 *)B->m[Y], (br_vector3 *)A->m[Z]); + BrVector3Normalise((br_vector3 *)A->m[X], (br_vector3 *)A->m[X]); + BrVector3Cross((br_vector3 *)A->m[Y], (br_vector3 *)A->m[Z], (br_vector3 *)A->m[X]); + + A(3, 0) = B(3, 0); + A(3, 1) = B(3, 1); + A(3, 2) = B(3, 2); +} + +/* + * From Graphic Gems II - The Rolling Ball, Andrew J. Hanson (pp. 51) + * + * given incremental device scalars, dx,dy, and radius of ball - + * + * Find axis of rotation: + * + * dr = sqrt(dx^2+dy^2) + * nx = -dy/dr + * ny = +dx/dr + * nz = 0 + * + * Find angle to rotate about n: + * + * cos(a) = radius/sqrt(radius^2 + dr^2) + * sin(a) = dr/sqrt(radius^2 + dr^2) + * + * Now plug these values into a rotation by an angle about a vector + */ + +void BR_PUBLIC_ENTRY BrMatrix34RollingBall(br_matrix34 *mat, int dx, int dy, int radius) +{ + br_scalar nx, ny; + br_scalar ca, sa; + br_scalar dr, h; + + dr = BR_LENGTH2(BrIntToScalar(dx), BrIntToScalar(dy)); + + if (dr == BR_SCALAR(0.0)) + { + BrMatrix34Identity(mat); + return; + } + + nx = -BR_DIV(BrIntToScalar(dy), dr); + ny = BR_DIV(BrIntToScalar(dx), dr); + + h = BR_LENGTH2(BrIntToScalar(radius), dr); + ca = BR_DIV(BrIntToScalar(radius), h); + sa = BR_DIV(dr, h); + + M(0, 0) = ca + BR_MUL(BR_MUL(nx, nx), (S1 - ca)); + M(1, 0) = BR_MUL(BR_MUL(nx, ny), (S1 - ca)); + M(2, 0) = BR_MUL(ny, sa); + + M(0, 1) = M(1, 0); + M(1, 1) = ca + BR_MUL(BR_MUL(ny, ny), (S1 - ca)); + M(2, 1) = -BR_MUL(nx, sa); + + M(0, 2) = -M(2, 0); + M(1, 2) = -M(2, 1); + M(2, 2) = ca; + + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; +} + +void BR_PUBLIC_ENTRY BrMatrix34Copy4(br_matrix34 *A, br_matrix4 *B) +{ + A(0, 0) = B(0, 0); + A(0, 1) = B(0, 1); + A(0, 2) = B(0, 2); + A(1, 0) = B(1, 0); + A(1, 1) = B(1, 1); + A(1, 2) = B(1, 2); + A(2, 0) = B(2, 0); + A(2, 1) = B(2, 1); + A(2, 2) = B(2, 2); + A(3, 0) = B(3, 0); + A(3, 1) = B(3, 1); + A(3, 2) = B(3, 2); +} + +/* + * [a b c d] = [ e f g 0 ] . transpose(M) + * (unit vector) + * + * (Private function) + */ +void BrMatrix34TApplyFV(br_vector3 *A, br_fvector3 *B, br_matrix34 *C) +{ + A->v[0] = BR_FMAC3(B->v[0], C(0, 0), B->v[1], C(0, 1), B->v[2], C(0, 2)); + A->v[1] = BR_FMAC3(B->v[0], C(1, 0), B->v[1], C(1, 1), B->v[2], C(1, 2)); + A->v[2] = BR_FMAC3(B->v[0], C(2, 0), B->v[1], C(2, 1), B->v[2], C(2, 2)); +} + +/* + * vec_a = vec_b * mat + */ +void BR_PUBLIC_ENTRY BrMatrix34Apply(br_vector3 *A, br_vector4 *B, br_matrix34 *C) +{ + A->v[0] = BR_MAC4(B->v[0], C(0, 0), B->v[1], C(1, 0), B->v[2], C(2, 0), B->v[3], C(3, 0)); + A->v[1] = BR_MAC4(B->v[0], C(0, 1), B->v[1], C(1, 1), B->v[2], C(2, 1), B->v[3], C(3, 1)); + A->v[2] = BR_MAC4(B->v[0], C(0, 2), B->v[1], C(1, 2), B->v[2], C(2, 2), B->v[3], C(3, 2)); +} + +/* + * [a b c ] = [ e f g ] . M + */ +void BR_PUBLIC_ENTRY BrMatrix34ApplyP(br_vector3 *A, br_vector3 *B, br_matrix34 *C) +{ + A->v[0] = BR_MAC3(B->v[0], C(0, 0), B->v[1], C(1, 0), B->v[2], C(2, 0)) + C(3, 0); + A->v[1] = BR_MAC3(B->v[0], C(0, 1), B->v[1], C(1, 1), B->v[2], C(2, 1)) + C(3, 1); + A->v[2] = BR_MAC3(B->v[0], C(0, 2), B->v[1], C(1, 2), B->v[2], C(2, 2)) + C(3, 2); +} + +/* + * [a b c d] = [ e f g 0 ] . M + */ +void BR_PUBLIC_ENTRY BrMatrix34ApplyV(br_vector3 *A, br_vector3 *B, br_matrix34 *C) +{ + A->v[0] = BR_MAC3(B->v[0], C(0, 0), B->v[1], C(1, 0), B->v[2], C(2, 0)); + A->v[1] = BR_MAC3(B->v[0], C(0, 1), B->v[1], C(1, 1), B->v[2], C(2, 1)); + A->v[2] = BR_MAC3(B->v[0], C(0, 2), B->v[1], C(1, 2), B->v[2], C(2, 2)); +} + +/* + * vec_a = vec_b * transpose(M) + */ +void BR_PUBLIC_ENTRY BrMatrix34TApply(br_vector4 *A, br_vector4 *B, br_matrix34 *C) +{ + A->v[0] = BR_MAC3(B->v[0], C(0, 0), B->v[1], C(0, 1), B->v[2], C(0, 2)); + A->v[1] = BR_MAC3(B->v[0], C(1, 0), B->v[1], C(1, 1), B->v[2], C(1, 2)); + A->v[2] = BR_MAC3(B->v[0], C(2, 0), B->v[1], C(2, 1), B->v[2], C(2, 2)); + A->v[3] = BR_ADD(BR_MAC3(B->v[0], C(3, 0), B->v[1], C(3, 1), B->v[2], C(3, 2)), B->v[3]); +} + +/* + * [a b c] = [ e f g] . transpose(M) + */ +void BR_PUBLIC_ENTRY BrMatrix34TApplyP(br_vector3 *A, br_vector3 *B, br_matrix34 *C) +{ + A->v[0] = BR_MAC3(B->v[0], C(0, 0), B->v[1], C(0, 1), B->v[2], C(0, 2)); + A->v[1] = BR_MAC3(B->v[0], C(1, 0), B->v[1], C(1, 1), B->v[2], C(1, 2)); + A->v[2] = BR_MAC3(B->v[0], C(2, 0), B->v[1], C(2, 1), B->v[2], C(2, 2)); +} + +/* + * [a b c d] = [ e f g 0 ] . transpose(M) + */ +void BR_PUBLIC_ENTRY BrMatrix34TApplyV(br_vector3 *A, br_vector3 *B, br_matrix34 *C) +{ + A->v[0] = BR_MAC3(B->v[0], C(0, 0), B->v[1], C(0, 1), B->v[2], C(0, 2)); + A->v[1] = BR_MAC3(B->v[0], C(1, 0), B->v[1], C(1, 1), B->v[2], C(1, 2)); + A->v[2] = BR_MAC3(B->v[0], C(2, 0), B->v[1], C(2, 1), B->v[2], C(2, 2)); +} + +/* + * XXX - Apply vectors of vectors through matrix + * + * BrMatrix34ApplyNV() + * BrMatrix34ApplyNP() + * BrMatrix34ApplyN() + */ + +/* + * Composite matrix operations - + * pre and post-multiply with an existing matrix + */ + +void BR_PUBLIC_ENTRY BrMatrix34Pre(br_matrix34 *mat, br_matrix34 *A) +{ + BrMatrix34Mul(&mattmp2, A, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34Post(br_matrix34 *mat, br_matrix34 *A) +{ + BrMatrix34Mul(&mattmp2, mat, A); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreRotateX(br_matrix34 *mat, br_angle rx) +{ + BrMatrix34RotateX(&mattmp1, rx); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostRotateX(br_matrix34 *mat, br_angle rx) +{ + BrMatrix34RotateX(&mattmp1, rx); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreRotateY(br_matrix34 *mat, br_angle ry) +{ + BrMatrix34RotateY(&mattmp1, ry); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostRotateY(br_matrix34 *mat, br_angle ry) +{ + BrMatrix34RotateY(&mattmp1, ry); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreRotateZ(br_matrix34 *mat, br_angle rz) +{ + BrMatrix34RotateZ(&mattmp1, rz); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostRotateZ(br_matrix34 *mat, br_angle rz) +{ + BrMatrix34RotateZ(&mattmp1, rz); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreRotate(br_matrix34 *mat, br_angle r, br_vector3 *axis) +{ + BrMatrix34Rotate(&mattmp1, r, axis); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostRotate(br_matrix34 *mat, br_angle r, br_vector3 *axis) +{ + BrMatrix34Rotate(&mattmp1, r, axis); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreTranslate(br_matrix34 *mat, br_scalar x, br_scalar y, br_scalar z) +{ + BrMatrix34Translate(&mattmp1, x, y, z); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostTranslate(br_matrix34 *mat, br_scalar x, br_scalar y, br_scalar z) +{ + BrMatrix34Translate(&mattmp1, x, y, z); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreScale(br_matrix34 *mat, br_scalar sx, br_scalar sy, br_scalar sz) +{ + BrMatrix34Scale(&mattmp1, sx, sy, sz); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostScale(br_matrix34 *mat, br_scalar sx, br_scalar sy, br_scalar sz) +{ + BrMatrix34Scale(&mattmp1, sx, sy, sz); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreShearX(br_matrix34 *mat, br_scalar sy, br_scalar sz) +{ + BrMatrix34ShearX(&mattmp1, sy, sz); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostShearX(br_matrix34 *mat, br_scalar sy, br_scalar sz) +{ + BrMatrix34ShearX(&mattmp1, sy, sz); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreShearY(br_matrix34 *mat, br_scalar sx, br_scalar sz) +{ + BrMatrix34ShearY(&mattmp1, sx, sz); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostShearY(br_matrix34 *mat, br_scalar sx, br_scalar sz) +{ + BrMatrix34ShearY(&mattmp1, sx, sz); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreShearZ(br_matrix34 *mat, br_scalar sx, br_scalar sy) +{ + BrMatrix34ShearZ(&mattmp1, sx, sy); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostShearZ(br_matrix34 *mat, br_scalar sx, br_scalar sy) +{ + BrMatrix34ShearZ(&mattmp1, sx, sy); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} diff --git a/bren/FW/matrix4.c b/bren/FW/matrix4.c new file mode 100644 index 00000000..fd8e6590 --- /dev/null +++ b/bren/FW/matrix4.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: matrix4.c 1.2 1995/02/22 21:42:11 sam Exp $ + * $Locker: $ + * + * A very unoptimised set of transforms - these should each + * be re-done for the sparse multiplication. + * + * 4x4 Matrices + * + */ + +#include "fw.h" +#include "shortcut.h" + +static char rscid[] = "$Id: matrix4.c 1.2 1995/02/22 21:42:11 sam Exp $"; + +/* + * A = B + */ +void BR_PUBLIC_ENTRY BrMatrix4Copy(br_matrix4 *A, br_matrix4 *B) +{ + A(0, 0) = B(0, 0); + A(0, 1) = B(0, 1); + A(0, 2) = B(0, 2); + A(0, 3) = B(0, 3); + A(1, 0) = B(1, 0); + A(1, 1) = B(1, 1); + A(1, 2) = B(1, 2); + A(1, 3) = B(1, 3); + A(2, 0) = B(2, 0); + A(2, 1) = B(2, 1); + A(2, 2) = B(2, 2); + A(2, 3) = B(2, 3); + A(3, 0) = B(3, 0); + A(3, 1) = B(3, 1); + A(3, 2) = B(3, 2); + A(3, 3) = B(3, 3); +} + +/* + * A = B*C + */ +void BR_PUBLIC_ENTRY BrMatrix4Mul(br_matrix4 *A, br_matrix4 *B, br_matrix4 *C) +{ + A(0, 0) = BR_MAC4(B(0, 0), C(0, 0), B(0, 1), C(1, 0), B(0, 2), C(2, 0), B(0, 3), C(3, 0)); + A(0, 1) = BR_MAC4(B(0, 0), C(0, 1), B(0, 1), C(1, 1), B(0, 2), C(2, 1), B(0, 3), C(3, 1)); + A(0, 2) = BR_MAC4(B(0, 0), C(0, 2), B(0, 1), C(1, 2), B(0, 2), C(2, 2), B(0, 3), C(3, 2)); + A(0, 3) = BR_MAC4(B(0, 0), C(0, 3), B(0, 1), C(1, 3), B(0, 2), C(2, 3), B(0, 3), C(3, 3)); + + A(1, 0) = BR_MAC4(B(1, 0), C(0, 0), B(1, 1), C(1, 0), B(1, 2), C(2, 0), B(1, 3), C(3, 0)); + A(1, 1) = BR_MAC4(B(1, 0), C(0, 1), B(1, 1), C(1, 1), B(1, 2), C(2, 1), B(1, 3), C(3, 1)); + A(1, 2) = BR_MAC4(B(1, 0), C(0, 2), B(1, 1), C(1, 2), B(1, 2), C(2, 2), B(1, 3), C(3, 2)); + A(1, 3) = BR_MAC4(B(1, 0), C(0, 3), B(1, 1), C(1, 3), B(1, 2), C(2, 3), B(1, 3), C(3, 3)); + + A(2, 0) = BR_MAC4(B(2, 0), C(0, 0), B(2, 1), C(1, 0), B(2, 2), C(2, 0), B(2, 3), C(3, 0)); + A(2, 1) = BR_MAC4(B(2, 0), C(0, 1), B(2, 1), C(1, 1), B(2, 2), C(2, 1), B(2, 3), C(3, 1)); + A(2, 2) = BR_MAC4(B(2, 0), C(0, 2), B(2, 1), C(1, 2), B(2, 2), C(2, 2), B(2, 3), C(3, 2)); + A(2, 3) = BR_MAC4(B(2, 0), C(0, 3), B(2, 1), C(1, 3), B(2, 2), C(2, 3), B(2, 3), C(3, 3)); + + A(3, 0) = BR_MAC4(B(3, 0), C(0, 0), B(3, 1), C(1, 0), B(3, 2), C(2, 0), B(3, 3), C(3, 0)); + A(3, 1) = BR_MAC4(B(3, 0), C(0, 1), B(3, 1), C(1, 1), B(3, 2), C(2, 1), B(3, 3), C(3, 1)); + A(3, 2) = BR_MAC4(B(3, 0), C(0, 2), B(3, 1), C(1, 2), B(3, 2), C(2, 2), B(3, 3), C(3, 2)); + A(3, 3) = BR_MAC4(B(3, 0), C(0, 3), B(3, 1), C(1, 3), B(3, 2), C(2, 3), B(3, 3), C(3, 3)); +} + +/* + * mat = Identity + */ +void BR_PUBLIC_ENTRY BrMatrix4Identity(br_matrix4 *mat) +{ + M(0, 0) = S1; + M(0, 1) = S0; + M(0, 2) = S0; + M(0, 3) = S0; + M(1, 0) = S0; + M(1, 1) = S1; + M(1, 2) = S0; + M(1, 3) = S0; + M(2, 0) = S0; + M(2, 1) = S0; + M(2, 2) = S1; + M(2, 3) = S0; + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; + M(3, 3) = S1; +} + +void BR_PUBLIC_ENTRY BrMatrix4Scale(br_matrix4 *mat, br_scalar sx, br_scalar sy, br_scalar sz) +{ + M(0, 0) = sx; + M(0, 1) = S0; + M(0, 2) = S0; + M(0, 3) = S0; + M(1, 0) = S0; + M(1, 1) = sy; + M(1, 2) = S0; + M(1, 3) = S0; + M(2, 0) = S0; + M(2, 1) = S0; + M(2, 2) = sz; + M(2, 3) = S0; + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; + M(3, 3) = S1; +} + +/* + * Invert a 4x4 matrix: + * -1 + * A = B + * + * Based on "Matrix Inversion" by Richard Carling - Graphics Gems pg. 470 + * + * returns the determinant + */ +br_scalar BR_PUBLIC_ENTRY BrMatrix4Inverse(br_matrix4 *A, br_matrix4 *B) +{ + int i, j; + br_scalar det, idet; + + /* calculate the adjoint matrix */ + + BrMatrix4Adjoint(A, B); + + /* + * Calculate the 4x4 determinant + * if the determinant is zero, + * then the inverse matrix is not unique. + */ + + det = BrMatrix4Determinant(B); + + if (BR_ABS(det) < BR_SCALAR_EPSILON * 2) + return S0; + + /* + * Scale the adjoint matrix to get the inverse + */ + idet = BR_RCP(det); + + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) + A(i, j) = BR_MUL(A(i, j), idet); + + return det; +} + +#define DETERMINANT2(a, b, c, d) BR_MAC2((a), (d), -(b), (c)) + +static br_scalar Determinant3(br_scalar a1, br_scalar a2, br_scalar a3, br_scalar b1, br_scalar b2, br_scalar b3, + br_scalar c1, br_scalar c2, br_scalar c3) +{ + return BR_MAC3(a1, DETERMINANT2(b2, b3, c2, c3), -b1, DETERMINANT2(a2, a3, c2, c3), c1, + DETERMINANT2(a2, a3, b2, b3)); +} + +/* + * return determinant(mat) + * + */ +br_scalar BR_PUBLIC_ENTRY BrMatrix4Determinant(br_matrix4 *mat) +{ + br_scalar a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4; + + a1 = M(0, 0); + b1 = M(0, 1); + c1 = M(0, 2); + d1 = M(0, 3); + + a2 = M(1, 0); + b2 = M(1, 1); + c2 = M(1, 2); + d2 = M(1, 3); + + a3 = M(2, 0); + b3 = M(2, 1); + c3 = M(2, 2); + d3 = M(2, 3); + + a4 = M(3, 0); + b4 = M(3, 1); + c4 = M(3, 2); + d4 = M(3, 3); + + return BR_MAC4( + a1, Determinant3(b2, b3, b4, c2, c3, c4, d2, d3, d4), -b1, Determinant3(a2, a3, a4, c2, c3, c4, d2, d3, d4), c1, + Determinant3(a2, a3, a4, b2, b3, b4, d2, d3, d4), -d1, Determinant3(a2, a3, a4, b2, b3, b4, c2, c3, c4)); +} + +/* + * A = adjoint(B) + */ + +void BR_PUBLIC_ENTRY BrMatrix4Adjoint(br_matrix4 *A, br_matrix4 *B) +{ + br_scalar a1, a2, a3, a4, b1, b2, b3, b4; + br_scalar c1, c2, c3, c4, d1, d2, d3, d4; + + a1 = B(0, 0); + b1 = B(0, 1); + c1 = B(0, 2); + d1 = B(0, 3); + + a2 = B(1, 0); + b2 = B(1, 1); + c2 = B(1, 2); + d2 = B(1, 3); + + a3 = B(2, 0); + b3 = B(2, 1); + c3 = B(2, 2); + d3 = B(2, 3); + + a4 = B(3, 0); + b4 = B(3, 1); + c4 = B(3, 2); + d4 = B(3, 3); + + /* row column labeling reversed since we transpose rows & columns */ + + A(0, 0) = Determinant3(b2, b3, b4, c2, c3, c4, d2, d3, d4); + A(1, 0) = -Determinant3(a2, a3, a4, c2, c3, c4, d2, d3, d4); + A(2, 0) = Determinant3(a2, a3, a4, b2, b3, b4, d2, d3, d4); + A(3, 0) = -Determinant3(a2, a3, a4, b2, b3, b4, c2, c3, c4); + + A(0, 1) = -Determinant3(b1, b3, b4, c1, c3, c4, d1, d3, d4); + A(1, 1) = Determinant3(a1, a3, a4, c1, c3, c4, d1, d3, d4); + A(2, 1) = -Determinant3(a1, a3, a4, b1, b3, b4, d1, d3, d4); + A(3, 1) = Determinant3(a1, a3, a4, b1, b3, b4, c1, c3, c4); + + A(0, 2) = Determinant3(b1, b2, b4, c1, c2, c4, d1, d2, d4); + A(1, 2) = -Determinant3(a1, a2, a4, c1, c2, c4, d1, d2, d4); + A(2, 2) = Determinant3(a1, a2, a4, b1, b2, b4, d1, d2, d4); + A(3, 2) = -Determinant3(a1, a2, a4, b1, b2, b4, c1, c2, c4); + + A(0, 3) = -Determinant3(b1, b2, b3, c1, c2, c3, d1, d2, d3); + A(1, 3) = Determinant3(a1, a2, a3, c1, c2, c3, d1, d2, d3); + A(2, 3) = -Determinant3(a1, a2, a3, b1, b2, b3, d1, d2, d3); + A(3, 3) = Determinant3(a1, a2, a3, b1, b2, b3, c1, c2, c3); +} + +/* + * Generate a perspective tranform + * + */ +void BR_PUBLIC_ENTRY BrMatrix4Perspective(br_matrix4 *mat, br_angle field_of_view, br_scalar aspect, br_scalar hither, + br_scalar yon) +{ + br_scalar scale = BR_DIV(BR_COS((br_angle)(field_of_view / 2)), BR_SIN((br_angle)(field_of_view / 2))); + + M(0, 0) = BR_DIV(scale, aspect); + M(1, 1) = scale; + M(2, 2) = BR_DIV((yon + hither), (yon - hither)); + M(3, 2) = BR_CONST_MUL(BR_MULDIV(yon, hither, (yon - hither)), -2); + + M(0, 1) = S0; + M(0, 2) = S0; + M(0, 3) = S0; + M(1, 0) = S0; + M(1, 2) = S0; + M(1, 3) = S0; + M(2, 0) = S0; + M(2, 1) = S0; + M(2, 3) = BR_SCALAR(-1); + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 3) = S0; +} + +/* + * vec_a = vec_b * mat + */ +void BR_PUBLIC_ENTRY BrMatrix4Apply(br_vector4 *A, br_vector4 *B, br_matrix4 *C) +{ + A->v[0] = BR_MAC4(B->v[0], C(0, 0), B->v[1], C(1, 0), B->v[2], C(2, 0), B->v[3], C(3, 0)); + A->v[1] = BR_MAC4(B->v[0], C(0, 1), B->v[1], C(1, 1), B->v[2], C(2, 1), B->v[3], C(3, 1)); + A->v[2] = BR_MAC4(B->v[0], C(0, 2), B->v[1], C(1, 2), B->v[2], C(2, 2), B->v[3], C(3, 2)); + A->v[3] = BR_MAC4(B->v[0], C(0, 3), B->v[1], C(1, 3), B->v[2], C(2, 3), B->v[3], C(3, 3)); +} + +/* + * [a b c d] = [ e f g 1 ] . M + */ +void BR_PUBLIC_ENTRY BrMatrix4ApplyP(br_vector4 *A, br_vector3 *B, br_matrix4 *C) +{ + A->v[0] = BR_MAC3(B->v[0], C(0, 0), B->v[1], C(1, 0), B->v[2], C(2, 0)) + C(3, 0); + A->v[1] = BR_MAC3(B->v[0], C(0, 1), B->v[1], C(1, 1), B->v[2], C(2, 1)) + C(3, 1); + A->v[2] = BR_MAC3(B->v[0], C(0, 2), B->v[1], C(1, 2), B->v[2], C(2, 2)) + C(3, 2); + A->v[3] = BR_MAC3(B->v[0], C(0, 3), B->v[1], C(1, 3), B->v[2], C(2, 3)) + C(3, 3); +} + +/* + * [a b c d] = [ e f g 0 ] . M + */ +void BR_PUBLIC_ENTRY BrMatrix4ApplyV(br_vector4 *A, br_vector3 *B, br_matrix4 *C) +{ + A->v[0] = BR_MAC3(B->v[0], C(0, 0), B->v[1], C(1, 0), B->v[2], C(2, 0)); + A->v[1] = BR_MAC3(B->v[0], C(0, 1), B->v[1], C(1, 1), B->v[2], C(2, 1)); + A->v[2] = BR_MAC3(B->v[0], C(0, 2), B->v[1], C(1, 2), B->v[2], C(2, 2)); + A->v[3] = BR_MAC3(B->v[0], C(0, 3), B->v[1], C(1, 3), B->v[2], C(2, 3)); +} + +/* + * vec_a = vec_b * mat + */ +void BR_PUBLIC_ENTRY BrMatrix4TApply(br_vector4 *A, br_vector4 *B, br_matrix4 *C) +{ + A->v[0] = BR_MAC4(B->v[0], C(0, 0), B->v[1], C(0, 1), B->v[2], C(0, 2), B->v[3], C(0, 3)); + A->v[1] = BR_MAC4(B->v[0], C(1, 0), B->v[1], C(1, 1), B->v[2], C(1, 2), B->v[3], C(1, 3)); + A->v[2] = BR_MAC4(B->v[0], C(2, 0), B->v[1], C(2, 1), B->v[2], C(2, 2), B->v[3], C(2, 3)); + A->v[3] = BR_MAC4(B->v[0], C(3, 0), B->v[1], C(3, 1), B->v[2], C(3, 2), B->v[3], C(3, 3)); +} + +/* + * [a b c d] = [ e f g 1 ] . M + */ +void BR_PUBLIC_ENTRY BrMatrix4TApplyP(br_vector4 *A, br_vector3 *B, br_matrix4 *C) +{ + A->v[0] = BR_MAC3(B->v[0], C(0, 0), B->v[1], C(0, 1), B->v[2], C(0, 2)) + C(0, 3); + A->v[1] = BR_MAC3(B->v[0], C(1, 0), B->v[1], C(1, 1), B->v[2], C(1, 2)) + C(1, 3); + A->v[2] = BR_MAC3(B->v[0], C(2, 0), B->v[1], C(2, 1), B->v[2], C(2, 2)) + C(2, 3); + A->v[3] = BR_MAC3(B->v[0], C(3, 0), B->v[1], C(3, 1), B->v[2], C(3, 2)) + C(3, 3); +} + +/* + * [a b c d] = [ e f g 0 ] . M + */ +void BR_PUBLIC_ENTRY BrMatrix4TApplyV(br_vector4 *A, br_vector3 *B, br_matrix4 *C) +{ + A->v[0] = BR_MAC3(B->v[0], C(0, 0), B->v[1], C(0, 1), B->v[2], C(0, 2)); + A->v[1] = BR_MAC3(B->v[0], C(1, 0), B->v[1], C(1, 1), B->v[2], C(1, 2)); + A->v[2] = BR_MAC3(B->v[0], C(2, 0), B->v[1], C(2, 1), B->v[2], C(2, 2)); + A->v[3] = BR_MAC3(B->v[0], C(3, 0), B->v[1], C(3, 1), B->v[2], C(3, 2)); +} + +void BR_PUBLIC_ENTRY BrMatrix4Copy34(br_matrix4 *A, br_matrix34 *B) +{ + A(0, 0) = B(0, 0); + A(0, 1) = B(0, 1); + A(0, 2) = B(0, 2); + A(1, 0) = B(1, 0); + A(1, 1) = B(1, 1); + A(1, 2) = B(1, 2); + A(2, 0) = B(2, 0); + A(2, 1) = B(2, 1); + A(2, 2) = B(2, 2); + A(3, 0) = B(3, 0); + A(3, 1) = B(3, 1); + A(3, 2) = B(3, 2); + A(0, 3) = S0; + A(1, 3) = S0; + A(2, 3) = S0; + A(3, 3) = S1; +} + +/** + ** Private functions + **/ + +/* + * A = A*C + */ +void BR_PUBLIC_ENTRY BrMatrix4Pre34(br_matrix4 *A, br_matrix34 *B) +{ + br_matrix4 C = *A; +#define _C(x, y) C.m[x][y] + + A(0, 0) = BR_MAC3(B(0, 0), _C(0, 0), B(0, 1), _C(1, 0), B(0, 2), _C(2, 0)); + A(0, 1) = BR_MAC3(B(0, 0), _C(0, 1), B(0, 1), _C(1, 1), B(0, 2), _C(2, 1)); + A(0, 2) = BR_MAC3(B(0, 0), _C(0, 2), B(0, 1), _C(1, 2), B(0, 2), _C(2, 2)); + A(0, 3) = BR_MAC3(B(0, 0), _C(0, 3), B(0, 1), _C(1, 3), B(0, 2), _C(2, 3)); + + A(1, 0) = BR_MAC3(B(1, 0), _C(0, 0), B(1, 1), _C(1, 0), B(1, 2), _C(2, 0)); + A(1, 1) = BR_MAC3(B(1, 0), _C(0, 1), B(1, 1), _C(1, 1), B(1, 2), _C(2, 1)); + A(1, 2) = BR_MAC3(B(1, 0), _C(0, 2), B(1, 1), _C(1, 2), B(1, 2), _C(2, 2)); + A(1, 3) = BR_MAC3(B(1, 0), _C(0, 3), B(1, 1), _C(1, 3), B(1, 2), _C(2, 3)); + + A(2, 0) = BR_MAC3(B(2, 0), _C(0, 0), B(2, 1), _C(1, 0), B(2, 2), _C(2, 0)); + A(2, 1) = BR_MAC3(B(2, 0), _C(0, 1), B(2, 1), _C(1, 1), B(2, 2), _C(2, 1)); + A(2, 2) = BR_MAC3(B(2, 0), _C(0, 2), B(2, 1), _C(1, 2), B(2, 2), _C(2, 2)); + A(2, 3) = BR_MAC3(B(2, 0), _C(0, 3), B(2, 1), _C(1, 3), B(2, 2), _C(2, 3)); + + A(3, 0) = BR_MAC3(B(3, 0), _C(0, 0), B(3, 1), _C(1, 0), B(3, 2), _C(2, 0)) + _C(3, 0); + A(3, 1) = BR_MAC3(B(3, 0), _C(0, 1), B(3, 1), _C(1, 1), B(3, 2), _C(2, 1)) + _C(3, 1); + A(3, 2) = BR_MAC3(B(3, 0), _C(0, 2), B(3, 1), _C(1, 2), B(3, 2), _C(2, 2)) + _C(3, 2); + A(3, 3) = BR_MAC3(B(3, 0), _C(0, 3), B(3, 1), _C(1, 3), B(3, 2), _C(2, 3)) + _C(3, 3); +} diff --git a/bren/FW/matrixc.c b/bren/FW/matrixc.c new file mode 100644 index 00000000..58ff34f5 --- /dev/null +++ b/bren/FW/matrixc.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: matrixc.c 1.2 1995/02/22 21:42:12 sam Exp $ + * $Locker: $ + * + * Composite matrix operations - pre and post-multiply with an existing matrix + */ + +#include "fw.h" +#include "shortcut.h" + +static char rscid[] = "$Id: matrixc.c 1.2 1995/02/22 21:42:12 sam Exp $"; + +/** + ** 3x4 Transforms + **/ + +static br_matrix34 mattmp1, mattmp2; + +void BR_PUBLIC_ENTRY BrMatrix34Pre(br_matrix34 *mat, br_matrix34 *A) +{ + BrMatrix34Mul(&mattmp2, A, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34Post(br_matrix34 *mat, br_matrix34 *A) +{ + BrMatrix34Mul(&mattmp2, mat, A); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreRotateX(br_matrix34 *mat, br_angle rx) +{ + BrMatrix34RotateX(&mattmp1, rx); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostRotateX(br_matrix34 *mat, br_angle rx) +{ + BrMatrix34RotateX(&mattmp1, rx); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreRotateY(br_matrix34 *mat, br_angle ry) +{ + BrMatrix34RotateY(&mattmp1, ry); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostRotateY(br_matrix34 *mat, br_angle ry) +{ + BrMatrix34RotateY(&mattmp1, ry); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreRotateZ(br_matrix34 *mat, br_angle rz) +{ + BrMatrix34RotateZ(&mattmp1, rz); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostRotateZ(br_matrix34 *mat, br_angle rz) +{ + BrMatrix34RotateZ(&mattmp1, rz); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreRotate(br_matrix34 *mat, br_angle r, br_vector3 *axis) +{ + BrMatrix34Rotate(&mattmp1, r, axis); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostRotate(br_matrix34 *mat, br_angle r, br_vector3 *axis) +{ + BrMatrix34Rotate(&mattmp1, r, axis); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreTranslate(br_matrix34 *mat, br_scalar x, br_scalar y, br_scalar z) +{ + BrMatrix34Translate(&mattmp1, x, y, z); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostTranslate(br_matrix34 *mat, br_scalar x, br_scalar y, br_scalar z) +{ + BrMatrix34Translate(&mattmp1, x, y, z); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreScale(br_matrix34 *mat, br_scalar sx, br_scalar sy, br_scalar sz) +{ + BrMatrix34Scale(&mattmp1, sx, sy, sz); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostScale(br_matrix34 *mat, br_scalar sx, br_scalar sy, br_scalar sz) +{ + BrMatrix34Scale(&mattmp1, sx, sy, sz); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreShearX(br_matrix34 *mat, br_scalar sy, br_scalar sz) +{ + BrMatrix34ShearX(&mattmp1, sy, sz); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostShearX(br_matrix34 *mat, br_scalar sy, br_scalar sz) +{ + BrMatrix34ShearX(&mattmp1, sy, sz); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreShearY(br_matrix34 *mat, br_scalar sx, br_scalar sz) +{ + BrMatrix34ShearY(&mattmp1, sx, sz); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostShearY(br_matrix34 *mat, br_scalar sx, br_scalar sz) +{ + BrMatrix34ShearY(&mattmp1, sx, sz); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PreShearZ(br_matrix34 *mat, br_scalar sx, br_scalar sy) +{ + BrMatrix34ShearZ(&mattmp1, sx, sy); + BrMatrix34Mul(&mattmp2, &mattmp1, mat); + BrMatrix34Copy(mat, &mattmp2); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostShearZ(br_matrix34 *mat, br_scalar sx, br_scalar sy) +{ + BrMatrix34ShearZ(&mattmp1, sx, sy); + BrMatrix34Mul(&mattmp2, mat, &mattmp1); + BrMatrix34Copy(mat, &mattmp2); +} diff --git a/bren/FW/mem.c b/bren/FW/mem.c new file mode 100644 index 00000000..decebdd2 --- /dev/null +++ b/bren/FW/mem.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: mem.c 1.5 1995/02/22 21:42:13 sam Exp $ + * $Locker: $ + * + * Low level wrappers for allocator access + */ +#include +#include + +#include "fw.h" +#include "brassert.h" + +#define MEM_LOG 0 + +void *BR_PUBLIC_ENTRY BrMemAllocate(br_size_t size, br_uint_8 type) +{ + void *b; + br_uint_32 up; + + UASSERT(fw.resource_class_index[type] != NULL); + + ASSERT(fw.mem->allocate != NULL); + + b = fw.mem->allocate(size, type); + +#if MEM_LOG + BrLogPrintf("BrMemAllocate(%d,%s) = %p\n", size, fw.resource_class_index[type]->identifier, b); +#endif + + /* + * Clear block + */ + memset(b, 0, size); + + return b; +} + +void BR_PUBLIC_ENTRY BrMemFree(void *block) +{ + UASSERT(block != NULL); + +#if 0 + /* + * Breaks the modularity a bit - but make sure + * we are not trying to free a resource + */ + UASSERT(!BrResCheck(block,0)); +#endif + +#if MEM_LOG + BrLogPrintf("BrMemFree(%p)\n", block); +#endif + + ASSERT(fw.mem->free != NULL); + + fw.mem->free(block); +} + +br_size_t BR_PUBLIC_ENTRY BrMemInquire(br_uint_8 type) +{ + br_size_t i; + + UASSERT(fw.resource_class_index[type] != NULL); + + ASSERT(fw.mem->inquire != NULL); + + i = fw.mem->inquire(type); + +#if MEM_LOG + BrLogPrintf("BrMemInquire(%s) = %d\n", fw.resource_class_index[type]->identifier, i); +#endif + + return i; +} + +/* + * calloc() equivalent + */ +void *BR_PUBLIC_ENTRY BrMemCalloc(int nelems, br_size_t size, br_uint_8 type) +{ + void *b; + + UASSERT(fw.resource_class_index[type] != NULL); + + ASSERT(fw.mem->allocate != NULL); + + b = fw.mem->allocate(size * nelems, type); + memset(b, 0, size * nelems); + +#if MEM_LOG + BrLogPrintf("BrMemCalloc(%d,%d,%s) = %p\n", nelems, size, fw.resource_class_index[type]->identifier, b); +#endif + + return b; +} + +/* + * strdup() equivalent + */ +char *BR_PUBLIC_ENTRY BrMemStrDup(char *str) +{ + int l; + char *nstr; + + UASSERT(str != NULL); + + l = strlen(str); + +#if MEM_LOG + BrLogPrintf("BrMemStrDup(%s)\n", str); +#endif + + nstr = BrMemAllocate(l + 1, BR_MEMORY_STRING); + + strcpy(nstr, str); + + return nstr; +} diff --git a/bren/FW/memloops.c b/bren/FW/memloops.c new file mode 100644 index 00000000..c75b3638 --- /dev/null +++ b/bren/FW/memloops.c @@ -0,0 +1,261 @@ +#include +#include +#include + +#include + +static br_uint_8 const __bit_to_mask_s[] = { + 0b11111111, 0b01111111, 0b00111111, 0b00011111, 0b00001111, 0b00000111, 0b00000011, 0b00000001, 0b00000000, +}; + +static br_uint_8 const __bit_to_mask_e[] = { + 0b00000000, 0b10000000, 0b11000000, 0b11100000, 0b11110000, 0b11111000, 0b11111100, 0b11111110, 0b11111111, +}; + +void BR_ASM_CALL _MemPixelSet(char *dest, br_uint_32 bytes, br_uint_32 colour) +{ + br_uint_32 *dword_dest = (br_uint_32 *)dest; + + br_uint_32 const bit0 = bytes * CHAR_BIT; + br_uint_32 const bit1 = sizeof(*dword_dest) * CHAR_BIT; + + br_uint_32 mask = ((1 << bit0) - 1) << (bit1 - bit0); + + *dword_dest &= ~mask; + *dword_dest |= colour & mask; +} + +br_uint_32 BR_ASM_CALL _MemPixelGet(char *dest, br_uint_32 bytes) +{ + br_uint_32 *dword_dest = (br_uint_32 *)dest; + + br_uint_32 bit0 = bytes * CHAR_BIT; + br_uint_32 bit1 = sizeof(*dword_dest) * CHAR_BIT; + br_uint_32 mask = ((1 << bit0) - 1) << (bit1 - bit0); + + br_uint_32 pixel = *dword_dest; + return pixel & mask; +} + +void BR_ASM_CALL _MemCopy_A(char *dest, char *src, br_uint_32 pixels, br_uint_32 bpp) +{ + br_uint_32 stride = pixels * bpp; + + union { + char *ptr; + uintptr_t value; + br_int_32 *u32; + } __dest = {.ptr = dest}, __src = {.ptr = src}; + + while ((__dest.value & 3) != 0) + { + *__dest.ptr = *__src.ptr; + __dest.ptr++; + __src.ptr++; + } + + stride /= sizeof(*__src.u32); + for (br_uint_32 i = 0; i < stride; i += bpp) + { + *__dest.u32 = *__src.u32; + __dest.ptr += bpp; + __src.ptr += bpp; + } + + while (((uintptr_t)stride & 3) != 0) + { + *__dest.ptr = *__src.ptr; + __dest.ptr++; + __src.ptr++; + stride--; + } +} + +void BR_ASM_CALL _MemFill_A(char *dest, br_uint_32 pixels, br_uint_32 bpp, br_uint_32 colour) +{ + union { + char *ptr; + br_uint_8 *u8; + br_uint_16 *u16; + br_uint_32 *u32; + } __dest = {.ptr = dest}; + + br_uint_32 mono = (0x01010101 * (colour & 0xFF)) & ((1 << (bpp * CHAR_BIT)) - 1); + if (bpp == 1 || colour == mono) + { + memset(dest, colour, pixels * bpp); + } + else if (bpp == 2) + { + for (br_size_t i = 0; i < pixels; i++) + { + __dest.u16[i] = colour; + } + } + else if (bpp == 3) + { + for (br_size_t i = 0; i < pixels; i += 3) + { + __dest.u8[i] = colour >> 16; + __dest.u8[i + 1] = colour >> 8; + __dest.u8[i + 2] = colour; + } + } + else + { + for (br_size_t i = 0; i < pixels; i++) + { + __dest.u32[i] = colour; + } + } +} + +void BR_ASM_CALL _MemRectCopy_A(char *dest, char *src, br_uint_32 pwidth, br_uint_32 pheight, br_int_32 d_stride, + br_int_32 s_stride, br_uint_32 bpp) +{ + br_uint_32 const line_diff = pwidth * bpp; + + d_stride -= line_diff; + s_stride -= line_diff; + + for (br_uint_32 i = 0; i < pheight; i++) + { + _MemCopy_A(dest, src, pwidth, bpp); + dest += d_stride; + src += s_stride; + } +} + +void BR_ASM_CALL _MemRectFill_A(char *dest, br_uint_32 pwidth, br_uint_32 pheight, br_int_32 d_stride, br_uint_32 bpp, + br_uint_32 colour) +{ + br_uint_32 const line_diff = pwidth * bpp; + d_stride -= line_diff; + + for (br_uint_32 i = 0; i < pheight; i++) + { + _MemFill_A(dest, pwidth, bpp, colour); + dest += d_stride; + } +} + +static inline void __COPY_BITS_CORE_N(char *dest, br_int_32 d_stride, br_uint_8 *src, br_uint_32 s_stride, + br_uint_8 mask_s, br_uint_8 mask_e, br_uint_32 nrows, br_uint_32 bpp, + br_uint_32 colour) +{ + // TODO(bjrkk): Get this one properly sorted out as it is currently broken + do + { + br_int_32 bppt = bpp; + br_uint_8 src_byte = *src & mask_s; + + while (bppt >= 0) + { + char *curr_dest = dest; + + if (bppt == 0) + { + src_byte &= mask_e; + } + else + { + src++; + } + + for (int x = 0; x < CHAR_BIT; x++) + { + if (!__BrBuiltinAddU8Overflow(src_byte, src_byte, &src_byte)) + { + continue; + } + if (bpp == 1) + { + curr_dest[x * bpp] = (colour & 0xFF); + } + else if (bpp == 2) + { + curr_dest[x * bpp + 0] = (colour & 0xFF00) >> 8; + curr_dest[x * bpp + 1] = (colour & 0x00FF); + } + else if (bpp == 3) + { + curr_dest[x * bpp + 0] = (colour & 0xFF0000) >> 16; + curr_dest[x * bpp + 1] = (colour & 0x00FF00) >> 8; + curr_dest[x * bpp + 2] = (colour & 0x0000FF); + } + else if (bpp == 4) + { + br_uint_32 *dword_dest = (br_uint_32 *)curr_dest; + dword_dest[x] = colour; + } + } + + src_byte = *src; + curr_dest += CHAR_BIT * bpp; + bppt--; + } + + dest += d_stride; + src += s_stride; + nrows--; + } while (nrows > 0); +} + +static inline void __COPY_BITS_CORE_1(char *dest, br_int_32 d_stride, br_uint_8 *src, br_uint_32 s_stride, + br_uint_8 mask_s, br_uint_8 mask_e, br_uint_32 nrows, br_uint_32 bpp, + br_uint_32 colour) +{ + br_uint_8 mask_combined = mask_s & mask_e; + + do + { + br_uint_8 src_byte = *src & mask_combined; + for (int x = 0; x < CHAR_BIT; x++) + { + if (!__BrBuiltinAddU8Overflow(src_byte, src_byte, &src_byte)) + { + continue; + } + if (bpp == 1) + { + dest[x * bpp] = (colour & 0xFF); + } + else if (bpp == 2) + { + dest[x * bpp + 0] = (colour & 0xFF00) >> 8; + dest[x * bpp + 1] = (colour & 0x00FF); + } + else if (bpp == 3) + { + dest[x * bpp + 0] = (colour & 0xFF0000) >> 16; + dest[x * bpp + 1] = (colour & 0x00FF00) >> 8; + dest[x * bpp + 2] = (colour & 0x0000FF); + } + else if (bpp == 4) + { + br_uint_32 *dword_dest = (br_uint_32 *)dest; + dword_dest[x] = colour; + } + } + dest += d_stride; + src += s_stride; + nrows--; + } while (nrows > 0); +} + +void BR_ASM_CALL _MemCopyBits_A(char *dest, br_int_32 d_stride, br_uint_8 *src, br_uint_32 s_stride, + br_uint_32 start_bit, br_uint_32 end_bit, br_uint_32 nrows, br_uint_32 bpp, + br_uint_32 colour) +{ + br_uint_8 mask_s = __bit_to_mask_s[start_bit & 7]; + br_uint_8 mask_e = __bit_to_mask_e[end_bit & 7]; + + if ((end_bit >> 3) != 0) + { + __COPY_BITS_CORE_N(dest, d_stride, src, s_stride, mask_s, mask_e, nrows, bpp, colour); + } + else + { + __COPY_BITS_CORE_1(dest, d_stride, src, s_stride, mask_s, mask_e, nrows, bpp, colour); + } +} \ No newline at end of file diff --git a/bren/FW/ofileops.c b/bren/FW/ofileops.c new file mode 100644 index 00000000..8d0c8846 --- /dev/null +++ b/bren/FW/ofileops.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: ofileops.c 1.5 1995/02/22 21:42:15 sam Exp $ + * $Locker: $ + * + * $ BC<"make -f makefile.wtc %s.pp;"> + * + * Out of date file operations + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "brender.h" +#include "brhton.h" +#include "animate.h" +#include "datafile.h" + +static char rscid[] = "$Id: ofileops.c 1.5 1995/02/22 21:42:15 sam Exp $"; + +/* + * For digging around in points etc - makes things slightly easier to read + */ +#define X 0 +#define Y 1 +#define Z 2 +#define W 3 + +#define U 0 +#define V 1 + +#if 0 +/* + * File structures + */ +typedef struct br_file_info { + br_int_32 type; + br_int_32 version; +} br_file_info; + +typedef struct br_chunk_header { + br_int_32 id; + br_int_32 length; +} br_chunk_header; + +typedef struct br_file_pixmap { + br_int_32 width; + br_int_32 height; +} br_file_pixmap; + +typedef struct br_file_material { + /* */ + br_uint_16 flags; + + br_float red; + br_float green; + br_float blue; + + br_float ka; + br_float kd; + br_float ks; + + br_float opacity; + + char identifier[1]; +} br_file_material; + +typedef struct br_file_actor_data { + char identifier[16]; + long type; + br_float matrix34[4][3]; +} br_file_actor_data; + +typedef struct br_file_actor { + /* */ + + br_file_actor_data file; + + struct br_file_actor *prev; + struct br_file_actor *next; + struct br_file_actor *child; + struct br_file_actor *sibling; + struct br_file_actor *parent; +} br_file_actor; + +typedef struct br_file_animation { + br_float matrix[4][4]; +} br_file_animation; + +typedef struct br_file_anim { + /* */ + + char *identifier; + struct br_animation *frames; +} br_file_anim ; + +typedef struct br_file_model { + /* */ + char identifier[1]; +} br_file_model; + +typedef struct br_file_vertex { + br_float x; + br_float y; + br_float z; +} br_file_vertex; + +typedef struct br_file_vertex_uv { + br_float x; + br_float y; + br_float z; + br_float u; + br_float v; +} br_file_vertex_uv; + +typedef struct br_file_face { + br_uint_16 v1; + br_uint_16 v2; + br_uint_16 v3; + + br_uint_16 material; + br_uint_32 smoothing; +} br_file_face; +#endif + +extern br_animation *anim[20]; + +br_model *objects[50]; + +/* + * Read animation frames from the file. + */ +int BR_PUBLIC_ENTRY BrOldAnimLoad(char *filename, br_animation ***anim, int *num_frames, br_model **objects) +{ + int count = 0; + int frame = 0, num = 0; + br_animation *temp; + br_animation **frames; + FILE *fp; + char *name; + + fp = FOPEN(filename, "rb"); + + for (;;) + { + if (DfDataInterpret(fread, fseek, fp) == 0) + break; + + temp = (br_animation *)DfPop(DFST_ANIM_TRANSFORM, &count); + NEW_PTR_N(frames, count + 1); + *num_frames = count; + while (count > 0) + { + frames[count] = temp; + temp = (br_animation *)DfPop(DFST_ANIM_TRANSFORM, &count); + } + frames[count] = temp; + name = (char *)DfPop(DFST_ANIM_NAME, NULL); + count = BrActorFind(name, objects); + + if (count >= 0) + anim[count] = frames; + num++; + } + + FCLOSE(fp); + + return num; +} + +/* + * Find the named model in the renderer's current set, return Model pointer + */ +br_model *BR_PUBLIC_ENTRY BrOldModelFind(char *name, br_model **objects) +{ + int i; + for (i = 1; objects[i]; i++) + if (strcmp(name, objects[i]->identifier) == 0) + return objects[i]; + return objects[0]; +} + +/* + * Find the named model in the renderer's current set, return Actor index + */ +br_uint_32 BR_PUBLIC_ENTRY BrOldActorFind(char *name, br_model **objects) +{ + int i; + for (i = 0; objects[i]; i++) + if (strncmp(name, objects[i]->identifier, 10) == 0) + return i; + return -1; +} + +/* + * read file type of a file from the p3d_file_info block + * a file + */ +br_uint_32 BR_PUBLIC_ENTRY BrOldTypeRead(char *filename) +{ + br_file_info *info; + FILE *fp; + + fp = FOPEN(filename, "rb"); + DfTypeInterpret(fread, fseek, fp); + info = (br_file_info *)DfPop(DFST_FILE_INFO, NULL); + FCLOSE(fp); + + return info->type; +} diff --git a/bren/FW/onscreen.c b/bren/FW/onscreen.c new file mode 100644 index 00000000..7774dc01 --- /dev/null +++ b/bren/FW/onscreen.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: onscreen.c 1.9 1995/02/22 21:42:16 sam Exp $ + * $Locker: $ + * + */ +#include "fw.h" +#include "brassert.h" +#include "shortcut.h" + +static char rscid[] = "$Id: onscreen.c 1.9 1995/02/22 21:42:16 sam Exp $"; + +/* + * Check the model's bounding box against the view volume and return + * one of: + * + * OSC_REJECT - Model is completely off screen + * OSC_PARTIAL - Model is partially on screen + * OSC_ACCEPT - Model is completely on screen + * + * Works by transforming the 6 planes that bound the view volume into + * model space. We have the model_to_screen transfrom. To transform a + * plane (screen to model), use the inverse of the transpose, ie: transpose + * of model_to_screen. Since the view plane equations are just zero's + * and ones, the transformed plane equation can be generated by adds/subs + * of specific rows of the transform. + * + * To test the (axis aligned) box against the view plane, only two vertices + * need testing - those that lie along the diagonal corresponding to the + * direction of the plane's normal. + * + * The components of these test vertices are selected from min/max + * by looking at the sign of the X,Y,Z components of the normal + * + * XXX Could probably write a mean version of this is assembler + */ + +#define MAKE_EQN(sign, row) \ + { \ + eqn.v[X] = fw.model_to_screen.m[0][3] sign fw.model_to_screen.m[0][row]; \ + eqn.v[Y] = fw.model_to_screen.m[1][3] sign fw.model_to_screen.m[1][row]; \ + eqn.v[Z] = fw.model_to_screen.m[2][3] sign fw.model_to_screen.m[2][row]; \ + eqn.v[W] = -(fw.model_to_screen.m[3][3] sign fw.model_to_screen.m[3][row]); \ + } + +#define TEST_NOT_IN \ + (BR_MAC3(eqn.v[X], ((eqn.v[X] > 0) ? (bounds->min.v[X]) : (bounds->max.v[X])), eqn.v[Y], \ + ((eqn.v[Y] > 0) ? (bounds->min.v[Y]) : (bounds->max.v[Y])), eqn.v[Z], \ + ((eqn.v[Z] > 0) ? (bounds->min.v[Z]) : (bounds->max.v[Z]))) < eqn.v[W]) + +#define TEST_OUT \ + (BR_MAC3(eqn.v[X], ((eqn.v[X] > 0) ? (bounds->max.v[X]) : (bounds->min.v[X])), eqn.v[Y], \ + ((eqn.v[Y] > 0) ? (bounds->max.v[Y]) : (bounds->min.v[Y])), eqn.v[Z], \ + ((eqn.v[Z] > 0) ? (bounds->max.v[Z]) : (bounds->min.v[Z]))) < eqn.v[W]) + +br_uint_8 BR_PUBLIC_ENTRY BrOnScreenCheck(br_bounds *bounds) +{ + int accept = 1; + br_vector4 eqn; + int c; + + UASSERT(fw.rendering); + + /* + * Left - screen space plane eqn. = ( 1, 0, 0, 1) + */ + MAKE_EQN(+, 0); + + if (TEST_OUT) + return OSC_REJECT; + + if (TEST_NOT_IN) + accept = 0; + + /* + * Right - screen space plane eqn. = (-1, 0, 0, 1) + */ + MAKE_EQN(-, 0); + + if (TEST_OUT) + return OSC_REJECT; + + if (accept && TEST_NOT_IN) + accept = 0; + + /* + * Bottom - screen space plane eqn. = ( 0, 1, 0, 1) + */ + MAKE_EQN(+, 1); + + if (TEST_OUT) + return OSC_REJECT; + + if (accept && TEST_NOT_IN) + accept = 0; + + /* + * Top - screen space plane eqn. = ( 0,-1, 0, 1) + */ + MAKE_EQN(-, 1); + + if (TEST_OUT) + return OSC_REJECT; + + if (accept && TEST_NOT_IN) + accept = 0; + + /* + * Yon - screen space plane eqn. = ( 0, 0, 1, 1) + */ + MAKE_EQN(+, 2); + + if (TEST_OUT) + return OSC_REJECT; + + if (accept && TEST_NOT_IN) + accept = 0; + + /* + * Hither - screen space plane eqn. = ( 0, 0,-1, 0) + */ + eqn.v[X] = -fw.model_to_screen.m[0][2]; + eqn.v[Y] = -fw.model_to_screen.m[1][2]; + eqn.v[Z] = -fw.model_to_screen.m[2][2]; + eqn.v[W] = fw.model_to_screen.m[3][2]; + + if (TEST_OUT) + return OSC_REJECT; + + if (accept && TEST_NOT_IN) + accept = 0; + + /* + * Any user clip planes + */ + for (c = 0; c < fw.nactive_clip_planes; c++) + { + BrMatrix4TApply(&eqn, &fw.active_clip_planes[c].screen_plane, &fw.model_to_screen); + eqn.v[W] = -eqn.v[W]; + + if (TEST_OUT) + return OSC_REJECT; + + if (accept && TEST_NOT_IN) + accept = 0; + } + + return accept ? OSC_ACCEPT : OSC_PARTIAL; +} diff --git a/bren/FW/pick.c b/bren/FW/pick.c new file mode 100644 index 00000000..c16591b5 --- /dev/null +++ b/bren/FW/pick.c @@ -0,0 +1,651 @@ +/* + * Copyright (c) 1994-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: pick.c 1.15 1995/08/31 16:29:36 sam Exp $ + * $Locker: sam $ + * + * Pick traversal and testing + */ +#include "fw.h" +#include "shortcut.h" +#include "brassert.h" + +static char rscid[] = "$Id: pick.c 1.15 1995/08/31 16:29:36 sam Exp $"; + +static br_matrix34 pick_model_to_view; + +/* + * Test a bounding box 'b' against the current pick ray '*rp - t . *rd' + * + * (NB, the direction of the ray is -ve as compared to normal usage) + * + * The active section of the ray is given with t_near and t_far + * + * If the active section of the ray intersets the box, then returns + * TRUE, and stores the new t_near and t_far + */ +static int PickBoundsTestRay(br_bounds *b, br_vector3 *rp, br_vector3 *rd, br_scalar t_near, br_scalar t_far, + br_scalar *new_t_near, br_scalar *new_t_far) +{ + int i; + br_scalar s, t; + + /* + * Find section of ray that intersects bounding box, if any, by + * intersecting the half spaces defined by the bounding planes + * with the ray. + * + * The planes tested against are - + * + * eqn d + * +X 1, 0, 0, -max[0] + * +Y 0, 1, 0, -max[1] + * +Z 0, 0, 1, -max[2] + * -X -1, 0, 0, min[0] + * -Y 0,-1, 0, min[1] + * -Z 0, 0,-1, min[2] + * + * The plane to line intersection is (for a general case) + * + * t = -(d + plane_eqn . position) + * -------------------------- + * plane_eqn . direction + * + * The actual calculations take into acount the special case of the + * equations, and that the direction as passed in is -ve. + * + */ + + /* + * For each axis, examine the slab made by the planes that are normal to it + */ + for (i = 0; i < 3; i++) + { + /* + * See which way ray goes relative to axis + */ + if (rd->v[i] > (2 * BR_SCALAR_EPSILON)) + { + /* + * Positive axis towards ray, negative axis away from ray + */ + s = BR_RCP(rd->v[i]); + + t = BR_MUL(rp->v[i] - b->max.v[i], s); + if (t > t_near) + t_near = t; + + t = BR_MUL(rp->v[i] - b->min.v[i], s); + if (t < t_far) + t_far = t; + } + else if (rd->v[i] < -(2 * BR_SCALAR_EPSILON)) + { + /* + * Positive axis away from ray, negative axis towards ray + */ + s = BR_RCP(rd->v[i]); + + t = BR_MUL(rp->v[i] - b->max.v[i], s); + if (t < t_far) + t_far = t; + + t = BR_MUL(rp->v[i] - b->min.v[i], s); + if (t > t_near) + t_near = t; + } + else + { + /* + * Ray is perp. to axis - check origin vs. both planes + */ + if (rp->v[i] > b->max.v[i] || rp->v[i] < b->min.v[i]) + { + /* + * Ray is outside planes + */ + return 0; + } + } + } + + /* + * If there is any of the ray left, record the near point + * and return true + */ + if (t_near <= t_far) + { + *new_t_near = t_near; + *new_t_far = t_far; + return 1; + } + else + return 0; +} + +/* + * Traversal function for Picking, tests and actor, and recurse for + * children + */ +static int ActorPick2D(br_actor *ap, br_model *model, br_material *material, br_pick2d_cbfn *callback, void *arg) +{ + br_actor *a; + br_model *this_model; + br_material *this_material; + br_matrix34 m_to_v; + br_matrix34 v_to_m; + br_scalar t_near, t_far; + int r = 0; + + this_model = ap->model ? ap->model : model; + this_material = ap->material ? ap->material : material; + + /* + * Concatenate transform of this actor onto current + */ + m_to_v = pick_model_to_view; + BrMatrix34PreTransform(&pick_model_to_view, &ap->t); + + /* + * Investigate this actor + */ + switch (ap->type) + { + + case BR_ACTOR_MODEL: + + /* + * Work out view to model transform and transform + * the pick ray. + * + * The pick ray is (0,0,0) - t . (0,0,1), so + * this coresponds to the fourth and third rows + * of the v_to_m matrix + */ + BrMatrix34Inverse(&v_to_m, &pick_model_to_view); + + if (PickBoundsTestRay(&this_model->bounds, (br_vector3 *)v_to_m.m[3], (br_vector3 *)v_to_m.m[2], BR_SCALAR(0.0), + BR_SCALAR_MAX, &t_near, &t_far)) + { + br_vector3 dir; + dir.v[0] = -v_to_m.m[2][0]; + dir.v[1] = -v_to_m.m[2][1]; + dir.v[2] = -v_to_m.m[2][2]; + /* + * Invoke callback (with correct direction) + */ + r = callback(ap, this_model, this_material, (br_vector3 *)v_to_m.m[3], &dir, t_near, t_far, arg); + if (r) + break; + } + + if (r) + break; + + /* FALL THROUGH */ + default: + BR_FOR_SIMPLELIST(&ap->children, a) + { + r = ActorPick2D(a, this_model, this_material, callback, arg); + if (r) + break; + } + + break; + + case BR_ACTOR_BOUNDS: + case BR_ACTOR_BOUNDS_CORRECT: + /* + * Only recurse to children if view ray intersects bounding box + */ + UASSERT(a->type_data != NULL); + + BrMatrix34Inverse(&v_to_m, &pick_model_to_view); + + if (PickBoundsTestRay(ap->type_data, (br_vector3 *)v_to_m.m[3], (br_vector3 *)v_to_m.m[2], BR_SCALAR(0.0), + BR_SCALAR_MAX, &t_near, &t_far)) + BR_FOR_SIMPLELIST(&ap->children, a) + { + r = ActorPick2D(a, this_model, this_material, callback, arg); + if (r) + break; + } + + break; + } + + /* + * Restore transform + */ + pick_model_to_view = m_to_v; + + return r; +} + +/* + * Pick objects from a given scene by casting a ray through the given + * viewport pixel attached to the given camera. + * + * A callback will be invoked for each actor whose bounds intersect + * this ray. + * + * The callback is given the ray point & direction in the actor's + * local space, and the 't' values of the intersections of the ray + * with the bounding box. + * + * If the callback returns a non-zero value, traversal stops, and the + * value is returned from BrScenePick2D + * + * A general purpose 'void *' argument is passed down to the callback + */ +int BR_PUBLIC_ENTRY BrScenePick2D(br_actor *world, br_actor *camera, br_pixelmap *viewport, int pick_x, int pick_y, + br_pick2d_cbfn *callback, void *arg) +{ + br_matrix34 camera_tfm; + br_scalar scale; + br_camera *camera_data; + + UASSERT(callback != NULL); + + UASSERT(camera->type == BR_ACTOR_CAMERA); + UASSERT(camera->type_data != NULL); + + camera_data = camera->type_data; + + /* + * Build view->world transform + */ + BrActorToRoot(camera, world, &camera_tfm); + BrMatrix34Inverse(&pick_model_to_view, &camera_tfm); + + /* + * Build view to screen transform s.t. ray is along -ve Z axis + * and starts at the origin + * + */ + switch (camera_data->type) + { + + case BR_CAMERA_PERSPECTIVE_FOV: + + scale = BR_DIV(BR_COS((br_angle)(camera_data->field_of_view / 2)), + BR_SIN((br_angle)(camera_data->field_of_view / 2))); + + BrMatrix34PostScale(&pick_model_to_view, BR_DIV(scale, camera_data->aspect), scale, BR_SCALAR(1.0)); + + BrMatrix34PostShearZ(&pick_model_to_view, BR_DIV(BrIntToScalar(2 * pick_x), BrIntToScalar(viewport->width)), + BR_DIV(BrIntToScalar(-2 * pick_y), BrIntToScalar(viewport->height))); + break; + + case BR_CAMERA_PARALLEL: + BrMatrix34PostTranslate(&pick_model_to_view, S0, S0, camera_data->hither_z); + BrMatrix34PostScale(&pick_model_to_view, BR_RCP(camera_data->width), BR_RCP(camera_data->height), + BR_RCP(camera_data->yon_z - camera_data->hither_z)); + + BrMatrix34PostTranslate(&pick_model_to_view, BR_DIV(BrIntToScalar(-2 * pick_x), BrIntToScalar(viewport->width)), + BR_DIV(BrIntToScalar(2 * pick_y), BrIntToScalar(viewport->height)), S0); + + break; + } + /* + * Traverse world + */ + return ActorPick2D(world, fw.default_model, fw.default_material, callback, arg); +} + +/* + * Work out whether two bounding boxes into different coordinate frames + * interset + */ +#define MAKE_EQN(axis, sign, distance) \ + { \ + eqn.v[0] = sign p_to_m.m[0][axis]; \ + eqn.v[1] = sign p_to_m.m[1][axis]; \ + eqn.v[2] = sign p_to_m.m[2][axis]; \ + eqn.v[3] = sign p_to_m.m[3][axis] distance; \ + } + +#define TEST_NOT_IN \ + (BR_MAC3(eqn.v[X], ((eqn.v[X] > 0) ? (bounds->min.v[X]) : (bounds->max.v[X])), eqn.v[Y], \ + ((eqn.v[Y] > 0) ? (bounds->min.v[Y]) : (bounds->max.v[Y])), eqn.v[Z], \ + ((eqn.v[Z] > 0) ? (bounds->min.v[Z]) : (bounds->max.v[Z]))) < eqn.v[W]) + +#define TEST_OUT \ + (BR_MAC3(eqn.v[X], ((eqn.v[X] > 0) ? (bounds->max.v[X]) : (bounds->min.v[X])), eqn.v[Y], \ + ((eqn.v[Y] > 0) ? (bounds->max.v[Y]) : (bounds->min.v[Y])), eqn.v[Z], \ + ((eqn.v[Z] > 0) ? (bounds->max.v[Z]) : (bounds->min.v[Z]))) < eqn.v[W]) + +static int PickBoundsTestBox(br_bounds *model_bounds, br_bounds *bounds, br_matrix34 *m_to_p) +{ + br_matrix34 p_to_m; + br_vector4 eqn; + int i; + + BrMatrix34Inverse(&p_to_m, m_to_p); + + /* + * For each plane of the model box, check to see if the pick box + * is completely outside it + */ + for (i = 0; i < 3; i++) + { + /* + * Min X + */ + MAKE_EQN(i, -, +model_bounds->min.v[i]); + + if (TEST_OUT) + return 0; + + /* + * Max X + */ + MAKE_EQN(i, +, -model_bounds->max.v[i]); + + if (TEST_OUT) + return 0; + } + + return 1; +} + +/* + * Recursive function for 3D picking within a hierachy + */ +static int ActorPick3D(br_actor *ap, br_model *model, br_material *material, br_bounds *bounds, + br_pick3d_cbfn *callback, void *arg) +{ + br_actor *a; + br_model *this_model; + br_material *this_material; + br_matrix34 m_to_v; + int r = 0; + + this_model = ap->model ? ap->model : model; + this_material = ap->material ? ap->material : material; + + /* + * Concatenate transform of this actor onto current + */ + m_to_v = pick_model_to_view; + BrMatrix34PreTransform(&pick_model_to_view, &ap->t); + + switch (ap->type) + { + + case BR_ACTOR_MODEL: + if (PickBoundsTestBox(&this_model->bounds, bounds, &pick_model_to_view)) + { + /* + * Invoke callback + */ + r = callback(ap, this_model, this_material, &m_to_v, bounds, arg); + } + + /* FALL THROUGH */ + default: + BR_FOR_SIMPLELIST(&ap->children, a) + { + r = ActorPick3D(a, this_model, this_material, bounds, callback, arg); + if (r) + break; + } + + break; + + case BR_ACTOR_BOUNDS: + case BR_ACTOR_BOUNDS_CORRECT: + /* + * Only recurse into bounds if pick_bounds intersects + */ + UASSERT(a->type_data != NULL); + + if (PickBoundsTestBox(ap->type_data, bounds, &pick_model_to_view)) + { + BR_FOR_SIMPLELIST(&ap->children, a) + { + r = ActorPick3D(a, this_model, this_material, bounds, callback, arg); + if (r) + break; + } + } + break; + } + + /* + * Restore transform + */ + pick_model_to_view = m_to_v; + + return r; +} + +/* + * Find any actors whose bounding boxes intersect a 3D + * pick box + */ +int BR_PUBLIC_ENTRY BrScenePick3D(br_actor *world, br_actor *actor, br_bounds *bounds, br_pick3d_cbfn *callback, + void *arg) +{ + br_matrix34 mat; + + UASSERT(world != NULL); + UASSERT(actor != NULL); + UASSERT(bounds != NULL); + UASSERT(callback != NULL); + + /* + * Work out transform from world to base actor + */ + BrActorToRoot(actor, world, &mat); + BrMatrix34Inverse(&pick_model_to_view, &mat); + + /* + * Traverse the world + */ + return ActorPick3D(world, fw.default_model, fw.default_material, bounds, callback, arg); +} + +/* + * Intersect a models's faces with a ray segment + * + * XXX Possible options - + * + * All faces + * Nearest face + * Nearest vertex of hit face + * U,V parameters of hit point + * + */ +int BR_PUBLIC_ENTRY BrModelPick2D(br_model *model, br_material *material, br_vector3 *ray_pos, br_vector3 *ray_dir, + br_scalar t_near, br_scalar t_far, br_modelpick2d_cbfn *callback, void *arg) +{ + br_face *fp; + int f, axis_m, axis_0, axis_1; + br_scalar t, d, n; + br_vector3 p; + br_scalar u0, u1, u2, v0, v1, v2; + br_scalar alpha, beta; + br_vector2 map; + int v, e, r; + br_material *this_material; + + t_near -= BR_SCALAR(0.001); + t_far += BR_SCALAR(0.001); + + /* + * For each face in model... + */ + for (f = 0, fp = model->faces; f < model->nfaces; f++, fp++) + { + /* + * Work out face's material + */ + this_material = fp->material ? fp->material : material; + + /* + * Intersect ray with plane of polygon + */ + d = BrFVector3Dot(&fp->n, ray_dir); + + /* + * If ray is parallel to face, ignore it + */ + if (BR_ABS(d) < 2 * BR_SCALAR_EPSILON) + continue; + + /* + * If d is +ve, ray goes in same dirn as normal - ignore face if single sided + */ + if (!(this_material->flags & (BR_MATF_TWO_SIDED | BR_MATF_ALWAYS_VISIBLE)) && d > S0) + continue; + + t = -BR_DIV(BrFVector3Dot(&fp->n, ray_pos) - fp->d, d); + + /* + * Ignore face if intersection is outside ray segment + */ + if (t < t_near || t > t_far) + continue; + + /* + * Work out intersection point + */ + BrVector3Scale(&p, ray_dir, t); + BrVector3Add(&p, &p, ray_pos); + + /* + * Work out dominant axis of normal + */ + axis_m = 0; + if (BR_ABS(fp->n.v[1]) > BR_ABS(fp->n.v[0])) + axis_m = 1; + + if (BR_ABS(fp->n.v[2]) > BR_ABS(fp->n.v[axis_m])) + axis_m = 2; + + switch (axis_m) + { + case 0: + axis_0 = 1; + axis_1 = 2; + break; + case 1: + axis_0 = 0; + axis_1 = 2; + break; + case 2: + axis_0 = 0; + axis_1 = 1; + break; + } + + /* + * Work out point in polygon (Gems I, pg 392) + */ + u0 = model->vertices[fp->vertices[0]].p.v[axis_0]; + v0 = model->vertices[fp->vertices[0]].p.v[axis_1]; + + u1 = model->vertices[fp->vertices[1]].p.v[axis_0] - u0; + v1 = model->vertices[fp->vertices[1]].p.v[axis_1] - v0; + + u2 = model->vertices[fp->vertices[2]].p.v[axis_0] - u0; + v2 = model->vertices[fp->vertices[2]].p.v[axis_1] - v0; + + u0 = p.v[axis_0] - u0; + v0 = p.v[axis_1] - v0; + + if (BR_ABS(u1) <= (2 * BR_SCALAR_EPSILON)) + { + + if (BR_ABS(u0) > BR_ABS(u2)) + continue; + + if (u2 == S0) + continue; + + beta = BR_DIV(u0, u2); + + if (beta >= S0 && beta <= S1) + alpha = BR_DIV(BR_SUB(v0, BR_MUL(beta, v2)), v1); + else + continue; + } + else + { + n = BR_MAC2(v0, u1, -u0, v1); + d = BR_MAC2(v2, u1, -u2, v1); + + if (BR_ABS(n) > BR_ABS(d)) + continue; + + if (d == S0) + continue; + + beta = BR_DIV(n, d); + if (beta >= S0 && beta <= S1) + alpha = BR_DIV(BR_SUB(u0, BR_MUL(beta, u2)), u1); + else + continue; + } + + if (alpha < S0 || (alpha + beta) > S1) + continue; + + /* + * Point is in polygon + */ + + /* + * Interpolate u,v + */ + BrVector2Scale(&map, &model->vertices[fp->vertices[1]].map, alpha); + BrVector2AccumulateScale(&map, &model->vertices[fp->vertices[2]].map, beta); + BrVector2AccumulateScale(&map, &model->vertices[fp->vertices[0]].map, (S1 - (alpha + beta))); + + /* + * Find `nearest' vertex and edge - partition triangle + * along the bisectors of each corner + */ + v = 0; + e = 1; + + if (alpha > beta) + { + /* + * Edge 2 vs. Edge 1 + */ + if (alpha < (S1 - BR_CONST_MUL(beta, 2))) + e = 2; + /* + * Vertex 2 vs. Edge 0 + */ + if (alpha > (BR_SCALAR(0.5) - BR_CONST_DIV(beta, 2))) + v = 2; + } + else + { + /* + * Edge 0 vs. Edge 1 + */ + if (alpha < (BR_SCALAR(0.5) - BR_CONST_DIV(beta, 2))) + e = 0; + + /* + * Vertex 1 vs. Edge 0 + */ + if (alpha > (S1 - BR_CONST_MUL(beta, 2))) + v = 1; + } + + /* + * Invoke callback + */ + r = callback(model, this_material, ray_pos, ray_dir, t, f, e, v, &p, &map, arg); + + if (r) + return r; + } + + return 0; +} diff --git a/bren/FW/pixelmap.c b/bren/FW/pixelmap.c new file mode 100644 index 00000000..f5e491c4 --- /dev/null +++ b/bren/FW/pixelmap.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: pixelmap.c 1.17 1995/08/31 16:29:37 sam Exp $ + * $Locker: $ + * + * Manipulating pixelmaps + */ + +#include "fw.h" +#include "brassert.h" + +static char rscid[] = "$Id: pixelmap.c 1.17 1995/08/31 16:29:37 sam Exp $"; + +/* + * Useful info about each pixelmap type + */ +static struct pm_type_info +{ + /* + * Size, in bits, of each pixel (including padding) + */ + br_uint_16 bits; + + /* + * Size, in bytes, that should be used for saving/loading + */ + br_uint_16 file_size; + + /* + * Alignment of rows, in pixels + */ + br_uint_16 align; + + /* + * Mask of channels in pixelmap + */ + br_uint_16 channels; + +} pm_type_info[] = { + { + 1, + 1, + 32, + BR_PMCHAN_INDEX, + }, /* BR_PMT_INDEX_1 */ + { + 2, + 1, + 16, + BR_PMCHAN_INDEX, + }, /* BR_PMT_INDEX_2 */ + { + 4, + 1, + 8, + BR_PMCHAN_INDEX, + }, /* BR_PMT_INDEX_4 */ + { + 8, + 1, + 4, + BR_PMCHAN_INDEX, + }, /* BR_PMT_INDEX_8 */ + + { + 16, + 2, + 2, + BR_PMCHAN_RGB, + }, /* BR_PMT_RGB_555 */ + { + 16, + 2, + 2, + BR_PMCHAN_RGB, + }, /* BR_PMT_RGB_565 */ + { + 24, + 3, + 4, + BR_PMCHAN_RGB, + }, /* BR_PMT_RGB_888 */ + { + 32, + 4, + 1, + BR_PMCHAN_RGB, + }, /* BR_PMT_RGBX_888 */ + { + 32, + 4, + 1, + BR_PMCHAN_RGB | BR_PMCHAN_ALPHA, + }, /* BR_PMT_RGBA_8888 */ + + { + 16, + 1, + 2, + BR_PMCHAN_YUV, + }, /* BR_PMT_YUYV_8888 */ + { + 32, + 1, + 1, + BR_PMCHAN_YUV, + }, /* BR_PMT_YUV_888 */ + + { + 16, + 2, + 4, + BR_PMCHAN_DEPTH, + }, /* BR_PMT_DEPTH_16 */ + { + 32, + 4, + 4, + BR_PMCHAN_DEPTH, + }, /* BR_PMT_DEPTH_32 */ + { + 8, + 1, + 4, + BR_PMCHAN_ALPHA, + }, /* BR_PMT_ALPHA_8 */ + {16, 2, 2, BR_PMCHAN_INDEX | BR_PMCHAN_ALPHA}, /* BR_PMT_INDEXA_88 */ +}; + +/* + * Allocate a new, pixelmap of the given type and size + * + * If the 'pixels' pointer is NULL, an appropriate area of memeory will be allocated + * + */ +br_pixelmap *BR_PUBLIC_ENTRY BrPixelmapAllocate(br_uint_8 type, br_uint_16 w, br_uint_16 h, void *pixels, int flags) +{ + br_pixelmap *pm; + struct pm_type_info *tip = pm_type_info + type; + + pm = BrResAllocate(fw.res, sizeof(*pm), BR_MEMORY_PIXELMAP); + + UASSERT(type < BR_ASIZE(pm_type_info)); + + /* + * Fill in base structure + */ + pm->identifier = NULL; + pm->type = type; + pm->map = NULL; + pm->flags = BR_PMF_LINEAR; + pm->base_x = 0; + pm->base_y = 0; + + pm->width = w; + pm->height = h; + + pm->origin_x = 0; + pm->origin_y = 0; + + /* + * Work out size of a row + */ + pm->row_bytes = tip->bits * tip->align * ((w + tip->align - 1) / tip->align) / 8; + + if (((pm->row_bytes * 8) % tip->bits) == 0) + pm->flags |= BR_PMF_ROW_WHOLEPIXELS; + + /* + * Allocate pixels + */ + if (pixels) + pm->pixels = pixels; + else + pm->pixels = BrResAllocate(pm, pm->row_bytes * pm->height, BR_MEMORY_PIXELS); + + /* + * Make it a bottom up bitmap if required + */ + if (flags & BR_PMAF_INVERTED) + { + pm->pixels = (char *)pm->pixels + pm->row_bytes * (pm->height - 1); + pm->row_bytes = -pm->row_bytes; + } + + return pm; +} + +/* + * Create a new pixelmap that references a sub-rectangle of another pixelmap + */ +br_pixelmap *BR_PUBLIC_ENTRY BrPixelmapAllocateSub(br_pixelmap *pm, br_uint_16 x, br_uint_16 y, br_uint_16 w, + br_uint_16 h) +{ + br_pixelmap *npm; + + /* + * Create the new structure and copy + */ + npm = BrResAllocate(fw.res, sizeof(*pm), BR_MEMORY_PIXELMAP); + + *npm = *pm; + + /* + * Pixel rows are not contiguous + */ + npm->flags &= ~BR_PMF_LINEAR; + + /* + * Create sub-window (clipped against original) + */ + x = (x <= pm->width) ? x : pm->width; + y = (y <= pm->height) ? y : pm->height; + + npm->base_x += x; + npm->base_y += y; + + npm->origin_x = 0; + npm->origin_y = 0; + + npm->width = ((x + w) <= pm->width) ? w : (pm->width - x); + npm->height = ((y + h) <= pm->height) ? h : (pm->height - y); + + return npm; +} + +/* + * Return the load/save size for a given pixelmap + */ +br_uint_16 BR_PUBLIC_ENTRY BrPixelmapFileSize(br_pixelmap *pm) +{ + ASSERT(pm && (pm->type < BR_ASIZE(pm_type_info))); + + return pm_type_info[pm->type].file_size; +} + +/* + * Return the pixel size in bits + */ +br_uint_16 BR_PUBLIC_ENTRY BrPixelmapPixelSize(br_pixelmap *pm) +{ + ASSERT(pm && (pm->type < BR_ASIZE(pm_type_info))); + + return pm_type_info[pm->type].bits; +} + +/* + * Return a mask of the channels that a pixelmap has + */ +br_uint_16 BR_PUBLIC_ENTRY BrPixelmapChannels(br_pixelmap *pm) +{ + ASSERT(pm && (pm->type < BR_ASIZE(pm_type_info))); + + return pm_type_info[pm->type].channels; +} diff --git a/bren/FW/pmdsptch.c b/bren/FW/pmdsptch.c new file mode 100644 index 00000000..1a3ab1ba --- /dev/null +++ b/bren/FW/pmdsptch.c @@ -0,0 +1,713 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: pmdsptch.c 1.6 1995/08/31 16:29:38 sam Exp $ + * $Locker: sam $ + * + * Pixelmap operations + */ +#include +#include +#include + +#include "fw.h" +#include "brassert.h" + +static char rscid[] = "$Id: pmdsptch.c 1.6 1995/08/31 16:29:38 sam Exp $"; + +void BR_PUBLIC_ENTRY BrPixelmapFree(br_pixelmap *src) +{ + br_context *ctx = CONTEXT(src); + + ctx->free(ctx, src); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrPixelmapMatch(br_pixelmap *src, br_uint_8 match_type) +{ + br_context *ctx = CONTEXT(src); + + return ctx->match(ctx, src, match_type); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrPixelmapClone(br_pixelmap *src) +{ + br_context *ctx = CONTEXT(src); + + return ctx->clone(ctx, src); +} + +void BR_PUBLIC_ENTRY BrPixelmapFill(br_pixelmap *dst, br_uint_32 colour) +{ + br_context *ctx = CONTEXT(dst); + + ctx->fill(ctx, dst, colour); +} + +void BR_PUBLIC_ENTRY BrPixelmapRectangle(br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_16 w, br_uint_16 h, + br_uint_32 colour) +{ + br_context *ctx = CONTEXT(dst); + + x += dst->origin_x; + y += dst->origin_y; + + ctx->rectangle(ctx, dst, x, y, w, h, colour); +} + +void BR_PUBLIC_ENTRY BrPixelmapRectangle2(br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_16 w, br_uint_16 h, + br_uint_32 colour1, br_uint_32 colour2) +{ + br_context *ctx = CONTEXT(dst); + + x += dst->origin_x; + y += dst->origin_y; + + ctx->rectangle2(ctx, dst, x, y, w, h, colour1, colour2); +} + +void BR_PUBLIC_ENTRY BrPixelmapRectangleCopy(br_pixelmap *dst, br_int_16 dx, br_int_16 dy, br_pixelmap *src, + br_int_16 sx, br_int_16 sy, br_uint_16 w, br_uint_16 h) +{ + br_context *s_ctx = CONTEXT(src); + br_context *d_ctx = CONTEXT(dst); + + sx += src->origin_x; + sy += src->origin_y; + + dx += dst->origin_x; + dy += dst->origin_y; + + /* + * Trivial reject + */ + if (dx >= dst->width || dy >= dst->height) + return; + + if (sx >= src->width || sy >= src->height) + return; + + if ((dx + w) <= 0 || (dy + h) <= 0) + return; + + if ((sx + w) <= 0 || (sy + h) <= 0) + return; + + /* + * Clip rectangle to destination + */ + if (dx < 0) + { + w += dx; + sx -= dx; + dx = 0; + } + + if (dy < 0) + { + h += dy; + sy -= dy; + dy = 0; + } + + if ((dx + w) > dst->width) + w = dst->width - dx; + + if ((dy + h) > dst->height) + h = dst->height - dy; + + /* + * Clip rectangle to source + */ + if (sx < 0) + { + w += sx; + dx -= sx; + sx = 0; + } + + if (sy < 0) + { + h += sy; + dy -= sy; + sy = 0; + } + + if ((sx + w) > src->width) + w = src->width - sx; + + if ((sy + h) > src->height) + h = src->height - sy; + + /* + * Don't draw empty rectangles + */ + if (w == 0 || h == 0) + return; + + /* + * Invoke one of three driver functions + * device -> device + * device -> memory + * memory -> device + * or Generic handler + */ + if (s_ctx->device == d_ctx->device) + /* + * If the same device, just let the device get on with it + */ + d_ctx->rectangle_copy(d_ctx, dst, dx, dy, src, sx, sy, w, h); + else if (s_ctx->device == &_BrMemoryDevice) + /* + * Spot case of copying to device (from memory) + */ + d_ctx->rectangle_copy_to(d_ctx, dst, dx, dy, src, sx, sy, w, h); + else if (d_ctx->device == &_BrMemoryDevice) + /* + * Spot case of copying from device (to memory) + */ + s_ctx->rectangle_copy_from(s_ctx, dst, dx, dy, src, sx, sy, w, h); + else + /* + * Otherwise use a general copy with intermediate buffer + */ + _BrGenericRectangleCopy(d_ctx, dst, dx, dy, src, sx, sy, w, h); +} + +void BR_PUBLIC_ENTRY BrPixelmapRectangleFill(br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_16 w, br_uint_16 h, + br_uint_32 colour) +{ + br_context *ctx = CONTEXT(dst); + + x += dst->origin_x; + y += dst->origin_y; + + /* + * Trivial reject + */ + if (x >= dst->width || y >= dst->height) + return; + + if ((x + w) <= 0 || (y + h) <= 0) + return; + + /* + * Clip rectangle to destination + */ + + if (x < 0) + { + w += x; + x = 0; + } + + if (y < 0) + { + h += y; + y = 0; + } + + if ((x + w) > dst->width) + w = dst->width - x; + + if ((y + h) > dst->height) + h = dst->height - y; + + /* + * Don't draw empty rectangles + */ + if (w == 0 || h == 0) + return; + + ctx->rectangle_fill(ctx, dst, x, y, w, h, colour); +} + +void BR_PUBLIC_ENTRY BrPixelmapDirtyRectangleCopy(br_pixelmap *dst, br_pixelmap *src, br_int_16 x, br_int_16 y, + br_uint_16 w, br_uint_16 h) +{ + br_context *ctx = CONTEXT(dst); + + x += dst->origin_x; + y += dst->origin_y; + + UASSERT(src->type == dst->type); + UASSERT(src->width == dst->width); + UASSERT(src->height == dst->height); + UASSERT(src->row_bytes == dst->row_bytes); + + /* + * Trivial reject + */ + if (x >= dst->width || y >= dst->height) + return; + + if ((x + w) <= 0 || (y + h) <= 0) + return; + + /* + * Clip rectangle to destination + */ + if (x < 0) + { + w += x; + x = 0; + } + + if (y < 0) + { + h += y; + y = 0; + } + + if ((x + w) > dst->width) + w = dst->width - x; + + if ((y + h) > dst->height) + h = dst->height - y; + + /* + * Don't draw empty rectangles + */ + if (w == 0 || h == 0) + return; + + ctx->dirty_rectangle_copy(ctx, dst, src, x, y, w, h); +} + +void BR_PUBLIC_ENTRY BrPixelmapDirtyRectangleFill(br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_16 w, + br_uint_16 h, br_uint_32 colour) +{ + br_context *ctx = CONTEXT(dst); + + x += dst->origin_x; + y += dst->origin_y; + + /* + * Trivial reject + */ + if (x >= dst->width || y >= dst->height) + return; + + if ((x + w) <= 0 || (y + h) <= 0) + return; + + /* + * Clip rectangle to destination + */ + if (x < 0) + { + w += x; + x = 0; + } + + if (y < 0) + { + h += y; + y = 0; + } + + if ((x + w) > dst->width) + w = dst->width - x; + + if ((y + h) > dst->height) + h = dst->height - y; + + /* + * Don't draw empty rectangles + */ + if (w == 0 || h == 0) + return; + + ctx->dirty_rectangle_fill(ctx, dst, x, y, w, h, colour); +} + +void BR_PUBLIC_ENTRY BrPixelmapPixelSet(br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_32 colour) +{ + br_context *ctx = CONTEXT(dst); + + x += dst->origin_x; + y += dst->origin_y; + + if (x < 0 || y < 0) + return; + + if (x >= dst->width || y >= dst->height) + return; + + ctx->pixel_set(ctx, dst, x, y, colour); +} + +br_uint_32 BR_PUBLIC_ENTRY BrPixelmapPixelGet(br_pixelmap *dst, br_int_16 x, br_int_16 y) +{ + br_context *ctx = CONTEXT(dst); + + x += dst->origin_x; + y += dst->origin_y; + + if (x < 0 || y < 0) + return 0; + + if (x >= dst->width || y >= dst->height) + return 0; + + return ctx->pixel_get(ctx, dst, x, y); +} + +void BR_PUBLIC_ENTRY BrPixelmapCopy(br_pixelmap *dst, br_pixelmap *src) +{ + br_context *s_ctx = CONTEXT(src); + br_context *d_ctx = CONTEXT(dst); + + UASSERT((dst->type == src->type) && (dst->width == src->width) && (dst->height == src->height)); + UASSERT((src->flags & BR_PMF_NO_ACCESS) == 0); + + /* + * Invoke one of three driver functions + * device -> device + * device -> memory + * memory -> device + * or Generic handler + */ + if (s_ctx->device == d_ctx->device) + /* + * If the same device, just let the device get on with it + */ + d_ctx->copy(d_ctx, dst, src); + else if (s_ctx->device == &_BrMemoryDevice) + /* + * Spot case of copying to device (from memory) + */ + d_ctx->copy_to(d_ctx, dst, src); + else if (d_ctx->device == &_BrMemoryDevice) + /* + * Spot case of copying from device (to memory) + */ + s_ctx->copy_from(s_ctx, dst, src); + else + /* + * Otherwise use a general copy with intermediate buffer + */ + _BrGenericCopy(d_ctx, dst, src); +} + +void BR_PUBLIC_ENTRY BrPixelmapLine(br_pixelmap *dst, br_int_16 x1, br_int_16 y1, br_int_16 x2, br_int_16 y2, + br_uint_32 colour) +{ + int temp; + br_int_16 w, h; + br_context *ctx = CONTEXT(dst); + + x1 += dst->origin_x; + y1 += dst->origin_y; + x2 += dst->origin_x; + y2 += dst->origin_y; + +#define SCALE(var, arg, num, den) ((var) = ((arg) * (num)) / (den)) + +#define USCALE(var, arg, num, den) ((var) = ((unsigned)(arg) * (unsigned)(num)) / (unsigned)(den)) + +#define EXCHG(a, b) \ + do \ + { \ + int __temp__ = (a); \ + (a) = (b); \ + (b) = __temp__; \ + } while (0) + +#define WHEN_CLIPPED + + w = dst->width - 1; + h = dst->height - 1; + + if (x1 > x2) + { + EXCHG(x1, x2); + EXCHG(y1, y2); + } + + if ((x2 < 0) || (x1 > w)) + { + return; + } + + if (y1 < y2) + { + if ((y2 < 0) || (y1 > h)) + { + return; + } + if (y1 < 0) + { + USCALE(temp, (x2 - x1), (0 - y1), (y2 - y1)); + if ((x1 += temp) > w) + { + return; + } + y1 = 0; + WHEN_CLIPPED; + } + if (y2 > h) + { + USCALE(temp, (x2 - x1), (y2 - h), (y2 - y1)); + if ((x2 -= temp) < 0) + { + return; + } + y2 = h; + WHEN_CLIPPED; + } + if (x1 < 0) + { + USCALE(temp, (y2 - y1), (0 - x1), (x2 - x1)); + y1 += temp; + x1 = 0; + WHEN_CLIPPED; + } + if (x2 > w) + { + USCALE(temp, (y2 - y1), (x2 - w), (x2 - x1)); + y2 -= temp; + x2 = w; + WHEN_CLIPPED; + } + } + else + { + if ((y1 < 0) || (y2 > h)) + { + return; + } + if (y1 > h) + { + USCALE(temp, (x2 - x1), (y1 - h), (y1 - y2)); + if ((x1 += temp) > w) + { + return; + } + y1 = h; + WHEN_CLIPPED; + } + if (y2 < 0) + { + USCALE(temp, (x2 - x1), (0 - y2), (y1 - y2)); + if ((x2 -= temp) < 0) + { + return; + } + y2 = 0; + WHEN_CLIPPED; + } + if (x1 < 0) + { + USCALE(temp, (y1 - y2), (0 - x1), (x2 - x1)); + y1 -= temp; + x1 = 0; + WHEN_CLIPPED; + } + if (x2 > w) + { + USCALE(temp, (y1 - y2), (x2 - w), (x2 - x1)); + y2 += temp; + x2 = w; + WHEN_CLIPPED; + } + } + + ctx->line(ctx, dst, x1, y1, x2, y2, colour); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrPixelmapDoubleBuffer(br_pixelmap *dst, br_pixelmap *src) +{ + br_context *ctx = CONTEXT(dst); + + ctx->double_buffer(ctx, dst, src); + + return src; +} + +void BR_PUBLIC_ENTRY BrPixelmapText(br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_32 colour, br_font *font, + char *text) +{ + int w, s_stride, c; + int rows, base; + int bytes; + br_context *ctx = CONTEXT(dst); + + x += dst->origin_x; + y += dst->origin_y; + + if (font == NULL) + font = ctx->font; + + /* + * Quit if off top, bottom or right screen + */ + if (y <= -font->glyph_y || y >= dst->height || x >= dst->width) + return; + + /* + * Clip to bottom of screen + */ + if (y + font->glyph_y > dst->height) + rows = dst->height - y; + else + rows = font->glyph_y; + + /* + * Clip to top of screen + */ + if (y < 0) + { + base = -y; + rows -= base; + y = 0; + } + else + { + base = 0; + } + + /* + * Remaining space until right edge + */ + c = dst->width - x; + + if (font->flags & BR_FONTF_PROPORTIONAL) + { + /* + * PROPORTIONAL + */ + for (; *text; text++) + { + w = font->width[*text]; + s_stride = (w + 7) / 8; + + if (x + w > 0) + { + ctx->copy_bits(ctx, dst, x, y, font->glyphs + font->encoding[*text] + base * s_stride, s_stride, + (x < 0) ? -x : 0, (w < c) ? w : c, rows, colour); + } + x += w + 1; + c -= w + 1; + + if (c <= 0) + break; + } + } + else + { + /* + * FIXED + */ + w = font->glyph_x; + s_stride = (w + 7) / 8; + + for (; *text; text++) + { + + if (x + w > 0) + { + ctx->copy_bits(ctx, dst, x, y, font->glyphs + font->encoding[*text] + base * s_stride, s_stride, + (x < 0) ? -x : 0, (w < c) ? w : c, rows, colour); + } + x += w + 1; + c -= w + 1; + + if (c <= 0) + break; + } + } +} + +void BR_PUBLIC_ENTRY BrPixelmapTextF(br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_32 colour, br_font *font, + char *fmt, ...) +{ + va_list args; + + /* + * Build output string + */ + va_start(args, fmt); + vsprintf(_br_scratch_string, fmt, args); + va_end(args); + + BrPixelmapText(dst, x, y, colour, font, _br_scratch_string); +} + +br_uint_16 BR_PUBLIC_ENTRY BrPixelmapTextWidth(br_pixelmap *dst, br_font *font, char *text) +{ + int i, j, w; + br_context *ctx = CONTEXT(dst); + + if (font == NULL) + font = ctx->font; + + if (font->flags & BR_FONTF_PROPORTIONAL) + { + /* + * return length of (proportional) string in pixels + */ + for (i = 0, w = 0, j = strlen(text); i < j; i++, text++) + w += font->width[*text] + 1; + + w -= 1; + return w; + } + else + return (font->glyph_x + 1) * strlen(text) - 1; +} + +br_uint_16 BR_PUBLIC_ENTRY BrPixelmapTextHeight(br_pixelmap *dst, br_font *font) +{ + br_context *ctx = CONTEXT(dst); + + if (font == NULL) + font = ctx->font; + + return font->glyph_y; +} + +void BR_PUBLIC_ENTRY BrPixelmapCopyBits(br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_8 *src, br_uint_16 s_stride, + br_uint_16 start_bit, br_uint_16 end_bit, br_uint_16 nrows, br_uint_32 colour) +{ + br_context *ctx = CONTEXT(dst); + + x += dst->origin_x; + y += dst->origin_y; + + /* + * Trivial reject + */ + if (x + start_bit >= dst->width) + return; + if (y >= dst->height) + return; + + if (x + end_bit <= 0) + return; + if (y + nrows <= 0) + return; + + /* + * Clip to destination + */ + if (x + end_bit > dst->width) + end_bit = dst->width - x; + + if (x + start_bit < 0) + start_bit = -x; + + if ((y + nrows) > dst->height) + nrows = dst->height - y; + + if (y < 0) + { + src -= y * s_stride; + nrows += y; + y = 0; + } + + if (end_bit < start_bit) + return; + + ctx->copy_bits(ctx, dst, x, y, src, s_stride, start_bit, end_bit, nrows, colour); +} diff --git a/bren/FW/pmgenops.c b/bren/FW/pmgenops.c new file mode 100644 index 00000000..70558adb --- /dev/null +++ b/bren/FW/pmgenops.c @@ -0,0 +1,397 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: pmgenops.c 1.6 1995/08/31 16:29:39 sam Exp $ + * $Locker: $ + * + * Generic Pixelmap operations + */ +#include + +#include "fw.h" +#include "brassert.h" + +static char rscid[] = "$Id: pmgenops.c 1.6 1995/08/31 16:29:39 sam Exp $"; + +#define PMAP_ADDRESS(pm, x, y, bpp) \ + ((char *)((pm)->pixels) + ((pm)->base_y + (y)) * (pm)->row_bytes + ((pm)->base_x + (x)) * (bpp)) + +void BR_ASM_CALL _BrGenericLine(br_context *ctx, br_pixelmap *dst, br_int_16 a1, br_int_16 b1, br_int_16 a2, + br_int_16 b2, br_uint_32 colour) +{ + /* + * Symmetric Double Step Line Algorithm by Brian Wyvill from "Graphics Gems", + * Academic Press, 1990 + */ + +#define LINEPLOT(x, y, flag) \ + do \ + { \ + if (flag) \ + { \ + ctx->pixel_set(ctx, dst, y, x, colour); \ + } \ + else \ + { \ + ctx->pixel_set(ctx, dst, x, y, colour); \ + } \ + } while (0) + +#define swap(a, b) \ + { \ + a ^= b; \ + b ^= a; \ + a ^= b; \ + } +#define absolute(i, j, k) ((i - j) * (k = ((i - j) < 0 ? -1 : 1))) + + int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left; + int x1, y1; + int sign_x, sign_y, step, reverse, i; + char *dest; + int bytes; + + bytes = BrPixelmapPixelSize(dst) >> 3; + + dx = absolute(a2, a1, sign_x); + dy = absolute(b2, b1, sign_y); + + if (dx == 0 && dy == 0) + { + ctx->pixel_set(ctx, dst, a1, b1, colour); + return; + } + + /* decide increment sign by the slope sign */ + if (sign_x == sign_y) + step = 1; + else + step = -1; + + if (dy > dx) + { /* chooses axis of greatest movement (make dx) */ + swap(a1, b1); + swap(a2, b2); + swap(dx, dy); + reverse = 1; + } + else + reverse = 0; + + /* note error check for dx==0 should be included here */ + if (a1 > a2) + { /* start from the smaller coordinate */ + x = a2; + y = b2; + x1 = a1; + y1 = b1; + } + else + { + x = a1; + y = b1; + x1 = a2; + y1 = b2; + } + + /* Note dx=n implies 0 - n or (dx+1) pixels to be set */ + /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */ + /* In fact (dx-1)/4 as 2 pixels are already plottted */ + + xend = (dx - 1) / 4; + pixels_left = (dx - 1) % 4; /* number of pixels left over at the end */ + LINEPLOT(x, y, reverse); + LINEPLOT(x1, y1, reverse); /* plot first two points */ + incr2 = 4 * dy - 2 * dx; + if (incr2 < 0) + { /* slope less than 1/2 */ + c = 2 * dy; + incr1 = 2 * c; + D = incr1 - dx; + + for (i = 0; i < xend; i++) + { /* plotting loop */ + ++x; + --x1; + if (D < 0) + { + /* pattern 1 forwards */ + LINEPLOT(x, y, reverse); + LINEPLOT(++x, y, reverse); + /* pattern 1 backwards */ + LINEPLOT(x1, y1, reverse); + LINEPLOT(--x1, y1, reverse); + D += incr1; + } + else + { + if (D < c) + { + /* pattern 2 forwards */ + LINEPLOT(x, y, reverse); + LINEPLOT(++x, y += step, reverse); + /* pattern 2 backwards */ + LINEPLOT(x1, y1, reverse); + LINEPLOT(--x1, y1 -= step, reverse); + } + else + { + /* pattern 3 forwards */ + LINEPLOT(x, y += step, reverse); + LINEPLOT(++x, y, reverse); + /* pattern 3 backwards */ + LINEPLOT(x1, y1 -= step, reverse); + LINEPLOT(--x1, y1, reverse); + } + D += incr2; + } + } /* end for */ + + /* plot last pattern */ + if (pixels_left) + { + if (D < 0) + { + LINEPLOT(++x, y, reverse); /* pattern 1 */ + if (pixels_left > 1) + LINEPLOT(++x, y, reverse); + if (pixels_left > 2) + LINEPLOT(--x1, y1, reverse); + } + else + { + if (D < c) + { + LINEPLOT(++x, y, reverse); /* pattern 2 */ + if (pixels_left > 1) + LINEPLOT(++x, y += step, reverse); + if (pixels_left > 2) + LINEPLOT(--x1, y1, reverse); + } + else + { + /* pattern 3 */ + LINEPLOT(++x, y += step, reverse); + if (pixels_left > 1) + LINEPLOT(++x, y, reverse); + if (pixels_left > 2) + LINEPLOT(--x1, y1 -= step, reverse); + } + } + } /* end if pixels_left */ + } + /* end slope < 1/2 */ + else + { /* slope greater than 1/2 */ + c = 2 * (dy - dx); + incr1 = 2 * c; + D = incr1 + dx; + for (i = 0; i < xend; i++) + { + ++x; + --x1; + if (D > 0) + { + /* pattern 4 forwards */ + LINEPLOT(x, y += step, reverse); + LINEPLOT(++x, y += step, reverse); + /* pattern 4 backwards */ + LINEPLOT(x1, y1 -= step, reverse); + LINEPLOT(--x1, y1 -= step, reverse); + D += incr1; + } + else + { + if (D < c) + { + /* pattern 2 forwards */ + LINEPLOT(x, y, reverse); + LINEPLOT(++x, y += step, reverse); + + /* pattern 2 backwards */ + LINEPLOT(x1, y1, reverse); + LINEPLOT(--x1, y1 -= step, reverse); + } + else + { + /* pattern 3 forwards */ + LINEPLOT(x, y += step, reverse); + LINEPLOT(++x, y, reverse); + /* pattern 3 backwards */ + LINEPLOT(x1, y1 -= step, reverse); + LINEPLOT(--x1, y1, reverse); + } + D += incr2; + } + } /* end for */ + /* plot last pattern */ + if (pixels_left) + { + if (D > 0) + { + LINEPLOT(++x, y += step, reverse); /* pattern 4 */ + if (pixels_left > 1) + LINEPLOT(++x, y += step, reverse); + if (pixels_left > 2) + LINEPLOT(--x1, y1 -= step, reverse); + } + else + { + if (D < c) + { + LINEPLOT(++x, y, reverse); /* pattern 2 */ + if (pixels_left > 1) + LINEPLOT(++x, y += step, reverse); + if (pixels_left > 2) + LINEPLOT(--x1, y1, reverse); + } + else + { + /* pattern 3 */ + LINEPLOT(++x, y += step, reverse); + if (pixels_left > 1) + LINEPLOT(++x, y, reverse); + if (pixels_left > 2) + { + if (D > c) /* step 3 */ + LINEPLOT(--x1, y1 -= step, reverse); + else /* step 2 */ + LINEPLOT(--x1, y1, reverse); + } + } + } + } + } +} + +void BR_ASM_CALL _BrGenericDoubleBuffer(br_context *ctx, br_pixelmap *dest, br_pixelmap *src) +{ + ctx->copy_to(ctx, dest, src); +} + +br_pixelmap *BR_ASM_CALL _BrGenericMatch(br_context *ctx, br_pixelmap *src, br_uint_8 match_type) +{ + int bytes, row_bytes; + br_pixelmap *pm = NULL; + + UASSERT(match_type < BR_PMMATCH_MAX); + + switch (match_type) + { + case BR_PMMATCH_OFFSCREEN: + /* + * Clone the source buffer + */ + pm = BrPixelmapAllocate(src->type, src->width, src->height, NULL, (src->row_bytes < 0) ? BR_PMAF_INVERTED : 0); + break; + + case BR_PMMATCH_DEPTH_16: + /* + * Allocate a DEPTH_16 pixelmap that has it's row_bytes as a multiple of the src row_bytes + */ + pm = BrPixelmapAllocate(BR_PMT_DEPTH_16, src->width, src->height, (void *)src, 0); + bytes = BrPixelmapPixelSize(src) >> 3; + + if (bytes != 0) + pm->row_bytes = (src->row_bytes * 2) / bytes; + else + pm->row_bytes = (src->row_bytes * 2); + + row_bytes = (pm->row_bytes > 0) ? pm->row_bytes : -pm->row_bytes; + pm->pixels = BrResAllocate(pm, row_bytes * pm->height, BR_MEMORY_PIXELS); + + if (pm->row_bytes < 0) + pm->pixels = (char *)pm->pixels + row_bytes * (pm->height - 1); + + break; + } + + return pm; +} + +/* + * Make a copy of a pixelmap + */ +br_pixelmap *BR_ASM_CALL _BrGenericClone(br_context *ctx, br_pixelmap *src) +{ + br_pixelmap *pm; + + pm = BrPixelmapAllocate(src->type, src->width, src->height, NULL, (src->row_bytes < 0) ? BR_PMAF_INVERTED : 0); + + BrPixelmapCopy(pm, src); + + return pm; +} + +/* + * Relase a pixelmap and all its associated resources + */ +void BR_ASM_CALL _BrGenericFree(br_context *ctx, br_pixelmap *src) +{ + BrResFree(src); +} + +void BR_ASM_CALL _BrGenericDirtyRectangleCopy(br_context *ctx, br_pixelmap *dst, br_pixelmap *src, br_uint_16 x, + br_uint_16 y, br_uint_16 w, br_uint_16 h) +{ + ctx->rectangle_copy(ctx, dst, x, y, src, x, y, w, h); +} + +void BR_ASM_CALL _BrGenericDirtyRectangleFill(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, + br_uint_16 w, br_uint_16 h, br_uint_32 colour) +{ + ctx->rectangle_fill(ctx, dst, x, y, w, h, colour); +} + +/* + * These should be moved into FW + */ +void BR_ASM_CALL _BrGenericRectangle(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, br_uint_16 w, + br_uint_16 h, br_uint_32 colour) +{ + int x1, y1; + + x1 = x + w - 1; + y1 = y + h - 1; + + ctx->line(ctx, dst, x, y, x1, y, colour); + ctx->line(ctx, dst, x, y, x, y1, colour); + + ctx->line(ctx, dst, x1, y1, x1, y, colour); + ctx->line(ctx, dst, x1, y1, x, y1, colour); +} + +void BR_ASM_CALL _BrGenericRectangle2(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, br_uint_16 w, + br_uint_16 h, br_uint_32 colour1, br_uint_32 colour2) +{ + int x1, y1; + + x1 = x + w - 1; + y1 = y + h - 1; + + ctx->line(ctx, dst, x, y, x1, y, colour1); + ctx->line(ctx, dst, x, y, x, y1, colour1); + + ctx->line(ctx, dst, x1, y1, x1, y, colour2); + ctx->line(ctx, dst, x1, y1, x, y1, colour2); +} + +void BR_ASM_CALL _BrGenericRectangleCopy(br_context *ctx, br_pixelmap *dst, br_uint_16 dx, br_uint_16 dy, + br_pixelmap *src, br_uint_16 sx, br_uint_16 sy, br_uint_16 w, br_uint_16 h) +{ + /* XXX */ + + /* + * Use a fixed size mmeory buffer (4K ?) + * + * Copy a rectangle at a time + * from source to memory + * from memory to destination + */ +} + +void BR_ASM_CALL _BrGenericCopy(br_context *ctx, br_pixelmap *dst, br_pixelmap *src) +{ + /* XXX */ + /* Use RectangleCopy */ +} diff --git a/bren/FW/pmmemops.c b/bren/FW/pmmemops.c new file mode 100644 index 00000000..94ff7bbc --- /dev/null +++ b/bren/FW/pmmemops.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: pmmemops.c 1.5 1995/08/31 16:29:41 sam Exp $ + * $Locker: $ + * + * Memeory Pixelmap operations + */ +#include + +#include "fw.h" +#include "brassert.h" + +static char rscid[] = "$Id: pmmemops.c 1.5 1995/08/31 16:29:41 sam Exp $"; + +#define PMAP_ADDRESS(pm, x, y, bpp) \ + ((char *)((pm)->pixels) + ((pm)->base_y + (y)) * (pm)->row_bytes + ((pm)->base_x + (x)) * (bpp)) + +/* + * Default device that just operates on normal memory pixelmaps + */ +br_device _BrMemoryDevice = { + {0}, + "Memory Device", +}; + +br_context _BrMemoryContext = { + "Memory Context", + &_BrMemoryDevice, + &_FontFixed3x5, + + _BrGenericFree, + _BrGenericMatch, + _BrGenericClone, + _BrGenericDoubleBuffer, + + _BrPmMemCopy, + _BrPmMemCopy, + _BrPmMemCopy, + + _BrPmMemFill, + _BrGenericRectangle, + _BrGenericRectangle2, + _BrPmMemRectangleCopyTo, + _BrPmMemRectangleCopyTo, + _BrPmMemRectangleCopyFrom, + _BrPmMemRectangleFill, + _BrPmMemDirtyRectangleCopy, + _BrPmMemDirtyRectangleFill, + _BrPmMemPixelSet, + _BrPmMemPixelGet, + _BrPmMemLine, + _BrPmMemCopyBits, +}; + +void BR_ASM_CALL _BrPmMemFill(br_context *ctx, br_pixelmap *dst, br_uint_32 colour) +{ + int i; + int bytes; + char *dest; + + /* + * normal pixelmap + */ + bytes = BrPixelmapPixelSize(dst) >> 3; + + if ((dst->flags & (BR_PMF_LINEAR | BR_PMF_ROW_WHOLEPIXELS)) == (BR_PMF_LINEAR | BR_PMF_ROW_WHOLEPIXELS) && + dst->row_bytes > 0) + { + /* + * Don't consider row ends - just blat the whole pixel block + */ + dest = PMAP_ADDRESS(dst, 0, (dst->row_bytes > 0) ? 0 : (dst->height - 1), bytes); + _MemFill_A(dest, dst->width * dst->height, bytes, colour); + } + else + { + dest = PMAP_ADDRESS(dst, 0, 0, bytes); + _MemRectFill_A(dest, dst->width, dst->height, dst->row_bytes, bytes, colour); + } +} + +void BR_ASM_CALL _BrPmMemRectangleCopyTo(br_context *ctx, br_pixelmap *dst, br_uint_16 dx, br_uint_16 dy, + br_pixelmap *src, br_uint_16 sx, br_uint_16 sy, br_uint_16 w, br_uint_16 h) +{ + int i, bytes; + char *source, *dest; + br_context *src_ctx; + + /* + * Make sure the source is readable + */ + UASSERT((src->flags & BR_PMF_NO_ACCESS) == 0); + UASSERT(src->type == dst->type); + + src_ctx = CONTEXT(src); + + bytes = BrPixelmapPixelSize(src) >> 3; + + source = PMAP_ADDRESS(src, sx, sy, bytes); + dest = PMAP_ADDRESS(dst, dx, dy, bytes); + + _MemRectCopy_A(dest, source, w, h, dst->row_bytes, src->row_bytes, bytes); +} + +void BR_ASM_CALL _BrPmMemRectangleCopyFrom(br_context *ctx, br_pixelmap *dst, br_uint_16 dx, br_uint_16 dy, + br_pixelmap *src, br_uint_16 sx, br_uint_16 sy, br_uint_16 w, br_uint_16 h) +{ + int i, bytes; + char *source, *dest; + br_context *dst_context; + + /* + * Make sure the destination is writeable + */ + UASSERT((dst->flags & BR_PMF_NO_ACCESS) == 0); + UASSERT(src->type == dst->type); + + dst_context = CONTEXT(dst); + + bytes = BrPixelmapPixelSize(src) >> 3; + + source = PMAP_ADDRESS(src, sx, sy, bytes); + dest = PMAP_ADDRESS(dst, dx, dy, bytes); + + _MemRectCopy_A(dest, source, w, h, dst->row_bytes, src->row_bytes, bytes); +} + +void BR_ASM_CALL _BrPmMemRectangleFill(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, br_uint_16 w, + br_uint_16 h, br_uint_32 colour) +{ + int i, bytes, j; + char *dest; + + bytes = BrPixelmapPixelSize(dst) >> 3; + + dest = PMAP_ADDRESS(dst, x, y, bytes); + + _MemRectFill_A(dest, w, h, dst->row_bytes, bytes, colour); +} + +void BR_ASM_CALL _BrPmMemDirtyRectangleCopy(br_context *ctx, br_pixelmap *dst, br_pixelmap *src, br_uint_16 x, + br_uint_16 y, br_uint_16 w, br_uint_16 h) +{ + _BrPmMemRectangleCopyTo(ctx, dst, x, y, src, x, y, w, h); +} + +void BR_ASM_CALL _BrPmMemDirtyRectangleFill(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, br_uint_16 w, + br_uint_16 h, br_uint_32 colour) +{ + _BrPmMemRectangleFill(ctx, dst, x, y, w, h, colour); +} + +void BR_ASM_CALL _BrPmMemCopy(br_context *ctx, br_pixelmap *dst, br_pixelmap *src) +{ + int i; + int bytes; + char *source, *dest; + br_context *src_ctx; + + UASSERT((dst->type == src->type) && (dst->width == src->width) && (dst->height == src->height)); + UASSERT((src->flags & BR_PMF_NO_ACCESS) == 0); + + src_ctx = CONTEXT(src); + + bytes = BrPixelmapPixelSize(dst) >> 3; + + if ((dst->flags & (BR_PMF_LINEAR | BR_PMF_ROW_WHOLEPIXELS)) == (BR_PMF_LINEAR | BR_PMF_ROW_WHOLEPIXELS) && + (src->flags & (BR_PMF_LINEAR | BR_PMF_ROW_WHOLEPIXELS)) == (BR_PMF_LINEAR | BR_PMF_ROW_WHOLEPIXELS) && + dst->row_bytes > 0 && src->row_bytes > 0) + { + + dest = PMAP_ADDRESS(dst, 0, (dst->row_bytes > 0) ? 0 : (dst->height - 1), bytes); + source = PMAP_ADDRESS(src, 0, (dst->row_bytes > 0) ? 0 : (dst->height - 1), bytes); + + _MemCopy_A(dest, source, (dst->row_bytes * dst->height) / bytes, bytes); + } + else + { + dest = PMAP_ADDRESS(dst, 0, 0, bytes); + source = PMAP_ADDRESS(src, 0, 0, bytes); + + _MemRectCopy_A(dest, source, dst->width, dst->height, dst->row_bytes, src->row_bytes, bytes); + } +} + +void BR_ASM_CALL _BrPmMemPixelSet(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y, br_uint_32 colour) +{ + int bytes; + char *dest; + + /* + * plot to normal pixelmap + */ + bytes = BrPixelmapPixelSize(dst) >> 3; + + dest = PMAP_ADDRESS(dst, x, y, bytes); + + _MemPixelSet(dest, bytes, colour); +} + +br_uint_32 BR_ASM_CALL _BrPmMemPixelGet(br_context *ctx, br_pixelmap *dst, br_uint_16 x, br_uint_16 y) +{ + int bytes; + char *dest; + + /* + * plot to normal pixelmap + */ + bytes = BrPixelmapPixelSize(dst) >> 3; + + dest = PMAP_ADDRESS(dst, x, y, bytes); + + return _MemPixelGet(dest, bytes); +} + +void BR_ASM_CALL _BrPmMemLine(br_context *ctx, br_pixelmap *dst, br_int_16 a1, br_int_16 b1, br_int_16 a2, br_int_16 b2, + br_uint_32 colour) +{ + /* + * Symmetric Double Step Line Algorithm by Brian Wyvill from "Graphics Gems", + * Academic Press, 1990 + */ + +#define LINEPLOT(x, y, flag) \ + do \ + { \ + if (flag) \ + { \ + dest = PMAP_ADDRESS(dst, y, x, bytes); \ + } \ + else \ + { \ + dest = PMAP_ADDRESS(dst, x, y, bytes); \ + } \ + _MemPixelSet(dest, bytes, colour); \ + } while (0) + +#define swap(a, b) \ + { \ + a ^= b; \ + b ^= a; \ + a ^= b; \ + } +#define absolute(i, j, k) ((i - j) * (k = ((i - j) < 0 ? -1 : 1))) + + int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left; + int x1, y1; + int sign_x, sign_y, step, reverse, i; + char *dest; + int bytes; + + bytes = BrPixelmapPixelSize(dst) >> 3; + + dx = absolute(a2, a1, sign_x); + dy = absolute(b2, b1, sign_y); + + if (dx == 0 && dy == 0) + { + dest = PMAP_ADDRESS(dst, a1, b1, bytes); + _MemPixelSet(dest, bytes, colour); + return; + }; + + /* decide increment sign by the slope sign */ + if (sign_x == sign_y) + step = 1; + else + step = -1; + + if (dy > dx) + { /* chooses axis of greatest movement (make dx) */ + swap(a1, b1); + swap(a2, b2); + swap(dx, dy); + reverse = 1; + } + else + reverse = 0; + + /* note error check for dx==0 should be included here */ + if (a1 > a2) + { /* start from the smaller coordinate */ + x = a2; + y = b2; + x1 = a1; + y1 = b1; + } + else + { + x = a1; + y = b1; + x1 = a2; + y1 = b2; + } + + /* Note dx=n implies 0 - n or (dx+1) pixels to be set */ + /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */ + /* In fact (dx-1)/4 as 2 pixels are already plottted */ + + xend = (dx - 1) / 4; + pixels_left = (dx - 1) % 4; /* number of pixels left over at the end */ + LINEPLOT(x, y, reverse); + LINEPLOT(x1, y1, reverse); /* plot first two points */ + incr2 = 4 * dy - 2 * dx; + if (incr2 < 0) + { /* slope less than 1/2 */ + c = 2 * dy; + incr1 = 2 * c; + D = incr1 - dx; + + for (i = 0; i < xend; i++) + { /* plotting loop */ + ++x; + --x1; + if (D < 0) + { + /* pattern 1 forwards */ + LINEPLOT(x, y, reverse); + LINEPLOT(++x, y, reverse); + /* pattern 1 backwards */ + LINEPLOT(x1, y1, reverse); + LINEPLOT(--x1, y1, reverse); + D += incr1; + } + else + { + if (D < c) + { + /* pattern 2 forwards */ + LINEPLOT(x, y, reverse); + LINEPLOT(++x, y += step, reverse); + /* pattern 2 backwards */ + LINEPLOT(x1, y1, reverse); + LINEPLOT(--x1, y1 -= step, reverse); + } + else + { + /* pattern 3 forwards */ + LINEPLOT(x, y += step, reverse); + LINEPLOT(++x, y, reverse); + /* pattern 3 backwards */ + LINEPLOT(x1, y1 -= step, reverse); + LINEPLOT(--x1, y1, reverse); + } + D += incr2; + } + } /* end for */ + + /* plot last pattern */ + if (pixels_left) + { + if (D < 0) + { + LINEPLOT(++x, y, reverse); /* pattern 1 */ + if (pixels_left > 1) + LINEPLOT(++x, y, reverse); + if (pixels_left > 2) + LINEPLOT(--x1, y1, reverse); + } + else + { + if (D < c) + { + LINEPLOT(++x, y, reverse); /* pattern 2 */ + if (pixels_left > 1) + LINEPLOT(++x, y += step, reverse); + if (pixels_left > 2) + LINEPLOT(--x1, y1, reverse); + } + else + { + /* pattern 3 */ + LINEPLOT(++x, y += step, reverse); + if (pixels_left > 1) + LINEPLOT(++x, y, reverse); + if (pixels_left > 2) + LINEPLOT(--x1, y1 -= step, reverse); + } + } + } /* end if pixels_left */ + } + /* end slope < 1/2 */ + else + { /* slope greater than 1/2 */ + c = 2 * (dy - dx); + incr1 = 2 * c; + D = incr1 + dx; + for (i = 0; i < xend; i++) + { + ++x; + --x1; + if (D > 0) + { + /* pattern 4 forwards */ + LINEPLOT(x, y += step, reverse); + LINEPLOT(++x, y += step, reverse); + /* pattern 4 backwards */ + LINEPLOT(x1, y1 -= step, reverse); + LINEPLOT(--x1, y1 -= step, reverse); + D += incr1; + } + else + { + if (D < c) + { + /* pattern 2 forwards */ + LINEPLOT(x, y, reverse); + LINEPLOT(++x, y += step, reverse); + + /* pattern 2 backwards */ + LINEPLOT(x1, y1, reverse); + LINEPLOT(--x1, y1 -= step, reverse); + } + else + { + /* pattern 3 forwards */ + LINEPLOT(x, y += step, reverse); + LINEPLOT(++x, y, reverse); + /* pattern 3 backwards */ + LINEPLOT(x1, y1 -= step, reverse); + LINEPLOT(--x1, y1, reverse); + } + D += incr2; + } + } /* end for */ + /* plot last pattern */ + if (pixels_left) + { + if (D > 0) + { + LINEPLOT(++x, y += step, reverse); /* pattern 4 */ + if (pixels_left > 1) + LINEPLOT(++x, y += step, reverse); + if (pixels_left > 2) + LINEPLOT(--x1, y1 -= step, reverse); + } + else + { + if (D < c) + { + LINEPLOT(++x, y, reverse); /* pattern 2 */ + if (pixels_left > 1) + LINEPLOT(++x, y += step, reverse); + if (pixels_left > 2) + LINEPLOT(--x1, y1, reverse); + } + else + { + /* pattern 3 */ + LINEPLOT(++x, y += step, reverse); + if (pixels_left > 1) + LINEPLOT(++x, y, reverse); + if (pixels_left > 2) + { + if (D > c) /* step 3 */ + LINEPLOT(--x1, y1 -= step, reverse); + else /* step 2 */ + LINEPLOT(--x1, y1, reverse); + } + } + } + } + } +} + +void BR_ASM_CALL _BrPmMemCopyBits(br_context *ctx, br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_8 *src, + br_uint_16 s_stride, br_uint_16 start_bit, br_uint_16 end_bit, br_uint_16 nrows, + br_uint_32 colour) +{ + int bytes = BrPixelmapPixelSize(dst) >> 3; + + _MemCopyBits_A(PMAP_ADDRESS(dst, x, y, bytes), dst->row_bytes, src, s_stride, start_bit, end_bit, nrows, bytes, + colour); +} diff --git a/bren/FW/pool.c b/bren/FW/pool.c new file mode 100644 index 00000000..0ab90dad --- /dev/null +++ b/bren/FW/pool.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: pool.c 1.13 1995/08/31 16:29:42 sam Exp $ + * $Locker: $ + * + * Memory pool allocation (fixed size objects) + */ +#include "fw.h" +#include "brassert.h" + +static char rscid[] = "$Id: pool.c 1.13 1995/08/31 16:29:42 sam Exp $"; + +#if BR_POOL_DEBUG +#undef PoolAllocate +#undef PoolFree +#endif + +br_pool *BR_PUBLIC_ENTRY BrPoolAllocate(int block_size, int chunk_size, br_uint_8 mem_type) +{ + br_pool *pool = BrResAllocate(NULL, sizeof(*pool), BR_MEMORY_POOL); + + pool->free = NULL; + + if (block_size < sizeof(br_pool_block)) + block_size = sizeof(br_pool_block); + + pool->block_size = (block_size + BR_POOL_ALIGN) & ~BR_POOL_ALIGN; + pool->chunk_size = chunk_size; + pool->mem_type = mem_type; +#if BR_POOL_DEBUG + pool->count = 0; + pool->max_count = 0; +#endif + + return pool; +} + +void BR_PUBLIC_ENTRY BrPoolFree(br_pool *pool) +{ + UASSERT(BrResCheck(pool, 1)); + UASSERT(BrResClass(pool) == BR_MEMORY_POOL); + UASSERT(pool != NULL); + + BrResFree(pool); +} + +/* + * Goes through the child resources of the pool, + * and for each one that has a class matching the + * pool's mem_type, divides it up into blocks and + * adds them to the free list + */ + +static int BR_CALLBACK PoolBlockRelink(char *chunk, br_pool *pool) +{ + int size; + br_pool_block *free_ptr; + + /* + * Ignore blocks that are not of the appropriate type + */ + if (BrResClass(chunk) != (br_uint_8)pool->mem_type) + return 0; + + /* + * Go through block linking it into free list + */ + free_ptr = pool->free; + + for (size = BrResSize(chunk); size >= pool->block_size; size -= pool->block_size) + { + + ((br_pool_block *)chunk)->next = free_ptr; + free_ptr = (br_pool_block *)chunk; + chunk += pool->block_size; + } + + pool->free = free_ptr; + + return 0; +} + +/* + * Add another chunk of blocks to the end of the + * pool + */ +void BR_ASM_CALLBACK BrPoolAddChunk(br_pool *pool) +{ + br_pool_block *bp, *obp; + unsigned int i; + char *ptr; + + /* + * Allocate a new block of the appropriate size + */ + bp = BrResAllocate(pool, pool->block_size * pool->chunk_size, (br_uint_8)pool->mem_type); + + /* + * Link the block in chunk into free list + */ + PoolBlockRelink((char *)bp, pool); + +#if 0 + obp = pool->free; + + for(i=0; ichunk_size; i++) { + bp->next = obp; + obp = bp; + bp = (br_pool_block *)((char *)bp + pool->block_size); + } + + pool->free = obp; +#endif +} + +void *BR_PUBLIC_ENTRY BrPoolBlockAllocate(br_pool *pool) +{ + br_pool_block *bp; + + if (pool->free == NULL) + BrPoolAddChunk(pool); + +#if BR_POOL_DEBUG + if (++pool->count > pool->max_count) + pool->max_count = pool->count; +#endif + + bp = pool->free; + pool->free = bp->next; + return bp; +} + +void BR_PUBLIC_ENTRY BrPoolBlockFree(br_pool *pool, void *b) +{ + br_pool_block *bp = (br_pool_block *)b; + + bp->next = pool->free; + pool->free = bp; + +#if BR_POOL_DEBUG + pool->count--; +#endif +} + +void BR_PUBLIC_ENTRY BrPoolEmpty(br_pool *pool) +{ + /* + * Clear out free list + */ + pool->free = NULL; + + /* + * Go through each child resource and add + * appropriate chunks to the free list + */ + BrResChildEnum(pool, (br_resenum_cbfn *)PoolBlockRelink, pool); + +#if BR_POOL_DEBUG + pool->count = 0; + pool->max_count = 0; +#endif +} diff --git a/bren/FW/prelight.c b/bren/FW/prelight.c new file mode 100644 index 00000000..51322c1c --- /dev/null +++ b/bren/FW/prelight.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: prelight.c 1.1 1995/03/29 16:41:47 sam Exp $ + * $Locker: $ + * + * Bits of the lighting model for indexed pixels + */ +#include "fw.h" +#include "shortcut.h" +#include "brassert.h" + +static char rscid[] = "$Id: prelight.c 1.1 1995/03/29 16:41:47 sam Exp $"; + +/* + * Set the per-vertex i,r,g,b values for the model. + * + * This must be called during rendering - eg: as part of a model callback. + * If you simply want to light a few models, then sandwich the call between + * ZbSceneRenderBegin() and ZbSceneRenderEnd() + * + * If 'a' != NULL, The values are generated as if the model were attached to + * the actor 'a', otherwise the model will be in the current frame + */ +void BR_PUBLIC_ENTRY BrSceneModelLight(br_model *model, br_material *default_material, br_actor *root, br_actor *a) +{ + int gv, g, v; + br_vertex *vp; + br_material *material; + br_vertex_group *gp = model->vertex_groups; + br_scalar comp[NUM_COMPONENTS]; + br_matrix34 m2v; + + UASSERT(fw.rendering == 1); + + if (default_material == NULL) + default_material = fw.default_material; + + /* + * Save the old model_to_view matrix + */ + m2v = fw.model_to_view; + + /* + * Work out transform from actor to world + */ + if (a != NULL && root != NULL) + BrActorToRoot(a, root, &fw.model_to_view); + + BrMatrix34Inverse(&fw.view_to_model, &fw.model_to_view); + + v = 0; + + /* + * Setup lighting + */ + SurfacePerModel(); + + for (g = 0; g < model->nvertex_groups; g++, gp++) + { + + fw.material = (gp->material ? gp->material : default_material); + fw.index_base = BR_SCALAR(0.0); + fw.index_range = BR_SCALAR(255.0); + + for (gv = 0, vp = gp->vertices; gv < gp->nvertices; gv++, v++, vp++) + { + /* + * Call lighting functions for vertex + */ + LightingIndex(vp, &vp->n, comp); + LightingColour(vp, &vp->n, comp); + + /* + * Copy components into vertex + */ + vp->index = BrScalarToInt(comp[C_I]); + vp->red = BrScalarToInt(comp[C_R]); + vp->grn = BrScalarToInt(comp[C_G]); + vp->blu = BrScalarToInt(comp[C_B]); + } + } + + fw.model_to_view = m2v; +} diff --git a/bren/FW/prepmap.c b/bren/FW/prepmap.c new file mode 100644 index 00000000..c041011e --- /dev/null +++ b/bren/FW/prepmap.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: prepmap.c 1.2 1995/02/22 21:42:23 sam Exp $ + * $Locker: $ + * + * Precompute information for texture maps + */ + +#include "fw.h" +#include "brassert.h" +#include "shortcut.h" + +static char rscid[] = "$Id: prepmap.c 1.2 1995/02/22 21:42:23 sam Exp $"; + +void BR_PUBLIC_ENTRY BrMapUpdate(br_pixelmap *map, br_uint_16 flags) +{ + /* + * Call any renderer function + */ + if (fw.map_update) + fw.map_update(map, flags); +} diff --git a/bren/FW/prepmatl.c b/bren/FW/prepmatl.c new file mode 100644 index 00000000..83a04418 --- /dev/null +++ b/bren/FW/prepmatl.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: prepmatl.c 1.6 1995/02/22 21:42:24 sam Exp $ + * $Locker: $ + * + * Precompute information for materials + */ + +#include "fw.h" +#include "brassert.h" +#include "shortcut.h" + +static char rscid[] = "$Id: prepmatl.c 1.6 1995/02/22 21:42:24 sam Exp $"; + +void BR_PUBLIC_ENTRY BrMaterialUpdate(br_material *mat, br_uint_16 flags) +{ + mat->prep_flags &= ~(MATUF_SURFACE_VERTICES | MATUF_SURFACE_FACES); + + if (mat->flags & BR_MATF_SMOOTH) + mat->prep_flags |= MATUF_SURFACE_VERTICES; + else + mat->prep_flags |= MATUF_SURFACE_FACES; + + if (mat->colour_map) + mat->prep_flags |= MATUF_SURFACE_VERTICES; + + /* + * Call any renderer function + */ + if (fw.material_update) + fw.material_update(mat, flags); +} diff --git a/bren/FW/prepmesh.c b/bren/FW/prepmesh.c new file mode 100644 index 00000000..53924ab9 --- /dev/null +++ b/bren/FW/prepmesh.c @@ -0,0 +1,1391 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: prepmesh.c 1.35 1995/08/31 16:29:43 sam Exp $ + * $Locker: sam $ + * + * Precompute information for triangle meshes: + * Face normals + * Vertex normals + * Edge numbers + * Bounding radius + */ +#include +#include + +#if DEBUG +#include +#include +#endif + +#include "fw.h" +#include "brassert.h" +#include "shortcut.h" + +static char rscid[] = "$Id: prepmesh.c 1.35 1995/08/31 16:29:43 sam Exp $"; + +#define SORT_MAT_TYPES 0 + +/* + * Temporary structure used whilst processing normals and groups + */ +struct group_temp_vertex +{ + br_material *m; + br_vertex *v; + br_int_32 group; + br_int_32 index; + br_face *fp; + br_vector3 n; + + /* XXX Should pack down to + br_vector3 n; + br_int_16 vertex; + br_int_16 face; + */ +}; + +/* + * Scratch space for edges - the temporary edge structures are hashed + * on their first vertex - all similar vertices are the singly linked in + * a chain + */ +struct pm_temp_edge +{ + struct pm_temp_edge *next; /* next in chain */ + short first; /* First vertex */ + short last; /* Last Vertex */ + char other; /* Edge is used in other direction */ +}; + +static struct pm_temp_edge *pm_edge_table; +static struct pm_temp_edge **pm_edge_hash; + +static char *pm_edge_scratch; +static int num_edges = 0; + +static int FwAddEdge(short first, short last) +{ + struct pm_temp_edge *tep; + + /* + * See if edge exists and can be used in other direction + */ + for (tep = pm_edge_hash[last]; tep; tep = tep->next) + { + + if (tep->last == first && tep->other == 0) + { + /* + * Yup, flag as used and return index + */ + tep->other = 1; + return tep - pm_edge_table; + } + } + + /* + * Create new edge + */ + tep = pm_edge_table + num_edges; + + tep->first = first; + tep->last = last; + tep->other = 0; + tep->next = pm_edge_hash[first]; + pm_edge_hash[first] = tep; + + return num_edges++; +} + +/* + * Comparison function for qsorting pointers to faces + */ +static int BR_CALLBACK FacesCompare(const void *p1, const void *p2) +{ + const br_face *f1 = *(br_face **)p1, *f2 = *(br_face **)p2; + +#if SORT_MAT_TYPES + int flags1, flags2; + + flags1 = f1->material ? f1->material->flags : 0; + flags2 = f2->material ? f2->material->flags : 0; + + if (flags1 > flags2) + return 1; + if (flags1 < flags2) + return -1; +#endif + + if (f1->material > f2->material) + return 1; + if (f1->material < f2->material) + return -1; + + return 0; +} + +/* + * Compare temp vertices by X,Y,Z + */ +static int BR_CALLBACK TVCompare_XYZ(const void *p1, const void *p2) +{ + const struct group_temp_vertex *tv1 = *(struct group_temp_vertex **)p1; + const struct group_temp_vertex *tv2 = *(struct group_temp_vertex **)p2; + int i; + + if (tv1->v == tv2->v) + return 0; + + for (i = 0; i < 3; i++) + { + if (tv1->v->p.v[i] > tv2->v->p.v[i]) + return 1; + if (tv1->v->p.v[i] < tv2->v->p.v[i]) + return -1; + } + + return 0; +} + +#if 0 +/* + * Compare temp vertices by vertex pointer + */ +static int BR_CALLBACK TVCompare_V(const void *p1, const void *p2) +{ + const struct group_temp_vertex *tv1 = *(struct group_temp_vertex **)p1; + const struct group_temp_vertex *tv2 = *(struct group_temp_vertex **)p2; + + if(tv1->v > tv2->v) + return 1; + if(tv1->v < tv2->v) + return -1; + + return 0; +} +#endif + +/* + * Compare temp vertices by Material, X,Y,Z,U,V Normal + */ +static int BR_CALLBACK TVCompare_MXYZUVN(const void *p1, const void *p2) +{ + const struct group_temp_vertex *tv1 = *(struct group_temp_vertex **)p1; + const struct group_temp_vertex *tv2 = *(struct group_temp_vertex **)p2; + int i; + +#if SORT_MAT_TYPES + int flags1, flags2; + + flags1 = tv1->m ? tv1->m->flags : 0; + flags2 = tv2->m ? tv2->m->flags : 0; + + /* + * Material + */ + if (flags1 > flags2) + return 1; + if (flags1 < flags2) + return -1; +#endif + + if (tv1->m > tv2->m) + return 1; + if (tv1->m < tv2->m) + return -1; + + if (tv1->v != tv2->v) + { + /* + * X,Y,Z + */ + for (i = 0; i < 3; i++) + { + if (tv1->v->p.v[i] > tv2->v->p.v[i]) + return 1; + if (tv1->v->p.v[i] < tv2->v->p.v[i]) + return -1; + } + + /* + * U,V + */ + for (i = 0; i < 2; i++) + { + if (tv1->v->map.v[i] > tv2->v->map.v[i]) + return 1; + if (tv1->v->map.v[i] < tv2->v->map.v[i]) + return -1; + } + } + + /* + * Normal + */ + for (i = 0; i < 3; i++) + { + if (tv1->n.v[i] > tv2->n.v[i]) + return 1; + if (tv1->n.v[i] < tv2->n.v[i]) + return -1; + } + + return 0; +} + +/* + * Compare temp vertices by material, vertex pointer, Normal + */ +static int BR_CALLBACK TVCompare_MVN(const void *p1, const void *p2) +{ + const struct group_temp_vertex *tv1 = *(struct group_temp_vertex **)p1; + const struct group_temp_vertex *tv2 = *(struct group_temp_vertex **)p2; + int i; + +#if SORT_MAT_TYPES + int flags1, flags2; + + flags1 = tv1->m ? tv1->m->flags : 0; + flags2 = tv2->m ? tv2->m->flags : 0; + + /* + * Material + */ + if (flags1 > flags2) + return 1; + if (flags1 < flags2) + return -1; +#endif + + /* + * Material + */ + if (tv1->m > tv2->m) + return 1; + if (tv1->m < tv2->m) + return -1; + + if (tv1->v > tv2->v) + return 1; + if (tv1->v < tv2->v) + return -1; + + /* + * Normal + */ + for (i = 0; i < 3; i++) + { + if (tv1->n.v[i] > tv2->n.v[i]) + return 1; + if (tv1->n.v[i] < tv2->n.v[i]) + return -1; + } + + return 0; +} + +/* + * Work out face normals for original faces + */ +static void PlaneEqn(br_vector3 *v0, br_vector3 *v1, br_vector3 *v2, br_fvector3 *fn, br_scalar *d) +{ +#if 0 + br_vector3 a,b,n; + + BrVector3Sub(&a,v1,v0); + BrVector3Sub(&b,v2,v0); + BrVector3Cross(&n,&a,&b); + BrFVector3Normalise(fn,&n); + + *d = BrFVector3Dot(fn,v0); +#endif + +#if 1 + /* + * Do plane equation calcs. in floating point to + * get the accuracy + */ + br_vector3 a, b; + float ax, ay, az; + float bx, by, bz; + float nx, ny, nz; + float l; + + BrVector3Sub(&a, v1, v0); + BrVector3Sub(&b, v2, v0); + + ax = BrScalarToFloat(a.v[0]); + ay = BrScalarToFloat(a.v[1]); + az = BrScalarToFloat(a.v[2]); + + bx = BrScalarToFloat(b.v[0]); + by = BrScalarToFloat(b.v[1]); + bz = BrScalarToFloat(b.v[2]); + + nx = ay * bz - az * by; + ny = az * bx - ax * bz; + nz = ax * by - ay * bx; + + l = sqrt(nx * nx + ny * ny + nz * nz); + + if (l != 0) + { + l = 1.0 / l; + nx *= l; + ny *= l; + nz *= l; + + fn->v[0] = BR_FRACTION(nx); + fn->v[1] = BR_FRACTION(ny); + fn->v[2] = BR_FRACTION(nz); + } + else + { + fn->v[0] = BR_FRACTION(0.0); + fn->v[1] = BR_FRACTION(0.0); + fn->v[2] = BR_FRACTION(1.0); + } + + *d = BrFVector3Dot(fn, v0); +#endif +} + +static void PrepareFaceNormals(br_model *model) +{ + br_vertex *vertices = model->vertices; + br_face *fp; + int f; + + ASSERT(model->faces && model->vertices); + + fp = model->faces; + for (f = 0; f < model->nfaces; f++, fp++) + PlaneEqn(&vertices[fp->vertices[0]].p, &vertices[fp->vertices[1]].p, &vertices[fp->vertices[2]].p, &fp->n, + &fp->d); +} + +/* + * Work out face normals for prepared faces + */ +static void PrepareFaceNormalsFast(br_model *model) +{ + br_vector3 a, b, n; + br_vertex *vertices = model->prepared_vertices; + br_face *fp; + int f; + + ASSERT(model->prepared_faces && model->prepared_vertices); + + fp = model->prepared_faces; + for (f = 0; f < model->nfaces; f++, fp++) + PlaneEqn(&vertices[fp->vertices[0]].p, &vertices[fp->vertices[1]].p, &vertices[fp->vertices[2]].p, &fp->n, + &fp->d); +} + +/* + * Work out vertex normals for prepared vertices - ignores smoothing groups + */ +static void PrepareVertexNormalsFast(br_model *model) +{ + int f, v; + br_face *fp; + br_vertex *vp; + br_vector3 *vertex_sums, *vsp; + + /* + * Allocate vertex normal sums + */ + vertex_sums = BrScratchAllocate(model->nprepared_vertices * sizeof(*vertex_sums)); + memset(vertex_sums, 0, model->nprepared_vertices * sizeof(*vertex_sums)); + + /* + * For each face, add face's normal to it's attached vertices + */ + fp = model->prepared_faces; + for (f = 1; f < model->nprepared_faces; f++, fp++) + { + BrVector3Accumulate(vertex_sums + fp->vertices[0], &fp->n); + BrVector3Accumulate(vertex_sums + fp->vertices[1], &fp->n); + BrVector3Accumulate(vertex_sums + fp->vertices[2], &fp->n); + } + + /* + * Normalise the accumulated vectors into the vertices + */ + vp = model->prepared_vertices; + vsp = vertex_sums; + + for (v = 0; v < model->nprepared_vertices; v++, vp++, vsp++) + { + BrFVector3Normalise(&vp->n, vsp); + } + + BrScratchFree(vertex_sums); +} + +/* + * Rearrange faces into groups by material + */ +static void PrepareFaces(br_model *model) +{ + int f, g, count; + br_face **face_ptrs; + + ASSERT(model != NULL); + ASSERT(model->faces != NULL); + + /* + * Undo any sharing of prepared faces + */ + if (model->faces == model->prepared_faces) + { + ASSERT(model->nfaces == model->nprepared_faces); + model->prepared_faces = NULL; + model->nprepared_faces = 0; + } + + /* + * Release any previous array if it is not the right size + */ + if (model->prepared_faces && (model->nfaces != model->nprepared_faces)) + { + BrResFree(model->prepared_faces); + model->prepared_faces = NULL; + model->nprepared_faces = 0; + } + + /* + * Allocate a prepared_faces table of the right size + */ + if (model->prepared_faces == NULL) + { + + model->prepared_faces = + BrResAllocate(model, model->nfaces * sizeof(*model->prepared_faces), BR_MEMORY_PREPARED_FACES); + + model->nprepared_faces = model->nfaces; + } + + ASSERT(model->nprepared_faces == model->nfaces); + + /* + * Sort the faces based on (if available) material type,and then material pointer + */ + face_ptrs = BrScratchAllocate(sizeof(*face_ptrs) * model->nprepared_faces); + + for (f = 0; f < model->nfaces; f++) + face_ptrs[f] = model->faces + f; + + BrQsort(face_ptrs, model->nprepared_faces, sizeof(*face_ptrs), FacesCompare); + + /* + * Build face tags array + */ + if (model->flags & BR_MODF_GENERATE_TAGS) + { + + if (model->face_tags) + BrResFree(model->face_tags); + + model->face_tags = BrResAllocate(model, sizeof(*model->face_tags) * model->nprepared_faces, BR_MEMORY_SCRATCH); + + for (f = 0; f < model->nprepared_faces; f++) + model->face_tags[f] = face_ptrs[f] - model->faces; + } + + /* + * Build new face table + */ + for (f = 0; f < model->nprepared_faces; f++) + { + model->prepared_faces[f] = *face_ptrs[f]; + } + + /* + * Release scratch + */ + BrScratchFree(face_ptrs); + + /* + * Release any old faces + */ + if (!(model->flags & BR_MODF_KEEP_ORIGINAL)) + { + ASSERT(model->faces); + BrResFree(model->faces); + model->faces = model->prepared_faces; + model->nfaces = model->nprepared_faces; + } +} + +/* + * Don't do any sorting, the prepared faces are the same as the faces + */ +static void PrepareFacesFast(br_model *model) +{ + int f, g, count; + + /* + * If there is a sorted copy of the faces, ditch it + */ + if (model->prepared_faces && (model->prepared_faces != model->faces)) + BrResFree(model->prepared_faces); + + model->nprepared_faces = model->nfaces; + model->prepared_faces = model->faces; + + /* + * Build face tags array + */ + if (model->flags & BR_MODF_GENERATE_TAGS) + { + + if (model->face_tags) + BrResFree(model->face_tags); + + model->face_tags = BrResAllocate(model, sizeof(*model->face_tags) * model->nprepared_faces, BR_MEMORY_SCRATCH); + + for (f = 0; f < model->nprepared_faces; f++) + model->face_tags[f] = f; + } +} + +static void PrepareFaceGroups(br_model *model) +{ + int f, g, count; + + /* + * Go through sorted faces and find number of groups + */ + for (f = 1, g = 1; f < model->nprepared_faces; f++) + if (model->prepared_faces[f].material != model->prepared_faces[f - 1].material) + g++; + + /* + * Allocate and fill in face group table + */ + if (model->face_groups != NULL && model->nface_groups != g) + { + /* + * Remove any old table + */ + BrResFree(model->face_groups); + model->face_groups = NULL; + } + + if (model->face_groups == NULL) + model->face_groups = BrResAllocate(model, g * sizeof(*model->face_groups), BR_MEMORY_GROUPS); + + model->nface_groups = g; + model->face_groups[0].faces = model->prepared_faces; + + for (f = 1, g = 0, count = 1; f < model->nprepared_faces; f++, count++) + { + if (model->prepared_faces[f].material != model->prepared_faces[f - 1].material) + { + model->face_groups[g].material = model->prepared_faces[f - 1].material; + model->face_groups[g].nfaces = count; + model->face_groups[g + 1].faces = model->prepared_faces + f; + count = 0; + g++; + } + } + model->face_groups[g].material = model->prepared_faces[f - 1].material; + model->face_groups[g].nfaces = count; +} + +/* + * Given a group of temp_vertices that are deemeed to be co-incident, + * accumulate the normals for each vertex by adding all + * normals in the groups that share at least 1 smoothing group + */ +static void AccumulateSmoothing(struct group_temp_vertex **start, struct group_temp_vertex **end) +{ + struct group_temp_vertex **outer, **inner; + + for (outer = start; outer < end; outer++) + for (inner = start; inner < end; inner++) + if ((*outer)->fp->smoothing & (*inner)->fp->smoothing) + BrVector3Accumulate(&(*outer)->n, &(*inner)->fp->n); +} + +/* + * Generate the prepared vertex table - split vertices at material and smoothing group boundaries + */ +br_material **PrepareVertices(br_model *model) +{ + struct group_temp_vertex *temp_verts, *gtvp, **sorted; + int f, v, count, i, ntemps, num_shared, simple_smoothing; + br_face *fp; + br_vertex *old_vertices, *vp; + br_qsort_cbfn *vertex_compare_1; + br_qsort_cbfn *vertex_compare_2; + br_uint_16 *shared_table; + void *scratch; + br_size_t scratch_size; + br_material **materials; + + ASSERT(model != NULL); + ASSERT(model->vertices != NULL); + + /* + * Undo any sharing of prepared vertices + */ + if (model->vertices == model->prepared_vertices) + { + ASSERT(model->nvertices == model->nprepared_vertices); + model->prepared_vertices = NULL; + model->nprepared_vertices = 0; + } + + if (model->flags & BR_MODF_DONT_WELD) + { + vertex_compare_1 = TVCompare_XYZ; + vertex_compare_2 = TVCompare_MVN; + } + else + { + vertex_compare_1 = TVCompare_XYZ; + vertex_compare_2 = TVCompare_MXYZUVN; + } + + ASSERT(model->vertices != NULL && model->nvertices != 0); + + /* + * Create a per face vertex table, and a table of pointers + * to each member, which is then sorted in various ways + */ + ntemps = model->nprepared_faces * 3; + + scratch_size = ntemps * (sizeof(*temp_verts) + sizeof(*sorted)); + scratch = BrScratchAllocate(scratch_size); + + memset(scratch, 0, scratch_size); + + temp_verts = scratch; + sorted = (struct group_temp_vertex **)(temp_verts + ntemps); + + gtvp = temp_verts; + + for (i = 0, f = 0, fp = model->prepared_faces; f < model->nprepared_faces; f++, fp++) + { + for (v = 0; v < 3; v++, i++, gtvp++) + { + + ASSERT(gtvp < temp_verts + model->nprepared_faces * 3); + + gtvp->m = fp->material; + gtvp->v = model->vertices + fp->vertices[v]; + gtvp->fp = fp; + + sorted[i] = gtvp; + } + } + + ASSERT(i == ntemps); + ASSERT(gtvp == temp_verts + ntemps); + + /* + * Accumulate normals for each group of temp verts + * that reference the same original vertex + */ + BrQsort(sorted, ntemps, sizeof(*sorted), vertex_compare_1); + + for (v = 0, i = 0; v < ntemps - 1; v++) + { + + if (vertex_compare_1(sorted + v, sorted + v + 1)) + { + /* + * Process a group of vertices + */ + AccumulateSmoothing(sorted + i, sorted + v + 1); + i = v + 1; + } + } + + AccumulateSmoothing(sorted + i, sorted + ntemps); + + /* + * Resort pointers by material, vertex, normal + */ + BrQsort(sorted, ntemps, sizeof(*sorted), vertex_compare_2); + + /* + * Count distinct and vertices + */ + count = 0; + for (v = 0, i = 0; v < ntemps - 1; v++) + { + + sorted[v]->index = count; + + /* + * New Vertex + */ + if (vertex_compare_2(sorted + v, sorted + v + 1)) + count++; + } + sorted[v]->index = count; + count++; + + /* + * Remove any previous prepared table + */ + if (model->prepared_vertices != NULL && model->nprepared_vertices != count) + { + BrResFree(model->prepared_vertices); + model->prepared_vertices = NULL; + model->nprepared_vertices = 0; + } + + /* + * Allocate new vertex table + */ + if (model->prepared_vertices == NULL) + model->prepared_vertices = BrResAllocate(model, count * sizeof(br_vertex), BR_MEMORY_PREPARED_VERTICES); + model->nprepared_vertices = count; + + /* + * Generate new vertices and an index of materials for each vertex + */ + count = 0; + vp = model->prepared_vertices; + materials = BrResAllocate(model, sizeof(*materials) * model->nprepared_vertices, BR_MEMORY_SCRATCH); + + for (v = 0, i = 0; v < ntemps - 1; v++) + { + + ASSERT(sorted[v]->index == count); + + /* + * New Vertex + */ + if (sorted[v]->index != sorted[v + 1]->index) + { + *vp = *sorted[v]->v; + BrFVector3Normalise(&vp->n, &sorted[v]->n); + materials[count] = sorted[v]->m; + count++; + vp++; + } + } + + /* + * Handle last vertex + */ + *vp = *sorted[v]->v; + BrFVector3Normalise(&vp->n, &sorted[v]->n); + materials[count] = sorted[v]->m; + + /* + * Relink faces to new vertices + */ + gtvp = temp_verts; + + for (i = 0, f = 0, fp = model->prepared_faces; f < model->nprepared_faces; f++, fp++) + for (v = 0; v < 3; v++, i++, gtvp++) + fp->vertices[v] = gtvp->index; + + /* + * Build vertex tags array + */ + if (model->flags & BR_MODF_GENERATE_TAGS) + { + + if (model->vertex_tags) + BrResFree(model->vertex_tags); + + model->vertex_tags = + BrResAllocate(model, sizeof(*model->vertex_tags) * model->nprepared_vertices, BR_MEMORY_SCRATCH); + + for (v = 0; v < ntemps; v++) + model->vertex_tags[temp_verts[v].index] = temp_verts[v].v - model->vertices; + } + + /* + * Free up scratch space + */ + BrScratchFree(scratch); + + /* + * Release the old vertices, if not needed + */ + if (!(model->flags & BR_MODF_KEEP_ORIGINAL)) + { + if (model->vertices) + BrResFree(model->vertices); + + /* + * Share vertices with prepared + */ + model->vertices = model->prepared_vertices; + model->nvertices = model->nprepared_vertices; + } + + return materials; +} + +/* + * Generate the prepared vertex table - quick and dirty + * May create more vertices than necessary + */ +br_material **PrepareVerticesFast(br_model *model) +{ + struct + { + br_vertex *v; + br_material *m; + } * temp_verts, **vert_index; + br_material **materials; + br_face *fp; + br_size_t scratch_size; + int f, v; + int count = 0; + + ASSERT(model != NULL); + ASSERT(model->vertices != NULL); + + /* + * Undo any sharing of prepared vertices + */ + if (model->vertices == model->prepared_vertices) + { + ASSERT(model->nvertices == model->nprepared_vertices); + model->prepared_vertices = NULL; + model->nprepared_vertices = 0; + } + + scratch_size = model->nvertices * sizeof(*vert_index) + model->nprepared_faces * 3 * sizeof(*temp_verts); + + vert_index = BrScratchAllocate(scratch_size); + temp_verts = (void *)((char *)vert_index + model->nvertices * sizeof(*vert_index)); + + memset(vert_index, 0, model->nvertices * sizeof(*vert_index)); + + for (f = 0, fp = model->prepared_faces; f < model->nprepared_faces; f++, fp++) + { + for (v = 0; v < 3; v++) + { + /* + * See if the vertex has already been allocated, and if the material matches + */ + if ((vert_index[fp->vertices[v]]) && vert_index[fp->vertices[v]]->m == fp->material) + { + + fp->vertices[v] = vert_index[fp->vertices[v]] - temp_verts; + continue; + } + + /* + * Build a new vertex + */ + temp_verts[count].v = model->vertices + fp->vertices[v]; + temp_verts[count].m = fp->material; + vert_index[fp->vertices[v]] = temp_verts + count; + fp->vertices[v] = count; + + count++; + } + } + + /* + * Build the new vertex and material tables + */ + /* + * Remove any previous prepared table + */ + if (model->prepared_vertices != NULL && model->nprepared_vertices != count) + { + BrResFree(model->prepared_vertices); + model->prepared_vertices = NULL; + model->nprepared_vertices = 0; + } + + /* + * Allocate new vertex table + */ + if (model->prepared_vertices == NULL) + model->prepared_vertices = BrResAllocate(model, count * sizeof(br_vertex), BR_MEMORY_PREPARED_VERTICES); + model->nprepared_vertices = count; + + materials = BrResAllocate(model, sizeof(*materials) * count, BR_MEMORY_SCRATCH); + + for (v = 0; v < model->nprepared_vertices; v++) + { + model->prepared_vertices[v] = *temp_verts[v].v; + materials[v] = temp_verts[v].m; + } + + /* + * Build vertex tags array + */ + if (model->flags & BR_MODF_GENERATE_TAGS) + { + + if (model->vertex_tags) + BrResFree(model->vertex_tags); + + model->vertex_tags = + BrResAllocate(model, sizeof(*model->vertex_tags) * model->nprepared_vertices, BR_MEMORY_SCRATCH); + + for (v = 0; v < model->nprepared_vertices; v++) + model->vertex_tags[v] = temp_verts[v].v - model->vertices; + } + + /* + * Release scratch space + */ + BrScratchFree(vert_index); + + /* + * Release the old vertices, if not needed + */ + if (!(model->flags & BR_MODF_KEEP_ORIGINAL)) + { + if (model->vertices) + BrResFree(model->vertices); + + /* + * Share vertices with prepared + */ + model->vertices = model->prepared_vertices; + model->nvertices = model->nprepared_vertices; + } + + return materials; +} + +static void PrepareVertexGroups(br_model *model, br_material **vertex_materials) +{ + int g, v, count; + br_vertex *vp; + br_vertex_group *gp; + + /* + * Count material groups + */ + for (v = 1, g = 1; v < model->nprepared_vertices; v++) + if (vertex_materials[v] != vertex_materials[v - 1]) + g++; + + /* + * Allocate and fill in vertex group table + */ + if (model->vertex_groups) + BrResFree(model->vertex_groups); + + model->vertex_groups = BrResAllocate(model, g * sizeof(*model->vertex_groups), BR_MEMORY_GROUPS); + model->nvertex_groups = g; + + /* + * Generate new vertex groups + */ + gp = model->vertex_groups; + vp = model->prepared_vertices; + + gp->vertices = vp; + gp->material = vertex_materials[0]; + + for (v = 1, vp++; v < model->nprepared_vertices; v++, vp++) + { + if (vertex_materials[v] != vertex_materials[v - 1]) + { + gp->nvertices = vp - gp->vertices; + gp++; + gp->vertices = vp; + gp->material = vertex_materials[v]; + } + } + + gp->nvertices = vp - gp->vertices; +} + +/* + * Build edge references for each face + */ +void PrepareEdges(br_model *model) +{ + br_size_t scratch_size; + br_face *fp; + int f; + + scratch_size = model->nfaces * 3 * sizeof(*pm_edge_table) + model->nvertices * sizeof(*pm_edge_hash); + + pm_edge_scratch = BrScratchAllocate(scratch_size); + + /* + * Divvy up scratch area and clear hash pointers + */ + pm_edge_hash = (struct pm_temp_edge **)pm_edge_scratch; + pm_edge_table = (struct pm_temp_edge *)(pm_edge_scratch + model->nvertices * sizeof(*pm_edge_hash)); + + memset(pm_edge_hash, 0, model->nvertices * sizeof(*pm_edge_hash)); + + /* + * Accumulate shared edges from each face + */ + num_edges = 0; + fp = model->faces; + + for (f = 0; f < model->nfaces; f++, fp++) + { + fp->edges[0] = FwAddEdge(fp->vertices[0], fp->vertices[1]); + fp->edges[1] = FwAddEdge(fp->vertices[1], fp->vertices[2]); + fp->edges[2] = FwAddEdge(fp->vertices[2], fp->vertices[0]); + } + + model->nedges = num_edges; + + BrScratchFree(pm_edge_scratch); +} + +/* + * Find bounding radius of model + */ +static void PrepareBoundingRadius(br_model *model) +{ + br_scalar d, max = BR_SCALAR(0.0); + int v; + br_vertex *vp; + + /* + * XXX this is really dodgy in fixed point + */ + for (v = 0, vp = model->vertices; v < model->nvertices; v++, vp++) + { + d = BrVector3LengthSquared(&vp->p); + + if (d > max) + max = d; + } + + model->radius = BR_SQRT(max); +} + +#if DEBUG +void VertexDump(char *prefix, br_vertex *vp) +{ + BrLogPrintf("%sp=(% 5.2g,% 5.2g,% 5.2g) map=(% 5.2g,% 5.2g) n=(% 5.2g,% 5.2g,% 5.2g) r=%d\n", prefix, + BrScalarToFloat(vp->p.v[X]), BrScalarToFloat(vp->p.v[Y]), BrScalarToFloat(vp->p.v[Z]), + BrScalarToFloat(vp->map.v[X]), BrScalarToFloat(vp->map.v[Y]), + BrScalarToFloat(BrFractionToScalar(vp->n.v[X])), BrScalarToFloat(BrFractionToScalar(vp->n.v[Y])), + BrScalarToFloat(BrFractionToScalar(vp->n.v[Z])), vp->r); +} + +void FaceDump(char *prefix, br_face *fp) +{ + BrLogPrintf("%svertices=(%2d,%2d,%2d) edges=(%2d,%2d,%2d) smoothing=%04x flags=%02x material=%s\n", prefix, + fp->vertices[0], fp->vertices[1], fp->vertices[2], fp->edges[0], fp->edges[1], fp->edges[2], + fp->smoothing, fp->flags, + fp->material ? (fp->material->identifier ? fp->material->identifier : "???") : "DEFAULT"); +} + +void FaceGroupDump(char *prefix, br_face_group *gp, br_face *base_face) +{ + BrLogPrintf("%sfaces = %p (%d) nfaces=%d material=%s\n", prefix, gp->faces, gp->faces - base_face, gp->nfaces, + gp->material ? (gp->material->identifier ? gp->material->identifier : "???") : "DEFAULT"); +} + +void VertexGroupDump(char *prefix, br_vertex_group *gp, br_vertex *base_vertex) +{ + BrLogPrintf("%svertices = %p (%d) nvertices=%d material=%s\n", prefix, gp->vertices, gp->vertices - base_vertex, + gp->nvertices, + gp->material ? (gp->material->identifier ? gp->material->identifier : "???") : "DEFAULT"); +} + +void ModelDump(char *prefix, br_model *model) +{ + int v; + int f; + char tmp[80]; + + /* + * Print all the model entries + */ + BrLogPrintf("%sidentifier = \"%s\"\n", prefix, model->identifier ? model->identifier : "NULL"); + BrLogPrintf("%svertices = %p\n", prefix, model->vertices); + BrLogPrintf("%sfaces = %p\n", prefix, model->faces); + BrLogPrintf("%snvertices = %d\n", prefix, model->nvertices); + BrLogPrintf("%snfaces = %d\n", prefix, model->nfaces); + BrLogPrintf("%spivot = (%g,%g,%g)\n", prefix, BrScalarToFloat(model->pivot.v[X]), + BrScalarToFloat(model->pivot.v[X]), BrScalarToFloat(model->pivot.v[X])); + BrLogPrintf("%sflags = %04x\n", prefix, model->flags); + BrLogPrintf("%sradius = %g\n", prefix, BrScalarToFloat(model->radius)); + BrLogPrintf("%snface_groups = %d\n", prefix, model->nface_groups); + BrLogPrintf("%snvertex_groups = %d\n", prefix, model->nvertex_groups); + BrLogPrintf("%snedges = %d\n", prefix, model->nedges); + BrLogPrintf("%snprepared_vertices = %d\n", prefix, model->nprepared_vertices); + BrLogPrintf("%snprepared_faces = %d\n", prefix, model->nprepared_faces); + BrLogPrintf("%sface_groups = %p\n", prefix, model->face_groups); + BrLogPrintf("%svertex_groups = %p\n", prefix, model->vertex_groups); + BrLogPrintf("%sprepared_vertices = %p\n", prefix, model->prepared_vertices); + BrLogPrintf("%sprepared_faces = %p\n", prefix, model->prepared_faces); + + BrLogPrintf("\n"); + if (model->vertices) + { + for (v = 0; v < model->nvertices; v++) + { + sprintf(tmp, "model->vertices[%2d].", v); + VertexDump(tmp, model->vertices + v); + } + } + + BrLogPrintf("\n"); + + if (model->faces) + { + for (f = 0; f < model->nfaces; f++) + { + sprintf(tmp, "model->faces[%2d].", f); + FaceDump(tmp, model->faces + f); + } + } + + BrLogPrintf("\n"); + if (model->prepared_vertices) + { + for (v = 0; v < model->nprepared_vertices; v++) + { + sprintf(tmp, "model->prepared_vertices[%2d].", v); + VertexDump(tmp, model->prepared_vertices + v); + } + } + + BrLogPrintf("\n"); + + if (model->prepared_faces) + { + for (f = 0; f < model->nprepared_faces; f++) + { + sprintf(tmp, "model->prepared_faces[%2d].", f); + FaceDump(tmp, model->prepared_faces + f); + } + } + + BrLogPrintf("\n"); + + if (model->face_groups) + { + for (f = 0; f < model->nface_groups; f++) + { + sprintf(tmp, "model->face_groups[%2d].", f); + FaceGroupDump(tmp, model->face_groups + f, model->prepared_faces); + } + } + + BrLogPrintf("\n"); + + if (model->vertex_groups) + { + for (v = 0; v < model->nvertex_groups; v++) + { + sprintf(tmp, "model->vertex_groups[%2d].", v); + VertexGroupDump(tmp, model->vertex_groups + v, model->prepared_vertices); + } + } +} + +#endif + +/* + * Find bounding box of model + */ +static void PrepareBoundingBox(br_model *model) +{ + int axis, v; + br_vertex *vp; + br_scalar x; + + /* + * Initialise bounding box to first vertex + */ + for (axis = 0; axis < 3; axis++) + model->bounds.min.v[axis] = model->bounds.max.v[axis] = model->prepared_vertices[0].p.v[axis]; + + /* + * Expand bounding box with remaining vertices + */ + for (v = 1, vp = model->prepared_vertices + 1; v < model->nprepared_vertices; v++, vp++) + { + for (axis = 0; axis < 3; axis++) + { + + x = vp->p.v[axis]; + + if (x > model->bounds.max.v[axis]) + model->bounds.max.v[axis] = x; + + if (x < model->bounds.min.v[axis]) + model->bounds.min.v[axis] = x; + } + } +} + +/* + * Do all model preprocessing + */ +void BR_PUBLIC_ENTRY BrModelUpdate(br_model *model, br_uint_16 flags) +{ + int g, f, v, count, axis; + br_vector3 a, b, n; + br_vertex *vertices = model->vertices, *vp, *old_vertices; + br_face *fp; + br_scalar d, max; + br_material *mp, **mpp; + +#if 0 + BrLogPrintf("Before ModelUpdate...\n"); + ModelDump(" ", model); +#endif + + /* + * Do not do anything if model is marked as being pre-prepared + */ + if (model->flags & BR_MODF_PREPREPARED) + return; + + /* + * If model has no faces, remove groups and do nothing involving + * faces + */ + if (model->faces == NULL || model->vertices == NULL) + return; + + if (model->nfaces == 0) + { + if (model->face_groups) + BrResFree(model->face_groups); + model->face_groups = NULL; + + flags &= ~(BR_MODU_NORMALS | BR_MODU_EDGES | BR_MODU_GROUPS); + } + + /* + * Check that faces do not reference non-existant vertices + */ + fp = model->faces; + + for (f = 0; f < model->nfaces; f++, fp++) + for (v = 0; v < 3; v++) + if (fp->vertices[v] >= model->nvertices) + BR_ERROR2("face references invalid vertex f=%d v=%d", f, v); + /* + * See if pivot point is not zero + */ + if ((model->pivot.v[0] != S0) || (model->pivot.v[1] != S0) || (model->pivot.v[2] != S0)) + model->prep_flags |= MODUF_HAS_PIVOT; + else + model->prep_flags &= ~MODUF_HAS_PIVOT; + + /* + * Edge numbers + */ + if (flags & BR_MODU_EDGES) + PrepareEdges(model); + + /* + * Vertex normals and groups + */ + if (flags & BR_MODU_GROUPS) + { + + if (model->flags & BR_MODF_QUICK_UPDATE) + { + /* + * Dont sort faces or vertices + */ + PrepareFaceNormals(model); + + PrepareFacesFast(model); + PrepareFaceGroups(model); + + mpp = PrepareVerticesFast(model); + PrepareVertexGroups(model, mpp); + BrResFree(mpp); + + PrepareVertexNormalsFast(model); + + model->prep_flags &= ~MODUF_VERTEX_GROUPS_MATCH; + } + else + { + /* + * Sort faces into groups the slow way + */ + PrepareFaceNormals(model); + + PrepareFaces(model); + PrepareFaceGroups(model); + + mpp = PrepareVertices(model); + PrepareVertexGroups(model, mpp); + BrResFree(mpp); + + model->prep_flags |= MODUF_VERTEX_GROUPS_MATCH; + } + + /* + * Offset prepared vertices by pivot point + */ + if (model->prep_flags & MODUF_HAS_PIVOT) + { + for (v = 0; v < model->nprepared_vertices; v++) + { + model->prepared_vertices[v].p.v[0] -= model->pivot.v[0]; + model->prepared_vertices[v].p.v[1] -= model->pivot.v[1]; + model->prepared_vertices[v].p.v[2] -= model->pivot.v[2]; + } + } + } + + /* + * Bounding radius + * + */ + if (flags & BR_MODU_RADIUS) + PrepareBoundingRadius(model); + + /* + * Bounding box + */ + if (flags & BR_MODU_BOUNDING_BOX) + PrepareBoundingBox(model); + + if ((flags & (BR_MODU_NORMALS | BR_MODU_GROUPS)) == BR_MODU_NORMALS) + { + /* + * Just regenerate normals + */ + /* + * Copy XYZ from original faces - if available + */ + if ((model->flags & (BR_MODF_KEEP_ORIGINAL | BR_MODF_GENERATE_TAGS)) == + (BR_MODF_KEEP_ORIGINAL | BR_MODF_GENERATE_TAGS)) + { + + for (v = 0, vp = model->prepared_vertices; v < model->nprepared_vertices; v++, vp++) + { + vp->p.v[0] = model->vertices[model->vertex_tags[v]].p.v[0] - model->pivot.v[0]; + vp->p.v[1] = model->vertices[model->vertex_tags[v]].p.v[1] - model->pivot.v[1]; + vp->p.v[2] = model->vertices[model->vertex_tags[v]].p.v[2] - model->pivot.v[2]; + } + } + + PrepareFaceNormalsFast(model); + PrepareVertexNormalsFast(model); + } + + /* + * Call any renderer function + */ + if (fw.model_update) + fw.model_update(model, flags); + +#if 0 + BrLogPrintf("After ModelUpdate...\n"); + ModelDump(" ", model); +#endif +} diff --git a/bren/FW/preptab.c b/bren/FW/preptab.c new file mode 100644 index 00000000..84d11145 --- /dev/null +++ b/bren/FW/preptab.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: preptab.c 1.2 1995/02/22 21:42:26 sam Exp $ + * $Locker: $ + * + * Precompute information for tables + */ + +#include "fw.h" +#include "brassert.h" +#include "shortcut.h" + +static char rscid[] = "$Id: preptab.c 1.2 1995/02/22 21:42:26 sam Exp $"; + +void BR_PUBLIC_ENTRY BrTableUpdate(br_pixelmap *table, br_uint_16 flags) +{ + /* + * Call any renderer function + */ + if (fw.table_update) + fw.table_update(table, flags); +} diff --git a/bren/FW/quantize.c b/bren/FW/quantize.c new file mode 100644 index 00000000..47be6a0a --- /dev/null +++ b/bren/FW/quantize.c @@ -0,0 +1,596 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: quantize.c 1.2 1995/02/22 21:42:27 sam Exp $ + * $Locker: $ + * + * + */ + +/********************************************************************** + C Implementation of Wu's Color Quantizer (v. 2) + (see Graphics Gems vol. II, pp. 126-133) + +Author: Xiaolin Wu + Dept. of Computer Science + Univ. of Western Ontario + London, Ontario N6A 5B7 + wu@csd.uwo.ca + +Algorithm: Greedy orthogonal bipartition of RGB space for variance + minimization aided by inclusion-exclusion tricks. + For speed no nearest neighbor search is done. Slightly + better performance can be expected by more sophisticated + but more expensive versions. + +The author thanks Tom Lane at Tom_Lane@G.GP.CS.CMU.EDU for much of +additional documentation and a cure to a previous bug. + +Free to distribute, comments and suggestions are appreciated. + +Converted by SamL for use in avc + by SE for use in Brender + +**********************************************************************/ + +#include +#include +#include + +#include "brender.h" + +#define MAXCOLOR 256 + +#define RED 2 +#define GREEN 1 +#define BLUE 0 + +struct box +{ + int r0; /* min value, exclusive */ + int r1; /* max value, inclusive */ + int g0; + int g1; + int b0; + int b1; + int vol; +}; + +/* Histogram is in elements 1..HISTSIZE along each axis, + * element 0 is for base or marginal value + * NB: these must start out 0! + */ + +static long wt[33][33][33]; +static long mr[33][33][33]; +static long mg[33][33][33]; +static long mb[33][33][33]; +static float m2[33][33][33]; + +/* + * Output lookup table + */ +static unsigned char tag[32 * 32 * 32]; +static int tag_dist[32 * 32 * 32]; + +/* + * color look-up table size + */ +static int K; + +/* + * Fast LUT of n^2 for n = 0..255 + */ +static long square_table[256]; + +/* + * At conclusion of the histogram step, we can interpret + * wt[r][g][b] = sum over voxel of P(c) + * mr[r][g][b] = sum over voxel of r*P(c) , similarly for mg, mb + * m2[r][g][b] = sum over voxel of c^2*P(c) + * Actually each of these should be divided by 'size' to give the usual + * interpretation of P() as ranging from 0 to 1, but we needn't do that here. + */ + +/* We now convert histogram into moments so that we can rapidly calculate + * the sums of the above quantities over any desired box. + */ + +static long palette_dist[256]; +static long palette_count[256]; + +/* + * compute cumulative moments. + */ +static void Moments(void) +{ + unsigned short int ind1, ind2; + unsigned char i, r, g, b; + long line, line_r, line_g, line_b; + long area[33], area_r[33], area_g[33], area_b[33]; + float line2, area2[33]; + + for (r = 1; r <= 32; ++r) + { + + for (i = 0; i <= 32; ++i) + area2[i] = area[i] = area_r[i] = area_g[i] = area_b[i] = 0; + + for (g = 1; g <= 32; ++g) + { + line2 = line = line_r = line_g = line_b = 0; + + for (b = 1; b <= 32; ++b) + { + ind1 = (r << 10) + (r << 6) + r + (g << 5) + g + b; /* [r][g][b] */ + line += ((long *)wt)[ind1]; + line_r += ((long *)mr)[ind1]; + line_g += ((long *)mg)[ind1]; + line_b += ((long *)mb)[ind1]; + line2 += ((float *)m2)[ind1]; + + area[b] += line; + area_r[b] += line_r; + area_g[b] += line_g; + area_b[b] += line_b; + area2[b] += line2; + + ind2 = ind1 - 1089; /* [r-1][g][b] */ + + ((long *)wt)[ind1] = ((long *)wt)[ind2] + area[b]; + ((long *)mr)[ind1] = ((long *)mr)[ind2] + area_r[b]; + ((long *)mg)[ind1] = ((long *)mg)[ind2] + area_g[b]; + ((long *)mb)[ind1] = ((long *)mb)[ind2] + area_b[b]; + ((float *)m2)[ind1] = ((float *)m2)[ind2] + area2[b]; + } + } + } +} + +/* + * Compute sum over a box of any given statistic + */ +static long Vol(struct box *cube, long mmt[33][33][33]) +{ + return (mmt[cube->r1][cube->g1][cube->b1] - mmt[cube->r1][cube->g1][cube->b0] - mmt[cube->r1][cube->g0][cube->b1] + + mmt[cube->r1][cube->g0][cube->b0] - mmt[cube->r0][cube->g1][cube->b1] + mmt[cube->r0][cube->g1][cube->b0] + + mmt[cube->r0][cube->g0][cube->b1] - mmt[cube->r0][cube->g0][cube->b0]); +} + +/* + * The next two routines allow a slightly more efficient calculation + * of Vol() for a proposed subbox of a given box. The sum of Top() + * and Bottom() is the Vol() of a subbox split in the given direction + * and with the specified new upper bound. + */ + +/* + * Compute part of Vol(cube, mmt) that doesn't depend on r1, g1, or b1 + * (depending on dir) + */ +static long Bottom(struct box *cube, unsigned char dir, long mmt[33][33][33]) +{ + switch (dir) + { + case RED: + return (-mmt[cube->r0][cube->g1][cube->b1] + mmt[cube->r0][cube->g1][cube->b0] + + mmt[cube->r0][cube->g0][cube->b1] - mmt[cube->r0][cube->g0][cube->b0]); + break; + case GREEN: + return (-mmt[cube->r1][cube->g0][cube->b1] + mmt[cube->r1][cube->g0][cube->b0] + + mmt[cube->r0][cube->g0][cube->b1] - mmt[cube->r0][cube->g0][cube->b0]); + break; + case BLUE: + return (-mmt[cube->r1][cube->g1][cube->b0] + mmt[cube->r1][cube->g0][cube->b0] + + mmt[cube->r0][cube->g1][cube->b0] - mmt[cube->r0][cube->g0][cube->b0]); + break; + } + return 0; +} + +/* + * Compute remainder of Vol(cube, mmt), substituting pos for + * r1, g1, or b1 (depending on dir) + */ +static long Top(struct box *cube, unsigned char dir, int pos, long mmt[33][33][33]) +{ + switch (dir) + { + case RED: + return (mmt[pos][cube->g1][cube->b1] - mmt[pos][cube->g1][cube->b0] - mmt[pos][cube->g0][cube->b1] + + mmt[pos][cube->g0][cube->b0]); + break; + case GREEN: + return (mmt[cube->r1][pos][cube->b1] - mmt[cube->r1][pos][cube->b0] - mmt[cube->r0][pos][cube->b1] + + mmt[cube->r0][pos][cube->b0]); + break; + case BLUE: + return (mmt[cube->r1][cube->g1][pos] - mmt[cube->r1][cube->g0][pos] - mmt[cube->r0][cube->g1][pos] + + mmt[cube->r0][cube->g0][pos]); + break; + } + return 0; +} + +/* + * Compute the weighted variance of a box + * NB: as with the raw statistics, this is really the variance * size + */ +static float Var(struct box *cube) +{ + float dr, dg, db, xx; + + dr = Vol(cube, mr); + dg = Vol(cube, mg); + db = Vol(cube, mb); + xx = m2[cube->r1][cube->g1][cube->b1] - m2[cube->r1][cube->g1][cube->b0] - m2[cube->r1][cube->g0][cube->b1] + + m2[cube->r1][cube->g0][cube->b0] - m2[cube->r0][cube->g1][cube->b1] + m2[cube->r0][cube->g1][cube->b0] + + m2[cube->r0][cube->g0][cube->b1] - m2[cube->r0][cube->g0][cube->b0]; + + return (xx - (dr * dr + dg * dg + db * db) / (float)Vol(cube, wt)); +} + +/* + * We want to minimize the sum of the variances of two subboxes. + * The sum(c^2) terms can be ignored since their sum over both subboxes + * is the same (the sum for the whole box) no matter where we split. + * The remaining terms have a minus sign in the variance formula, + * so we drop the minus sign and MAXIMIZE the sum of the two terms. + */ + +static float Maximize(struct box *cube, unsigned char dir, int first, int last, int *cut, long whole_r, long whole_g, + long whole_b, long whole_w) +{ + long half_r, half_g, half_b, half_w; + long base_r, base_g, base_b, base_w; + int i; + float temp, max; + + base_r = Bottom(cube, dir, mr); + base_g = Bottom(cube, dir, mg); + base_b = Bottom(cube, dir, mb); + base_w = Bottom(cube, dir, wt); + + max = 0.0; + *cut = -1; + for (i = first; i < last; ++i) + { + half_r = base_r + Top(cube, dir, i, mr); + half_g = base_g + Top(cube, dir, i, mg); + half_b = base_b + Top(cube, dir, i, mb); + half_w = base_w + Top(cube, dir, i, wt); + + /* + * now half_x is sum over lower half of box, if split at i + */ + if (half_w == 0) + { + /* + * subbox could be empty of pixels! + * never split into an empty box + */ + continue; + } + else + { + temp = ((float)half_r * half_r + (float)half_g * half_g + (float)half_b * half_b) / half_w; + } + + half_r = whole_r - half_r; + half_g = whole_g - half_g; + half_b = whole_b - half_b; + half_w = whole_w - half_w; + + if (half_w == 0) + { + /* + * subbox could be empty of pixels! + * never split into an empty box + */ + continue; + } + else + { + temp += ((float)half_r * half_r + (float)half_g * half_g + (float)half_b * half_b) / half_w; + } + + if (temp > max) + { + max = temp; + *cut = i; + } + } + return (max); +} + +static int Cut(struct box *set1, struct box *set2) +{ + unsigned char dir; + int cutr, cutg, cutb; + float maxr, maxg, maxb; + long whole_r, whole_g, whole_b, whole_w; + + whole_r = Vol(set1, mr); + whole_g = Vol(set1, mg); + whole_b = Vol(set1, mb); + whole_w = Vol(set1, wt); + + maxr = Maximize(set1, RED, set1->r0 + 1, set1->r1, &cutr, whole_r, whole_g, whole_b, whole_w); + maxg = Maximize(set1, GREEN, set1->g0 + 1, set1->g1, &cutg, whole_r, whole_g, whole_b, whole_w); + maxb = Maximize(set1, BLUE, set1->b0 + 1, set1->b1, &cutb, whole_r, whole_g, whole_b, whole_w); + + if ((maxr >= maxg) && (maxr >= maxb)) + { + dir = RED; + if (cutr < 0) + return 0; /* can't split the box */ + } + else + { + if ((maxg >= maxr) && (maxg >= maxb)) + dir = GREEN; + else + dir = BLUE; + } + + set2->r1 = set1->r1; + set2->g1 = set1->g1; + set2->b1 = set1->b1; + + switch (dir) + { + case RED: + set2->r0 = set1->r1 = cutr; + set2->g0 = set1->g0; + set2->b0 = set1->b0; + break; + case GREEN: + set2->g0 = set1->g1 = cutg; + set2->r0 = set1->r0; + set2->b0 = set1->b0; + break; + case BLUE: + set2->b0 = set1->b1 = cutb; + set2->r0 = set1->r0; + set2->g0 = set1->g0; + break; + } + + set1->vol = (set1->r1 - set1->r0) * (set1->g1 - set1->g0) * (set1->b1 - set1->b0); + set2->vol = (set2->r1 - set2->r0) * (set2->g1 - set2->g0) * (set2->b1 - set2->b0); + return 1; +} + +static void Mark(struct box *cube, int label) +{ + int r, g, b; + + for (r = cube->r0; r < cube->r1; r++) + for (g = cube->g0; g < cube->g1; g++) + for (b = cube->b0; b < cube->b1; b++) + ((unsigned char *)tag)[(r << 10) + (g << 5) + b] = label; +} + +void BR_PUBLIC_ENTRY BrQuantBegin(void) +{ + int i; + + /* + * make table of squares + */ + for (i = 0; i < 256; ++i) + square_table[i] = i * i; + + /* + * Clear all static workspace + */ + memset(wt, 0, sizeof(wt)); + memset(mr, 0, sizeof(mr)); + memset(mg, 0, sizeof(mg)); + memset(mb, 0, sizeof(mb)); + memset(m2, 0, sizeof(m2)); + memset(tag, 0, sizeof(tag)); +} + +void BR_PUBLIC_ENTRY BrQuantEnd(void) +{ +} + +/* + * Add an image to quantizing process + * + * Accumulate 3-D color histogram of counts, r/g/b, c^2 + */ +void BR_PUBLIC_ENTRY BrQuantAddColours(br_uint_8 *colours, br_uint_32 size) +{ + int ind, r, g, b; + int inr, ing, inb; + long i; + + for (i = 0; i < size; i++) + { + /* + * Fetch components of pixel + */ + r = colours[0]; + g = colours[1]; + b = colours[2]; + colours += 3; + + inr = (r >> 3) + 1; + ing = (g >> 3) + 1; + inb = (b >> 3) + 1; + + ind = (inr << 10) + (inr << 6) + inr + (ing << 5) + ing + inb; + + ((long *)wt)[ind]++; + ((long *)mr)[ind] += r; + ((long *)mg)[ind] += g; + ((long *)mb)[ind] += b; + ((float *)m2)[ind] += (float)(square_table[r] + square_table[g] + square_table[b]); + } +} + +void BR_PUBLIC_ENTRY BrQuantMakePalette(int base, int num_entries, br_pixelmap *palette) +{ + struct box cube[MAXCOLOR]; + int next; + register long int i, weight; + register int k; + float vv[MAXCOLOR], temp; + br_colour colour, *palette_entry; + + if (num_entries > MAXCOLOR) + BR_ERROR1("Too many palette entries (MAXCOLOR = %d)", MAXCOLOR); + + K = num_entries; + + /* + * Calculate moments + */ + Moments(); + + /* + * Partition RGB space + */ + + /* + * One big partition over whole space + */ + cube[0].r0 = cube[0].g0 = cube[0].b0 = 0; + cube[0].r1 = cube[0].g1 = cube[0].b1 = 32; + next = 0; + + for (i = 1; i < K; ++i) + { + if (Cut(&cube[next], &cube[i])) + { + /* + * volume test ensures we won't try to cut one-cell box + */ + vv[next] = (cube[next].vol > 1) ? Var(&cube[next]) : 0.0; + vv[i] = (cube[i].vol > 1) ? Var(&cube[i]) : 0.0; + } + else + { + vv[next] = 0.0; /* don't try to split this box again */ + i--; /* didn't create box i */ + } + + next = 0; + temp = vv[0]; + + for (k = 1; k <= i; ++k) + { + if (vv[k] > temp) + { + temp = vv[k]; + next = k; + } + } + if (temp <= 0.0) + { + K = i + 1; + /* + fprintf(stderr, "Only got %d boxes\n", K); + */ + break; + } + } + + palette_entry = palette->pixels; + + for (k = 0; k < K; k++) + { + Mark(&cube[k], k); + weight = Vol(&cube[k], wt); + + if (weight) + palette_entry[k + base] = ((Vol(&cube[k], mr) / weight) << 16) + ((Vol(&cube[k], mg) / weight) << 8) + + (Vol(&cube[k], mb) / weight); + } +} + +void BR_PUBLIC_ENTRY BrQuantMapColours(int base, br_uint_8 *colours, br_uint_8 *mapped_colours, int size) +{ + int i; + int inr, ing, inb; + + for (i = 0; i < size; i++) + { + + inr = (colours[0] >> 3); + ing = (colours[1] >> 3); + inb = (colours[2] >> 3); + colours += 3; + + *mapped_colours++ = tag[(inr << 10) + (ing << 5) + inb] + base; + } +} + +void BR_PUBLIC_ENTRY BrQuantPrepareMapping(int base, int num_entries, br_pixelmap *palette) +{ + int r, g, b; + int dr2, dg2; + br_uint_8 pr, pg, pb; + int p; + int s, d; + int t; + br_colour *palette_entry; + + /* + * Initialise RGB cube to max. distances + */ + for (t = 0; t < 32 * 32 * 32; t++) + { + tag_dist[t] = 32767; + tag[t] = 0; + } + + /* + * For each palette entry + */ + for (p = 0, palette_entry = palette->pixels; p < num_entries; p++, palette_entry++) + { + + pr = BR_RED(*(palette_entry + base)) >> 3; + pg = BR_GRN(*(palette_entry + base)) >> 3; + pb = BR_BLU(*(palette_entry + base)) >> 3; + + /* + * Walk through RGB cube + */ + for (r = 0; r < 32; r++) + { + + d = (int)r - (int)pr; + dr2 = d * d; + + for (g = 0; g < 32; g++) + { + + d = (int)g - (int)pg; + dg2 = d * d; + + for (b = 0; b < 32; b++) + { + + /* + * If this point is nearer to the current palette + * entry, use that instead + */ + t = (r << 10) + (g << 5) + b; + + d = (int)b - (int)pb; + s = dr2 + dg2 + d * d; + + if (s < tag_dist[t]) + { + tag_dist[t] = s; + tag[t] = p; + } + } + } + } + } +} diff --git a/bren/FW/quat.c b/bren/FW/quat.c new file mode 100644 index 00000000..25d5e276 --- /dev/null +++ b/bren/FW/quat.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: quat.c 1.11 1995/02/22 21:42:28 sam Exp $ + * $Locker: $ + * + * Unit quaternion manipulation - based on + * "Quaternion Calculus and Fast Animation" Ken Shoemake + * + */ + +#include "fw.h" +#include "shortcut.h" + +static char rscid[] = "$Id: quat.c 1.11 1995/02/22 21:42:28 sam Exp $"; + +br_quat *BR_PUBLIC_ENTRY BrQuatMul(br_quat *q, br_quat *l, br_quat *r) +{ +#if 1 + /* + * Quaternion multiply using 8 muls (but more adds) + */ + br_scalar x1, x2, x3, x4, x5, x6, x7, x8; + br_scalar s, t; + + x1 = BR_MUL((lZ - lY), (rY - rZ)); + x2 = BR_MUL((lW + lX), (rW + rX)); + x3 = BR_MUL((lW - lX), (rY + rZ)); + x4 = BR_MUL((lZ + lY), (rW - rX)); + + x5 = BR_MUL((lZ - lX), (rX - rY)); + x6 = BR_MUL((lZ + lX), (rX + rY)); + x7 = BR_MUL((lW + lY), (rW - rZ)); + x8 = BR_MUL((lW - lY), (rW + rZ)); + + s = x6 + x7 + x8; + t = BR_CONST_DIV(x5 + s, 2); + + qW = x1 + t - x6; + qX = x2 + t - s; + qY = x3 + t - x8; + qZ = x4 + t - x7; +#endif + +#if 0 + br_quat t; + + /* + * Normal 16 muls + */ + tW = BR_MAC4(lW,rW,-lX,rX,-lY,rY,-lZ,rZ); + tX = BR_MAC4(lW,rX, lX,rW, lY,rZ,-lZ,rY); + tY = BR_MAC4(lW,rY, lY,rW, lZ,rX,-lX,rZ); + tZ = BR_MAC4(lW,rZ, lZ,rW, lX,rY,-lY,rX); + + *q = t; +#endif + + return q; +} + +br_quat *BR_PUBLIC_ENTRY BrQuatNormalise(br_quat *q, br_quat *qq) +{ + br_scalar s = BR_DIV(S1, BR_LENGTH4(qqX, qqY, qqZ, qqW)); + + qX = BR_MUL(qqX, s); + qY = BR_MUL(qqY, s); + qZ = BR_MUL(qqZ, s); + qW = BR_MUL(qqW, s); + + return q; +} + +br_quat *BR_PUBLIC_ENTRY BrQuatInvert(br_quat *q, br_quat *qq) +{ + qX = -qqX; + qY = -qqY; + qZ = -qqZ; + qW = qqW; + + return q; +} + +br_quat *BR_PUBLIC_ENTRY BrQuatSlerp(br_quat *q, br_quat *l, br_quat *r, br_scalar a, br_int_16 spins) +{ + int omega, omega_spin; + br_scalar s_omega, c_omega; + br_scalar scale_l, scale_r; + br_quat t; + + c_omega = BR_MAC4(lX, rX, lY, rY, lZ, rZ, lW, rW); + + /* + * Take shortest route + */ + if (c_omega < 0) + { + tX = -rX; + tY = -rY; + tZ = -rZ; + tW = -rW; + c_omega = -c_omega; + } + else + { + tX = rX; + tY = rY; + tZ = rZ; + tW = rW; + } + + if ((S1 - c_omega) > BR_SCALAR_EPSILON) + { + /* + * Normal case + */ + omega = BR_ACOS(c_omega); + omega_spin = omega + spins * BR_ANGLE_RAD(PI); + + s_omega = BR_SIN((br_angle)omega); + scale_l = BR_DIV(BR_SIN((br_angle)(omega - BR_MUL(a, omega_spin))), s_omega); + scale_r = BR_DIV(BR_SIN((br_angle)BR_MUL(a, omega_spin)), s_omega); + } + else + { + /* + * Ends very close + */ + scale_l = S1 - a; + scale_r = a; + } + + qX = BR_MAC2(scale_l, lX, scale_r, tX); + qY = BR_MAC2(scale_l, lY, scale_r, tY); + qZ = BR_MAC2(scale_l, lZ, scale_r, tZ); + qW = BR_MAC2(scale_l, lW, scale_r, tW); + + return q; +} + +br_matrix34 *BR_PUBLIC_ENTRY BrQuatToMatrix34(br_matrix34 *mat, br_quat *q) +{ + br_scalar xs, ys, zs; + br_scalar wx, wy, wz; + br_scalar xx, xy, xz; + br_scalar yy, yz, zz; + + /* NB: unit quat is assumed */ + + xs = BR_CONST_MUL(qX, 2); + ys = BR_CONST_MUL(qY, 2); + zs = BR_CONST_MUL(qZ, 2); + + wx = BR_MUL(qW, xs); + wy = BR_MUL(qW, ys); + wz = BR_MUL(qW, zs); + xx = BR_MUL(qX, xs); + xy = BR_MUL(qX, ys); + xz = BR_MUL(qX, zs); + yy = BR_MUL(qY, ys); + yz = BR_MUL(qY, zs); + zz = BR_MUL(qZ, zs); + + M(0, 0) = S1 - (yy + zz); + M(1, 0) = xy - wz; + M(2, 0) = xz + wy; + + M(0, 1) = xy + wz; + M(1, 1) = S1 - (xx + zz); + M(2, 1) = yz - wx; + + M(0, 2) = xz - wy; + M(1, 2) = yz + wx; + M(2, 2) = S1 - (xx + yy); + + M(3, 0) = S0; + M(3, 1) = S0; + M(3, 2) = S0; + + return mat; +} + +br_quat *BR_PUBLIC_ENTRY BrMatrix34ToQuat(br_quat *q, br_matrix34 *mat) +{ + br_scalar tr, s; + int i, j, k; + + tr = M(0, 0) + M(1, 1) + M(2, 2); + + if (tr >= S0) + { + s = BR_SQRT(tr + S1); + qW = BR_CONST_DIV(s, 2); + + s = BR_DIV(BR_SCALAR(0.5), s); + + qX = BR_MUL(M(1, 2) - M(2, 1), s); + qY = BR_MUL(M(2, 0) - M(0, 2), s); + qZ = BR_MUL(M(0, 1) - M(1, 0), s); + } + else + { + static int n[] = {1, 2, 0}; + + i = 0; + if (M(1, 1) > M(0, 0)) + i = 1; + if (M(2, 2) > M(i, i)) + i = 2; + + j = n[i]; + k = n[j]; + + s = BR_SQRT(M(i, i) - (M(j, j) + M(k, k)) + S1); + qi(i) = BR_CONST_DIV(s, 2); + + s = BR_DIV(BR_SCALAR(0.5), s); + + qW = BR_MUL(M(j, k) - M(k, j), s); + qi(j) = BR_MUL(M(i, j) + M(j, i), s); + qi(k) = BR_MUL(M(i, k) + M(k, i), s); + } + + return q; +} + +br_matrix4 *BR_PUBLIC_ENTRY BrQuatToMatrix4(br_matrix4 *mat, br_quat *q) +{ + br_matrix34 tmp; + + BrQuatToMatrix34(&tmp, q); + BrMatrix4Copy34(mat, &tmp); + + return mat; +} + +br_quat *BR_PUBLIC_ENTRY BrMatrix4ToQuat(br_quat *q, br_matrix4 *mat) +{ + br_matrix34 tmp; + + BrMatrix34Copy4(&tmp, mat); + + return BrMatrix34ToQuat(q, &tmp); +} diff --git a/bren/FW/register.c b/bren/FW/register.c new file mode 100644 index 00000000..5f7b7f12 --- /dev/null +++ b/bren/FW/register.c @@ -0,0 +1,364 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: register.c 1.12 1995/03/16 11:57:07 sam Exp $ + * $Locker: $ + * + * Generic code for lists of registered items. Used for models, materials, + * textures, tables, cameras, lights, scenes + * + * Each registry is a doubly linked list of chunks of data, the first + * member of an item should be a pointer the the item's name + */ +#include "fw.h" +#include "brassert.h" + +static char rscid[] = "$Id: register.c 1.12 1995/03/16 11:57:07 sam Exp $"; + +/* + * Compare a pattern against a string + * + * Return true if pattern matches string + * + * Patterns have the magic characters '*' and '?' + * + * '*' matches 0 or more characters + * '?' matches any single character + * '/' terminates the pattern + * + * Patterns are anchored at start and end of string + * + * Recursive approach, implemented with tail recursion - + * + * match (p,s) + * + * case first(p) in + * + * NULL - TRUE if s is empty else FALSE + * + * '*' - TRUE if match rest(q) against any substring from s to end of s + * else + * FALSE + * + * '?' - TRUE if first(s) != NULL and match(rest(p),rest(r)) + * + * default - TRUE if first(p) == first(s) and match(rest(p),rest(r)) + * + */ + +#if 1 /* case insensitive for the moment */ +#define UPPER(c) (((c) >= 'a' && (c) <= 'z') ? ((c) - ('a' - 'A')) : (c)) +#define MATCH_CHAR(a, b) (UPPER(a) == UPPER(b)) +#else +#define MATCH_CHAR(a, b) ((a) == (b)) +#endif + +int NamePatternMatch(char *p, char *s) +{ + char *cp; + + /* + * A NULL pattern matches everything + */ + if (p == NULL) + return 1; + + /* + * A NULL string never matches + */ + if (s == NULL) + return 0; + + for (;;) + switch (*p) + { + + case '/': + case '\0': + /* + * Empty pattern only matches empty string + */ + return *s == '\0'; + + case '*': + /* + * Match p+1 in any position from s to end of s + */ + cp = s; + do + if (NamePatternMatch(p + 1, cp)) + return 1; + while (*cp++); + + return 0; + + case '?': + /* + * Match any character followed by matching(p+1, s+1) + */ + if (*s == '\0') + return 0; + + p++, s++; /* Tail recurse */ + continue; + + default: + /* + * Match this character followed by matching(p+1, s+1) + */ + if (!MATCH_CHAR(*s, *p)) + return 0; + + p++, s++; /* Tail recurse */ + continue; + } +} + +/* + * Initialise a registry + */ +void *RegistryNew(br_registry *reg) +{ + UASSERT(reg != NULL); + + /* + * Intitialise linked list + */ + BrNewList(®->list); + + /* + * List is empty + */ + reg->count = 0; + + return reg; +} + +/* + * Release all items on a registry + */ +void *RegistryClear(br_registry *reg) +{ + br_registry_entry *e; + + UASSERT(reg != NULL); + + while (e = BR_HEAD(®->list), BR_NEXT(e)) + { + BR_REMOVE(e); + BrResFree(e); + } + + /* + * List is empty + */ + reg->count = 0; + + return reg; +} + +/* + * Add one new item to a registry + */ +void *RegistryAdd(br_registry *reg, void *item) +{ + br_registry_entry *e; + + UASSERT(reg != NULL); + UASSERT(item != NULL); + + e = BrResAllocate(fw.res, sizeof(*e), BR_MEMORY_REGISTRY); + e->item = item; + BR_ADDHEAD(reg, e); + + reg->count++; + + return item; +} + +/* + * Add items from a table of pointers to a registry + */ +int RegistryAddMany(br_registry *reg, void **items, int n) +{ + int i; + UASSERT(reg != NULL); + UASSERT(items != NULL); + + /* + * Walk through table adding items + */ + for (i = 0; i < n; i++) + RegistryAdd(reg, *items++); + + return n; +} + +/* + * Remove a single item from the registry + */ +void *RegistryRemove(br_registry *reg, void *item) +{ + br_registry_entry *e; + void *r; + + UASSERT(reg != NULL); + UASSERT(item != NULL); + + /* + * Find item in list + */ + BR_FOR_LIST(®->list, e) + if (e->item == item) + break; + + /* + * If item was not in list, return NULL + */ + if (!BR_NEXT(e)) + return NULL; + + /* + * Take item of list, remember contents, and free node + */ + BR_REMOVE(e); + r = e->item; + BrResFree(e); + + reg->count--; + + return r; +} + +/* + * Remove a table of referenced items from a registry + */ +int RegistryRemoveMany(br_registry *reg, void **items, int n) +{ + int i, r; + + UASSERT(reg != NULL); + UASSERT(items != NULL); + + /* + * Remove all the items from a table, keeping a count of how + * many were actually removed + */ + for (i = 0, r = 0; i < n; i++) + if (RegistryRemove(reg, *items++)) + r++; + + return r; +} + +/* + * Find the first item in registry whose name matches a given pattern + * + * If no item can be found, then call a find_failed hook if it exists + */ +void *RegistryFind(br_registry *reg, char *pattern) +{ + br_registry_entry *e; + + UASSERT(reg != NULL); + + /* + * Find item in list + */ + BR_FOR_LIST(®->list, e) + if (NamePatternMatch(pattern, *e->item)) + return e->item; + + if (reg->find_failed_hook) + return reg->find_failed_hook(pattern); + else + return NULL; +} + +int RegistryFindMany(br_registry *reg, char *pattern, void **items, int max) +{ + br_registry_entry *e; + int n = 0; + + /* + * Find all matching items in list + */ + BR_FOR_LIST(®->list, e) + { + /* + * make sure there is space in output table + */ + if (n >= max) + break; + + /* + * If entry matches, add to table + */ + if (NamePatternMatch(pattern, *e->item)) + { + *items++ = e->item; + n++; + } + } + + return n; +} + +/* + * Count how many items in registry match pattern + * + * If pattern == NULL, return total in registry + */ +int RegistryCount(br_registry *reg, char *pattern) +{ + br_registry_entry *e; + int n; + + UASSERT(reg != NULL); + + if (pattern == NULL) + return reg->count; + + /* + * Find all matching items in list + */ + n = 0; + + BR_FOR_LIST(®->list, e) + if (NamePatternMatch(pattern, *e->item)) + n++; + + return n; +} + +/* + * Call a function for every item in a registry. Stop early if callback + * returns !=0, and return that value + */ +int RegistryEnum(br_registry *reg, char *pattern, br_enum_cbfn *callback, void *arg) +{ + br_registry_entry *e; + int r; + + UASSERT(reg != NULL); + UASSERT(callback != NULL); + + /* + * If pattern in NULL, invoke callback for _EVERYTHING_ + * else invoke callback for items that match pattern + */ + if (pattern == NULL) + { + BR_FOR_LIST_R(®->list, e) + if (r = callback(e->item, arg)) + return r; + } + else + { + BR_FOR_LIST_R(®->list, e) + if (NamePatternMatch(pattern, *e->item)) + if (r = callback(e->item, arg)) + return r; + } + return 0; +} diff --git a/bren/FW/register.h b/bren/FW/register.h new file mode 100644 index 00000000..4e6f3ee7 --- /dev/null +++ b/bren/FW/register.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: register.h 1.7 1995/03/16 11:57:08 sam Exp $ + * $Locker: $ + * + * + */ + +#ifndef _REGISTER_H_ +#define _REGISTER_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + * An entry in a registry - doubly linked list and pointers to data + * + * It is assumed that the first thing in the data structure is a pointer + * to the item's name + */ + typedef struct br_registry_entry + { + struct br_node node; + char **item; + } br_registry_entry; + + typedef void *BR_CALLBACK br_find_failed_cbfn(char *pattern); + typedef br_uint_32 BR_CALLBACK br_enum_cbfn(void *item, void *arg); + + /* + * Base structure for registry + */ + typedef struct br_registery + { + /* + * Anchor structure + */ + struct br_list list; + + /* + * Number of items in list + */ + int count; + + /* + * Hook that is called when RegistryFind fails + */ + br_find_failed_cbfn *find_failed_hook; + + } br_registry; + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/bren/FW/regsupt.c b/bren/FW/regsupt.c new file mode 100644 index 00000000..038a1fa2 --- /dev/null +++ b/bren/FW/regsupt.c @@ -0,0 +1,659 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: regsupt.c 1.4 1995/03/01 15:26:21 sam Exp $ + * $Locker: $ + * + * Public registry functions + */ +#include + +#include "fw.h" +#include "brassert.h" +#include "datafile.h" + +static char rs[] = "$Id: regsupt.c 1.4 1995/03/01 15:26:21 sam Exp $"; + +/** + ** Specific versions of registry calls for each class + **/ + +#if 0 +/* + * Macro to define all the calls except BrXXXAdd() + */ +#define REG_CALLS(class, type, reg) \ + \ + type *BR_PUBLIC_ENTRY Br##class##Remove(type *##lname##) \ + { \ + return RegistryRemove(&fw.reg, ##lname##); \ + } \ + \ + type *BR_PUBLIC_ENTRY Br##class##Find(char *pattern) \ + { \ + return RegistryFind(&fw.reg, pattern); \ + } \ + \ + br_uint_32 BR_PUBLIC_ENTRY Br##class##AddMany(type **items, int n) \ + { \ + return RegistryAddMany(&fw.reg, items, n); \ + } \ + \ + br_uint_32 BR_PUBLIC_ENTRY Br##class##RemoveMany(type **items, int n) \ + { \ + return RegistryRemoveMany(&fw.reg, items, n); \ + } \ + \ + br_uint_32 BR_PUBLIC_ENTRY Br##class##FindMany(char *pattern, type **items, int max) \ + { \ + return RegistryFindMany(&fw.reg, pattern, items, max); \ + } \ + \ + br_uint_32 BR_PUBLIC_ENTRY Br##class##Count(char *pattern) \ + { \ + return RegistryCount(&fw.reg, pattern); \ + } \ + \ + br_uint_32 BR_PUBLIC_ENTRY Br##class##Enum(char *pattern, int (*callback)(type * item, void *arg), void *arg) \ + { \ + return RegistryEnum(&fw.reg, pattern, callback, arg); \ + } + +#endif + +/* + * Models + */ +br_model *BR_PUBLIC_ENTRY BrModelAdd(br_model *model) +{ + /* + * Check that model was allocated + */ + UASSERT(BrResCheck(model, 1)); + UASSERT(BrResClass(model) == BR_MEMORY_MODEL); + + RegistryAdd(&fw.reg_models, model); + BrModelUpdate(model, BR_MODU_ALL); + + model->prep_flags |= MODUF_REGISTERED; + + return model; +} + +br_model *BR_PUBLIC_ENTRY BrModelRemove(br_model *model) +{ + model->prep_flags &= ~MODUF_REGISTERED; + + return RegistryRemove(&fw.reg_models, model); +} + +br_model *BR_PUBLIC_ENTRY BrModelFind(char *pattern) +{ + return RegistryFind(&fw.reg_models, pattern); +} + +br_model_find_cbfn *BR_PUBLIC_ENTRY BrModelFindHook(br_model_find_cbfn *hook) +{ + br_model_find_cbfn *old = (br_model_find_cbfn *)fw.reg_models.find_failed_hook; + fw.reg_models.find_failed_hook = (br_find_failed_cbfn *)hook; + + return old; +} + +br_uint_32 BR_PUBLIC_ENTRY BrModelAddMany(br_model **items, int n) +{ + int i, r = 0; + + for (i = 0; i < n; i++) + if (BrModelAdd(*items++) != NULL) + r++; + + return r; +} + +br_uint_32 BR_PUBLIC_ENTRY BrModelRemoveMany(br_model **items, int n) +{ + int i, r = 0; + + for (i = 0; i < n; i++) + if (BrModelRemove(*items++) != NULL) + r++; + + return r; +} + +br_uint_32 BR_PUBLIC_ENTRY BrModelFindMany(char *pattern, br_model **items, int max) +{ + return RegistryFindMany(&fw.reg_models, pattern, (void **)items, max); +} + +br_uint_32 BR_PUBLIC_ENTRY BrModelCount(char *pattern) +{ + return RegistryCount(&fw.reg_models, pattern); +} + +br_uint_32 BR_PUBLIC_ENTRY BrModelEnum(char *pattern, br_model_enum_cbfn *callback, void *arg) +{ + return RegistryEnum(&fw.reg_models, pattern, (br_enum_cbfn *)callback, arg); +} + +/* + * Materials + */ +br_material *BR_PUBLIC_ENTRY BrMaterialAdd(br_material *material) +{ + /* + * Check that material was allocated + */ + UASSERT(BrResCheck(material, 1)); + UASSERT(BrResClass(material) == BR_MEMORY_MATERIAL); + + BrMaterialUpdate(material, BR_MATU_ALL); + + material->prep_flags |= MODUF_REGISTERED; + + return RegistryAdd(&fw.reg_materials, material); +} + +br_material *BR_PUBLIC_ENTRY BrMaterialRemove(br_material *material) +{ + material->prep_flags &= ~MODUF_REGISTERED; + + return RegistryRemove(&fw.reg_materials, material); +} + +br_material *BR_PUBLIC_ENTRY BrMaterialFind(char *pattern) +{ + return RegistryFind(&fw.reg_materials, pattern); +} + +br_material_find_cbfn *BR_PUBLIC_ENTRY BrMaterialFindHook(br_material_find_cbfn *hook) +{ + br_material_find_cbfn *old = (br_material_find_cbfn *)fw.reg_materials.find_failed_hook; + fw.reg_materials.find_failed_hook = (br_find_failed_cbfn *)hook; + + return old; +} + +br_uint_32 BR_PUBLIC_ENTRY BrMaterialAddMany(br_material **items, int n) +{ + int i, r = 0; + + for (i = 0; i < n; i++) + if (BrMaterialAdd(*items++) != NULL) + r++; + + return r; +} + +br_uint_32 BR_PUBLIC_ENTRY BrMaterialRemoveMany(br_material **items, int n) +{ + int i, r = 0; + + for (i = 0; i < n; i++) + if (BrMaterialRemove(*items++) != NULL) + r++; + + return r; +} + +br_uint_32 BR_PUBLIC_ENTRY BrMaterialFindMany(char *pattern, br_material **items, int max) +{ + return RegistryFindMany(&fw.reg_materials, pattern, (void **)items, max); +} + +br_uint_32 BR_PUBLIC_ENTRY BrMaterialCount(char *pattern) +{ + return RegistryCount(&fw.reg_materials, pattern); +} + +br_uint_32 BR_PUBLIC_ENTRY BrMaterialEnum(char *pattern, br_material_enum_cbfn *callback, void *arg) +{ + return RegistryEnum(&fw.reg_materials, pattern, (br_enum_cbfn *)callback, arg); +} + +/* + * Textures + */ +br_pixelmap *BR_PUBLIC_ENTRY BrMapAdd(br_pixelmap *pixelmap) +{ + return RegistryAdd(&fw.reg_textures, pixelmap); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrMapRemove(br_pixelmap *pixelmap) +{ + return RegistryRemove(&fw.reg_textures, pixelmap); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrMapFind(char *pattern) +{ + return RegistryFind(&fw.reg_textures, pattern); +} + +br_map_find_cbfn *BR_PUBLIC_ENTRY BrMapFindHook(br_map_find_cbfn *hook) +{ + br_map_find_cbfn *old = (br_map_find_cbfn *)fw.reg_textures.find_failed_hook; + fw.reg_textures.find_failed_hook = (br_find_failed_cbfn *)hook; + + return old; +} + +br_uint_32 BR_PUBLIC_ENTRY BrMapAddMany(br_pixelmap **items, int n) +{ + return RegistryAddMany(&fw.reg_textures, (void **)items, n); +} + +br_uint_32 BR_PUBLIC_ENTRY BrMapRemoveMany(br_pixelmap **items, int n) +{ + return RegistryRemoveMany(&fw.reg_textures, (void **)items, n); +} + +br_uint_32 BR_PUBLIC_ENTRY BrMapFindMany(char *pattern, br_pixelmap **items, int max) +{ + return RegistryFindMany(&fw.reg_textures, pattern, (void **)items, max); +} + +br_uint_32 BR_PUBLIC_ENTRY BrMapCount(char *pattern) +{ + return RegistryCount(&fw.reg_textures, pattern); +} + +br_uint_32 BR_PUBLIC_ENTRY BrMapEnum(char *pattern, br_map_enum_cbfn *callback, void *arg) +{ + return RegistryEnum(&fw.reg_textures, pattern, (br_enum_cbfn *)callback, arg); +} + +/* + * Tables + */ +br_pixelmap *BR_PUBLIC_ENTRY BrTableAdd(br_pixelmap *pixelmap) +{ + return RegistryAdd(&fw.reg_tables, pixelmap); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrTableRemove(br_pixelmap *pixelmap) +{ + return RegistryRemove(&fw.reg_tables, pixelmap); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrTableFind(char *pattern) +{ + return RegistryFind(&fw.reg_tables, pattern); +} + +br_table_find_cbfn *BR_PUBLIC_ENTRY BrTableFindHook(br_table_find_cbfn *hook) +{ + br_table_find_cbfn *old = (br_table_find_cbfn *)fw.reg_tables.find_failed_hook; + fw.reg_tables.find_failed_hook = (br_find_failed_cbfn *)hook; + + return old; +} + +br_uint_32 BR_PUBLIC_ENTRY BrTableAddMany(br_pixelmap **items, int n) +{ + return RegistryAddMany(&fw.reg_tables, (void **)items, n); +} + +br_uint_32 BR_PUBLIC_ENTRY BrTableRemoveMany(br_pixelmap **items, int n) +{ + return RegistryRemoveMany(&fw.reg_tables, (void **)items, n); +} + +br_uint_32 BR_PUBLIC_ENTRY BrTableFindMany(char *pattern, br_pixelmap **items, int max) +{ + return RegistryFindMany(&fw.reg_tables, pattern, (void **)items, max); +} + +br_uint_32 BR_PUBLIC_ENTRY BrTableCount(char *pattern) +{ + return RegistryCount(&fw.reg_tables, pattern); +} + +br_uint_32 BR_PUBLIC_ENTRY BrTableEnum(char *pattern, br_table_enum_cbfn *callback, void *arg) +{ + + return RegistryEnum(&fw.reg_tables, pattern, (br_enum_cbfn *)callback, arg); +} + +/* + * Resource Classes + */ +br_resource_class *BR_PUBLIC_ENTRY BrResClassAdd(br_resource_class *rclass) +{ + br_resource_class *r; + + UASSERT(rclass != NULL); + + /* + * The registry resource is initally faked + */ + UASSERT(rclass->res_class == BR_MEMORY_REGISTRY || rclass->res_class == BR_MEMORY_ANCHOR || + fw.resource_class_index[rclass->res_class] == NULL); + + r = RegistryAdd(&fw.reg_resource_classes, rclass); + + if (r != NULL) + fw.resource_class_index[rclass->res_class] = r; + + return r; + r; +} + +br_resource_class *BR_PUBLIC_ENTRY BrResClassRemove(br_resource_class *rclass) +{ + br_resource_class *r; + + UASSERT(rclass != NULL); + UASSERT(fw.resource_class_index[rclass->res_class] != NULL); + + r = RegistryRemove(&fw.reg_resource_classes, rclass); + + if (r != NULL) + fw.resource_class_index[rclass->res_class] = NULL; + + return r; +} + +br_resource_class *BR_PUBLIC_ENTRY BrResClassFind(char *pattern) +{ + return RegistryFind(&fw.reg_resource_classes, pattern); +} + +br_resclass_find_cbfn *BR_PUBLIC_ENTRY BrResClassFindHook(br_resclass_find_cbfn *hook) +{ + br_resclass_find_cbfn *old = (br_resclass_find_cbfn *)fw.reg_resource_classes.find_failed_hook; + + fw.reg_resource_classes.find_failed_hook = (br_find_failed_cbfn *)hook; + + return old; +} + +br_uint_32 BR_PUBLIC_ENTRY BrResClassAddMany(br_resource_class **items, int n) +{ + int i; + + for (i = 0; i < n; i++) + BrResClassAdd(*items++); + + return n; +} + +br_uint_32 BR_PUBLIC_ENTRY BrResClassRemoveMany(br_resource_class **items, int n) +{ + int i, r; + + for (i = 0, r = 0; i < n; i++) + if (BrResClassRemove(*items++)) + r++; + + return r; +} + +br_uint_32 BR_PUBLIC_ENTRY BrResClassFindMany(char *pattern, br_resource_class **items, int max) +{ + return RegistryFindMany(&fw.reg_resource_classes, pattern, (void **)items, max); +} + +br_uint_32 BR_PUBLIC_ENTRY BrResClassCount(char *pattern) +{ + return RegistryCount(&fw.reg_resource_classes, pattern); +} + +br_uint_32 BR_PUBLIC_ENTRY BrResClassEnum(char *pattern, br_resclass_enum_cbfn *callback, void *arg) +{ + return RegistryEnum(&fw.reg_resource_classes, pattern, (br_enum_cbfn *)callback, arg); +} + +/* + * Generate U and V values for a model's vertices. + * + * The vertices are optionally transformed by a 3x4 matrix + * + * The u,v values are then assigned according to one of the + * following schemes - + * + * Planar mapping: + * u = (x+1)/2 + * v = (y+1)/2 + * + * Spherical mapping: + * u = atan2(-z,x)/2*pi + * v = 1-atan2(sqrt(x*x+z*z),y)/pi + * + * Cylindrical mapping: + * u = atan2(-z,x)/2*pi + * v = (y+1)/2 + * + * Disc mapping: + * u = atan2(-z,x)/2*pi + * v = sqrt(x*x+z*z) + */ +void BR_PUBLIC_ENTRY BrModelApplyMap(br_model *model, int map_type, br_matrix34 *xform) +{ + int v; + br_vertex *vp; + br_vector3 mv; + br_matrix34 default_xform; + br_scalar d; + + UASSERT(model != NULL); + UASSERT(model->vertices != NULL); + UASSERT(map_type >= 0 && map_type <= BR_APPLYMAP_NONE); + + /* + * If no default provided, use identity + */ + if (xform == NULL) + { + BrMatrix34Identity(&default_xform); + xform = &default_xform; + } + + /* + * Set mapping for each vertex + */ + for (v = 0, vp = model->vertices; v < model->nvertices; v++, vp++) + { + BrMatrix34ApplyP(&mv, &vp->p, xform); + + switch (map_type) + { + case BR_APPLYMAP_NONE: + /* + * No mapping: + * u = 0 + * v = 0 + */ + vp->map.v[0] = BR_SCALAR(0.0); + vp->map.v[1] = BR_SCALAR(0.0); + break; + + case BR_APPLYMAP_PLANE: + /* + * Planar mapping: + * u = (x+1)/2 + * v = (y+1)/2 + */ + vp->map.v[0] = BR_MUL(mv.v[0] + BR_SCALAR(1.0), BrFractionToScalar(BR_FRACTION(0.5))); + + vp->map.v[1] = BR_MUL(mv.v[1] + BR_SCALAR(1.0), BrFractionToScalar(BR_FRACTION(0.5))); + break; + + case BR_APPLYMAP_SPHERE: + /* + * Spherical mapping: + * u = atan2(-z,x)/2*pi + * v = 1-atan2(sqrt(x*x+z*z),y)/pi + */ + vp->map.v[0] = BR_DIV(BrAngleToDegree(BR_ATAN2(-mv.v[2], mv.v[0])), BR_SCALAR(360.0)); + + d = BR_LENGTH2(mv.v[0], mv.v[2]); + + vp->map.v[1] = BR_SCALAR(1.0) - BR_DIV(BrAngleToDegree(BR_ATAN2(d, mv.v[1])), BR_SCALAR(180.0)); + + break; + + case BR_APPLYMAP_CYLINDER: + /* + * Cylindrical mapping: + * u = atan2(-z,x)/2*pi + * v = (y+1)/2 + */ + vp->map.v[0] = BR_DIV(BrAngleToDegree(BR_ATAN2(-mv.v[2], mv.v[0])), BR_SCALAR(360.0)); + + vp->map.v[1] = BR_MUL(mv.v[1] + BR_SCALAR(1.0), BrFractionToScalar(BR_FRACTION(0.5))); + break; + + case BR_APPLYMAP_DISC: + /* + * Disc mapping: + * u = atan2(-y,x)/2*pi + * v = sqrt(x*x+y*y) + */ + vp->map.v[0] = BR_DIV(BrAngleToDegree(BR_ATAN2(-mv.v[1], mv.v[0])), BR_SCALAR(360.0)); + + vp->map.v[1] = BR_LENGTH2(mv.v[0], mv.v[1]); + break; + } + } +} + +/* + * Work out a transform such that it can be fed to BrModelApplyMap + * and have the mapping type fit the bounds of the model exactly + * + * The two axis along which the mapping can be applied are provided - + * + * BR_FITMAP_PLUS_X, + * BR_FITMAP_PLUS_Y, + * BR_FITMAP_PLUS_Z, + * BR_FITMAP_MINUS_X, + * BR_FITMAP_MINUS_Y, + * BR_FITMAP_MINUS_Z, + * + * Returns the supplied pointer to 'transform' + */ + +br_matrix34 *BR_PUBLIC_ENTRY BrModelFitMap(br_model *model, int axis_0, int axis_1, br_matrix34 *transform) +{ + br_vector3 axis_3; + br_vector3 tr; + br_vector3 sc; + int i; + + static br_vector3 axis_vectors[] = { + BR_VECTOR3(1, 0, 0), /* +X */ + BR_VECTOR3(0, 1, 0), /* +Y */ + BR_VECTOR3(0, 0, 1), /* +Z */ + BR_VECTOR3(-1, 0, 0), /* -X */ + BR_VECTOR3(0, -1, 0), /* -Y */ + BR_VECTOR3(0, 0, -1), /* -Z */ + }; + + UASSERT(model != NULL); + UASSERT(transform != NULL); + UASSERT(axis_0 >= BR_FITMAP_PLUS_X && axis_0 <= BR_FITMAP_MINUS_Z); + UASSERT(axis_1 >= BR_FITMAP_PLUS_X && axis_1 <= BR_FITMAP_MINUS_Z); + + /* + * Start the mapping transform by filling in the two user + * supplied axes (as columns), and then using a cross product to generate + * the third column. + */ + BrMatrix34Identity(transform); + + BrVector3Cross(&axis_3, axis_vectors + axis_0, axis_vectors + axis_1); + + for (i = 0; i < 3; i++) + { + transform->m[i][0] = axis_vectors[axis_0].v[i]; + transform->m[i][1] = axis_vectors[axis_1].v[i]; + transform->m[i][2] = axis_3.v[i]; + } + + /* + * Find the translation to align the object with the mapping + */ + for (i = 0; i < 3; i++) + tr.v[i] = -(BR_CONST_DIV(model->bounds.max.v[i], 2) + BR_CONST_DIV(model->bounds.min.v[i], 2)); + + /* + * Find the scale to fit object to the mapping + */ + for (i = 0; i < 3; i++) + if (model->bounds.max.v[i] != model->bounds.min.v[i]) + sc.v[i] = BR_RCP(BR_CONST_DIV(model->bounds.max.v[i], 2) - BR_CONST_DIV(model->bounds.min.v[i], 2)); + else + sc.v[i] = BR_SCALAR(1.0); + + BrMatrix34PreScale(transform, sc.v[0], sc.v[1], sc.v[2]); + BrMatrix34PreTranslate(transform, tr.v[0], tr.v[1], tr.v[2]); + + return transform; +} + +/* + * Free a model + */ +void BR_PUBLIC_ENTRY BrModelFree(br_model *m) +{ + UASSERT(m != NULL); + + BrResFree(m); +} + +/* + * Allocate a model of a given size + */ +br_model *BR_PUBLIC_ENTRY BrModelAllocate(char *name, int nvertices, int nfaces) +{ + br_model *m; + + UASSERT(nvertices >= 0); + UASSERT(nfaces >= 0); + + m = BrResAllocate(fw.res, sizeof(*m), BR_MEMORY_MODEL); + + m->nvertices = nvertices; + m->nfaces = nfaces; + + if (name) + m->identifier = BrResStrDup(m, name); + + if (nvertices) + m->vertices = BrResAllocate(m, nvertices * sizeof(*m->vertices), BR_MEMORY_VERTICES); + + if (nfaces) + m->faces = BrResAllocate(m, nfaces * sizeof(*m->faces), BR_MEMORY_FACES); + + return m; +} + +/* + * Allocate a material + */ +br_material *BR_PUBLIC_ENTRY BrMaterialAllocate(char *name) +{ + br_material *m; + + m = BrResAllocate(fw.res, sizeof(*m), BR_MEMORY_MATERIAL); + + *m = *fw.default_material; + + if (name) + m->identifier = BrResStrDup(m, name); + else + m->identifier = NULL; + + return m; +} + +/* + * Free a material + */ +void BR_PUBLIC_ENTRY BrMaterialFree(br_material *m) +{ + UASSERT(m != NULL); + + BrResFree(m); +} diff --git a/bren/FW/rendsupt.c b/bren/FW/rendsupt.c new file mode 100644 index 00000000..b0fdc2ee --- /dev/null +++ b/bren/FW/rendsupt.c @@ -0,0 +1,920 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: rendsupt.c 1.36 1995/02/22 21:42:33 sam Exp $ + * $Locker: $ + * + * Misc. support routines for renderer + */ +#include + +#include "fw.h" +#include "brassert.h" +#include "datafile.h" + +static char rscid[] = "$Id: rendsupt.c 1.36 1995/02/22 21:42:33 sam Exp $"; + +/* + * Accumulate the transform between an actor and the root + * + * XXX Could accumulate a flag to say that matrix is only rotation + * and translation - makes invertion cheaper + * + * Returns a flag to indicate if the actor did have world + * as an ancestor + */ +int BrActorToRoot(br_actor *a, br_actor *world, br_matrix34 *m) +{ + UASSERT(a != NULL); + UASSERT(world != NULL); + UASSERT(m != NULL); + + /* + * Catch stupid case + */ + if (a == world) + { + BrMatrix34Identity(m); + return 1; + } + + /* + * Start with actor's transform + */ + BrMatrix34Transform(m, &a->t); + a = a->parent; + + /* + * Accumulate all the transforms up to the root (ignoring any + * identity transforms) + */ + for (; a && a != world; a = a->parent) + if (a->t.type != BR_TRANSFORM_IDENTITY) + BrMatrix34PostTransform(m, &a->t); + + return (a == world); +} + +/* + * Invoke a callback for each one of an actors children + */ +br_uint_32 BR_PUBLIC_ENTRY BrActorEnum(br_actor *parent, br_actor_enum_cbfn *callback, void *arg) +{ + br_actor *a; + br_uint_32 r; + + UASSERT(parent != NULL); + UASSERT(callback != NULL); + + BR_FOR_SIMPLELIST(&parent->children, a) + if ((r = callback(a, arg))) + return r; + + return 0; +} + +/* + * Find all the named actors matching a pattern in the given hierachy + * + */ +int BR_PUBLIC_ENTRY BrActorSearchMany(br_actor *root, char *pattern, br_actor **actors, int max) +{ + br_actor *a; + char *sub; + int n, remaining = max; + + UASSERT(root != NULL); + UASSERT(actors != NULL); + + /* + * Take first component of path, and match it against all children + * of the root actor + */ + + while (*pattern == '/') + pattern++; + + for (sub = pattern; (*sub != '\0') && (*sub != '/'); sub++) + ; + + while (*sub == '/') + sub++; + + BR_FOR_SIMPLELIST(&root->children, a) + { + + /* + * Abort if no more space for results + */ + if (remaining <= 0) + break; + + if (NamePatternMatch(pattern, a->identifier)) + { + /* + * If there is more path + * recurse with remainder of path + * else + * add actor to accumulated list + */ + + if (*sub != '\0') + { + n = BrActorSearchMany(a, sub, actors, remaining); + actors += n; + remaining -= n; + } + else + { + *actors++ = a; + remaining--; + } + } + } + + return max - remaining; +} + +/* + * Find the first named actor matching a pattern in the given hierachy + */ +br_actor *BR_PUBLIC_ENTRY BrActorSearch(br_actor *root, char *pattern) +{ + br_actor *a; + + UASSERT(root != NULL); + + if (BrActorSearchMany(root, pattern, &a, 1) == 1) + return a; + else + return NULL; +} + +/* + * Recursive function to propgate depth number down a hierachy + */ +static void RenumberActor(br_actor *a, int d) +{ + br_actor *ac; + + a->depth = d; + + BR_FOR_SIMPLELIST(&a->children, ac) + RenumberActor(ac, d + 1); +} + +/* + * Add an actor to the children of the given parent + */ +br_actor *BR_PUBLIC_ENTRY BrActorAdd(br_actor *parent, br_actor *a) +{ + br_actor *ac; + + UASSERT(a != NULL); + UASSERT(parent != NULL); + UASSERT(a->prev == NULL); + + /* + * Link this actor into sibling list of parent + */ + BR_SIMPLEADDHEAD(&parent->children, a); + a->parent = parent; + + /* + * Update depth for added hierachy + */ + a->depth = parent->depth + 1; + + BR_FOR_SIMPLELIST(&a->children, ac) + RenumberActor(ac, a->depth + 1); + + return a; +} + +br_actor *BR_PUBLIC_ENTRY BrActorRemove(br_actor *a) +{ + br_actor *ac; + + UASSERT(a != NULL); + UASSERT(a->prev != NULL); + + BR_SIMPLEREMOVE(a); + + /* + * Renumber the removed hierachy + */ + a->depth = 0; + + BR_FOR_SIMPLELIST(&a->children, ac) + RenumberActor(ac, 1); + + return a; +} + +/* + * Move an actor in the heirachy, but preserve it's apparent world + * transform by manipulating the transform + */ +void BR_PUBLIC_ENTRY BrActorRelink(br_actor *parent, br_actor *a) +{ +} + +/* + * Allocate a new actor structure and return a pointer to it + * + * Model actors are allocated from a pool associated with the renderer - + * this is a very common case and is worth the speedup + * + * All other actor types come from the normal heap - and include any + * type specific data bocks + * + */ +br_actor *BR_PUBLIC_ENTRY BrActorAllocate(br_uint_8 type, void *type_data) +{ + br_actor *a = NULL; + br_light *light; + br_camera *camera; + br_bounds *bounds; + br_vector4 *clip_plane; + + UASSERT(type < BR_ACTOR_MAX); + + a = BrResAllocate(fw.res, sizeof(*a), BR_MEMORY_ACTOR); + + /* + * Initialise common fields + */ + BrSimpleNewList((struct br_simple_list *)&a->children); + a->type = type; + a->depth = 0; + a->t.type = BR_TRANSFORM_MATRIX34; + BrMatrix34Identity(&a->t.t.mat); + + if (type_data) + { + + /* + * Fill in the type_data pointer + */ + a->type_data = type_data; + } + else + { + /* + * No type data - allocate a default + */ + switch (type) + { + + case BR_ACTOR_LIGHT: + /* + * Setup to be a directional light source + */ + light = BrResAllocate(a, sizeof(*light), BR_MEMORY_LIGHT); + a->type_data = light; + + light->type = BR_LIGHT_DIRECT; + light->colour = BR_COLOUR_RGB(255, 255, 255); + light->attenuation_c = BR_SCALAR(1.0); + light->cone_outer = BR_ANGLE_DEG(15.0); + light->cone_inner = BR_ANGLE_DEG(10.0); + break; + + case BR_ACTOR_CAMERA: + /* + * Perspective camera, 45 degree FOV + */ + camera = BrResAllocate(a, sizeof(*camera), BR_MEMORY_CAMERA); + a->type_data = camera; + + camera->type = BR_CAMERA_PERSPECTIVE; + camera->field_of_view = BR_ANGLE_DEG(45); + camera->hither_z = BR_SCALAR(1.0); + camera->yon_z = BR_SCALAR(10.0); + camera->aspect = BR_SCALAR(1.0); + break; + + case BR_ACTOR_BOUNDS: + /* + * Allocate a bounds structure + */ + bounds = BrResAllocate(a, sizeof(*bounds), BR_MEMORY_BOUNDS); + a->type_data = bounds; + break; + + case BR_ACTOR_CLIP_PLANE: + /* + * Allocate a 4-vector + */ + clip_plane = BrResAllocate(a, sizeof(*clip_plane), BR_MEMORY_BOUNDS); + a->type_data = clip_plane; + break; + } + } + + return a; +} + +/* + * Free an actor + */ +static void InternalActorFree(br_actor *a) +{ + /* + * Release any children + */ + while (BR_SIMPLEHEAD(&a->children)) + InternalActorFree(BR_SIMPLEREMOVE(a->children)); + + /* + * Release this actor + */ + BrResFree(a); +} + +void BR_PUBLIC_ENTRY BrActorFree(br_actor *a) +{ + UASSERT(a->prev == NULL); + + InternalActorFree(a); +} + +/** + ** Specific versions of registry calls for each class + **/ + +#if 0 +/* + * Macro to define all the calls except BrXXXAdd() + */ +#define REG_CALLS(class, type, reg) \ + \ + type *BR_PUBLIC_ENTRY Br##class##Remove(type *##lname##) \ + { \ + return RegistryRemove(&fw.reg, ##lname##); \ + } \ + \ + type *BR_PUBLIC_ENTRY Br##class##Find(char *pattern) \ + { \ + return RegistryFind(&fw.reg, pattern); \ + } \ + \ + int BR_PUBLIC_ENTRY Br##class##AddMany(type **items, int n) \ + { \ + return RegistryAddMany(&fw.reg, items, n); \ + } \ + \ + int BR_PUBLIC_ENTRY Br##class##RemoveMany(type **items, int n) \ + { \ + return RegistryRemoveMany(&fw.reg, items, n); \ + } \ + \ + int BR_PUBLIC_ENTRY Br##class##FindMany(char *pattern, type **items, int max) \ + { \ + return RegistryFindMany(&fw.reg, pattern, items, max); \ + } \ + \ + int BR_PUBLIC_ENTRY Br##class##Count(char *pattern) \ + { \ + return RegistryCount(&fw.reg, pattern); \ + } \ + \ + int BR_PUBLIC_ENTRY Br##class##Enum(char *pattern, int (*callback)(type * item, void *arg), void *arg) \ + { \ + return RegistryEnum(&fw.reg, pattern, callback, arg); \ + } + +#endif + +/* + * Models + */ +br_model *BR_PUBLIC_ENTRY BrModelAdd(br_model *model) +{ + RegistryAdd(&fw.reg_models, model); + BrModelPrepare(model, BR_MPREP_ALL); + return model; +} + +br_model *BR_PUBLIC_ENTRY BrModelRemove(br_model *model) +{ + return RegistryRemove(&fw.reg_models, model); +} + +br_model *BR_PUBLIC_ENTRY BrModelFind(char *pattern) +{ + return RegistryFind(&fw.reg_models, pattern); +} + +br_model_find_cbfn *BR_PUBLIC_ENTRY BrModelFindHook(br_model_find_cbfn *hook) +{ + br_model_find_cbfn *old = (br_model_find_cbfn *)fw.reg_models.find_failed_hook; + fw.reg_models.find_failed_hook = (br_find_failed_cbfn *)hook; + + return old; +} + +int BR_PUBLIC_ENTRY BrModelAddMany(br_model **items, int n) +{ + int i, r = 0; + + for (i = 0; i < n; i++) + if (BrModelAdd(*items++) != NULL) + r++; + + return r; +} + +int BR_PUBLIC_ENTRY BrModelRemoveMany(br_model **items, int n) +{ + return RegistryRemoveMany(&fw.reg_models, (void **)items, n); +} + +int BR_PUBLIC_ENTRY BrModelFindMany(char *pattern, br_model **items, int max) +{ + return RegistryFindMany(&fw.reg_models, pattern, (void **)items, max); +} + +int BR_PUBLIC_ENTRY BrModelCount(char *pattern) +{ + return RegistryCount(&fw.reg_models, pattern); +} + +int BR_PUBLIC_ENTRY BrModelEnum(char *pattern, br_model_enum_cbfn *callback, void *arg) +{ + return RegistryEnum(&fw.reg_models, pattern, (br_enum_cbfn *)callback, arg); +} + +/* + * Materials + */ +br_material *BR_PUBLIC_ENTRY BrMaterialAdd(br_material *material) +{ + BrMaterialPrepare(material, 0); + return RegistryAdd(&fw.reg_materials, material); +} + +br_material *BR_PUBLIC_ENTRY BrMaterialRemove(br_material *material) +{ + return RegistryRemove(&fw.reg_materials, material); +} + +br_material *BR_PUBLIC_ENTRY BrMaterialFind(char *pattern) +{ + return RegistryFind(&fw.reg_materials, pattern); +} + +br_material_find_cbfn *BR_PUBLIC_ENTRY BrMaterialFindHook(br_material_find_cbfn *hook) +{ + br_material_find_cbfn *old = (br_material_find_cbfn *)fw.reg_materials.find_failed_hook; + fw.reg_materials.find_failed_hook = (br_find_failed_cbfn *)hook; + + return old; +} + +int BR_PUBLIC_ENTRY BrMaterialAddMany(br_material **items, int n) +{ + int i, r = 0; + + for (i = 0; i < n; i++) + if (BrMaterialAdd(*items++) != NULL) + r++; + + return r; +} + +int BR_PUBLIC_ENTRY BrMaterialRemoveMany(br_material **items, int n) +{ + return RegistryRemoveMany(&fw.reg_materials, (void **)items, n); +} + +int BR_PUBLIC_ENTRY BrMaterialFindMany(char *pattern, br_material **items, int max) +{ + return RegistryFindMany(&fw.reg_materials, pattern, (void **)items, max); +} + +int BR_PUBLIC_ENTRY BrMaterialCount(char *pattern) +{ + return RegistryCount(&fw.reg_materials, pattern); +} + +int BR_PUBLIC_ENTRY BrMaterialEnum(char *pattern, br_material_enum_cbfn *callback, void *arg) +{ + return RegistryEnum(&fw.reg_materials, pattern, (br_enum_cbfn *)callback, arg); +} + +/* + * Textures + */ +br_pixelmap *BR_PUBLIC_ENTRY BrMapAdd(br_pixelmap *pixelmap) +{ + return RegistryAdd(&fw.reg_textures, pixelmap); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrMapRemove(br_pixelmap *pixelmap) +{ + return RegistryRemove(&fw.reg_textures, pixelmap); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrMapFind(char *pattern) +{ + return RegistryFind(&fw.reg_textures, pattern); +} + +br_map_find_cbfn *BR_PUBLIC_ENTRY BrMapFindHook(br_map_find_cbfn *hook) +{ + br_map_find_cbfn *old = (br_map_find_cbfn *)fw.reg_textures.find_failed_hook; + fw.reg_textures.find_failed_hook = (br_find_failed_cbfn *)hook; + + return old; +} + +int BR_PUBLIC_ENTRY BrMapAddMany(br_pixelmap **items, int n) +{ + return RegistryAddMany(&fw.reg_textures, (void **)items, n); +} + +int BR_PUBLIC_ENTRY BrMapRemoveMany(br_pixelmap **items, int n) +{ + return RegistryRemoveMany(&fw.reg_textures, (void **)items, n); +} + +int BR_PUBLIC_ENTRY BrMapFindMany(char *pattern, br_pixelmap **items, int max) +{ + return RegistryFindMany(&fw.reg_textures, pattern, (void **)items, max); +} + +int BR_PUBLIC_ENTRY BrMapCount(char *pattern) +{ + return RegistryCount(&fw.reg_textures, pattern); +} + +int BR_PUBLIC_ENTRY BrMapEnum(char *pattern, br_map_enum_cbfn *callback, void *arg) +{ + return RegistryEnum(&fw.reg_textures, pattern, (br_enum_cbfn *)callback, arg); +} + +/* + * Tables + */ +br_pixelmap *BR_PUBLIC_ENTRY BrTableAdd(br_pixelmap *pixelmap) +{ + return RegistryAdd(&fw.reg_tables, pixelmap); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrTableRemove(br_pixelmap *pixelmap) +{ + return RegistryRemove(&fw.reg_tables, pixelmap); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrTableFind(char *pattern) +{ + return RegistryFind(&fw.reg_tables, pattern); +} + +br_table_find_cbfn *BR_PUBLIC_ENTRY BrTableFindHook(br_table_find_cbfn *hook) +{ + br_table_find_cbfn *old = (br_table_find_cbfn *)fw.reg_tables.find_failed_hook; + fw.reg_tables.find_failed_hook = (br_find_failed_cbfn *)hook; + + return old; +} + +int BR_PUBLIC_ENTRY BrTableAddMany(br_pixelmap **items, int n) +{ + return RegistryAddMany(&fw.reg_tables, (void **)items, n); +} + +int BR_PUBLIC_ENTRY BrTableRemoveMany(br_pixelmap **items, int n) +{ + return RegistryRemoveMany(&fw.reg_tables, (void **)items, n); +} + +int BR_PUBLIC_ENTRY BrTableFindMany(char *pattern, br_pixelmap **items, int max) +{ + return RegistryFindMany(&fw.reg_tables, pattern, (void **)items, max); +} + +int BR_PUBLIC_ENTRY BrTableCount(char *pattern) +{ + return RegistryCount(&fw.reg_tables, pattern); +} + +int BR_PUBLIC_ENTRY BrTableEnum(char *pattern, br_table_enum_cbfn *callback, void *arg) +{ + + return RegistryEnum(&fw.reg_tables, pattern, (br_enum_cbfn *)callback, arg); +} + +/* + * Resource Classes + */ +br_resource_class *BR_PUBLIC_ENTRY BrResClassAdd(br_resource_class *rclass) +{ + br_resource_class *r; + + UASSERT(rclass != NULL); + + /* + * The registry resource is initally faked + */ + UASSERT(rclass->res_class == BR_MEMORY_REGISTRY || rclass->res_class == BR_MEMORY_ANCHOR || + fw.resource_class_index[rclass->res_class] == NULL); + + r = RegistryAdd(&fw.reg_resource_classes, rclass); + + if (r != NULL) + fw.resource_class_index[rclass->res_class] = r; + + return r; +} + +br_resource_class *BR_PUBLIC_ENTRY BrResClassRemove(br_resource_class *rclass) +{ + br_resource_class *r; + + UASSERT(rclass != NULL); + UASSERT(fw.resource_class_index[rclass->res_class] != NULL); + + r = RegistryRemove(&fw.reg_resource_classes, rclass); + + if (r != NULL) + fw.resource_class_index[rclass->res_class] = NULL; + + return r; +} + +br_resource_class *BR_PUBLIC_ENTRY BrResClassFind(char *pattern) +{ + return RegistryFind(&fw.reg_resource_classes, pattern); +} + +br_resclass_find_cbfn *BR_PUBLIC_ENTRY BrResClassFindHook(br_resclass_find_cbfn *hook) +{ + br_resclass_find_cbfn *old = (br_resclass_find_cbfn *)fw.reg_resource_classes.find_failed_hook; + + fw.reg_resource_classes.find_failed_hook = (br_find_failed_cbfn *)hook; + + return old; +} + +int BR_PUBLIC_ENTRY BrResClassAddMany(br_resource_class **items, int n) +{ + int i; + + for (i = 0; i < n; i++) + BrResClassAdd(*items++); + + return n; +} + +int BR_PUBLIC_ENTRY BrResClassRemoveMany(br_resource_class **items, int n) +{ + int i, r; + + for (i = 0, r = 0; i < n; i++) + if (BrResClassRemove(*items++)) + r++; + + return r; +} + +int BR_PUBLIC_ENTRY BrResClassFindMany(char *pattern, br_resource_class **items, int max) +{ + return RegistryFindMany(&fw.reg_resource_classes, pattern, (void **)items, max); +} + +int BR_PUBLIC_ENTRY BrResClassCount(char *pattern) +{ + return RegistryCount(&fw.reg_resource_classes, pattern); +} + +int BR_PUBLIC_ENTRY BrResClassEnum(char *pattern, br_resclass_enum_cbfn *callback, void *arg) +{ + return RegistryEnum(&fw.reg_resource_classes, pattern, (br_enum_cbfn *)callback, arg); +} + +/* + * Generate U and V values for a model's vertices. + * + * The vertices are optionally transformed by a 3x4 matrix + * + * The u,v values are then assigned according to one of the + * following schemes - + * + * Planar mapping: + * u = (x+1)/2 + * v = (y+1)/2 + * + * Spherical mapping: + * u = atan2(-z,x)/2*pi + * v = 1-atan2(sqrt(x*x+z*z),y)/pi + * + * Cylindrical mapping: + * u = atan2(-z,x)/2*pi + * v = (y+1)/2 + */ +void BR_PUBLIC_ENTRY BrModelApplyMap(br_model *model, int map_type, br_matrix34 *xform) +{ + int v; + br_vertex *vp; + br_vector3 mv; + br_matrix34 default_xform; + br_scalar d; + + UASSERT(model != NULL); + UASSERT(model->vertices != NULL); + UASSERT(map_type >= 0 && map_type <= BR_APPLYMAP_CYLINDER); + + /* + * If no default provided, use identity + */ + if (xform == NULL) + { + BrMatrix34Identity(&default_xform); + xform = &default_xform; + } + + /* + * Set mapping for each vertex + */ + for (v = 0, vp = model->vertices; v < model->nvertices; v++, vp++) + { + BrMatrix34ApplyP(&mv, &vp->p, xform); + + switch (map_type) + { + case BR_APPLYMAP_PLANE: + /* + * Planar mapping: + * u = (x+1)/2 + * v = (y+1)/2 + */ + vp->map.v[0] = BR_MUL(mv.v[0] + BR_SCALAR(1.0), BrFractionToScalar(BR_FRACTION(0.5))); + + vp->map.v[1] = BR_MUL(mv.v[1] + BR_SCALAR(1.0), BrFractionToScalar(BR_FRACTION(0.5))); + break; + + case BR_APPLYMAP_SPHERE: + /* + * Spherical mapping: + * u = atan2(-z,x)/2*pi + * v = 1-atan2(sqrt(x*x+z*z),y)/pi + */ + vp->map.v[0] = BR_DIV(BrAngleToDegree(BR_ATAN2(-mv.v[2], mv.v[0])), BR_SCALAR(360.0)); + + d = BR_LENGTH2(mv.v[0], mv.v[2]); + + vp->map.v[1] = BR_SCALAR(1.0) - BR_DIV(BrAngleToDegree(BR_ATAN2(d, mv.v[1])), BR_SCALAR(180.0)); + + break; + + case BR_APPLYMAP_CYLINDER: + /* + * Cylindrical mapping: + * u = atan2(-z,x)/2*pi + * v = (y+1)/2 + */ + vp->map.v[0] = BR_DIV(BrAngleToDegree(BR_ATAN2(-mv.v[2], mv.v[0])), BR_SCALAR(360.0)); + + vp->map.v[1] = BR_MUL(mv.v[1] + BR_SCALAR(1.0), BrFractionToScalar(BR_FRACTION(0.5))); + break; + } + } +} + +/* + * Work out a transform such that it can be fed to BrModelApplyMap + * and have the mapping type fit the bounds of the model exactly + * + * The two axis along which the mapping can be applied are provided - + * + * BR_FITMAP_PLUS_X, + * BR_FITMAP_PLUS_Y, + * BR_FITMAP_PLUS_Z, + * BR_FITMAP_MINUS_X, + * BR_FITMAP_MINUS_Y, + * BR_FITMAP_MINUS_Z, + * + * Returns the supplied pointer to 'transform' + */ + +br_matrix34 *BR_PUBLIC_ENTRY BrModelFitMap(br_model *model, int axis_0, int axis_1, br_matrix34 *transform) +{ + br_vector3 axis_3; + br_vector3 tr; + br_vector3 sc; + int i; + + static br_vector3 axis_vectors[] = { + BR_VECTOR3(1, 0, 0), /* +X */ + BR_VECTOR3(0, 1, 0), /* +Y */ + BR_VECTOR3(0, 0, 1), /* +Z */ + BR_VECTOR3(-1, 0, 0), /* -X */ + BR_VECTOR3(0, -1, 0), /* -Y */ + BR_VECTOR3(0, 0, -1), /* -Z */ + }; + + UASSERT(model != NULL); + UASSERT(transform != NULL); + UASSERT(axis_0 >= BR_FITMAP_PLUS_X && axis_0 <= BR_FITMAP_MINUS_Z); + UASSERT(axis_1 >= BR_FITMAP_PLUS_X && axis_1 <= BR_FITMAP_MINUS_Z); + + /* + * Start the mapping transform by filling in the two user + * supplied axes (as columns), and then using a cross product to generate + * the third column. + */ + BrMatrix34Identity(transform); + + BrVector3Cross(&axis_3, axis_vectors + axis_0, axis_vectors + axis_1); + + for (i = 0; i < 3; i++) + { + transform->m[i][0] = axis_vectors[axis_0].v[i]; + transform->m[i][1] = axis_vectors[axis_1].v[i]; + transform->m[i][2] = axis_3.v[i]; + } + + /* + * Find the translation to align the object with the mapping + */ + for (i = 0; i < 3; i++) + tr.v[i] = -(BR_CONST_DIV(model->bounds.max.v[i], 2) + BR_CONST_DIV(model->bounds.min.v[i], 2)); + + /* + * Find the scale to fit object to the mapping + */ + for (i = 0; i < 3; i++) + if (model->bounds.max.v[i] != model->bounds.min.v[i]) + sc.v[i] = BR_RCP(BR_CONST_DIV(model->bounds.max.v[i], 2) - BR_CONST_DIV(model->bounds.min.v[i], 2)); + else + sc.v[i] = BR_SCALAR(1.0); + + BrMatrix34PreScale(transform, sc.v[0], sc.v[1], sc.v[2]); + BrMatrix34PreTranslate(transform, tr.v[0], tr.v[1], tr.v[2]); + + return transform; +} + +/* + * Free a model + */ +void BR_PUBLIC_ENTRY BrModelFree(br_model *m) +{ + UASSERT(m != NULL); + + BrResFree(m); +} + +/* + * Allocate a model of a given size + */ +br_model *BR_PUBLIC_ENTRY BrModelAllocate(char *name, int nvertices, int nfaces) +{ + br_model *m; + + UASSERT(nvertices >= 0); + UASSERT(nfaces >= 0); + + m = BrResAllocate(fw.res, sizeof(*m), BR_MEMORY_MODEL); + + m->nvertices = nvertices; + m->nfaces = nfaces; + + if (name) + m->identifier = BrResStrDup(m, name); + + if (nvertices) + m->vertices = BrResAllocate(m, nvertices * sizeof(*m->vertices), BR_MEMORY_VERTICES); + + if (nfaces) + m->faces = BrResAllocate(m, nfaces * sizeof(*m->faces), BR_MEMORY_FACES); + + return m; +} + +/* + * Allocate a material + */ +br_material *BR_PUBLIC_ENTRY BrMaterialAllocate(char *name) +{ + br_material *m; + + m = BrResAllocate(fw.res, sizeof(*m), BR_MEMORY_MATERIAL); + + if (name) + m->identifier = BrResStrDup(m, name); + + return m; +} + +/* + * Free a material + */ +void BR_PUBLIC_ENTRY BrMaterialFree(br_material *m) +{ + UASSERT(m != NULL); + + BrResFree(m); +} diff --git a/bren/FW/resource.c b/bren/FW/resource.c new file mode 100644 index 00000000..97ccf967 --- /dev/null +++ b/bren/FW/resource.c @@ -0,0 +1,431 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: resource.c 1.9 1995/08/31 16:29:45 sam Exp $ + * $Locker: $ + * + * Generic code for maintaining a hierachy of resources + * + * Each resource has - + * A class (one of the BR_RES_xxx constants) + * A size + * A block of memory of 'size' bytes + * 0 or more child resources + * + * XXX + * Add optional source file/line tracking + */ +#include +#include + +#if DEBUG +#include +#endif + +#include "fw.h" +#include "brassert.h" + +static char rscid[] = "$Id: resource.c 1.9 1995/08/31 16:29:45 sam Exp $"; + +/* + * The granularity of resource sizes + */ +#define BR_RES_GRANULARITY 8 +#define BR_RES_MAGIC 0xDEADBEEF + +/* + * The control structure prepended onto resource blocks + */ +struct resource_header +{ + br_simple_node node; + br_simple_list children; + br_uint_8 class; /* Class of resource */ + br_int_32 size : 32; /* Size of resource in */ + /* BR_RES_GRANULARITY units */ +#if BR_RES_TAGGING + br_uint_32 magic_num; + void *magic_ptr; +#endif +}; + +#if BR_RES_TAGGING +#define ISRESOURCE(res) ((res->magic_ptr == res) && (res->magic_num == BR_RES_MAGIC)) +#else +#define ISRESOURCE(res) 1 +#endif + +#define RES_BOUNDARY 16 +#define RES_ALIGN(x) ((void *)(((br_uint_ptr)(x) + (RES_BOUNDARY - 1)) & ~(RES_BOUNDARY - 1))) + +/* + * Align the resource pointer + */ +static void *ResToUser(struct resource_header *r) +{ + /* + * Move over the resource_header + */ + r++; + + /* + * Allocations should always be at least long word aligned + */ + ASSERT((((br_uint_ptr)r) & 3) == 0); + + /* + * Bump pointer up to next boundary + */ + return RES_ALIGN(r); +} + +/* + * Unalign the resource pointer + */ +static struct resource_header *UserToRes(void *r) +{ + union { + br_uint_32 *p32; + br_uint_8 *p8; + struct resource_header *pres; + } l = {r}; + +#if 0 + ASSERT( ((int) r & (RES_BOUNDARY-1)) == 0); +#endif + + /* + * the last long-word of the resource will always be non-zero - + * class/size or magic_num + * + * Move pointer back until we hit it + */ + + while (*l.p32 != BR_RES_MAGIC) + { + l.p32--; + } + l.p8 -= offsetof(struct resource_header, magic_num); + + return l.pres; +} + +/* + * Create a new resource block of the given class, with 'size' bytes associated + * with it. + * + * If parent is not NULL it adds the new resource as a child + * + * Returns a pointer to the first byte of the resource data + */ +void *BR_PUBLIC_ENTRY BrResAllocate(void *vparent, br_size_t size, int class) +{ + struct resource_header *res; + struct resource_header *parent; + + UASSERT(fw.resource_class_index[class] != NULL); + + /* + * Work out size in BR_RES_GRANULARITY units + */ + size = (size + sizeof(struct resource_header) + (BR_RES_GRANULARITY - 1)) / BR_RES_GRANULARITY; + + res = BrMemAllocate(size * BR_RES_GRANULARITY + (RES_BOUNDARY - 1), class); + + res->class = class; + res->size = size; + BrSimpleNewList(&res->children); + +#if BR_RES_TAGGING + res->magic_num = BR_RES_MAGIC; + res->magic_ptr = res; +#endif + + if (vparent) + { + parent = UserToRes(vparent); + BR_SIMPLEADDHEAD(&parent->children, res); + } + + /* + * Return pointer to used data + */ + return ResToUser(res); +} + +/* + * Release a resource block - first calls BrResFree() for any child resources + * + * Removes resource from any parent list + * + * If the resource class has a destructor, that function is called + */ +static void BrResInternalFree(struct resource_header *res) +{ + UASSERT(ISRESOURCE(res)); + UASSERT(fw.resource_class_index[res->class] != NULL); + + /* + * Free any children + */ + while (BR_SIMPLEHEAD(&res->children)) + { + BrResInternalFree((struct resource_header *)BR_SIMPLEREMOVE(BR_SIMPLEHEAD(&res->children))); + } + + /* + * Remove from any parent list + */ + if (BR_SIMPLEINSERTED(res)) + { + BR_SIMPLEREMOVE(res); + } + + /* + * Call class destructor + */ + br_resource_class *res_class = fw.resource_class_index[res->class]; + if (res_class && res_class->free_cb) + { + res_class->free_cb(ResToUser(res), res->class, res->size); + } +#if BR_RES_TAGGING + /* + * Make sure memeory is no longer tagged as a resource + */ + res->magic_num = 1; + res->magic_ptr = NULL; +#endif + + /* + * Release block + */ + BrMemFree(res); +} + +/* + * Public entry for ResFree + */ +void BR_PUBLIC_ENTRY BrResFree(void *vres) +{ + UASSERT(vres != NULL); + + BrResInternalFree(UserToRes(vres)); +} + +/* + * Add a resource as a child of another + */ +void *BR_PUBLIC_ENTRY BrResAdd(void *vparent, void *vres) +{ + struct resource_header *res = UserToRes(vres); + struct resource_header *parent = UserToRes(vparent); + + UASSERT(vres != NULL); + UASSERT(vparent != NULL); + + UASSERT(ISRESOURCE(res)); + UASSERT(ISRESOURCE(parent)); + + /* + * Remove from any parent list + */ + if (BR_SIMPLEINSERTED(res)) + BR_SIMPLEREMOVE(res); + + BR_SIMPLEADDHEAD(&parent->children, res); + + return vres; +} + +/* + * Remove resource from parent + */ +void *BR_PUBLIC_ENTRY BrResRemove(void *vres) +{ + struct resource_header *res = UserToRes(vres); + + UASSERT(vres != NULL); + + UASSERT(ISRESOURCE(res)); + + BR_SIMPLEREMOVE(res); + + return vres; +} + +/* + * Return the class of a given resource + */ +br_uint_8 BR_PUBLIC_ENTRY BrResClass(void *vres) +{ + struct resource_header *res = UserToRes(vres); + + UASSERT(vres != NULL); + + UASSERT(ISRESOURCE(res)); + + return res->class; +} + +#if 0 +/* + * Return the parent of a given resource + */ +void * BR_PUBLIC_ENTRY BrResParent(void * vres) +{ + struct resource_header *res = UserToRes(vres); + + UASSERT(vres != NULL); + + UASSERT(ISRESOURCE(res)); + + return res->parent?ResToUser(res->parent):NULL; +} +#endif + +/* + * Return the size of a given resource + */ +br_uint_32 BR_PUBLIC_ENTRY BrResSize(void *vres) +{ + struct resource_header *res = UserToRes(vres); + + UASSERT(vres != NULL); + UASSERT(ISRESOURCE(res)); + + return (res->size * BR_RES_GRANULARITY) - sizeof(struct resource_header); +} + +/* + * Return the size of a resource, plus that of all it's children + */ + +static br_uint_32 BR_CALLBACK ResSizeTotal(void *vres, br_uint_32 *ptotal) +{ + /* + * Accumulate this size... + */ + ptotal += BrResSize(vres); + + /* + * ...then add the sizes of all the children + */ + BrResChildEnum(vres, (br_resenum_cbfn *)ResSizeTotal, (void *)ptotal); + + return 0; +} + +br_uint_32 BR_PUBLIC_ENTRY BrResSizeTotal(void *vres) +{ + br_uint_32 total = 0; + + ResSizeTotal(vres, &total); + + return total; +} + +/* + * Invoke a callback for each of the children of a resource + */ +br_uint_32 BR_PUBLIC_ENTRY BrResChildEnum(void *vres, br_resenum_cbfn *callback, void *arg) +{ + struct resource_header *res = UserToRes(vres); + struct resource_header *rp; + br_uint_32 r; + + UASSERT(vres != NULL); + UASSERT(ISRESOURCE(res)); + ASSERT(callback != NULL); + + BR_FOR_SIMPLELIST(&res->children, rp) + if (r = callback(ResToUser(rp), arg)) + return r; + + return 0; +} + +/* + * If tagging is enabled, then returns true if *vres is a resource + * block, otherwise returns no_tag + */ +br_uint_32 BR_PUBLIC_ENTRY BrResCheck(void *vres, int no_tag) +{ +#if BR_RES_TAGGING + struct resource_header *res = UserToRes(vres); + + return (res->magic_ptr == res) && (res->magic_num == BR_RES_MAGIC); +#else + return no_tag; +#endif +} + +/* + * strdup() equivalent + */ +char *BR_PUBLIC_ENTRY BrResStrDup(void *vparent, char *str) +{ + int l; + char *nstr; + + UASSERT(vparent != NULL); + UASSERT(str != NULL); + + l = strlen(str); + + nstr = BrResAllocate(vparent, l + 1, BR_MEMORY_STRING); + + strcpy(nstr, str); + + return nstr; +} + +#if 0 /* DEBUG */ +/* + * Debug function that will dump a resource hierachy + * + * Invokes a callback with each text line of the dump + */ +static void InternalResourceDump(struct resource_header *res, void (*putline)(char *str, void *arg), void *arg, int level) +{ +#if 1 + int i; + char *cp = _br_scratch_string; + struct resource_header *child; + br_resource_class *rclass; + + /* + * Blank out first bit of line + */ + for(i=0; i< level*2; i++) + *cp++ = ' '; + + /* + * Describe resource + */ + rclass= fw.resource_class_index[(unsigned char )res->class]; + + if(rclass == NULL) { + sprintf(cp,"0x%08x ??? (%02X)", res+1, res->class); + putline(_br_scratch_string,arg); + return; + } + + sprintf(cp,"0x%08x %-20s %d", ResToUser(res), rclass->identifier, res->size); + putline(_br_scratch_string,arg); + + /* + * Display any children + */ + BR_FOR_SIMPLELIST(&res->children,child) + InternalResourceDump(child, putline, arg, level+1); +#endif +} + +void BR_PUBLIC_ENTRY BrResDump(void *vres, void (*putline)(char *str, void *arg), void *arg) +{ + struct resource_header *res = UserToRes(vres); + + InternalResourceDump(res, putline, arg, 0); +} +#endif diff --git a/bren/FW/scalar.c b/bren/FW/scalar.c new file mode 100644 index 00000000..7a728451 --- /dev/null +++ b/bren/FW/scalar.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: scalar.c 1.2 1995/02/22 21:42:36 sam Exp $ + * $Locker: $ + * + * Symbols that are defined to make sure apps. link to the right library + */ +#include "fw.h" + +#if BASED_FIXED +int _BR_Fixed_Point_Scalar = 0; +#endif + +#if BASED_FLOAT +int _BR_Floating_Point_Scalar = 0; +#endif diff --git a/bren/FW/scale.c b/bren/FW/scale.c new file mode 100644 index 00000000..3469c347 --- /dev/null +++ b/bren/FW/scale.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: scale.c 1.2 1995/02/22 21:42:37 sam Exp $ + * $Locker: $ + * + * Image scaling (only RGB) + * Based on General filtered image rescaling, Dale Schumacher, Graphics Gems III p.8 + * + */ + +#include +#include +#include +#include + +#include "brender.h" +#include "scale.h" + +#define CLAMP(a, min, max) (a < min ? min : (a > max ? max : a)) + +#define BLACK 0x00 +#define WHITE 0xff + +typedef struct +{ + int pixel; + float weight; +} CONTRIB; + +typedef struct +{ + int n; + CONTRIB *p; +} CLIST; + +static CLIST *contrib; + +typedef struct +{ + char red, green, blue; +} RGB3; + +void BR_PUBLIC_ENTRY BrScaleBegin(void) +{ +} + +void BR_PUBLIC_ENTRY BrScaleEnd(void) +{ +} + +#if 0 +float box_filter(float t) +{ + if((t>-0.5) && (t<=0.5)) + return(1.0F); + else + return(0.0F); +} +float tri_filter(float t) +{ + if(t<0.0) t = -t; + if(t<1.0) + return(1.0F-t); + else + return(0.0F); +} +#endif + +#define Mitchell_support (2.0F) + +#define B (1.0F / 3.0F) +#define C (1.0F / 3.0F) + +static float Mitchell_filter(float t) +{ + float tt; + + tt = t * t; + if (t < 0) + t = -t; + if (t < 1.0F) + { + t = (((12.0F - 9.0F * B - 6.0F * C) * (t * tt)) + ((-18.0F + 12.0F * B + 6.0F * C) * tt) + (6.0F - 2 * B)); + return (t / 6.0F); + } + else if (t < 2.0F) + { + t = (((-1.0F * B - 6.0F * C) * (t * tt)) + ((6.0F * B + 30.0F * C) * tt) + ((-12.0F * B - 48.0F * C) * t) + + (8.0F * B + 24 * C)); + return (t / 6.0F); + } + return (0.0F); +} + +br_pixelmap *BR_PUBLIC_ENTRY BrPixelmapScale(br_pixelmap *src, br_uint_32 new_x, br_uint_32 new_y, float fwidth) +{ + float xscale, yscale; + float width, fscale; + float center, left, right; + float weight, rw, gw, bw; + br_pixelmap *temp; + char *identifier; + int i, j, k, n; + + char *src_pixels, *pm_pixels; + + if (src->type != BR_PMT_RGB_888) + BR_ERROR1("'%s' is not a suitable pixelmap to scale", src->identifier); + + identifier = BrMemAllocate(strlen(src->identifier) + 1, BR_MEMORY_STRING); + strcpy(identifier, src->identifier); + + /* + * Allocate temp pixelmap for horizontal scale + */ + temp = BrPixelmapAllocate(BR_PMT_RGB_888, new_x, src->height, NULL, 0); + xscale = (float)new_x / (double)src->width; + yscale = (float)new_y / (double)src->height; + + /* + * Precalculate filter contributions for a row + */ + contrib = BrMemAllocate(new_x * sizeof(CLIST), BR_MEMORY_SCRATCH); + if (xscale < 1.0) + { + width = fwidth / xscale; + fscale = 1.0 / xscale; + for (i = 0; i < new_x; ++i) + { + contrib[i].n = 0; + n = (int)(width * 2 + 1) * sizeof(CONTRIB); + contrib[i].p = BrMemAllocate(n, BR_MEMORY_SCRATCH); + center = (float)i / xscale; + left = ceil(center - width); + right = floor(center + width); + + for (j = left; j <= right; ++j) + { + weight = center - (float)j; + weight = Mitchell_filter(weight / fscale) / fscale; + if (j < 0) + { + n = -j; + } + else if (j >= src->width) + { + n = (src->width - j) + src->width - 1; + } + else + { + n = j; + } + k = contrib[i].n++; + contrib[i].p[k].pixel = n; + contrib[i].p[k].weight = weight; + } + } + } + else + { + for (i = 0; i < new_x; ++i) + { + contrib[i].n = 0; + contrib[i].p = BrMemAllocate((int)(fwidth * 2 + 1) * sizeof(CONTRIB), BR_MEMORY_SCRATCH); + center = (float)i / xscale; + left = ceil(center - fwidth); + right = floor(center + fwidth); + for (j = left; j <= right; ++j) + { + weight = center - (float)j; + weight = Mitchell_filter(weight); + if (j < 0) + { + n = -j; + } + else if (j >= src->width) + { + n = (src->width - j) + src->width - 1; + } + else + { + n = j; + } + k = contrib[i].n++; + contrib[i].p[k].pixel = n; + contrib[i].p[k].weight = weight; + } + } + } + + /* + * Apply filter to zoom horizontally from src to temp + */ + + src_pixels = src->pixels; + pm_pixels = temp->pixels; + + for (k = 0; k < temp->height; ++k, src_pixels += src->row_bytes, pm_pixels += temp->row_bytes) + { + for (i = 0; i < temp->width; ++i) + { + rw = bw = gw = 0.0; + for (j = 0; j < contrib[i].n; ++j) + { + rw += src_pixels[0 + 3 * contrib[i].p[j].pixel] * contrib[i].p[j].weight; + gw += src_pixels[1 + 3 * contrib[i].p[j].pixel] * contrib[i].p[j].weight; + bw += src_pixels[2 + 3 * contrib[i].p[j].pixel] * contrib[i].p[j].weight; + } + pm_pixels[0 + 3 * i] = CLAMP(rw, BLACK, WHITE); + pm_pixels[1 + 3 * i] = CLAMP(gw, BLACK, WHITE); + pm_pixels[2 + 3 * i] = CLAMP(bw, BLACK, WHITE); + } + } + + /* + * Free horizontal workspace + */ + for (i = 0; i < temp->width; i++) + BrMemFree(contrib[i].p); + BrMemFree(contrib); + + /* + * Allocate temp pixelmap for vertical scale + */ + src = temp; + temp = BrPixelmapAllocate(BR_PMT_RGB_888, new_x, new_y, NULL, 0); + + /* + * Precalculate filter contributions for a column + */ + contrib = BrMemAllocate(new_y * sizeof(CLIST), BR_MEMORY_SCRATCH); + if (yscale < 1.0) + { + width = fwidth / yscale; + fscale = 1.0 / yscale; + for (i = 0; i < new_y; ++i) + { + contrib[i].n = 0; + n = (int)(width * 2 + 1) * sizeof(CONTRIB); + contrib[i].p = BrMemAllocate(n, BR_MEMORY_SCRATCH); + center = (float)i / yscale; + left = ceil(center - width); + right = floor(center + width); + for (j = left; j <= right; ++j) + { + weight = center - (float)j; + weight = Mitchell_filter(weight / fscale) / fscale; + if (j < 0) + { + n = -j; + } + else if (j >= src->height) + { + n = (src->height - j) + src->height - 1; + } + else + { + n = j; + } + k = contrib[i].n++; + contrib[i].p[k].pixel = n; + contrib[i].p[k].weight = weight; + } + } + } + else + { + for (i = 0; i < new_y; ++i) + { + contrib[i].n = 0; + contrib[i].p = BrMemAllocate((int)(fwidth * 2 + 1) * sizeof(CONTRIB), BR_MEMORY_SCRATCH); + center = (float)i / yscale; + left = ceil(center - fwidth); + right = floor(center + fwidth); + for (j = left; j <= right; ++j) + { + weight = center - (float)j; + weight = Mitchell_filter(weight); + if (j < 0) + { + n = -j; + } + else if (j >= src->height) + { + n = (src->height - j) + src->height - 1; + } + else + { + n = j; + } + k = contrib[i].n++; + contrib[i].p[k].pixel = n; + contrib[i].p[k].weight = weight; + } + } + } + + /* + * set src to temp + * Apply filter to zoom vertically from src to temp + */ + + src_pixels = src->pixels; + pm_pixels = temp->pixels; + + for (k = 0; k < temp->width; ++k, src_pixels += 3, pm_pixels += 3) + { + for (i = 0; i < temp->height; ++i) + { + rw = gw = bw = 0.0; + for (j = 0; j < contrib[i].n; ++j) + { + rw += src_pixels[contrib[i].p[j].pixel * src->row_bytes + 0] * contrib[i].p[j].weight; + gw += src_pixels[contrib[i].p[j].pixel * src->row_bytes + 1] * contrib[i].p[j].weight; + bw += src_pixels[contrib[i].p[j].pixel * src->row_bytes + 2] * contrib[i].p[j].weight; + } + pm_pixels[0 + temp->row_bytes * i] = CLAMP(rw, BLACK, WHITE); + pm_pixels[1 + temp->row_bytes * i] = CLAMP(gw, BLACK, WHITE); + pm_pixels[2 + temp->row_bytes * i] = CLAMP(bw, BLACK, WHITE); + } + } + /* + * Free vertical workspace + */ + for (i = 0; i < temp->height; i++) + BrMemFree(contrib[i].p); + BrMemFree(contrib); + + BrPixelmapFree(src); + + temp->identifier = identifier; + + return temp; +} diff --git a/bren/FW/scratch.c b/bren/FW/scratch.c new file mode 100644 index 00000000..d42c7a33 --- /dev/null +++ b/bren/FW/scratch.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: scratch.c 1.7 1995/08/31 16:29:46 sam Exp $ + * $Locker: $ + * + * Manage a temporary scratchpad for the rest of the system + * + * Will only allow 1 buffer to be allocated at any time + */ +#include "fw.h" +#include "brassert.h" + +/* + * Allocate a scratch buffer of the given size + */ +void *BR_PUBLIC_ENTRY BrScratchAllocate(br_size_t size) +{ + if (fw.scratch_inuse) + BR_ERROR0("Scratchpad not available"); + + fw.scratch_last = size; + + if (size > fw.scratch_size) + { + if (fw.scratch_ptr) + BrResFree(fw.scratch_ptr); + + fw.scratch_ptr = BrResAllocate(fw.res, size, BR_MEMORY_SCRATCH); +#if 0 + fw.scratch_size = BrResSize(fw.scratch_ptr); +#else + fw.scratch_size = size; +#endif + } + + fw.scratch_inuse = 1; + + return fw.scratch_ptr; +} + +/* + * Release a scratch buffer + */ +void BR_PUBLIC_ENTRY BrScratchFree(void *scratch) +{ + UASSERT(fw.scratch_ptr == scratch); + + fw.scratch_inuse = 0; + +#if 0 /* Churn memory allocator */ + BrResFree(fw.scratch_ptr); + fw.scratch_ptr = NULL; + fw.scratch_size = 0; +#endif +} + +/* + * Free any allocated scratch buffer + */ +void BR_PUBLIC_ENTRY BrScratchFlush(void) +{ + if (fw.scratch_inuse) + BR_ERROR0("Scratchpad cannot be flushed while in use"); + + if (fw.scratch_ptr) + BrResFree(fw.scratch_ptr); + + fw.scratch_ptr = NULL; + fw.scratch_size = 0; +} + +/* + * Find out how much scratch space is 'easily' available + */ +br_size_t BR_PUBLIC_ENTRY BrScratchInquire(void) +{ + return fw.scratch_size; +} diff --git a/bren/FW/scrstr.c b/bren/FW/scrstr.c new file mode 100644 index 00000000..adf610a3 --- /dev/null +++ b/bren/FW/scrstr.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: scrstr.c 1.3 1995/05/25 13:24:06 sam Exp $ + * $Locker: $ + * + * A global scratchpad string used for printf and error operations + */ +#include "fw.h" + +/* + * Initialised to a value because IBM Cset++ LIB hides the symbol + * otherwise ??? + */ +char _br_scratch_string[512] = "SCRATCH"; diff --git a/bren/FW/shortcut.h b/bren/FW/shortcut.h new file mode 100644 index 00000000..c49c8cdc --- /dev/null +++ b/bren/FW/shortcut.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: shortcut.h 1.5 1995/02/22 21:42:40 sam Exp $ + * $Locker: $ + * + * Some shortcut macros to make matrix, euler, and quaternion access + * shorter to read + */ + +/* + * Matrices + */ +#define M(x, y) mat->m[x][y] +#define A(x, y) A->m[x][y] +#define B(x, y) B->m[x][y] +#define C(x, y) C->m[x][y] + +/* + * Quaternions + */ +#define lX (l->x) +#define lY (l->y) +#define lZ (l->z) +#define lW (l->w) + +#define rX (r->x) +#define rY (r->y) +#define rZ (r->z) +#define rW (r->w) + +#define qX (q->x) +#define qY (q->y) +#define qZ (q->z) +#define qW (q->w) + +#define tX (t.x) +#define tY (t.y) +#define tZ (t.z) +#define tW (t.w) + +#define qqX (qq->x) +#define qqY (qq->y) +#define qqZ (qq->z) +#define qqW (qq->w) + +#define qi(c) (((br_scalar *)(q))[c]) + +/* + * Euler angles + */ +#define eX (euler->a) +#define eY (euler->b) +#define eZ (euler->c) +#define eO (euler->order) + +/* + * Scalars + */ +#define S1 BR_SCALAR(1.0) +#define S0 BR_SCALAR(0.0) + +/* + * For digging around in points etc - makes things slightly easier to read + */ +#define X 0 +#define Y 1 +#define Z 2 +#define W 3 + +#define U 0 +#define V 1 diff --git a/bren/FW/surface.c b/bren/FW/surface.c new file mode 100644 index 00000000..b963fffd --- /dev/null +++ b/bren/FW/surface.c @@ -0,0 +1,617 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: surface.c 1.11 1995/03/29 16:41:24 sam Exp $ + * $Locker: $ + * + * Generation of surface properties + */ +#include "fw.h" +#include "shortcut.h" +#include "brassert.h" + +static char rscid[] = "$Id: surface.c 1.11 1995/03/29 16:41:24 sam Exp $"; + +/* + * Setup surface (lighting mapping etc) prior to a rendering traversal + */ +void SurfacePerScene(br_actor *world, int true_colour) +{ + int i, nm = 0, nv = 0, nc = 0; + br_light *light; + br_matrix34 this_to_world, this_to_view, view_to_this; + br_matrix4 screen_to_view; + br_matrix4 screen_to_this, tmp4; + br_active_light *alp; + + /* + * Set up lighting sub funtions depending on type of output pixels + */ + + if (true_colour) + { + fw.fn_table.direct = LightingColour_Dirn; + fw.fn_table.point = LightingColour_Point; + fw.fn_table.point_attn = LightingColour_PointAttn; + fw.fn_table.spot = LightingColour_Spot; + fw.fn_table.spot_attn = LightingColour_SpotAttn; + } + else + { + fw.fn_table.direct = LightingIndex_Dirn; + fw.fn_table.point = LightingIndex_Point; + fw.fn_table.point_attn = LightingIndex_PointAttn; + fw.fn_table.spot = LightingIndex_Spot; + fw.fn_table.spot_attn = LightingIndex_SpotAttn; + } + + /* + * Go through active light actors converting into active light + * instances + */ + for (i = 0; i < BR_MAX_LIGHTS; i++) + { + if (fw.enabled_lights[i] == NULL) + continue; + + light = fw.enabled_lights[i]->type_data; + + ASSERT(fw.enabled_lights[i]->type == BR_ACTOR_LIGHT); + ASSERT(light != NULL); + ASSERT(nm < BR_MAX_LIGHTS); + ASSERT(nv < BR_MAX_LIGHTS); + + /* + * Work out light->root transform - ignore light if not part of + * current hierachy + */ + if (BrActorToRoot(fw.enabled_lights[i], world, &this_to_world) == 0) + continue; + + /* + * Concatenate with world->view + */ + BrMatrix34Mul(&this_to_view, &this_to_world, &fw.model_to_view); + + /* + * Build view->light + */ + BrMatrix34Inverse(&view_to_this, &this_to_view); + + /* + * Select next active light structure + */ + if (light->type & BR_LIGHT_VIEW) + alp = fw.active_lights_view + nv++; + else + alp = fw.active_lights_model + nm++; + + /* + * Generate active data for type of light + */ + alp->light = light; + alp->type = light->type & BR_LIGHT_TYPE; + + alp->intensity = BR_RCP(light->attenuation_c); + + switch (alp->type) + { + + case BR_LIGHT_POINT: + /* + * Transform position (0,0,0,1) into view space + */ + BrVector3CopyMat34Row(&alp->view_position, &this_to_view, 3); + + if (light->attenuation_l == BR_SCALAR(0.0) && light->attenuation_q == BR_SCALAR(0.0)) + alp->light_sub_function = fw.fn_table.point; + else + alp->light_sub_function = fw.fn_table.point_attn; + break; + + case BR_LIGHT_DIRECT: + /* + * Transform direction (0,0,1,0) into view space - + * use T(I(l_to_v)) - or column 2 of view_to_this + */ + BrVector3CopyMat34Col(&alp->view_direction, &view_to_this, 2); + alp->light_sub_function = fw.fn_table.direct; + + if (light->type & BR_LIGHT_VIEW) + /* + * Scale direction vector by light intensity for direct lights + */ + BrVector3Scale(&alp->direction, &alp->view_direction, alp->intensity); + + break; + + case BR_LIGHT_SPOT: + /* + * Transform position and direction into view space + */ + BrVector3CopyMat34Row(&alp->view_position, &this_to_view, 3); + BrVector3CopyMat34Col(&alp->view_direction, &view_to_this, 2); + + if (light->attenuation_l == BR_SCALAR(0.0) && light->attenuation_q == BR_SCALAR(0.0)) + alp->light_sub_function = fw.fn_table.spot; + else + alp->light_sub_function = fw.fn_table.spot_attn; + + alp->spot_cosine_outer = BR_COS(light->cone_outer); + alp->spot_cosine_inner = BR_COS(light->cone_inner); + + break; + } + + /* + * Copy vectors for view lights + */ + if (light->type & BR_LIGHT_VIEW) + { + alp->position = alp->view_position; + alp->direction = alp->view_direction; + } + } + + fw.nactive_lights_model = nm; + fw.nactive_lights_view = nv; + + /* + * Spot special case of 'easy' lighting + */ + if (fw.nactive_lights_model == 1 && fw.nactive_lights_view == 0 && + fw.active_lights_model[0].type == BR_LIGHT_DIRECT) + fw.light_is_1md = 1; + else + fw.light_is_1md = 0; + + /* + * Set up surface funtions + */ + if (true_colour) + { + fw.fn_table.light = fw.light_is_1md ? LightingColour_1MD : LightingColour; + fw.fn_table.light_material = LightingColourCopyMaterial; + fw.fn_table.light_vertex = LightingColourCopyVertex; + fw.fn_table.face_light = LightingFaceColour; + fw.fn_table.light_texture = LightingColour_1MDT; + } + else + { + fw.fn_table.light = fw.light_is_1md ? LightingIndex_1MD : LightingIndex; + fw.fn_table.light_material = LightingIndexCopyMaterial; + fw.fn_table.light_vertex = LightingIndexCopyVertex; + fw.fn_table.face_light = LightingFaceIndex; + fw.fn_table.light_texture = LightingIndex_1MDT; + } + + /* + * Handle any enviroment anchor + */ + if (fw.enabled_environment) + { + if (fw.enabled_environment != world) + { + if (!BrActorToRoot(fw.enabled_environment, world, &this_to_world)) + BR_ERROR0("environment is not in world hierachy"); + BrMatrix34Inverse(&fw.model_to_environment, &this_to_world); + } + else + { + BrMatrix34Identity(&fw.model_to_environment); + } + } + + /* + * Process any clip planes + */ + nc = 0; + + for (i = 0; i < BR_MAX_CLIP_PLANES; i++) + { + + if (fw.enabled_clip_planes[i] == NULL) + continue; + + if (nc == 0) + { + /* + * Invert view->screen + */ + BrMatrix4Inverse(&screen_to_view, &fw.view_to_screen); + } + + /* + * Find clip plane->world, ignore if not in world + */ + if (BrActorToRoot(fw.enabled_clip_planes[i], world, &this_to_world) == 0) + continue; + + /* + * Make plane->view and invert it + */ + BrMatrix34Mul(&this_to_view, &this_to_world, &fw.model_to_view); + BrMatrix34Inverse(&view_to_this, &this_to_view); + + /* + * Make screen->plane + */ + BrMatrix4Copy34(&tmp4, &view_to_this); + + BrMatrix4Mul(&screen_to_this, &screen_to_view, &tmp4); + + /* + * Push plane through to screen space + */ + BrMatrix4TApply(&fw.active_clip_planes[nc].screen_plane, fw.enabled_clip_planes[i]->type_data, &screen_to_this); + + nc++; + } + + fw.nactive_clip_planes = nc; +} + +/* + * Process active lights before descending into a model + */ +void SurfacePerModel(void) +{ + int i; + br_active_light *alp; + + alp = fw.active_lights_model; + + for (i = 0; i < fw.nactive_lights_model; i++, alp++) + { + switch (alp->type) + { + case BR_LIGHT_DIRECT: + /* + * Transform light's direction + */ + BrMatrix34TApplyV(&alp->direction, &alp->view_direction, &fw.model_to_view); + BrVector3Normalise(&alp->direction, &alp->direction); + + /* + * Work out a unit half vector + */ + BrVector3Add(&alp->half, &alp->direction, &fw.eye_m_normalised); + BrVector3Normalise(&alp->half, &alp->half); + + /* + * Scale direction vector by light intensity + */ + BrVector3Scale(&alp->direction, &alp->direction, alp->intensity); + break; + + case BR_LIGHT_SPOT: + /* + * Transform light's direction and position + */ + BrMatrix34TApplyV(&alp->direction, &alp->view_direction, &fw.model_to_view); + BrVector3Normalise(&alp->direction, &alp->direction); + + /* FALL THROUGH */ + + case BR_LIGHT_POINT: + /* + * Transform light's position + */ + BrMatrix34ApplyP(&alp->position, &alp->view_position, &fw.view_to_model); + break; + } + } + + alp = fw.active_lights_view; + + for (i = 0; i < fw.nactive_lights_view; i++, alp++) + { + + if (alp->type == BR_LIGHT_DIRECT) + { + + /* + * Work out a unit half vector: + * eye = (0,0,1) + * half = normalise(light_direection + eye) + */ + alp->half = alp->view_direction; + alp->half.v[Z] += BR_SCALAR(1.0); + BrVector3Normalise(&alp->half, &alp->half); + } + } +} + +/* + * Dummy functions - in case renderer decides to invoke + * inappropriate function ptr + */ +void Surface_Null(br_vertex *v, br_scalar *comp) +{ +} + +void FaceSurface_Null(br_vertex *v, br_scalar *comp) +{ +} + +/* + * Process active lights before doing a group of lighting from the same material + */ +void SurfacePerMaterial(br_material *mat) +{ + br_scalar map_width, map_height; + + fw.material = mat; + + UASSERT(mat != NULL); + UASSERT(mat->prep_flags & MATUF_REGISTERED); + + ASSERT(mat->rptr != NULL); + + /* + * Catch special case of lit texture mapping + */ + if (fw.light_is_1md && mat->colour_map && + (mat->flags & (BR_MATF_LIGHT | BR_MATF_ENVIRONMENT_I | BR_MATF_ENVIRONMENT_L | BR_MATF_DECAL | + BR_MATF_I_FROM_U | BR_MATF_I_FROM_V | BR_MATF_U_FROM_I | BR_MATF_V_FROM_I | BR_MATF_PRELIT)) == + BR_MATF_LIGHT) + { + + fw.surface_fn = fw.fn_table.light_texture; + fw.face_surface_fn = fw.fn_table.face_light; + + map_width = BrIntToScalar(mat->colour_map->width); + map_height = BrIntToScalar(mat->colour_map->height); + + fw.map_transform.m[0][0] = BR_MUL(mat->map_transform.m[0][0], map_width); + fw.map_transform.m[1][0] = BR_MUL(mat->map_transform.m[1][0], map_width); + fw.map_transform.m[2][0] = BR_MUL(mat->map_transform.m[2][0], map_width); + + fw.map_transform.m[0][1] = BR_MUL(mat->map_transform.m[0][1], map_height); + fw.map_transform.m[1][1] = BR_MUL(mat->map_transform.m[1][1], map_height); + fw.map_transform.m[2][1] = BR_MUL(mat->map_transform.m[2][1], map_height); + + fw.index_base = BR_SCALAR(0.5); + if (mat->index_shade) + fw.index_range = BrIntToScalar(mat->index_shade->height - 1); + return; + } + + /* + * Select the basic colour functions + */ + switch (mat->flags & (BR_MATF_LIGHT | BR_MATF_PRELIT)) + { + + case 0: + fw.surface_fn = fw.fn_table.light_material; + fw.face_surface_fn = fw.fn_table.face_light; + break; + + case BR_MATF_LIGHT: + + fw.surface_fn = fw.fn_table.light; + fw.face_surface_fn = fw.fn_table.face_light; + break; + + case BR_MATF_PRELIT: + case BR_MATF_PRELIT | BR_MATF_LIGHT: + + fw.surface_fn = fw.fn_table.light_vertex; + fw.face_surface_fn = fw.fn_table.face_light; + break; + } + + /* + * Does a mapping function need to be added as well? + */ + if (mat->colour_map) + { + + fw.surface_fn_after_map = fw.surface_fn; + + if (mat->flags & BR_MATF_ENVIRONMENT_I) + /* + * Environment map (infinite eye) + */ + fw.surface_fn = MapEnvironmentInfinite2D; + else if (mat->flags & BR_MATF_ENVIRONMENT_L) + /* + * Environment map (local eye) + */ + fw.surface_fn = MapEnvironmentLocal2D; + else if (mat->flags & (BR_MATF_LIGHT | BR_MATF_PRELIT)) + /* + * Normal texture mapping + */ + fw.surface_fn = MapFromVertex; + else + /* + * Texture, but no lighting + */ + fw.surface_fn = MapFromVertexOnly; + + /* + * If decalling - postpone scaling until triangle renderer + */ + fw.index_base = BR_SCALAR(0.5); + if (mat->flags & BR_MATF_DECAL) + { + fw.index_range = BR_SCALAR(255.0); + } + else + { + if (mat->index_shade) + fw.index_range = BrIntToScalar(mat->index_shade->height - 1); + } + + /* + * Setup map_base and map_scale + */ + map_width = BrIntToScalar(mat->colour_map->width); + map_height = BrIntToScalar(mat->colour_map->height); + + fw.map_transform.m[0][0] = BR_MUL(mat->map_transform.m[0][0], map_width); + fw.map_transform.m[1][0] = BR_MUL(mat->map_transform.m[1][0], map_width); + fw.map_transform.m[2][0] = BR_MUL(mat->map_transform.m[2][0], map_width); + + fw.map_transform.m[0][1] = BR_MUL(mat->map_transform.m[0][1], map_height); + fw.map_transform.m[1][1] = BR_MUL(mat->map_transform.m[1][1], map_height); + fw.map_transform.m[2][1] = BR_MUL(mat->map_transform.m[2][1], map_height); + } + else + { + /* + * Default base and range + */ + fw.index_base = BrIntToScalar(mat->index_base) + BR_SCALAR(0.5); + fw.index_range = BrIntToScalar(mat->index_range); + } + + /* + * Does a copy function need to be added? + */ + if (mat->flags & (BR_MATF_I_FROM_U | BR_MATF_I_FROM_V | BR_MATF_U_FROM_I | BR_MATF_V_FROM_I)) + { + + fw.surface_fn_after_copy = fw.surface_fn; + fw.surface_fn = CopyComponents; + } +} + +/* + * Add a light to the set that will illuminate the world + */ +void BR_PUBLIC_ENTRY BrLightEnable(br_actor *l) +{ + int i; + + UASSERT(l != NULL); + UASSERT(l->type == BR_ACTOR_LIGHT); + + /* + * Look to see if light is already enabled + */ + for (i = 0; i < BR_MAX_LIGHTS; i++) + if (fw.enabled_lights[i] == l) + return; + + /* + * Find a blank slot + */ + for (i = 0; i < BR_MAX_LIGHTS; i++) + { + if (fw.enabled_lights[i] == NULL) + { + fw.enabled_lights[i] = l; + return; + } + } + + BR_ERROR0("too many enabled lights"); +} + +/* + * Remove a light from the set that will illuminate the world + */ +void BR_PUBLIC_ENTRY BrLightDisable(br_actor *l) +{ + int i; + + UASSERT(l != NULL); + UASSERT(l->type == BR_ACTOR_LIGHT); + + /* + * Find light in table and remove it + */ + for (i = 0; i < BR_MAX_LIGHTS; i++) + { + if (fw.enabled_lights[i] == l) + { + fw.enabled_lights[i] = NULL; + return; + } + } +} + +/* + * Add a clip plane to world + */ +void BR_PUBLIC_ENTRY BrClipPlaneEnable(br_actor *cp) +{ + int i; + + UASSERT(cp != NULL); + UASSERT(cp->type == BR_ACTOR_CLIP_PLANE); + UASSERT(cp->type_data != NULL); + + /* + * Look to see if plane is already enabled + */ + for (i = 0; i < BR_MAX_CLIP_PLANES; i++) + if (fw.enabled_clip_planes[i] == cp) + return; + + /* + * Find a blank slot + */ + for (i = 0; i < BR_MAX_CLIP_PLANES; i++) + { + if (fw.enabled_clip_planes[i] == NULL) + { + fw.enabled_clip_planes[i] = cp; + return; + } + } + + BR_ERROR0("too many enabled clip planes"); +} + +/* + * Remove a clip plane + */ +void BR_PUBLIC_ENTRY BrClipPlaneDisable(br_actor *cp) +{ + int i; + + UASSERT(cp != NULL); + UASSERT(cp->type == BR_ACTOR_CLIP_PLANE); + + /* + * Find plane in table and remove it + */ + for (i = 0; i < BR_MAX_CLIP_PLANES; i++) + { + if (fw.enabled_clip_planes[i] == cp) + { + fw.enabled_clip_planes[i] = NULL; + return; + } + } +} + +/* + * Surface function to copy components around + */ +void BR_SURFACE_CALL CopyComponents(br_vertex *v, br_fvector3 *normal, br_scalar *comp) +{ + /* + * Call next surface function + */ + fw.surface_fn_after_copy(v, normal, comp); + + /* + * Do required component copies + */ + if (fw.material->flags & BR_MATF_I_FROM_U) + comp[C_I] = comp[C_U]; + + if (fw.material->flags & BR_MATF_I_FROM_V) + comp[C_I] = comp[C_V]; + + if (fw.material->flags & BR_MATF_U_FROM_I) + comp[C_U] = comp[C_I]; + + if (fw.material->flags & BR_MATF_V_FROM_I) + comp[C_V] = comp[C_I]; +} diff --git a/bren/FW/token.c b/bren/FW/token.c new file mode 100644 index 00000000..bf095fcd --- /dev/null +++ b/bren/FW/token.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: token.c 1.1 1995/07/28 19:03:11 sam Exp $ + * $Locker: $ + * + * Token allocation and debugging + */ +#include +#include +#include + +#include "fw.h" +#include "brassert.h" + +/** + ** Basic token database support + **/ + +br_token BR_PUBLIC_ENTRY BrTokenFind(char *pattern) +{ +} + +br_token BR_PUBLIC_ENTRY BrTokenFindMany(char *pattern) +{ +} + +br_token BR_PUBLIC_ENTRY BrTokenAdd(char *name, br_token value_hint) +{ +} + +#if 0 +int BR_PUBLIC_ENTRY BrTokenAddMany(br_token *result, int result_max); +{ +} +#endif + +int BR_PUBLIC_ENTRY BrTokenRemove(br_token) +{ +} + +#if 0 +int BR_PUBLIC_ENTRY BrTokenRemoveMany(); +{ +} +#endif + +void BR_PUBLIC_ENTRY BrTokenEnum(br_token) +{ +} + +int BR_PUBLIC_ENTRY BrTokenCount(char *pattern) +{ +} + +/* + * Support functions + */ +/* + * Convert a string to a token/value list + */ + +br_uint_32 *BR_PUBLIC_ENTRY BrTokenFromString(char *string) +{ +} + +br_uint_32 *BR_PUBLIC_ENTRY BrTokenToString(br_token *token) +{ +} + +br_uint_32 BR_PUBLIC_ENTRY BrTokenListExtract(br_token *list, br_token t) +{ +} + +int BR_PUBLIC_ENTRY BrTokenListExtractMany(br_token *list, ...) +{ +} diff --git a/bren/FW/token.h b/bren/FW/token.h new file mode 100644 index 00000000..13356471 --- /dev/null +++ b/bren/FW/token.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: token.h 1.1 1995/07/28 19:03:08 sam Exp $ + * $Locker: $ + * + */ +#ifndef _TOKEN_H_ +#define _TOKEN_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + * Tokens are unique 32 bit numbers that are assoicated with a name + * and a value type. + */ + typedef br_uint_32 br_token; + + /* + * Token values are 32 bit + */ + typedef br_uint_32 br_token_value; + + /* + * Values that can be associated with a token + */ + enum + { + /* Suffix used on tokens */ + BR_TT_NONE, /* */ + BR_TT_BOOLEAN, /* B */ + BR_TT_POINTER, /* P */ + BR_TT_STRING, /* S */ + BR_TT_TOKEN, /* T */ + + BR_TT_INT_8, /* I8 */ + BR_TT_UINT_8, /* U8 */ + BR_TT_INT_16, /* I16 */ + BR_TT_UINT_16, /* U16 */ + BR_TT_INT_32, /* I32 */ + BR_TT_UINT_32, /* U32 */ + + BR_TT_FIXED, /* X */ + BR_TT_FIXED_FRACTION, /* XF */ + BR_TT_FIXED_UFRACTION, /* XUF */ + + BR_TT_FLOAT, /* F */ + + BR_TT_DEVICE_HANDLE, /* H */ + BR_TT_VECTOR2, /* V2 */ + BR_TT_VECTOR3, /* V3 */ + BR_TT_VECTOR4, /* V4 */ + BR_TT_FVECTOR2, /* FV2 */ + BR_TT_FVECTOR3, /* FV3 */ + BR_TT_FVECTOR4, /* FV4 */ + BR_TT_MATRIX23, /* M23 */ + BR_TT_MATRIX34, /* M34 */ + BR_TT_MATRIX4, /* M4 */ + + BR_TT_ANGLE, /* A */ + BR_TT_COLOUR_RGB, /* RGB */ + }; + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/bren/FW/transfrm.c b/bren/FW/transfrm.c new file mode 100644 index 00000000..4215df28 --- /dev/null +++ b/bren/FW/transfrm.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: transfrm.c 1.18 1995/08/31 16:29:47 sam Exp $ + * $Locker: $ + * + */ + +#include "fw.h" +#include "shortcut.h" + +static char rscid[] = "$Id: transfrm.c 1.18 1995/08/31 16:29:47 sam Exp $"; + +/* + * A table of how transforms combine + */ +#define M34 BR_TRANSFORM_MATRIX34 +#define MLP BR_TRANSFORM_MATRIX34_LP +#define QUT BR_TRANSFORM_QUAT +#define EUL BR_TRANSFORM_EULER +#define LUP BR_TRANSFORM_LOOK_UP +#define TRA BR_TRANSFORM_TRANSLATION +#define IDT BR_TRANSFORM_IDENTITY + +br_uint_8 _CombineTransforms[BR_TRANSFORM_MAX][BR_TRANSFORM_MAX] = { + + /*M34, MLP, QUT, EUL, LUP, TRA, IDT */ + + /* M34 */ { + M34, + M34, + M34, + M34, + M34, + M34, + M34, + }, + /* MLP */ + { + M34, + MLP, + MLP, + MLP, + MLP, + MLP, + MLP, + }, + /* QUT */ + { + M34, + MLP, + MLP, + MLP, + MLP, + QUT, + QUT, + }, + /* EUL */ + { + M34, + MLP, + MLP, + MLP, + MLP, + EUL, + EUL, + }, + /* LUP */ + { + M34, + MLP, + MLP, + MLP, + MLP, + LUP, + LUP, + }, + /* TRA */ + { + M34, + MLP, + QUT, + EUL, + LUP, + TRA, + TRA, + }, + /* IDT */ + { + M34, + MLP, + QUT, + EUL, + LUP, + TRA, + IDT, + }, +}; + +void BR_PUBLIC_ENTRY BrTransformToMatrix34(br_matrix34 *mat, br_transform *xform) +{ + switch (xform->type) + { + case BR_TRANSFORM_MATRIX34: + case BR_TRANSFORM_MATRIX34_LP: + *mat = xform->t.mat; + break; + + case BR_TRANSFORM_QUAT: + + BrQuatToMatrix34(mat, &xform->t.quat.q); + + mat->m[W][X] = xform->t.quat.t.v[X]; + mat->m[W][Y] = xform->t.quat.t.v[Y]; + mat->m[W][Z] = xform->t.quat.t.v[Z]; + break; + + case BR_TRANSFORM_EULER: + + BrEulerToMatrix34(mat, &xform->t.euler.e); + + mat->m[W][X] = xform->t.euler.t.v[X]; + mat->m[W][Y] = xform->t.euler.t.v[Y]; + mat->m[W][Z] = xform->t.euler.t.v[Z]; + + break; + + case BR_TRANSFORM_TRANSLATION: + BrMatrix34Translate(mat, xform->t.look_up.t.v[X], xform->t.look_up.t.v[Y], xform->t.look_up.t.v[Z]); + + break; + + case BR_TRANSFORM_LOOK_UP: { + /* + * 1) Normalise Lookat vector to get Z component of matrix + * 2) Cross with up vector and normalise to get X component + * 3) Cross X & Z to get Y + */ + br_vector3 vx, vy, vz; + + BrVector3Normalise(&vz, &xform->t.look_up.look); + BrVector3Negate(&vz, &vz); + BrVector3Cross(&vx, &xform->t.look_up.up, &vz); + BrVector3Normalise(&vx, &vx); + BrVector3Cross(&vy, &vz, &vx); + + mat->m[X][X] = vx.v[X]; + mat->m[X][Y] = vx.v[Y]; + mat->m[X][Z] = vx.v[Z]; + mat->m[Y][X] = vy.v[X]; + mat->m[Y][Y] = vy.v[Y]; + mat->m[Y][Z] = vy.v[Z]; + mat->m[Z][X] = vz.v[X]; + mat->m[Z][Y] = vz.v[Y]; + mat->m[Z][Z] = vz.v[Z]; + + mat->m[W][X] = xform->t.look_up.t.v[X]; + mat->m[W][Y] = xform->t.look_up.t.v[Y]; + mat->m[W][Z] = xform->t.look_up.t.v[Z]; + } + break; + + case BR_TRANSFORM_IDENTITY: + BrMatrix34Identity(mat); + break; + } +} + +void BR_PUBLIC_ENTRY BrMatrix34PreTransform(br_matrix34 *mat, br_transform *xform) +{ + br_matrix34 tmp; + + if (xform->type == BR_TRANSFORM_IDENTITY) + return; + + BrMatrix34Transform(&tmp, xform); + BrMatrix34Pre(mat, &tmp); +} + +void BR_PUBLIC_ENTRY BrMatrix34PostTransform(br_matrix34 *mat, br_transform *xform) +{ + br_matrix34 tmp; + + if (xform->type == BR_TRANSFORM_IDENTITY) + return; + + BrTransformToMatrix34(&tmp, xform); + + BrMatrix34Post(mat, &tmp); +} + +void BR_PUBLIC_ENTRY BrMatrix4PreTransform(br_matrix4 *mat, br_transform *xform) +{ + br_matrix34 tmp; + + if (xform->type == BR_TRANSFORM_IDENTITY) + return; + + BrTransformToMatrix34(&tmp, xform); + + BrMatrix4Pre34(mat, &tmp); +} + +/* + * Convert a 3x4 into a transform + */ +void BR_PUBLIC_ENTRY BrMatrix34ToTransform(br_transform *xform, br_matrix34 *mat) +{ + switch (xform->type) + { + + case BR_TRANSFORM_MATRIX34: + xform->t.mat = *mat; + break; + + case BR_TRANSFORM_MATRIX34_LP: + xform->t.mat = *mat; + BrMatrix34LPNormalise(&xform->t.mat, &xform->t.mat); + break; + + case BR_TRANSFORM_QUAT: + BrMatrix34ToQuat(&xform->t.quat.q, mat); + + xform->t.quat.t.v[X] = mat->m[W][X]; + xform->t.quat.t.v[Y] = mat->m[W][Y]; + xform->t.quat.t.v[Z] = mat->m[W][Z]; + break; + + case BR_TRANSFORM_EULER: + + BrMatrix34ToEuler(&xform->t.euler.e, mat); + + xform->t.euler.t.v[X] = mat->m[W][X]; + xform->t.euler.t.v[Y] = mat->m[W][Y]; + xform->t.euler.t.v[Z] = mat->m[W][Z]; + break; + + case BR_TRANSFORM_TRANSLATION: + xform->t.translate.t.v[X] = mat->m[W][X]; + xform->t.translate.t.v[Y] = mat->m[W][Y]; + xform->t.translate.t.v[Z] = mat->m[W][Z]; + break; + + case BR_TRANSFORM_LOOK_UP: + + /* + * Copy the z vector into look + */ + BrVector3CopyMat34Row(&xform->t.look_up.look, mat, 2); + + /* + * If the UP vector is 0,0,0, set it to 0,1,0 + */ + if (xform->t.look_up.up.v[0] == S0 && xform->t.look_up.up.v[1] == S0 && xform->t.look_up.up.v[2] == S0) + BrVector3Set(&xform->t.look_up.up, S0, S1, S0); + + xform->t.look_up.t.v[X] = mat->m[W][X]; + xform->t.look_up.t.v[Y] = mat->m[W][Y]; + xform->t.look_up.t.v[Z] = mat->m[W][Z]; + break; + + case BR_TRANSFORM_IDENTITY: + break; + } +} + +/* + * Copy the source transform into the destination + * + * The destination type is retained. The operation tries + * to keep as much information about the transform as possible + */ +void BR_PUBLIC_ENTRY BrTransformToTransform(br_transform *dest, br_transform *src) +{ + br_matrix34 temp; + + /* + * If the types are the same, simply copy the data + */ + if (dest->type == src->type) + { + *dest = *src; + return; + } + + /* + * If the destination type is a 3x4 matrix, + * simply generate the source into it + */ + if (dest->type <= BR_TRANSFORM_MATRIX34_LP) + { + BrMatrix34Transform(&dest->t.mat, src); + + /* + * If source was not length preserving, + * Orthonormalise the matrix + */ + if (!IS_LP(src->type)) + BrMatrix34LPNormalise(&dest->t.mat, &dest->t.mat); + + return; + } + + /* + * Convert src to dest via temp. matrix + */ + BrTransformToMatrix34(&temp, src); + BrMatrix34ToTransform(dest, &temp); +} diff --git a/bren/FW/vecifns.h b/bren/FW/vecifns.h new file mode 100644 index 00000000..42446220 --- /dev/null +++ b/bren/FW/vecifns.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: vecifns.h 1.9 1995/03/01 15:26:24 sam Exp $ + * $Locker: $ + * + * Inline versions of the internal vector operations + */ + +#ifndef _VECIFNS_H_ +#define _VECIFNS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * v1=matrix[row] + */ +#define BrVector3CopyMat34Row(v1, matrix, row) \ + do \ + { \ + (v1)->v[0] = (matrix)->m[(row)][0]; \ + (v1)->v[1] = (matrix)->m[(row)][1]; \ + (v1)->v[2] = (matrix)->m[(row)][2]; \ + } while (0) + +/* + * v1=matrix[row] + */ +#define BrVector3CopyMat34Col(v1, matrix, col) \ + do \ + { \ + (v1)->v[0] = (matrix)->m[0][(col)]; \ + (v1)->v[1] = (matrix)->m[1][(col)]; \ + (v1)->v[2] = (matrix)->m[2][(col)]; \ + } while (0) + +/* + * = v1.v2 (v1 is a unit vector (word components)) + */ +#define BrFVector2Dot(v1, v2) BR_FMAC2((v1)->v[0], (v2)->v[0], (v1)->v[1], (v2)->v[1]) + +/* + * v1=v2 + */ +#define BrVector3CopyF(v1, v2) \ + do \ + { \ + (v1)->v[0] = BrFractionToScalar((v2)->v[0]); \ + (v1)->v[1] = BrFractionToScalar((v2)->v[1]); \ + (v1)->v[2] = BrFractionToScalar((v2)->v[2]); \ + } while (0) + +#define BrVector3ScaleF(v1, v2, s) \ + do \ + { \ + (v1)->v[0] = BR_MUL((v2)->v[0], BrFractionToScalar(s)); \ + (v1)->v[1] = BR_MUL((v2)->v[1], BrFractionToScalar(s)); \ + (v1)->v[2] = BR_MUL((v2)->v[2], BrFractionToScalar(s)); \ + } while (0) + +#define BrFVector3Scale(v1, v2, s) \ + do \ + { \ + (v1)->v[0] = BR_MUL(BrFractionToScalar((v2)->v[0]), (s)); \ + (v1)->v[1] = BR_MUL(BrFractionToScalar((v2)->v[1]), (s)); \ + (v1)->v[2] = BR_MUL(BrFractionToScalar((v2)->v[2]), (s)); \ + } while (0) + +/* + * v1=-v2 + */ +#define BrFVector3Negate(v1, v2) \ + do \ + { \ + (v1)->v[0] = -(v2)->v[0]; \ + (v1)->v[1] = -(v2)->v[1]; \ + (v1)->v[2] = -(v2)->v[2]; \ + } while (0) + +/* + * = v1.v2 (v1 is a unit vector (word components)) + */ +#define BrFVector3Dot(v1, v2) BR_FMAC3((v1)->v[0], (v2)->v[0], (v1)->v[1], (v2)->v[1], (v1)->v[2], (v2)->v[2]) + +/* + * v1 = v2/|v2| + */ +#define BrFVector3Normalise(v1, v2) \ + do \ + { \ + br_scalar _scale; \ + _scale = BR_LENGTH3((v2)->v[0], (v2)->v[1], (v2)->v[2]); \ + if (_scale > BR_SCALAR_EPSILON * 2) \ + { \ + _scale = BR_DIV(BR_FRACTION(1.0), _scale); \ + (v1)->v[0] = (br_fraction)BR_MUL((v2)->v[0], _scale); \ + (v1)->v[1] = (br_fraction)BR_MUL((v2)->v[1], _scale); \ + (v1)->v[2] = (br_fraction)BR_MUL((v2)->v[2], _scale); \ + } \ + else \ + { \ + (v1)->v[0] = BR_FRACTION(1.0); \ + (v1)->v[1] = BR_FRACTION(0.0); \ + (v1)->v[2] = BR_FRACTION(0.0); \ + } \ + } while (0) + +/* + * v1 = v2/|v2| + */ +#define BrFVector3NormaliseQuick(v1, v2) \ + do \ + { \ + scalar _scale; \ + _scale = BR_DIV(BR_FRACTION(1.0), BR_LENGTH3((v2)->v[0], (v2)->v[1], (v2)->v[2])); \ + BrVector3Scale(v1, v2, _scale); \ + } while (0) + +/* + * v1 = v2/|v2| (low precision) + */ +#if BASED_FIXED /* XXX - This should not be here */ +#define BrFVector3NormaliseLP(v1, v2) \ + do \ + { \ + br_scalar _scale; \ + _scale = BR_RLENGTH3((v2)->v[0], (v2)->v[1], (v2)->v[2]) >> 1; \ + BrVector3Scale(v1, v2, _scale); \ + } while (0) +#endif + +#if BASED_FLOAT +#define BrFVector3NormaliseLP(v1, v2) \ + do \ + { \ + br_scalar _scale; \ + _scale = BR_RLENGTH3((v2)->v[0], (v2)->v[1], (v2)->v[2]); \ + BrVector3ScaleF(v1, v2, _scale); \ + } while (0) +#endif + +/* + * v1=matrix[row] + */ +#define BrVector4CopyMat4Row(v1, matrix, row) \ + do \ + { \ + (v1)->v[0] = (matrix)->m[(row)][0]; \ + (v1)->v[1] = (matrix)->m[(row)][1]; \ + (v1)->v[2] = (matrix)->m[(row)][2]; \ + (v1)->v[3] = (matrix)->m[(row)][3]; \ + } while (0) + +/* + * v1=matrix[column] + */ +#define BrVector4CopyMat4Col(v1, matrix, col) \ + do \ + { \ + (v1)->v[0] = (matrix)->m[0][(col)]; \ + (v1)->v[1] = (matrix)->m[1][(col)]; \ + (v1)->v[2] = (matrix)->m[2][(col)]; \ + (v1)->v[3] = (matrix)->m[3][(col)]; \ + } while (0) + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/bren/FW/vector.c b/bren/FW/vector.c new file mode 100644 index 00000000..c2101add --- /dev/null +++ b/bren/FW/vector.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: vector.c 1.10 1995/08/31 16:29:49 sam Exp $ + * $Locker: $ + * + * Vector op. - some of these are redefined as macros in vecfns.h + * for speed. (but the real functions still exist for debugging purposes) + * + */ + +#undef _NO_VECTOR_MACROS +#define _NO_VECTOR_MACROS 1 + +#include "fw.h" +#include "shortcut.h" + +static char rscid[] = "$Id: vector.c 1.10 1995/08/31 16:29:49 sam Exp $"; + +/** + ** 2D Vectors + **/ +void BR_PUBLIC_ENTRY BrVector2Copy(br_vector2 *v1, br_vector2 *v2) +{ + v1->v[0] = v2->v[0]; + v1->v[1] = v2->v[1]; +} + +/* + * v1=(s1,s2) + */ +void BR_PUBLIC_ENTRY BrVector2Set(br_vector2 *v1, br_scalar s1, br_scalar s2) +{ + v1->v[0] = s1; + v1->v[1] = s2; +} + +void BR_PUBLIC_ENTRY BrVector2SetInt(br_vector2 *v1, int i1, int i2) +{ + v1->v[0] = BrIntToScalar(i1); + v1->v[1] = BrIntToScalar(i2); +} + +void BR_PUBLIC_ENTRY BrVector2SetFloat(br_vector2 *v1, float f1, float f2) +{ + v1->v[0] = BrFloatToScalar(f1); + v1->v[1] = BrFloatToScalar(f2); +} + +/* + * v1=-v2 + */ +void BR_PUBLIC_ENTRY BrVector2Negate(br_vector2 *v1, br_vector2 *v2) +{ + v1->v[0] = -v2->v[0]; + v1->v[1] = -v2->v[1]; +} + +/* + * v1=v2+v3 + */ +void BR_PUBLIC_ENTRY BrVector2Add(br_vector2 *v1, br_vector2 *v2, br_vector2 *v3) +{ + v1->v[0] = v2->v[0] + v3->v[0]; + v1->v[1] = v2->v[1] + v3->v[1]; +} + +/* + * v1+=v2 + */ +void BR_PUBLIC_ENTRY BrVector2Accumulate(br_vector2 *v1, br_vector2 *v2) +{ + v1->v[0] += v2->v[0]; + v1->v[1] += v2->v[1]; +} + +/* + * v1=v2-v3 + */ +void BR_PUBLIC_ENTRY BrVector2Sub(br_vector2 *v1, br_vector2 *v2, br_vector2 *v3) +{ + v1->v[0] = v2->v[0] - v3->v[0]; + v1->v[1] = v2->v[1] - v3->v[1]; +} + +/* + * v1=v2*scalar + */ +void BR_PUBLIC_ENTRY BrVector2Scale(br_vector2 *v1, br_vector2 *v2, br_scalar s) +{ + v1->v[0] = BR_MUL(v2->v[0], (s)); + v1->v[1] = BR_MUL(v2->v[1], (s)); +} + +/* + * v1=v2/scalar + */ +void BR_PUBLIC_ENTRY BrVector2InvScale(br_vector2 *v1, br_vector2 *v2, br_scalar s) +{ + v1->v[0] = BR_DIV(v2->v[0], (s)); + v1->v[1] = BR_DIV(v2->v[1], (s)); +} + +/* + * = v1.v2 + */ +br_scalar BR_PUBLIC_ENTRY BrVector2Dot(br_vector2 *v1, br_vector2 *v2) +{ + return BR_MAC2(v1->v[0], v2->v[0], v1->v[1], v2->v[1]); +} + +/* + * = |v1| + */ +br_scalar BR_PUBLIC_ENTRY BrVector2Length(br_vector2 *v1) +{ + return BR_LENGTH2(v1->v[0], v1->v[1]); +} + +/* + * = |v1| * |v1| + */ +br_scalar BR_PUBLIC_ENTRY BrVector2LengthSquared(br_vector2 *v1) +{ + return BR_SQR2(v1->v[0], v1->v[1]); +} + +/** + ** 3D VECTORS + **/ + +/* + * v1=v2 + */ +void BR_PUBLIC_ENTRY BrVector3Copy(br_vector3 *v1, br_vector3 *v2) +{ + v1->v[0] = v2->v[0]; + v1->v[1] = v2->v[1]; + v1->v[2] = v2->v[2]; +} + +/* + * v1=(s1,s2,s3) + */ +void BR_PUBLIC_ENTRY BrVector3Set(br_vector3 *v1, br_scalar s1, br_scalar s2, br_scalar s3) +{ + v1->v[0] = s1; + v1->v[1] = s2; + v1->v[2] = s3; +} + +void BR_PUBLIC_ENTRY BrVector3SetInt(br_vector3 *v1, int i1, int i2, int i3) +{ + v1->v[0] = BrIntToScalar(i1); + v1->v[1] = BrIntToScalar(i2); + v1->v[2] = BrIntToScalar(i3); +} + +void BR_PUBLIC_ENTRY BrVector3SetFloat(br_vector3 *v1, float f1, float f2, float f3) +{ + v1->v[0] = BrFloatToScalar(f1); + v1->v[1] = BrFloatToScalar(f2); + v1->v[2] = BrFloatToScalar(f3); +} + +/* + * v1=-v2 + */ +void BR_PUBLIC_ENTRY BrVector3Negate(br_vector3 *v1, br_vector3 *v2) +{ + v1->v[0] = -v2->v[0]; + v1->v[1] = -v2->v[1]; + v1->v[2] = -v2->v[2]; +} + +/* + * v1=v2+v3 + */ +void BR_PUBLIC_ENTRY BrVector3Add(br_vector3 *v1, br_vector3 *v2, br_vector3 *v3) +{ + v1->v[0] = v2->v[0] + v3->v[0]; + v1->v[1] = v2->v[1] + v3->v[1]; + v1->v[2] = v2->v[2] + v3->v[2]; +} + +/* + * v1+=v2 + */ +void BR_PUBLIC_ENTRY BrVector3Accumulate(br_vector3 *v1, br_vector3 *v2) +{ + v1->v[0] += v2->v[0]; + v1->v[1] += v2->v[1]; + v1->v[2] += v2->v[2]; +} + +/* + * v1=v2-v3 + */ +void BR_PUBLIC_ENTRY BrVector3Sub(br_vector3 *v1, br_vector3 *v2, br_vector3 *v3) +{ + v1->v[0] = v2->v[0] - v3->v[0]; + v1->v[1] = v2->v[1] - v3->v[1]; + v1->v[2] = v2->v[2] - v3->v[2]; +} + +/* + * v1=v2*scalar + */ +void BR_PUBLIC_ENTRY BrVector3Scale(br_vector3 *v1, br_vector3 *v2, br_scalar s) +{ + v1->v[0] = BR_MUL(v2->v[0], (s)); + v1->v[1] = BR_MUL(v2->v[1], (s)); + v1->v[2] = BR_MUL(v2->v[2], (s)); +} + +/* + * v1=v2/scalar + */ +void BR_PUBLIC_ENTRY BrVector3InvScale(br_vector3 *v1, br_vector3 *v2, br_scalar s) +{ + v1->v[0] = BR_DIV(v2->v[0], (s)); + v1->v[1] = BR_DIV(v2->v[1], (s)); + v1->v[2] = BR_DIV(v2->v[2], (s)); +} + +/* + * = v1.v2 + */ +br_scalar BR_PUBLIC_ENTRY BrVector3Dot(br_vector3 *v1, br_vector3 *v2) +{ + return BR_MAC3(v1->v[0], v2->v[0], v1->v[1], v2->v[1], v1->v[2], v2->v[2]); +} + +/* + * v1 = v2 x v3 + */ +void BR_PUBLIC_ENTRY BrVector3Cross(br_vector3 *v1, br_vector3 *v2, br_vector3 *v3) +{ + v1->v[0] = BR_MUL(v2->v[1], v3->v[2]) - BR_MUL(v2->v[2], v3->v[1]); + v1->v[1] = BR_MUL(v2->v[2], v3->v[0]) - BR_MUL(v2->v[0], v3->v[2]); + v1->v[2] = BR_MUL(v2->v[0], v3->v[1]) - BR_MUL(v2->v[1], v3->v[0]); +} + +/* + * = |v1| + */ +br_scalar BR_PUBLIC_ENTRY BrVector3Length(br_vector3 *v1) +{ + return BR_LENGTH3(v1->v[0], v1->v[1], v1->v[2]); +} + +/* + * = |v1| * |v1| + */ +br_scalar BR_PUBLIC_ENTRY BrVector3LengthSquared(br_vector3 *v1) +{ + return BR_SQR3(v1->v[0], v1->v[1], v1->v[2]); +} + +/* + * v1 = v2/|v2| + */ +void BR_PUBLIC_ENTRY BrVector3Normalise(br_vector3 *v1, br_vector3 *v2) +{ + br_scalar scale; + + scale = BR_LENGTH3(v2->v[0], v2->v[1], v2->v[2]); + + if (scale > BR_SCALAR_EPSILON * 2) + { + + scale = BR_DIV(BR_SCALAR(1.0), scale); + + v1->v[0] = BR_MUL(v2->v[0], scale); + v1->v[1] = BR_MUL(v2->v[1], scale); + v1->v[2] = BR_MUL(v2->v[2], scale); + } + else + { + v1->v[0] = BR_SCALAR(1.0); + v1->v[1] = BR_SCALAR(0.0); + v1->v[2] = BR_SCALAR(0.0); + } +} + +/* + * v1 = v2/|v2| (low precision) + */ +void BR_PUBLIC_ENTRY BrVector3NormaliseLP(br_vector3 *v1, br_vector3 *v2) +{ + br_scalar scale; + + scale = BR_RLENGTH3(v2->v[0], v2->v[1], v2->v[2]); + + if (scale != BR_SCALAR(0.0)) + { + v1->v[0] = BR_MUL(v2->v[0], scale); + v1->v[1] = BR_MUL(v2->v[1], scale); + v1->v[2] = BR_MUL(v2->v[2], scale); + } +} + +/** + ** 4D Vectors + **/ +/* + * = v1.v2 + */ +br_scalar BR_PUBLIC_ENTRY BrVector4Dot(br_vector4 *v1, br_vector4 *v2) +{ + return BR_MAC4(v1->v[0], v2->v[0], v1->v[1], v2->v[1], v1->v[2], v2->v[2], v1->v[3], v2->v[3]); +} + +/* + * v1=v2 + */ +void BR_PUBLIC_ENTRY BrVector4Copy(br_vector4 *v1, br_vector4 *v2) +{ + v1->v[0] = v2->v[0]; + v1->v[1] = v2->v[1]; + v1->v[2] = v2->v[2]; + v1->v[3] = v2->v[3]; +} + +/** + ** Private ops for fractional vectors + **/ + +/* + * = v1.v2 (v1 is a unit vector (word components)) + */ +br_scalar BrFVector2Dot(br_fvector2 *v1, br_vector2 *v2) +{ + return BR_FMAC2(v1->v[0], v2->v[0], v1->v[1], v2->v[1]); +} + +/* + * v1=v2 + */ +void BrFVector3Copy(br_fvector3 *v1, br_vector2 *v2) +{ + v1->v[0] = BrScalarToFraction(v2->v[0]); + v1->v[1] = BrScalarToFraction(v2->v[1]); + v1->v[2] = BrScalarToFraction(v2->v[2]); +} + +/* + * v1=v2*scalar + */ +void BrVector3ScaleF(br_vector3 *v1, br_fvector3 *v2, br_scalar s) +{ + v1->v[0] = BR_MUL(BrFractionToScalar(v2->v[0]), s); + v1->v[1] = BR_MUL(BrFractionToScalar(v2->v[1]), s); + v1->v[2] = BR_MUL(BrFractionToScalar(v2->v[2]), s); +} + +/* + * = v1.v2 (v1 is a unit vector (word components)) + */ +br_scalar BrFVector3Dot(br_fvector3 *v1, br_vector3 *v2) +{ + return BR_FMAC3(v1->v[0], v2->v[0], v1->v[1], v2->v[1], v1->v[2], v2->v[2]); +} + +/* + * v1 = v2/|v2| + */ +void BrFVector3Normalise(br_fvector3 *v1, br_vector3 *v2) +{ + br_scalar scale; + + scale = BR_LENGTH3(v2->v[0], v2->v[1], v2->v[2]); + + if (scale != BR_SCALAR(0.0)) + { + + scale = BR_DIV(BR_FRACTION(1.0), scale); + + v1->v[0] = (br_fraction)BR_MUL(v2->v[0], scale); + v1->v[1] = (br_fraction)BR_MUL(v2->v[1], scale); + v1->v[2] = (br_fraction)BR_MUL(v2->v[2], scale); + } + else + { + v1->v[0] = BR_FRACTION(1.0); + v1->v[1] = BR_FRACTION(0.0); + v1->v[2] = BR_FRACTION(0.0); + } +} + +/* + * v1 = v2/|v2| (low precision) + */ +void BrFVector3NormaliseLP(br_fvector3 *v1, br_vector3 *v2) +{ + br_scalar scale = BrScalarToFraction(BR_RLENGTH3(v1->v[0], v1->v[1], v1->v[2])); + + v1->v[0] = (br_fraction)BR_MUL(v2->v[0], scale); + v1->v[1] = (br_fraction)BR_MUL(v2->v[1], scale); + v1->v[2] = (br_fraction)BR_MUL(v2->v[2], scale); +} + +/* + * v1 = v2/|v2| + */ +void BR_PUBLIC_ENTRY BrVector2Normalise(br_vector2 *v1, br_vector2 *v2) +{ + br_scalar scale; + + scale = BR_LENGTH2(v2->v[0], v2->v[1]); + + if (scale > BR_SCALAR_EPSILON * 2) + { + + scale = BR_DIV(BR_SCALAR(1.0), scale); + + v1->v[0] = BR_MUL(v2->v[0], scale); + v1->v[1] = BR_MUL(v2->v[1], scale); + } + else + { + v1->v[0] = BR_SCALAR(1.0); + v1->v[1] = BR_SCALAR(0.0); + } +} diff --git a/bren/FW/wincoff.h b/bren/FW/wincoff.h new file mode 100644 index 00000000..a30ddff3 --- /dev/null +++ b/bren/FW/wincoff.h @@ -0,0 +1,213 @@ +/** + ** Structures that appear in a file + **/ + +struct msdos_header +{ + br_uint_16 magic; + br_uint_16 last_page_bytes; + br_uint_16 pages; + br_uint_16 n_relocations; + br_uint_16 header_size; + br_uint_16 minalloc; + br_uint_16 maxalloc; + br_uint_16 start_ss; + br_uint_16 start_sp; + br_uint_16 checksum; + br_uint_16 start_ip; + br_uint_16 start_cs; + br_uint_16 reloc_offset; + br_uint_16 overlay_number; + br_uint_16 _reserved0[4]; + br_uint_16 oem_id; + br_uint_16 oem_info; + br_uint_16 _reserved1[10]; + br_uint_32 new_header_offset; +}; + +struct coff_header +{ + br_uint_16 machine; + br_uint_16 n_sections; + br_uint_32 time_date; + br_uint_32 symbols_offset; + br_uint_32 n_symbols; + br_uint_16 opt_header_size; + br_uint_16 flags; +}; + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x14c +#define IMAGE_FILE_MACHINE_R3000 0x162 +#define IMAGE_FILE_MACHINE_R4000 0x166 +#define IMAGE_FILE_MACHINE_ALPHA 0x184 +#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 +#define IMAGE_FILE_32BIT_MACHINE 0x0100 +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 +#define IMAGE_FILE_SYSTEM 0x1000 +#define IMAGE_FILE_DLL 0x2000 +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 + +#define MAX_DATA_DIRECTORIES 16 + +struct nt_optional_header +{ + /* + * Standard Win32 header + */ + br_uint_16 magic; + br_uint_8 l_major; + br_uint_8 l_minor; + br_uint_32 code_size; + br_uint_32 data_size; + br_uint_32 bss_size; + br_uint_32 entry_point; + br_uint_32 code_base; + br_uint_32 data_base; + + /* + * NT specific header + */ + br_uint_32 image_base; + br_uint_32 section_alignment; + br_uint_32 file_alignment; + br_uint_16 os_major; + br_uint_16 os_minor; + br_uint_16 user_major; + br_uint_16 user_minor; + br_uint_16 subsys_major; + br_uint_16 subsys_minor; + br_uint_32 _reserved; + br_uint_32 image_size; + br_uint_32 header_size; + br_uint_32 file_checksum; + br_uint_16 subsystem; + br_uint_16 dll_flags; + br_uint_32 stack_reserve_size; + br_uint_32 stack_commit_size; + br_uint_32 heap_reserve_size; + br_uint_32 heap_commit_size; + br_uint_32 loader_flags; + br_uint_32 n_data_directories; + struct + { + br_uint_32 rva; + br_uint_32 size; + } directories[MAX_DATA_DIRECTORIES]; +}; + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 +#define IMAGE_SUBSYSTEM_NATIVE 1 +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 +#define IMAGE_SUBSYSTEM_OS2_CUI 5 +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 + +#define DIRECTORY_EXPORT 0 +#define DIRECTORY_IMPORT 1 +#define DIRECTORY_RESOURCE 2 +#define DIRECTORY_EXCEPTION 3 +#define DIRECTORY_SECURITY 4 +#define DIRECTORY_BASERELOC 5 +#define DIRECTORY_DEBUG 6 +#define DIRECTORY_COPYRIGHT 7 +#define DIRECTORY_GLOBALPTR 8 +#define DIRECTORY_TLS 9 +#define DIRECTORY_LOAD_CONFIG 10 + +struct section_header +{ + br_uint_8 section_name[8]; + br_uint_32 virtual_size; + br_uint_32 rva; + br_uint_32 data_size; + br_uint_32 data_offset; + br_uint_32 relocs_offset; + br_uint_32 linenums_offset; + br_uint_16 n_relocs; + br_uint_16 n_linenums; + br_uint_32 flags; +}; + +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 + +#define IMAGE_SCN_CNT_CODE 0x00000020 +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 + +#define IMAGE_SCN_LNK_OTHER 0x00000100 +#define IMAGE_SCN_LNK_INFO 0x00000200 +#define IMAGE_SCN_LNK_REMOVE 0x00000800 +#define IMAGE_SCN_LNK_COMDAT 0x00001000 + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 + +#define IMAGE_SCN_MEM_SHARED 0x10000000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 + +/* + * Base Relocation + */ +typedef struct basereloc_header +{ + br_uint_32 rva; + br_uint_32 size; +} basereloc_header; + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 + +#define ENTRY_TYPE(e) ((e) >> 12) +#define ENTRY_OFFSET(e) ((e)&0xfff) + +/* + * Exports + */ +typedef struct export_directory +{ + br_uint_32 flags; + br_uint_32 timestamp; + br_uint_16 major_version; + br_uint_16 minor_version; + br_uint_32 name; + br_uint_32 ordinal_base; + br_uint_32 n_entries; + br_uint_32 n_names; + br_uint_32 export_table; + br_uint_32 name_table; + br_uint_32 ordinal_table; +} export_directory; + +/* + * Imports + */ +typedef struct import_directory +{ + br_uint_32 lookup_table; + br_uint_32 timestamp; + br_uint_32 forwarder; + br_uint_32 name; + br_uint_32 address_table; +} import_directory; diff --git a/bren/ZB/586_macs.inc b/bren/ZB/586_macs.inc new file mode 100644 index 00000000..6a9158a1 --- /dev/null +++ b/bren/ZB/586_macs.inc @@ -0,0 +1,58 @@ +;; Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. +;; +;; $Id: 586_macs.inc 1.3 1995/02/22 21:53:24 sam Exp $ +;; $Locker: $ +;; +;; Various macros to play with optimisation on pentium +;; + ; Swap two registers - xchg is not a 'simple' insn + ; +SWAP macro ra,rb + if 0 + xchg ra,rb + else +; xor ra,rb +; xor rb,ra +; xor ra,rb + push ra + push rb + pop ra + pop rb + endif + endm + + ; Fix result of a fixed point multiply in edx:eax => eax + ; +FIX_MUL macro + if 0 + shrd eax,edx,16 + else + shr eax,16 + shl edx,16 + or eax,edx + endif + endm + + ; Fraction + ; +FIX_FMUL macro + if 0 + shrd eax,edx,15 + else + shr eax,15 + shl edx,17 + or eax,edx + endif + endm + + ; Fix input to fixed point divide in edx => edx:eax + ; +FIX_DIV macro + + mov eax,edx + sar edx,16 + shl eax,16 + + endm + + diff --git a/bren/ZB/awtmz.c b/bren/ZB/awtmz.c new file mode 100644 index 00000000..547bdedf --- /dev/null +++ b/bren/ZB/awtmz.c @@ -0,0 +1,373 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: awtmz.c 1.1 1995/08/31 16:52:48 sam Exp $ + * $Locker: $ + * + * Arbitary width texture mapper + */ +#include + +#include +#include + +#include "brender.h" +#include "zb.h" +#include "shortcut.h" +#include "brassert.h" + +#define swap(type, a, b) \ + { \ + type _; \ + _ = a; \ + a = b; \ + b = _; \ + } + +#define high16(a) ((br_uint_32)(a) >> 16) +#define sar16(num) (br_int_32)(br_int_16)((br_uint_32)(num) >> 16) + +extern int BR_ASM_CALL SafeFixedMac2Div(int, int, int, int, int); + +typedef void BR_ASM_CALL ScanLineCallFn(void); +typedef ScanLineCallFn *ScanLineCall; +typedef void BR_ASM_CALL TrapezoidRenderCall(void); + +TrapezoidRenderCall TrapezoidRenderPIZ2TA; +TrapezoidRenderCall TrapezoidRenderPIZ2TA_RGB_555; +TrapezoidRenderCall TrapezoidRenderPIZ2TA_RGB_888; + +TrapezoidRenderCall TrapezoidRenderPIZ2TAN; +TrapezoidRenderCall TrapezoidRenderPIZ2TAN_RGB_555; +TrapezoidRenderCall TrapezoidRenderPIZ2TAN_RGB_888; + +TrapezoidRenderCall TrapezoidRenderPIZ2TIA; +TrapezoidRenderCall TrapezoidRenderPIZ2TIA_RGB_555; +TrapezoidRenderCall TrapezoidRenderPIZ2TIA_RGB_888; + +static inline void TriangleRender_Generic_AWTMI(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c, br_boolean use_z_buffer, br_uint_32 bpp, + TrapezoidRenderCall trapezoid_render, br_boolean use_bump, + br_boolean use_light) +{ + /* + * v[0] and v[1] contain the (fractional) screen coordinates + * And comp[C_W] contain the 3-space z-value + * + * (v[0]-width/2)*comp[C_W] gives the 3-space x-values + * Similarly for y + */ + + int dv_int; + int offset; + int grad; + + br_fixed_ls g_divisor, dp1, dp2; + + int dv_int_nocarry; + int dv_int_carry; + int v_int_current; + int direction; + + int texture_height; + int colour_width; + + texture_height = zb.material->colour_map->height; + zb.awsl.texture_stride = zb.material->colour_map->row_bytes; + zb.awsl.texture_width = zb.material->colour_map->width; + + /* Optimal sort of 3 elements? */ + if (a->v[1] > b->v[1]) + { + if (b->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, a, c); + } + else if (a->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, a, b); + swap(struct temp_vertex_fixed *, b, c); + } + else + { + swap(struct temp_vertex_fixed *, a, b); + } + } + else if (b->v[1] > c->v[1]) + { + if (a->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, b, c); + swap(struct temp_vertex_fixed *, a, b); + } + else + { + swap(struct temp_vertex_fixed *, b, c); + } + } + + screen_scalar sxa, sxb, sxc, sya, syb, syc; + sxa = BrFixedToInt(a->v[0]); + sya = BrFixedToInt(a->v[1]); + sxb = BrFixedToInt(b->v[0]); + syb = BrFixedToInt(b->v[1]); + sxc = BrFixedToInt(c->v[0]); + syc = BrFixedToInt(c->v[1]); + + colour_width = zb.row_width / bpp; + + zb.top.x = sxb - sxa; + zb.top.y = syb - sya; + zb.top.count = syb - sya; + if (zb.top.count != 0) + { + zb.top.grad = BrFixedDiv(zb.top.x, zb.top.y); + zb.top.d_f = (zb.top.grad << 16); + zb.top.d_i = (zb.top.grad >> 16) + colour_width; + } + + zb.bot.x = sxc - sxb; + zb.bot.y = syc - syb; + zb.bot.count = syc - syb; + if (zb.bot.count != 0) + { + zb.bot.grad = BrFixedDiv(zb.bot.x, zb.bot.y); + zb.bot.d_f = (zb.bot.grad << 16); + zb.bot.d_i = (zb.bot.grad >> 16) + colour_width; + } + + zb.main.x = sxc - sxa; + zb.main.y = syc - sya; + if (zb.main.y != 0) + { + zb.main.grad = BrFixedDiv(zb.main.x, zb.main.y); + } + else + { + zb.main.grad = 0; + } + zb.main.d_f = (zb.main.grad << 16); + zb.main.d_i = (zb.main.grad >> 16) + colour_width; + + zb.main.f = (1 << 31); + zb.main.i = 0; + zb.top.f = (1 << 31); + zb.top.i = 0; + zb.bot.f = (1 << 31); + zb.bot.i = 0; + + zb.awsl.texture_stride = zb.material->colour_map->row_bytes; + zb.awsl.texture_width = zb.material->colour_map->width; + texture_height = zb.material->colour_map->height; + zb.awsl.texture_size = zb.awsl.texture_stride * texture_height; + zb.awsl.texture_start = zb.texture_buffer; + offset = BrFixedToInt(a->v[X]) + BrFixedToInt(a->v[Y]) * colour_width; + zb.awsl.start = zb.awsl.end = zb.colour_buffer + offset * bpp; + zb.awsl.zstart = (br_fixed_ls *)((br_uint_16 *)zb.depth_buffer + offset); + + g_divisor = zb.top.x * zb.main.y - zb.main.x * zb.top.y; + if (g_divisor == 0) + { + return; + } + + direction = zb.top.count && zb.top.grad >= zb.main.grad || zb.bot.count && zb.bot.grad < zb.main.grad; + +#define PARAM_SETUP(param, p) \ + { \ + dp1 = b->p - a->p; \ + dp2 = c->p - a->p; \ + param.grad_x = SafeFixedMac2Div(dp1, zb.main.y, dp2, -zb.top.y, g_divisor); \ + param.grad_y = SafeFixedMac2Div(dp2, zb.top.x, dp1, -zb.main.x, g_divisor); \ + param.current = a->p + param.grad_x / 2; \ + param.d_nocarry = BrFixedToInt(zb.main.grad) * param.grad_x + param.grad_y; \ + param.d_carry = param.d_nocarry + param.grad_x; \ + } + + if (use_light) + { + PARAM_SETUP(zb.pi, comp[C_I]); + } + + if (use_z_buffer) + { + PARAM_SETUP(zb.pz, v[Z]); + } + + PARAM_SETUP(zb.pu, comp[C_U]); + PARAM_SETUP(zb.pv, comp[C_V]); + + zb.awsl.du_nocarry = zb.pu.d_nocarry << 16; + zb.awsl.dv_nocarry = zb.pv.d_nocarry << 16; + zb.awsl.du_carry = zb.pu.d_carry << 16; + zb.awsl.dv_carry = zb.pv.d_carry << 16; + zb.awsl.u_current = zb.pu.current << 16; + zb.awsl.v_current = zb.pv.current << 16; + + /* + * Per scan line increments + */ + if (__BrBitHaxIsPow2(zb.awsl.texture_width)) + { + zb.awsl.du_int_nocarry = (sar16(zb.pu.d_nocarry) & zb.awsl.texture_width - 1) - zb.awsl.texture_width; + zb.awsl.du_int_carry = (sar16(zb.pu.d_carry) & zb.awsl.texture_width - 1) - zb.awsl.texture_width; + zb.awsl.u_int_current = (sar16(zb.pu.current) & zb.awsl.texture_width - 1); + } + else + { + zb.awsl.du_int_nocarry = sar16(zb.pu.d_nocarry) % zb.awsl.texture_width; + zb.awsl.du_int_carry = sar16(zb.pu.d_carry) % zb.awsl.texture_width; + zb.awsl.u_int_current = sar16(zb.pu.current) % zb.awsl.texture_width; + if (zb.awsl.du_int_nocarry >= 0) + { + zb.awsl.du_int_nocarry -= zb.awsl.texture_width; + } + if (zb.awsl.du_int_carry >= 0) + { + zb.awsl.du_int_carry -= zb.awsl.texture_width; + } + if (zb.awsl.u_int_current < 0) + { + zb.awsl.u_int_current += zb.awsl.texture_width; + } + } + + if (__BrBitHaxIsPow2(texture_height)) + { + dv_int_nocarry = (sar16(zb.pv.d_nocarry) & texture_height - 1) - texture_height; + dv_int_carry = (sar16(zb.pv.d_carry) & texture_height - 1) - texture_height; + v_int_current = (sar16(zb.pv.current) & texture_height - 1); + } + else + { + dv_int_nocarry = sar16(zb.pv.d_nocarry) % texture_height; + dv_int_carry = sar16(zb.pv.d_carry) % texture_height; + v_int_current = sar16(zb.pv.current) % texture_height; + if (dv_int_nocarry >= 0) + { + dv_int_nocarry -= texture_height; + } + if (dv_int_carry >= 0) + { + dv_int_carry -= texture_height; + } + if (v_int_current < 0) + { + v_int_current += texture_height; + } + } + + zb.awsl.dsource_nocarry = zb.awsl.du_int_nocarry * bpp + zb.awsl.texture_stride * dv_int_nocarry; + zb.awsl.dsource_carry = zb.awsl.du_int_carry * bpp + zb.awsl.texture_stride * dv_int_carry; + zb.awsl.source_current = zb.texture_buffer + zb.awsl.u_int_current * bpp + zb.awsl.texture_stride * v_int_current; + zb.awsl.u_int_current += 0x8000; + + if (direction) + { + zb.awsl.du = zb.pu.grad_x << 16; + zb.awsl.dv = zb.pv.grad_x << 16; + zb.awsl.du_int = sar16(zb.pu.grad_x) % zb.awsl.texture_width; + if (__BrBitHaxIsPow2(texture_height)) + { + dv_int = (sar16(zb.pv.grad_x) & texture_height - 1) - texture_height; + } + else + { + dv_int = sar16(zb.pv.grad_x) % texture_height; + if (dv_int >= 0) + { + dv_int -= texture_height; + } + } + } + else + { + zb.awsl.du = -zb.pu.grad_x << 16; + zb.awsl.dv = -zb.pv.grad_x << 16; + zb.awsl.du_int = sar16(-zb.pu.grad_x) % zb.awsl.texture_width; + if (__BrBitHaxIsPow2(texture_height)) + { + dv_int = (sar16(-zb.pv.grad_x) & texture_height - 1) - texture_height; + } + else + { + dv_int = (sar16(-zb.pv.grad_x) % texture_height); + } + if (dv_int >= 0) + { + dv_int -= texture_height; + } + } + + if (zb.awsl.du_int >= 0) + { + zb.awsl.du_int -= zb.awsl.texture_width; + } + + zb.awsl.dsource = zb.awsl.du_int * bpp + zb.awsl.texture_stride * dv_int; + zb.awsl.edge = &zb.top; + + ASSERT(zb.awsl.source_current >= zb.awsl.texture_start); + + trapezoid_render(); + + zb.awsl.end = zb.colour_buffer + high16(b->v[X]) * bpp + high16(b->v[Y]) * zb.row_width; + zb.awsl.edge = &zb.bot; + + ASSERT(zb.awsl.source_current >= zb.awsl.texture_start); + trapezoid_render(); +} + +void BR_ASM_CALL TriangleRenderPIZ2TIA(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c) +{ + TriangleRender_Generic_AWTMI(a, b, c, 1, 1, TrapezoidRenderPIZ2TIA, 0, 1); +} + +void BR_ASM_CALL TriangleRenderPIZ2TA(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c) +{ + TriangleRender_Generic_AWTMI(a, b, c, 1, 1, TrapezoidRenderPIZ2TA, 0, 0); +} + +void BR_ASM_CALL TriangleRenderPIZ2TAN(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c) +{ + TriangleRender_Generic_AWTMI(a, b, c, 1, 1, TrapezoidRenderPIZ2TAN, 1, 0); +} + +void BR_ASM_CALL TriangleRenderPIZ2TIA_RGB_555(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c) +{ + TriangleRender_Generic_AWTMI(a, b, c, 1, 2, TrapezoidRenderPIZ2TIA_RGB_555, 0, 1); +} + +void BR_ASM_CALL TriangleRenderPIZ2TA_RGB_555(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c) +{ + TriangleRender_Generic_AWTMI(a, b, c, 1, 2, TrapezoidRenderPIZ2TA_RGB_555, 0, 0); +} + +void BR_ASM_CALL TriangleRenderPIZ2TAN_RGB_555(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c) +{ + TriangleRender_Generic_AWTMI(a, b, c, 1, 2, TrapezoidRenderPIZ2TAN_RGB_555, 1, 0); +} + +void BR_ASM_CALL TriangleRenderPIZ2TIA_RGB_888(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c) +{ + TriangleRender_Generic_AWTMI(a, b, c, 1, 3, TrapezoidRenderPIZ2TIA_RGB_888, 0, 1); +} + +void BR_ASM_CALL TriangleRenderPIZ2TA_RGB_888(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c) +{ + TriangleRender_Generic_AWTMI(a, b, c, 1, 3, TrapezoidRenderPIZ2TA_RGB_888, 0, 0); +} + +void BR_ASM_CALL TriangleRenderPIZ2TAN_RGB_888(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c) +{ + TriangleRender_Generic_AWTMI(a, b, c, 1, 3, TrapezoidRenderPIZ2TAN_RGB_888, 1, 0); +} diff --git a/bren/ZB/bbox.c b/bren/ZB/bbox.c new file mode 100644 index 00000000..d1897c67 --- /dev/null +++ b/bren/ZB/bbox.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: bbox.c 1.22 1995/08/31 16:47:31 sam Exp $ + * $Locker: $ + * + * Bounding box rendering + */ + +#include "zb.h" +#include "shortcut.h" + +static char rscid[] = "$Id: bbox.c 1.22 1995/08/31 16:47:31 sam Exp $"; + +/* + * A pre-preocessed static cuboid model that we can fill in with + * appropriate vertex values to represent a bounding box + * + * Another way to do this is to use a cube model, and prepend a scale+xform + * that matches it to the bounds - this has the disadvantage of making + * the lighting do funny things unless BR_LIGHT_VIEW is used. I would prefer + * that the user only has to do this when they themselves have created + * a funny transform. + */ + +/* + * 8 Vertices + */ +static struct br_vertex zb_bounds_vertices[] = { + {BR_VECTOR3(-1, -1, -1), BR_VECTOR2(0, 0), 0, 0, 0, 0, 0, BR_FVECTOR3(-0.666, -0.333, -0.666)}, /* 0 */ + {BR_VECTOR3(-1, -1, 1), BR_VECTOR2(0, 0), 0, 0, 0, 0, 0, BR_FVECTOR3(-0.333, -0.666, 0.666)}, /* 1 */ + {BR_VECTOR3(-1, 1, -1), BR_VECTOR2(0, 0), 0, 0, 0, 0, 0, BR_FVECTOR3(-0.408, 0.816, -0.408)}, /* 2 */ + {BR_VECTOR3(-1, 1, 1), BR_VECTOR2(0, 0), 0, 0, 0, 0, 0, BR_FVECTOR3(-0.816, 0.408, 0.408)}, /* 3 */ + {BR_VECTOR3(1, -1, -1), BR_VECTOR2(0, 0), 0, 0, 0, 0, 0, BR_FVECTOR3(0.408, -0.816, -0.408)}, /* 4 */ + {BR_VECTOR3(1, -1, 1), BR_VECTOR2(0, 0), 0, 0, 0, 0, 0, BR_FVECTOR3(0.816, -0.408, 0.408)}, /* 5 */ + {BR_VECTOR3(1, 1, -1), BR_VECTOR2(0, 0), 0, 0, 0, 0, 0, BR_FVECTOR3(0.666, 0.333, -0.666)}, /* 6 */ + {BR_VECTOR3(1, 1, 1), BR_VECTOR2(0, 0), 0, 0, 0, 0, 0, BR_FVECTOR3(0.333, 0.666, 0.666)}, /* 7 */ +}; + +/* + * 12 Faces + */ +static struct br_face zb_bounds_faces[] = { + {{5, 6, 7}, {5, 13, 14}, NULL, 1, 1, 0, BR_FVECTOR3(1, 0, 0), BR_SCALAR(1)}, /* 6 */ + {{5, 4, 6}, {3, 4, 5}, NULL, 1, 4, 0, BR_FVECTOR3(1, 0, 0), BR_SCALAR(1)}, /* 1 */ + {{7, 6, 2}, {13, 6, 17}, NULL, 1, 4, 0, BR_FVECTOR3(0, 1, 0), BR_SCALAR(1)}, /* 9 */ + {{7, 2, 3}, {17, 0, 16}, NULL, 1, 1, 0, BR_FVECTOR3(0, 1, 0), BR_SCALAR(1)}, /* 10 */ + {{1, 5, 7}, {11, 14, 15}, NULL, 1, 4, 0, BR_FVECTOR3(0, 0, 1), BR_SCALAR(1)}, /* 7 */ + {{1, 7, 3}, {15, 16, 12}, NULL, 1, 1, 0, BR_FVECTOR3(0, 0, 1), BR_SCALAR(1)}, /* 8 */ + {{3, 0, 1}, {2, 8, 12}, NULL, 1, 1, 0, BR_FVECTOR3(-1, 0, 0), BR_SCALAR(1)}, /* 5 */ + {{3, 2, 0}, {0, 1, 2}, NULL, 1, 4, 0, BR_FVECTOR3(-1, 0, 0), BR_SCALAR(1)}, /* 0 */ + {{1, 0, 4}, {8, 9, 10}, NULL, 1, 4, 0, BR_FVECTOR3(0, -1, 0), BR_SCALAR(1)}, /* 3 */ + {{1, 4, 5}, {10, 3, 11}, NULL, 1, 1, 0, BR_FVECTOR3(0, -1, 0), BR_SCALAR(1)}, /* 4 */ + {{0, 6, 4}, {7, 4, 9}, NULL, 1, 1, 0, BR_FVECTOR3(0, 0, -1), BR_SCALAR(1)}, /* 11 */ + {{0, 2, 6}, {1, 6, 7}, NULL, 1, 4, 0, BR_FVECTOR3(0, 0, -1), BR_SCALAR(1)}, /* 2 */ +}; + +/* + * 1 Face Group + */ +static struct br_face_group zb_bounds_face_groups[] = {{NULL, zb_bounds_faces, 12}}; + +/* + * 1 Vertex Group + */ +static struct br_vertex_group zb_bounds_vertex_groups[] = {{NULL, zb_bounds_vertices, 8}}; + +static struct br_model zb_bounds_model = { + "zb_bounds", + zb_bounds_vertices, + zb_bounds_faces, + + 8, + 12, /* nV nF */ + + BR_VECTOR3(0, 0, 0), /* pivot */ + + 0, /* Flags */ + + NULL, + NULL, /* Custom, user */ + + BR_SCALAR(1.73205), /* radius */ + + { + BR_VECTOR3(-1, -1, -1), /* min */ + BR_VECTOR3(1, 1, 1), /* max */ + }, + + 8, /* nprepared_vertices */ + 12, /* nprepared_faces */ + + zb_bounds_faces, + zb_bounds_vertices, + + 1, /* nface_groups */ + 1, /* nvertex_groups */ + + zb_bounds_face_groups, + zb_bounds_vertex_groups, + + 18, /* nEdges */ + + NULL, + NULL, +}; + +/* + * Fills in above cuboid mesh that represents the given bounding box + */ +static br_model *ZbMakeMeshFromBounds(br_bounds *b) +{ + int i; + + /* + * Fill in vertices + */ + BrVector3Set(&zb_bounds_vertices[0].p, b->min.v[X], b->min.v[Y], b->min.v[Z]); + BrVector3Set(&zb_bounds_vertices[1].p, b->min.v[X], b->min.v[Y], b->max.v[Z]); + BrVector3Set(&zb_bounds_vertices[2].p, b->min.v[X], b->max.v[Y], b->min.v[Z]); + BrVector3Set(&zb_bounds_vertices[3].p, b->min.v[X], b->max.v[Y], b->max.v[Z]); + BrVector3Set(&zb_bounds_vertices[4].p, b->max.v[X], b->min.v[Y], b->min.v[Z]); + BrVector3Set(&zb_bounds_vertices[5].p, b->max.v[X], b->min.v[Y], b->max.v[Z]); + BrVector3Set(&zb_bounds_vertices[6].p, b->max.v[X], b->max.v[Y], b->min.v[Z]); + BrVector3Set(&zb_bounds_vertices[7].p, b->max.v[X], b->max.v[Y], b->max.v[Z]); + + /* + * Fill in plane equations of faces + */ + for (i = 0; i < 3; i++) + { + zb_bounds_faces[i * 2].d = zb_bounds_faces[1 + i * 2].d = b->max.v[i]; + zb_bounds_faces[6 + i * 2].d = zb_bounds_faces[7 + i * 2].d = -b->min.v[i]; + } + + /* + * Fill in bounds + */ + zb_bounds_model.bounds = *b; + + return &zb_bounds_model; +} + +/* + * Render bounding box points + */ +void ZbBoundingBoxRenderPoints(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen) +{ + ZbMeshRenderPoints(actor, ZbMakeMeshFromBounds(&model->bounds), material, style, on_screen); +} + +/* + * Render bounding box edges + */ +void ZbBoundingBoxRenderEdges(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen) +{ + ZbMeshRenderEdges(actor, ZbMakeMeshFromBounds(&model->bounds), material, style, on_screen); +} + +/* + * Render bounding box faces + */ +void ZbBoundingBoxRenderFaces(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen) +{ + ZbMeshRender(actor, ZbMakeMeshFromBounds(&model->bounds), material, style, on_screen); +} + +#if 0 +/* + * Debug rendering for zbmesh.c + */ +void GfxClipLine(int a1, int b1, int a2, int b2, int colour); + +/* + * Data structures used to hold bounding box - vertices are filled in from + * current model + */ +static struct bbox_vertex { + br_vector3 m; + br_vector4 s; +} bbox_vertices[8]; + +static struct bbox_edge { + int start; + int end; + int count; +} bbox_edges[] = { + {0,1}, /* 0 */ + {1,3}, /* 1 */ + {2,3}, /* 2 */ + {0,2}, /* 3 */ + {4,5}, /* 4 */ + {5,7}, /* 5 */ + {6,7}, /* 6 */ + {4,6}, /* 7 */ + {1,5}, /* 8 */ + {3,7}, /* 9 */ + {2,6}, /* 10 */ + {0,4}, /* 11 */ +}; + +static struct bbox_face { + int vertices[4]; + int edges[4]; + br_vector3 n; + br_scalar d; + int visible; +} bbox_faces[] = { + {{0,2,3,1},{ 3, 2, 1, 0},BR_VECTOR3( 0, 0,-1)}, /* 0 */ + {{0,4,6,2},{11, 7,10, 3},BR_VECTOR3(-1, 0, 0)}, /* 1 */ + {{0,1,5,4},{ 0, 8, 4,11},BR_VECTOR3( 0,-1, 0)}, /* 2 */ + {{7,6,4,5},{ 7, 4, 5, 6},BR_VECTOR3( 0, 0, 1)}, /* 3 */ + {{7,3,2,6},{ 2,10, 6, 9},BR_VECTOR3( 0, 1, 0)}, /* 4 */ + {{7,5,1,3},{ 5, 8, 1, 9},BR_VECTOR3( 1, 0, 0)}, /* 5 */ +}; + + +void StartBoundingBox(int on_screen) +{ + int colour = (on_screen==OSC_ACCEPT)?192+25:64+25; + int i,j; + struct bbox_face *fp; + struct bbox_edge *ep; + struct bbox_vertex *vp; + + /* + * Clear edge counts + */ + for(i=0; i< BR_ASIZE(bbox_edges); i++) + bbox_edges[i].count = 0; + + /* + * Fill in vertices from model + */ + for(i=0,vp = bbox_vertices; i<8; i++, vp++) { + /* + * Work out vertex from bounds + */ + vp->m.v[X] = (i & 1)?zb.model->bounds.max.v[X]:zb.model->bounds.min.v[X]; + vp->m.v[Y] = (i & 2)?zb.model->bounds.max.v[Y]:zb.model->bounds.min.v[Y]; + vp->m.v[Z] = (i & 4)?zb.model->bounds.max.v[Z]:zb.model->bounds.min.v[Z]; + + /* + * transform and project + */ + BrMatrix4ApplyP(&vp->s,&vp->m,&fw.model_to_screen); + + if(vp->s.v[W]) { +#if 0 + if(on_screen == OSC_ACCEPT) { + vp->m.v[X] = fw.vp_ox + BR_DIV(vp->s.v[X],vp->s.v[W]); + vp->m.v[Y] = fw.vp_oy + BR_DIV(vp->s.v[Y],vp->s.v[W]); + vp->m.v[Z] = BR_MULDIV(-BR_SCALAR(0x7fff),vp->s.v[Z],vp->s.v[W]); + } else +#endif + { + vp->m.v[X] = fw.vp_ox + BR_MULDIV(fw.vp_width, vp->s.v[X],vp->s.v[W]); + vp->m.v[Y] = fw.vp_oy + BR_MULDIV(fw.vp_height,vp->s.v[Y],vp->s.v[W]); + vp->m.v[Z] = BR_MULDIV(-BR_SCALAR(0x7fff),vp->s.v[Z],vp->s.v[W]); + } + } + } + + /* + * Fill in faces from model + */ + bbox_faces[0].d = -zb.model->bounds.min.v[Z]; + bbox_faces[1].d = -zb.model->bounds.min.v[X]; + bbox_faces[2].d = -zb.model->bounds.min.v[Y]; + bbox_faces[3].d = zb.model->bounds.max.v[Z]; + bbox_faces[4].d = zb.model->bounds.max.v[Y]; + bbox_faces[5].d = zb.model->bounds.max.v[X]; + + /* + * See which faces are visible + */ + for(i=0, fp = bbox_faces; i< BR_ASIZE(bbox_faces); i++, fp++) { + if(BrVector3Dot(&fp->n,&fw.eye_m) <= fp->d) { + fp->visible = 0; + continue; + } + + fp->visible = 1; + + for(j=0; j< 4; j++) + bbox_edges[fp->edges[j]].count++; + } + + /* + * Plot hidden edges + */ + for(i=0, ep = bbox_edges; i< BR_ASIZE(bbox_edges); i++, ep++) + if(ep->count == 0) + GfxClipLine( + BrScalarToInt(bbox_vertices[ep->start].m.v[X]+BR_SCALAR(0.5)), + BrScalarToInt(bbox_vertices[ep->start].m.v[Y]+BR_SCALAR(0.5)), + BrScalarToInt(bbox_vertices[ep->end].m.v[X]+BR_SCALAR(0.5)), + BrScalarToInt(bbox_vertices[ep->end].m.v[Y]+BR_SCALAR(0.5)), + colour); +} + +void EndBoundingBox(int on_screen) +{ + int colour = (on_screen==OSC_ACCEPT)?192+54:64+54; + int i; + struct bbox_edge *ep; + + /* + * Plot visible edges + */ + for(i=0, ep = bbox_edges; i< BR_ASIZE(bbox_edges); i++, ep++) + if(ep->count) + GfxClipLine( + BrScalarToInt(bbox_vertices[ep->start].m.v[X]+BR_SCALAR(0.5)), + BrScalarToInt(bbox_vertices[ep->start].m.v[Y]+BR_SCALAR(0.5)), + BrScalarToInt(bbox_vertices[ep->end].m.v[X] +BR_SCALAR(0.5)), + BrScalarToInt(bbox_vertices[ep->end].m.v[Y] +BR_SCALAR(0.5)), + colour); +} +#endif + diff --git a/bren/ZB/decal.c b/bren/ZB/decal.c new file mode 100644 index 00000000..f8f6c00f --- /dev/null +++ b/bren/ZB/decal.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: decal.c 1.2 1995/03/01 15:49:32 sam Exp $ + * $Locker: $ + * + * Decal triangles + */ +#include "zb.h" +#include "shortcut.h" +#include "blockops.h" +#include "brassert.h" + +static char rscid[] = "$Id: decal.c 1.2 1995/03/01 15:49:32 sam Exp $"; + +void BR_ASM_CALL TriangleRenderPIZ2TAD(struct temp_vertex *v0, struct temp_vertex *v1, struct temp_vertex *v2) +{ + /* + * Render the undercolour + */ + zb.pi.current = BrIntToScalar(zb.material->index_base); + TriangleRenderPIZ2(v0, v1, v2); + + /* + * Render the texture + */ + TriangleRenderPIZ2TA(v0, v1, v2); +} + +void BR_ASM_CALL TriangleRenderPIZ2TIAD(struct temp_vertex *v0, struct temp_vertex *v1, struct temp_vertex *v2) +{ + struct temp_vertex tv[3]; + br_scalar b, r; + + /* + * Make copies of the temp. vertices + */ + tv[0] = *v0; + tv[1] = *v1; + tv[2] = *v2; + + /* + * Render the undercolour + */ + b = BrIntToScalar(zb.material->index_base); + r = BR_CONST_DIV(BrIntToScalar(zb.material->index_range), 256); + + tv[0].comp[C_I] = b + BR_MUL(r, v0->comp[C_I]); + tv[1].comp[C_I] = b + BR_MUL(r, v1->comp[C_I]); + tv[2].comp[C_I] = b + BR_MUL(r, v2->comp[C_I]); + + TriangleRenderPIZ2I(tv + 0, tv + 1, tv + 2); + +#if 1 + + /* + * Render the texture + */ + r = BR_CONST_DIV(BrIntToScalar(zb.material->index_shade->height), 256); + + tv[0].comp[C_I] = BR_MUL(r, v0->comp[C_I]); + tv[1].comp[C_I] = BR_MUL(r, v1->comp[C_I]); + tv[2].comp[C_I] = BR_MUL(r, v2->comp[C_I]); + + TriangleRenderPIZ2TIA(tv + 0, tv + 1, tv + 2); +#endif +} diff --git a/bren/ZB/decalz.c b/bren/ZB/decalz.c new file mode 100644 index 00000000..a249bf0f --- /dev/null +++ b/bren/ZB/decalz.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: decalz.c 1.1 1995/08/31 16:52:48 sam Exp $ + * $Locker: $ + * + * Decal triangles + */ +#include "zb.h" +#include "shortcut.h" +#include "blockops.h" +#include "brassert.h" + +static char rscid[] = "$Id: decalz.c 1.1 1995/08/31 16:52:48 sam Exp $"; + +void BR_ASM_CALL TriangleRenderPIZ2TAD(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + /* + * Render the undercolour + */ + zb.pi.current = BrIntToFixed(zb.material->index_base); + TriangleRenderPIZ2(v0, v1, v2); + + /* + * Render the texture + */ + TriangleRenderPIZ2TA(v0, v1, v2); +} + +void BR_ASM_CALL TriangleRenderPIZ2TIAD(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + struct temp_vertex_fixed tv[3]; + br_scalar b, r; + + /* + * Make copies of the temp. vertices + */ + tv[0] = *v0; + tv[1] = *v1; + tv[2] = *v2; + + /* + * Render the undercolour + */ + b = BrIntToScalar(zb.material->index_base); + r = BR_CONST_DIV(BrIntToScalar(zb.material->index_range), 256); + + tv[0].comp[C_I] = BrScalarToFixed(b + BR_MUL(r, BrFixedToScalar(v0->comp[C_I]))); + tv[1].comp[C_I] = BrScalarToFixed(b + BR_MUL(r, BrFixedToScalar(v1->comp[C_I]))); + tv[2].comp[C_I] = BrScalarToFixed(b + BR_MUL(r, BrFixedToScalar(v2->comp[C_I]))); + + TriangleRenderPIZ2I(tv + 0, tv + 1, tv + 2); + +#if 1 + + /* + * Render the texture + */ + r = BR_CONST_DIV(BrIntToScalar(zb.material->index_shade->height), 256); + + tv[0].comp[C_I] = BrScalarToFixed(BR_MUL(r, BrFixedToScalar(v0->comp[C_I]))); + tv[1].comp[C_I] = BrScalarToFixed(BR_MUL(r, BrFixedToScalar(v1->comp[C_I]))); + tv[2].comp[C_I] = BrScalarToFixed(BR_MUL(r, BrFixedToScalar(v2->comp[C_I]))); + + TriangleRenderPIZ2TIA(tv + 0, tv + 1, tv + 2); +#endif +} + diff --git a/bren/ZB/dither.c b/bren/ZB/dither.c new file mode 100644 index 00000000..ab40d9af --- /dev/null +++ b/bren/ZB/dither.c @@ -0,0 +1,9 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: dither.c 1.1 1995/08/31 16:52:47 sam Exp $ + * $Locker: $ + * + */ + +int dither[4][4] = {{13, 8, 10, 3}, {1, 12, 6, 15}, {4, 9, 7, 14}, {16, 5, 11, 2}}; \ No newline at end of file diff --git a/bren/ZB/frcp.c b/bren/ZB/frcp.c new file mode 100644 index 00000000..706efae2 --- /dev/null +++ b/bren/ZB/frcp.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: frcp.c 1.1 1995/08/31 16:52:48 sam Exp $ + * $Locker: $ + * + * Floating point reciprocal table + */ + +float frcp[100] = { + 0.0f, 1 / 1.0f, 1 / 02.0f, 1 / 3.0f, 1 / 4.0f, 1 / 5.0f, 1 / 6.0f, 1 / 7.0f, 1 / 8.0f, 1 / 9.0f, + 1 / 10.0f, 1 / 11.0f, 1 / 12.0f, 1 / 13.0f, 1 / 14.0f, 1 / 15.0f, 1 / 16.0f, 1 / 17.0f, 1 / 18.0f, 1 / 19.0f, + 1 / 20.0f, 1 / 21.0f, 1 / 22.0f, 1 / 23.0f, 1 / 24.0f, 1 / 25.0f, 1 / 26.0f, 1 / 27.0f, 1 / 28.0f, 1 / 29.0f, + 1 / 30.0f, 1 / 31.0f, 1 / 32.0f, 1 / 33.0f, 1 / 34.0f, 1 / 35.0f, 1 / 36.0f, 1 / 37.0f, 1 / 38.0f, 1 / 39.0f, + 1 / 40.0f, 1 / 41.0f, 1 / 42.0f, 1 / 43.0f, 1 / 44.0f, 1 / 45.0f, 1 / 46.0f, 1 / 47.0f, 1 / 48.0f, 1 / 49.0f, + 1 / 50.0f, 1 / 51.0f, 1 / 52.0f, 1 / 53.0f, 1 / 54.0f, 1 / 55.0f, 1 / 56.0f, 1 / 57.0f, 1 / 58.0f, 1 / 59.0f, + 1 / 60.0f, 1 / 61.0f, 1 / 62.0f, 1 / 63.0f, 1 / 64.0f, 1 / 65.0f, 1 / 66.0f, 1 / 67.0f, 1 / 68.0f, 1 / 69.0f, + 1 / 70.0f, 1 / 71.0f, 1 / 72.0f, 1 / 73.0f, 1 / 74.0f, 1 / 75.0f, 1 / 76.0f, 1 / 77.0f, 1 / 78.0f, 1 / 79.0f, + 1 / 80.0f, 1 / 81.0f, 1 / 82.0f, 1 / 83.0f, 1 / 84.0f, 1 / 85.0f, 1 / 86.0f, 1 / 87.0f, 1 / 88.0f, 1 / 89.0f, + 1 / 90.0f, 1 / 91.0f, 1 / 92.0f, 1 / 93.0f, 1 / 94.0f, 1 / 95.0f, 1 / 96.0f, 1 / 97.0f, 1 / 98.0f, 1 / 99.0f, +}; diff --git a/bren/ZB/innera.inc.c b/bren/ZB/innera.inc.c new file mode 100644 index 00000000..a042a2f6 --- /dev/null +++ b/bren/ZB/innera.inc.c @@ -0,0 +1,358 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: innera.inc.c 1.7 1995/08/31 16:47:32 sam Exp $ + * + * Triangle renderer for arbitrary width linear texture mapping + */ +void BR_ASM_CALL FNAME(struct temp_vertex *_a, struct temp_vertex *_b, struct temp_vertex *_c) +{ + struct temp_vertex_fixed *a = (void *)_a; + struct temp_vertex_fixed *b = (void *)_b; + struct temp_vertex_fixed *c = (void *)_c; + + /* v[0] and v[1] contain the (fractional) screen coordinates */ + /* And comp[C_W] contain the 3-space z-value */ + + /* (v[0]-width/2)*comp[C_W] gives the 3-space x-values */ + /* Similarly for y */ + + float sxa, sxb, sxc, sya, syb, syc; + + int dv_int; + int offset; + int grad; + +#if FIX + br_fixed_ls g_divisor, dp1, dp2; +#else + float g_divisor, dp1, dp2; +#endif + + int dv_int_nocarry; + int dv_int_carry; + int v_int_current; + int direction; + + int texture_height; + int colour_width; + + // TrapezoidRenderCall *TrapezoidRender; + + texture_height = zb.material->colour_map->height; + awsl.texture_stride = zb.material->colour_map->row_bytes; + awsl.texture_width = zb.material->colour_map->width; + + // Optimal sort of 3 elements? + if (a->v[1] > b->v[1]) + { + if (b->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, a, c); + } + else + { + if (a->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, a, b); + swap(struct temp_vertex_fixed *, b, c); + } + else + { + swap(struct temp_vertex_fixed *, a, b); + } + } + } + else + { + if (b->v[1] > c->v[1]) + { + if (a->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, b, c); + swap(struct temp_vertex_fixed *, a, b); + } + else + { + swap(struct temp_vertex_fixed *, b, c); + } + } + } + + sxa = sar16(a->v[0]); + sya = sar16(a->v[1]); + sxb = sar16(b->v[0]); + syb = sar16(b->v[1]); + sxc = sar16(c->v[0]); + syc = sar16(c->v[1]); + + zb.top.x = sxb - sxa; + zb.top.y = syb - sya; + zb.bot.x = sxc - sxb; + zb.bot.y = syc - syb; + zb.main.x = sxc - sxa; + zb.main.y = syc - sya; + + awsl.texture_stride = zb.material->colour_map->row_bytes; + awsl.texture_width = zb.material->colour_map->width; + texture_height = zb.material->colour_map->height; + awsl.texture_size = awsl.texture_stride * texture_height; + awsl.texture_start = zb.texture_buffer; + + colour_width = zb.row_width / BPP; + + zb.main.grad = zb.main.x * _reciprocal[zb.main.y]; + zb.main.d_f = zb.main.grad << 16; + grad = sar16(zb.main.grad); + zb.main.d_i = grad + colour_width; + + zb.top.grad = zb.top.y ? zb.top.x * _reciprocal[zb.top.y] : 0; + zb.top.d_f = zb.top.grad << 16; + zb.top.d_i = sar16(zb.top.grad) + colour_width; + + zb.main.f = zb.top.f = 0x80000000; + + offset = high16(a->v[X]) + high16(a->v[Y]) * colour_width; + awsl.start = awsl.end = zb.colour_buffer + offset * BPP; + awsl.zstart = (char *)zb.depth_buffer + offset * 2; + zb.top.count = syb - sya; + + zb.bot.f = 0x80000000; + + zb.bot.grad = zb.bot.y ? zb.bot.x * _reciprocal[zb.bot.y] : 0; + zb.bot.d_f = zb.bot.grad << 16; + zb.bot.d_i = sar16(zb.bot.grad) + colour_width; + zb.bot.count = syc - syb; + + g_divisor = zb.top.x * zb.main.y - zb.main.x * zb.top.y; + if (g_divisor == 0) + { + return; + } + + direction = zb.top.count != 0 && zb.top.grad >= zb.main.grad || zb.bot.count != 0 && zb.bot.grad < zb.main.grad; + +#if FIX +#define PARAM_SETUP(param, p) \ + { \ + dp1 = b->p - a->p; \ + dp2 = c->p - a->p; \ + param.grad_x = SafeFixedMac2Div(dp1, zb.main.y, -dp2, zb.top.y, g_divisor); \ + param.grad_y = SafeFixedMac2Div(dp2, zb.top.x, -dp1, zb.main.x, g_divisor); \ + param.current = a->p + param.grad_x / 2; \ + param.d_nocarry = BrFixedToInt(zb.main.grad) * param.grad_x + param.grad_y; \ + param.d_carry = param.d_nocarry + param.grad_x; \ + } +#else +#define PARAM_SETUP(param, p) \ + { \ + dp1 = b->p - a->p; \ + dp2 = c->p - a->p; \ + param.grad_x = BrFloatToFixed((dp1 * BrIntToFixed(zb.main.y) - dp2 * BrIntToFixed(zb.top.y)) / g_divisor); \ + param.grad_y = BrFloatToFixed((dp2 * BrIntToFixed(zb.top.x) - dp1 * BrIntToFixed(zb.main.x)) / g_divisor); \ + param.current = a->p + param.grad_x / 2; \ + param.d_nocarry = BrFixedToInt(zb.main.grad) * param.grad_x + param.grad_y; \ + param.d_carry = param.d_nocarry + param.grad_x; \ + } +#endif + +#if LIGHT + PARAM_SETUP(zb.pi, comp[C_I]); +#endif + PARAM_SETUP(zb.pz, v[Z]); + + PARAM_SETUP(zb.pu, comp[C_U]); + PARAM_SETUP(zb.pv, comp[C_V]); + + awsl.du_nocarry = zb.pu.d_nocarry << 16; + awsl.dv_nocarry = zb.pv.d_nocarry << 16; + awsl.du_carry = zb.pu.d_carry << 16; + awsl.dv_carry = zb.pv.d_carry << 16; + awsl.u_current = zb.pu.current << 16; + awsl.v_current = zb.pv.current << 16; + + /* Per scan line increments */ + +#if WRAP + if (powerof2(awsl.texture_width)) + { + awsl.du_int_nocarry = (sar16(zb.pu.d_nocarry) & awsl.texture_width - 1) - awsl.texture_width; + awsl.du_int_carry = (sar16(zb.pu.d_carry) & awsl.texture_width - 1) - awsl.texture_width; + awsl.u_int_current = sar16(zb.pu.current) & awsl.texture_width - 1; + } + else + { + awsl.du_int_nocarry = sar16(zb.pu.d_nocarry) % awsl.texture_width; + awsl.du_int_carry = sar16(zb.pu.d_carry) % awsl.texture_width; + awsl.u_int_current = sar16(zb.pu.current) % awsl.texture_width; + if (awsl.du_int_nocarry >= 0) + awsl.du_int_nocarry -= awsl.texture_width; + if (awsl.du_int_carry >= 0) + awsl.du_int_carry -= awsl.texture_width; + if (awsl.u_int_current < 0) + awsl.u_int_current += awsl.texture_width; + } + + if (powerof2(texture_height)) + { + dv_int_nocarry = (sar16(zb.pv.d_nocarry) & texture_height - 1) - texture_height; + dv_int_carry = (sar16(zb.pv.d_carry) & texture_height - 1) - texture_height; + v_int_current = sar16(zb.pv.current) & texture_height - 1; + } + else + { + dv_int_nocarry = sar16(zb.pv.d_nocarry) % texture_height; + dv_int_carry = sar16(zb.pv.d_carry) % texture_height; + v_int_current = sar16(zb.pv.current) % texture_height; + if (dv_int_nocarry >= 0) + dv_int_nocarry -= texture_height; + if (dv_int_carry >= 0) + dv_int_carry -= texture_height; + if (v_int_current < 0) + v_int_current += texture_height; + } + + awsl.dsource_nocarry = awsl.du_int_nocarry * BPP + awsl.texture_stride * dv_int_nocarry; + awsl.dsource_carry = awsl.du_int_carry * BPP + awsl.texture_stride * dv_int_carry; + awsl.source_current = zb.texture_buffer + awsl.u_int_current * BPP + awsl.texture_stride * v_int_current; + awsl.u_int_current += 0x8000; + + if (direction) + { + awsl.du = zb.pu.grad_x << 16; + awsl.dv = zb.pv.grad_x << 16; + awsl.du_int = sar16(zb.pu.grad_x) % awsl.texture_width; + if (powerof2(texture_height)) + dv_int = (sar16(zb.pv.grad_x) & texture_height - 1) - texture_height; + else + { + dv_int = sar16(zb.pv.grad_x) % texture_height; + if (dv_int >= 0) + { + dv_int -= texture_height; + } + } + } + else + { + awsl.du = -zb.pu.grad_x << 16; + awsl.dv = -zb.pv.grad_x << 16; + awsl.du_int = sar16(-zb.pu.grad_x) % awsl.texture_width; + + if (powerof2(texture_height)) + { + dv_int = (sar16(-zb.pv.grad_x) & texture_height - 1) - texture_height; + } + else + { + dv_int = (sar16(-zb.pv.grad_x) % texture_height); + } + + if (dv_int >= 0) + { + dv_int -= texture_height; + } + } + + if (awsl.du_int >= 0) + { + awsl.du_int -= awsl.texture_width; + } +#else /* WRAP */ + + if (powerof2(awsl.texture_width)) + { + awsl.du_int_nocarry = mod2n(sar16(zb.pu.d_nocarry), awsl.texture_width); + awsl.du_int_carry = mod2n(sar16(zb.pu.d_carry), awsl.texture_width); + awsl.u_int_current = sar16(zb.pu.current) & awsl.texture_width - 1; + } + else + { + awsl.du_int_nocarry = sar16(zb.pu.d_nocarry) % awsl.texture_width; + awsl.du_int_carry = sar16(zb.pu.d_carry) % awsl.texture_width; + awsl.u_int_current = sar16(zb.pu.current) % awsl.texture_width; + } + + if (powerof2(texture_height)) + { + dv_int_nocarry = mod2n(sar16(zb.pv.d_nocarry), texture_height); + dv_int_carry = mod2n(sar16(zb.pv.d_carry), texture_height); + v_int_current = sar16(zb.pv.current) & texture_height - 1; + } + else + { + dv_int_nocarry = sar16(zb.pv.d_nocarry) % texture_height; + dv_int_carry = sar16(zb.pv.d_carry) % texture_height; + v_int_current = sar16(zb.pv.current) % texture_height; + } + + awsl.dsource_nocarry = awsl.du_int_nocarry * BPP + awsl.texture_stride * dv_int_nocarry; + awsl.dsource_carry = awsl.du_int_carry * BPP + awsl.texture_stride * dv_int_carry; + awsl.source_current = zb.texture_buffer + awsl.u_int_current * BPP + awsl.texture_stride * v_int_current; + awsl.u_int_current += 0x8000; + + if (direction) + { + awsl.du = zb.pu.grad_x << 16; + awsl.dv = zb.pv.grad_x << 16; + awsl.du_int = sar16(zb.pu.grad_x) % awsl.texture_width; + if (texture_height & texture_height - 1) + { + dv_int = sar16(zb.pv.grad_x) % texture_height; + } + else + { + dv_int = mod2n(sar16(zb.pv.grad_x), texture_height); + } + } + else + { + awsl.du = -zb.pu.grad_x << 16; + awsl.dv = -zb.pv.grad_x << 16; + awsl.du_int = sar16(-zb.pu.grad_x) % awsl.texture_width; + if (texture_height & texture_height - 1) + { + dv_int = sar16(-zb.pv.grad_x) % texture_height; + } + else + { + dv_int = mod2n(sar16(-zb.pv.grad_x), texture_height); + } + } + +#endif /* WRAP */ + + awsl.dsource = awsl.du_int * BPP + awsl.texture_stride * dv_int; + awsl.edge = &zb.top; + + ASSERT(awsl.source_current >= awsl.texture_start); + +#if BPP == 1 +#if LIGHT + TrapezoidRenderPIZ2TIA(); +#else + TrapezoidRenderPIZ2TA(); +#endif +#elif BPP == 2 + TrapezoidRenderPIZ2TA_RGB555(); +#elif BPP == 3 + TrapezoidRenderPIZ2TA_RGB888(); +#endif + + awsl.end = zb.colour_buffer + high16(b->v[X]) * BPP + high16(b->v[Y]) * zb.row_width; + awsl.edge = &zb.bot; + + ASSERT(awsl.source_current >= awsl.texture_start); + +#if BPP == 1 +#if LIGHT + TrapezoidRenderPIZ2TIA(); +#else + TrapezoidRenderPIZ2TA(); +#endif +#elif BPP == 2 + TrapezoidRenderPIZ2TA_RGB555(); +#elif BPP == 3 + TrapezoidRenderPIZ2TA_RGB888(); +#endif +} diff --git a/bren/ZB/innerp.inc.c b/bren/ZB/innerp.inc.c new file mode 100644 index 00000000..208931e3 --- /dev/null +++ b/bren/ZB/innerp.inc.c @@ -0,0 +1,534 @@ +/* $Id: innerp.inc.c 1.4 1995/03/01 15:49:34 sam Exp $ */ +/* Perspective texture mapped triangle renderer */ + +#define SHIFT 1 + +/* Macros for moving left, right, up and down in texture */ +void BR_ASM_CALL FNAME(struct temp_vertex *_a, struct temp_vertex *_b, struct temp_vertex *_c) +{ + struct temp_vertex_fixed *a = (void *)_a; + struct temp_vertex_fixed *b = (void *)_b; + struct temp_vertex_fixed *c = (void *)_c; + + /* v[0] and v[1] contain the (fractional) screen coordinates */ + /* And comp[C_W] contain the 3-space z-value */ + + /* (v[0]-width/2)*comp[C_W] gives the 3-space x-values */ + /* Similarly for y */ + float sxa, sxb, sxc, sya, syb, syc; + float WbWc, WcWa, WaWb; + float bvcx, bvcy, bvcz, cvax, cvay, cvaz, avbx, avby, avbz; + float dUx, dUy, dUz, dVx, dVy, dVz, nx, ny; + float fW; + float au, av, bu, bv, cu, cv; + + unsigned int iU, iV; + int idUx, idUy, idVx, idVy, idWx, idWy; + +#if FIX + br_fixed_ls +#else + float +#endif + dp1, + dp2, g_divisor; + + /* We need two sets of iterators: */ + /* One for following scan lines */ + /* Another for following the start of scan lines */ + + int udW_nocarry; + int vdW_nocarry; + int dU_nocarry, dV_nocarry, dW_nocarry; + int udom, vdom; + int offset; + int u_base, v_base; + + int carry, grad; + + float tmpf; + int tmpi, tmp1, tmp2, tmp3; + int range; + + /* Optimal sort of 3 elements? */ + + if (a->v[1] > b->v[1]) + { + if (b->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, a, c); + } + else + { + if (a->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, a, b); + swap(struct temp_vertex_fixed *, b, c); + } + else + { + swap(struct temp_vertex_fixed *, a, b); + } + } + } + else + { + if (b->v[1] > c->v[1]) + { + if (a->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, b, c); + swap(struct temp_vertex_fixed *, a, b); + } + else + { + swap(struct temp_vertex_fixed *, b, c); + } + } + } + + if (PerspCheat) + { + + range = a->v[0] - b->v[0]; + if ((tmpi = a->v[0] - c->v[0]) > range) + range = tmpi; + if ((tmpi = b->v[0] - c->v[0]) > range) + range = tmpi; + if ((tmpi = b->v[0] - a->v[0]) > range) + range = tmpi; + if ((tmpi = c->v[0] - a->v[0]) > range) + range = tmpi; + if ((tmpi = c->v[0] - b->v[0]) > range) + range = tmpi; + + if ((tmpi = c->v[1] - a->v[1]) > range) + range = tmpi; + range /= 0x10000; + + tmp1 = a->comp[C_W]; + tmp2 = b->comp[C_W]; + tmp3 = c->comp[C_W]; + if (tmp1 > tmp2) + swap(int, tmp1, tmp2); + if (tmp2 > tmp3) + swap(int, tmp2, tmp3); + if (tmp1 > tmp2) + tmp1 = tmp2; + if (tmp3 < 0) + return; + while ((tmp1 | tmp3) & 0xffff0000) + { + tmp1 /= 2; + tmp3 /= 2; + } + + if ((tmp3 - tmp1) * range < cutoff * tmp1) + { +#if SIZE == 256 && LIGHT + TriangleRenderPIZ2TI(_a, _b, _c); +#elif SIZE == 256 && !LIGHT + TriangleRenderPIZ2T(_a, _b, _c); +#elif LIGHT + TriangleRenderPIZ2TIA(_a, _b, _c); +#elif !LIGHT + TriangleRenderPIZ2TA(_a, _b, _c); +#endif + return; + } + } + + sxa = sar16(a->v[0] - fw.vp_width); + sxb = sar16(b->v[0] - fw.vp_width); + sxc = sar16(c->v[0] - fw.vp_width); + sya = sar16(a->v[1] - fw.vp_height); + syb = sar16(b->v[1] - fw.vp_height); + syc = sar16(c->v[1] - fw.vp_height); + + if (sya == syc) + return; + + /* The compiler hopefully has the sense to substitute multiplications here */ + + u_base = a->comp[C_U]; + if (b->comp[C_U] < u_base) + u_base = b->comp[C_U]; + if (c->comp[C_U] < u_base) + u_base = c->comp[C_U]; + v_base = a->comp[C_V]; + if (b->comp[C_V] < v_base) + v_base = b->comp[C_V]; + if (c->comp[C_V] < v_base) + v_base = c->comp[C_V]; + u_base &= 0xffff0000; + v_base &= 0xffff0000; + + au = (float)(a->comp[C_U] - u_base) / 0x10000; + bu = (float)(b->comp[C_U] - u_base) / 0x10000; + cu = (float)(c->comp[C_U] - u_base) / 0x10000; + av = (float)(a->comp[C_V] - v_base) / 0x10000; + bv = (float)(b->comp[C_V] - v_base) / 0x10000; + cv = (float)(c->comp[C_V] - v_base) / 0x10000; + + u_base /= 0x10000; + v_base /= 0x10000; + + WbWc = (float)b->comp[C_W] * (float)c->comp[C_W]; + WcWa = (float)c->comp[C_W] * (float)a->comp[C_W]; + WaWb = (float)a->comp[C_W] * (float)b->comp[C_W]; + + /* Compute cross products a x b using snapped integer coordinates */ + + bvcx = WbWc * (syb - syc); + bvcy = WbWc * (sxc - sxb); + bvcz = WbWc * (sxb * syc - syb * sxc); + + cvax = WcWa * (syc - sya); + cvay = WcWa * (sxa - sxc); + cvaz = WcWa * (sxc * sya - syc * sxa); + + avbx = WaWb * (sya - syb); + avby = WaWb * (sxb - sxa); + avbz = WaWb * (sxa * syb - sya * sxb); + + /* The u coordinate for the texel mapped to the screen at x,y */ + /* are given by u = int(U(x,y)/V(x,y)) */ + + dUx = bvcx * au + cvax * bu + avbx * cu; + dUy = bvcy * au + cvay * bu + avby * cu; + dUz = bvcz * au + cvaz * bu + avbz * cu; + + dVx = bvcx * av + cvax * bv + avbx * cv; + dVy = bvcy * av + cvay * bv + avby * cv; + dVz = bvcz * av + cvaz * bv + avbz * cv; + + nx = bvcx + cvax + avbx; + ny = bvcy + cvay + avby; + + fW = nx * sxa + ny * sya + bvcz + cvaz + avbz; + + if (fW < 0) + { + fW = -fW; + dUx = -dUx, dUy = -dUy; + dVx = -dVx, dVy = -dVy; + nx = -nx, ny = -ny; + } + + /* Now put U,V and various deltas into integers */ + + /* As u = int(U/V) we can multiply U and V by any factor we choose. */ + /* We choose the factor to make U and V representible by large */ + /* integers for greater accuracy. */ + + tmpf = fabs(au) + fabs(bu) + fabs(cu) + fabs(av) + fabs(bv) + fabs(cv); + tmpf = (float)(1 << 30) / (tmpf * fW); + + idUx = dUx * tmpf; + idUy = dUy * tmpf; + idVx = dVx * tmpf; + idVy = dVy * tmpf; + tsl.dWx = idWx = nx * tmpf; + idWy = ny * tmpf; + + tmpf *= fW; + + iU = au * tmpf; + iV = av * tmpf; + tsl.iW = tmpf; + if (!tsl.iW) + return; + + zb.top.x = sxb - sxa; + zb.top.y = syb - sya; + zb.bot.x = sxc - sxb; + zb.bot.y = syc - syb; + zb.main.x = sxc - sxa; + zb.main.y = syc - sya; + + g_divisor = zb.top.x * zb.main.y - zb.main.x * zb.top.y; + if (g_divisor == 0) + { + return; + } + + /* Calculate deltas along triangle edges */ + + zb.main.grad = zb.main.x * _reciprocal[zb.main.y]; + zb.main.d_f = zb.main.grad << 16; + grad = sar16(zb.main.grad); + zb.main.d_i = grad + zb.row_width; + + dU_nocarry = grad * idUx + idUy; + dV_nocarry = grad * idVx + idVy; + dW_nocarry = grad * idWx + idWy; + + zb.top.grad = zb.top.y ? zb.top.x * _reciprocal[zb.top.y] : 0; + zb.top.d_f = zb.top.grad << 16; + zb.top.d_i = sar16(zb.top.grad) + zb.row_width; + + /* Shift right by half a pixel */ + + zb.main.f = zb.top.f = 0x80000000; + + udom = au; + vdom = av; + + udW_nocarry = udom * dW_nocarry - dU_nocarry; + tsl.udW = udom * idWx - idUx; + + vdW_nocarry = vdom * dW_nocarry - dV_nocarry; + tsl.vdW = vdom * idWx - idVx; + + /* Eu and Ev are the 'Bresenham style' error terms */ + + tsl.Eu = iU - udom * tsl.iW; + tsl.Ev = iV - vdom * tsl.iW; + + tsl.source = ((vdom + v_base) & SIZE - 1) * SIZE | (udom + u_base) & SIZE - 1; + + offset = sar16(a->v[X]) + sar16(a->v[Y]) * zb.row_width - (g_divisor < 0); + tsl.start = tsl.end = zb.colour_buffer + offset; + tsl.zstart = (char *)zb.depth_buffer + (offset << 1); + zb.top.count = syb - sya; + + zb.bot.f = 0x80000000; + + zb.bot.grad = zb.bot.y ? zb.bot.x * _reciprocal[zb.bot.y] : 0; + zb.bot.d_f = zb.bot.grad << 16; + zb.bot.d_i = sar16(zb.bot.grad) + zb.row_width; + zb.bot.count = syc - syb; + +#if FIX +#define PARAM_SETUP(param, p) \ + { \ + dp1 = b->p - a->p; \ + dp2 = c->p - a->p; \ + param.grad_x = SafeFixedMac2Div(dp1, zb.main.y, -dp2, zb.top.y, g_divisor); \ + param.grad_y = SafeFixedMac2Div(dp2, zb.top.x, -dp1, zb.main.x, g_divisor); \ + param.current = a->p + (g_divisor >= 0 ? param.grad_x / 2 : -param.grad_x / 2); \ + param.d_nocarry = BrFixedToInt(zb.main.grad) * param.grad_x + param.grad_y; \ + param.d_carry = param.d_nocarry + param.grad_x; \ + } +#else +#define PARAM_SETUP(param, p) \ + { \ + dp1 = BrFixedToFloat(b->p - a->p); \ + dp2 = BrFixedToFloat(c->p - a->p); \ + param.grad_x = BrFloatToFixed((dp1 * zb.main.y - dp2 * zb.top.y) / g_divisor); \ + param.grad_y = BrFloatToFixed((dp2 * zb.top.x - dp1 * zb.main.x) / g_divisor); \ + param.current = a->p + param.grad_x / 2; \ + param.d_nocarry = BrFixedToInt(zb.main.grad) * param.grad_x + param.grad_y; \ + param.d_carry = param.d_nocarry + param.grad_x; \ + } +#endif + +#if LIGHT + PARAM_SETUP(zb.pi, comp[C_I]); +#endif + PARAM_SETUP(zb.pz, v[Z]); + +#if SHIFT + + /* shift by 1/2 pixel */ + + if (g_divisor >= 0) + { + tsl.iW += tsl.dWx / 2; + tsl.Eu += -tsl.udW / 2; + tsl.Ev += -tsl.vdW / 2; + } + else + { + tsl.iW -= tsl.dWx / 2; + tsl.Eu -= -tsl.udW / 2; + tsl.Ev -= -tsl.vdW / 2; + } + + if ((signed)tsl.iW < 0) + return; + while (tsl.Eu >= (signed)tsl.iW) + { + tsl.Eu -= tsl.iW; + tsl.source = incu(tsl.source, SIZE); + tsl.udW += tsl.dWx; + udW_nocarry += dW_nocarry; + } + while (tsl.Eu < 0) + { + tsl.Eu += tsl.iW; + tsl.source = decu(tsl.source, SIZE); + tsl.udW -= tsl.dWx; + udW_nocarry -= dW_nocarry; + } + while (tsl.Ev >= (signed)tsl.iW) + { + tsl.Ev -= tsl.iW; + tsl.source = incv(tsl.source, SIZE); + tsl.vdW += tsl.dWx; + vdW_nocarry += dW_nocarry; + } + while (tsl.Ev < 0) + { + tsl.Ev += tsl.iW; + tsl.source = decv(tsl.source, SIZE); + tsl.vdW -= tsl.dWx; + vdW_nocarry -= dW_nocarry; + } +#endif + + while (zb.top.count--) + { + /* Start of second innermost loop */ + +#if SIZE == 256 && LIGHT + ScanLinePIZ2TIP256(); +#elif SIZE == 256 && !LIGHT + ScanLinePIZ2TP256(); +#elif SIZE == 64 && LIGHT + ScanLinePIZ2TIP64(); +#elif SIZE == 64 && !LIGHT + ScanLinePIZ2TP64(); +#elif SIZE == 1024 && !LIGHT + ScanLinePIZ2TP1024(); +#elif SIZE == 1024 && LIGHT + ScanLinePIZ2TIP1024(); +#endif + + zb.top.f += zb.top.d_f; + carry = (unsigned)zb.top.f < (unsigned)zb.top.d_f; + tsl.end += zb.top.d_i + carry; + zb.main.f += zb.main.d_f; + carry = (unsigned)zb.main.f < (unsigned)zb.main.d_f; + tsl.iW += dW_nocarry; + tsl.Eu += -udW_nocarry; + tsl.Ev += -vdW_nocarry; + tsl.start += zb.main.d_i + carry; + tsl.zstart += zb.main.d_i + carry << 1; +#if LIGHT + zb.pi.current += zb.pi.d_nocarry; +#endif + zb.pz.current += zb.pz.d_nocarry; + if (carry) + { + tsl.iW += idWx; + tsl.Eu += -tsl.udW; + tsl.Ev += -tsl.vdW; +#if LIGHT + zb.pi.current += zb.pi.grad_x; +#endif + zb.pz.current += zb.pz.grad_x; + } + + /* The core perspective calculations along the main edge */ + + if ((signed)tsl.iW < 0) + return; + while (tsl.Eu >= (signed)tsl.iW) + { + tsl.Eu -= tsl.iW; + tsl.source = incu(tsl.source, SIZE); + tsl.udW += tsl.dWx; + udW_nocarry += dW_nocarry; + } + while (tsl.Eu < 0) + { + tsl.Eu += tsl.iW; + tsl.source = decu(tsl.source, SIZE); + tsl.udW -= tsl.dWx; + udW_nocarry -= dW_nocarry; + } + while (tsl.Ev >= (signed)tsl.iW) + { + tsl.Ev -= tsl.iW; + tsl.source = incv(tsl.source, SIZE); + tsl.vdW += tsl.dWx; + vdW_nocarry += dW_nocarry; + } + while (tsl.Ev < 0) + { + tsl.Ev += tsl.iW; + tsl.source = decv(tsl.source, SIZE); + tsl.vdW -= tsl.dWx; + vdW_nocarry -= dW_nocarry; + } + /* End of second innermost loop */ + } + + tsl.end = zb.colour_buffer + sar16(b->v[X]) + sar16(b->v[Y]) * zb.row_width - (g_divisor < 0); + + while (zb.bot.count--) + { + /* Start of second innermost loop */ + +#if SIZE == 256 && LIGHT + ScanLinePIZ2TIP256(); +#elif SIZE == 256 && !LIGHT + ScanLinePIZ2TP256(); +#elif SIZE == 64 && LIGHT + ScanLinePIZ2TIP64(); +#elif SIZE == 64 && !LIGHT + ScanLinePIZ2TP64(); +#elif SIZE == 1024 && !LIGHT + ScanLinePIZ2TP1024(); +#elif SIZE == 1024 && LIGHT + ScanLinePIZ2TIP1024(); +#endif + + zb.bot.f += zb.bot.d_f; + carry = (unsigned)zb.bot.f < (unsigned)zb.bot.d_f; + tsl.end += zb.bot.d_i + carry; + zb.main.f += zb.main.d_f; + carry = (unsigned)zb.main.f < (unsigned)zb.main.d_f; + tsl.iW += dW_nocarry; + tsl.Eu += -udW_nocarry; + tsl.Ev += -vdW_nocarry; + tsl.start += zb.main.d_i + carry; + tsl.zstart += zb.main.d_i + carry << 1; +#if LIGHT + zb.pi.current += zb.pi.d_nocarry; +#endif + zb.pz.current += zb.pz.d_nocarry; + if (carry) + { + tsl.iW += idWx; + tsl.Eu += -tsl.udW; + tsl.Ev += -tsl.vdW; +#if LIGHT + zb.pi.current += zb.pi.grad_x; +#endif + zb.pz.current += zb.pz.grad_x; + } + if ((signed)tsl.iW < 0) + return; + while (tsl.Eu >= (signed)tsl.iW) + { + tsl.Eu -= tsl.iW; + tsl.source = incu(tsl.source, SIZE); + tsl.udW += tsl.dWx; + udW_nocarry += dW_nocarry; + } + while (tsl.Eu < 0) + { + tsl.Eu += tsl.iW; + tsl.source = decu(tsl.source, SIZE); + tsl.udW -= tsl.dWx; + udW_nocarry -= dW_nocarry; + } + while (tsl.Ev >= (signed)tsl.iW) + { + tsl.Ev -= tsl.iW; + tsl.source = incv(tsl.source, SIZE); + tsl.vdW += tsl.dWx; + vdW_nocarry += dW_nocarry; + } + while (tsl.Ev < 0) + { + tsl.Ev += tsl.iW; + tsl.source = decv(tsl.source, SIZE); + tsl.vdW -= tsl.dWx; + vdW_nocarry -= dW_nocarry; + } + /* End of second innermost loop */ + } +} \ No newline at end of file diff --git a/bren/ZB/l_piz.c b/bren/ZB/l_piz.c new file mode 100644 index 00000000..4a7108c7 --- /dev/null +++ b/bren/ZB/l_piz.c @@ -0,0 +1,1560 @@ +/* + * Copyright (c) 1993 Argonaut Software Ltd. All rights reserved. + * + * $Id: l_piz.c 1.1 1995/08/31 16:52:48 sam Exp $ + * $Locker: $ + * + * Mesh rendering to produce points + */ +#include "zb.h" +#include "shortcut.h" +#include "blockops.h" +#include "brassert.h" + +static char rscid[] = "$Id: l_piz.c 1.1 1995/08/31 16:52:48 sam Exp $"; + +#define ABS(x) (((x) < 0) ? -(x) : (x)) +#define SWAP(type, a, b) \ + { \ + type _; \ + _ = a; \ + a = b; \ + b = _; \ + } + +#define ScalarsToRGB15(r, g, b) (((r) >> 19) & 0x1f | ((g) >> 14) & 0x3e0 | ((b) >> 9) & 0x7c00) + +#define ScalarsToRGB16(r, g, b) (((r) >> 19) & 0x1f | ((g) >> 14) & 0x7c0 | ((b) >> 8) & 0xf800) + +#define ScalarsToRGB24(r, g, b) (((b) >> 16) & 0xff | ((g) >> 8) & 0xff00 | ((b) >> 8) & 0xff0000) + +/* + * Line drawer - Proper Bresenham algorithm + */ + +void BR_ASM_CALL LineRenderPIZ2I(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1) +{ + br_fixed_ls dx, dy; + br_fixed_ls pm, dm, pz, dz, pi, di, x0, x1, y0, y1; + int error; + int count, offset, base; + int X0, Y0, X1, Y1; + char *ptr, *zptr; + int dptr, dzptr; + + x0 = v0->v[X]; + y0 = v0->v[Y]; + x1 = v1->v[X]; + y1 = v1->v[Y]; + +#if 0 + /* + * Clamp ends of line + * + * XXX - Should not be necessary! + */ + CLAMP_POINT(x0,y0); + CLAMP_POINT(x1,y1); +#endif + + X0 = BrFixedToInt(x0); + Y0 = BrFixedToInt(y0); + X1 = BrFixedToInt(x1); + Y1 = BrFixedToInt(y1); + + CLAMP_LP(X0, Y0); + CLAMP_LP(X1, Y1); + + dx = X1 - X0; + dy = Y1 - Y0; + + error = 0; + + if (ABS(dx) > ABS(dy)) + { + /* + * Major axis is X axis - ensure dx is +ve + */ + + if (dx < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = 1 + (dy > 0 ? zb.row_width : -zb.row_width); + dzptr = 2 + (dy > 0 ? zb.depth_row_width : -zb.depth_row_width); + dy = ABS(dy); + + if (dx < 0) + { + return; + } + + pz = v0->v[Z]; + pi = v0->comp[C_I]; + + if (dx > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dx)); + di = BrFixedDiv((v1->comp[C_I] - v0->comp[C_I]), BrIntToFixed(dx)); + } + else + { + dz = 0; + di = 0; + } + + ptr = (char *)zb.colour_buffer + X0 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dx; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + *(unsigned short *)zptr = pz >> 16; + *ptr = (br_uint_8)ScreenToInt(pi); + } + + error += dy; + if (error > 0) + { + error -= dx; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr++; + zptr += 2; + } + + /* + * Update parameters + */ + pi += di; + pz += dz; + } + } + else + { + /* + * Major axis is Y axis - ensure dy is +ve + */ + + if (dy < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = zb.row_width + (dx > 0 ? 1 : -1); + dzptr = zb.depth_row_width + (dx > 0 ? 2 : -2); + dx = ABS(dx); + + if (dy < 0) + return; + + pz = v0->v[Z]; + pi = v0->comp[C_I]; + + if (dy > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dy)); + di = BrFixedDiv((v1->comp[C_I] - v0->comp[C_I]), BrIntToFixed(dy)); + } + else + { + dz = 0; + di = 0; + } + + ptr = (char *)zb.colour_buffer + X0 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dy; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + *(unsigned short *)zptr = pz >> 16; + *ptr = (br_uint_8)ScreenToInt(pi); + } + + error += dx; + if (error > 0) + { + error -= dy; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr += zb.row_width; + zptr += zb.depth_row_width; + } + + /* + * Update parameters + */ + pi += di; + pz += dz; + } + } +} + +/* + * Arbitrary size lit textured line drawer + */ +void BR_ASM_CALL LineRenderPIZ2TI(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1) +{ + br_fixed_ls dx, dy; + br_fixed_ls pm, dm, pz, dz, pi, di, x0, x1, y0, y1; + br_fixed_ls pu, pv, du, dv; + int error; + int count, offset, base; + int X0, Y0, X1, Y1; + char *ptr, *zptr; + int dptr, dzptr; + int width, height, stride; + + width = zb.material->colour_map->width; + height = zb.material->colour_map->height; + stride = zb.material->colour_map->row_bytes; + + x0 = v0->v[X]; + y0 = v0->v[Y]; + x1 = v1->v[X]; + y1 = v1->v[Y]; + +#if 0 + /* + * Clamp ends of line + * + * XXX - Should not be necessary! + */ + CLAMP_POINT(x0,y0); + CLAMP_POINT(x1,y1); +#endif + + X0 = BrFixedToInt(x0); + Y0 = BrFixedToInt(y0); + X1 = BrFixedToInt(x1); + Y1 = BrFixedToInt(y1); + + CLAMP_LP(X0, Y0); + CLAMP_LP(X1, Y1); + + dx = X1 - X0; + dy = Y1 - Y0; + + error = 0; + + if (ABS(dx) > ABS(dy)) + { + /* + * Major axis is X axis - ensure dx is +ve + */ + + if (dx < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = 1 + (dy > 0 ? zb.row_width : -zb.row_width); + dzptr = 2 + (dy > 0 ? zb.depth_row_width : -zb.depth_row_width); + dy = ABS(dy); + + if (dx < 0) + return; + + pz = v0->v[Z]; + pi = v0->comp[C_I]; + pu = v0->comp[C_U] % BrIntToFixed(width); + if (pu < 0) + pu += BrIntToFixed(width); + pv = v0->comp[C_V] % BrIntToFixed(height); + if (pv < 0) + pv += BrIntToFixed(height); + + if (dx > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dx)); + di = BrFixedDiv((v1->comp[C_I] - v0->comp[C_I]), BrIntToFixed(dx)); + du = BrFixedDiv((v1->comp[C_U] - v0->comp[C_U]), BrIntToFixed(dx)); + dv = BrFixedDiv((v1->comp[C_V] - v0->comp[C_V]), BrIntToFixed(dx)); + + du = du % BrIntToFixed(width); + if (du > 0) + du -= BrIntToFixed(width); + dv = dv % BrIntToFixed(height); + if (dv > 0) + dv -= BrIntToFixed(height); + } + + ptr = (char *)zb.colour_buffer + X0 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dx; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + char texel; + texel = zb.texture_buffer[(pv >> 16) * stride + (pu >> 16)]; + + /* Transparency test */ + + if (texel) + { + *(unsigned short *)zptr = pz >> 16; + *ptr = zb.shade_table[((pi >> 8) & 0xff00) + texel]; + } + } + + error += dy; + if (error > 0) + { + error -= dx; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr++; + zptr += 2; + } + + /* + * Update parameters + */ + pi += di; + pz += dz; + pu += du; + if (pu < 0) + pu += BrIntToFixed(width); + pv += dv; + if (pv < 0) + pv += BrIntToFixed(height); + } + } + else + { + /* + * Major axis is Y axis - ensure dy is +ve + */ + + if (dy < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = zb.row_width + (dx > 0 ? 1 : -1); + dzptr = zb.depth_row_width + (dx > 0 ? 2 : -2); + dx = ABS(dx); + + if (dy < 0) + return; + + pz = v0->v[Z]; + pi = v0->comp[C_I]; + pu = v0->comp[C_U] % BrIntToFixed(width); + if (pu < 0) + pu += BrIntToFixed(width); + pv = v0->comp[C_V] % BrIntToFixed(height); + if (pv < 0) + pv += BrIntToFixed(height); + + if (dy > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dy)); + di = BrFixedDiv((v1->comp[C_I] - v0->comp[C_I]), BrIntToFixed(dy)); + du = BrFixedDiv((v1->comp[C_U] - v0->comp[C_U]), BrIntToFixed(dy)); + dv = BrFixedDiv((v1->comp[C_V] - v0->comp[C_V]), BrIntToFixed(dy)); + + du = du % BrIntToFixed(width); + if (du > 0) + du -= BrIntToFixed(width); + dv = dv % BrIntToFixed(height); + if (dv > 0) + dv -= BrIntToFixed(height); + } + + ptr = (char *)zb.colour_buffer + X0 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dy; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + char texel; + texel = zb.texture_buffer[(pv >> 16) * stride + (pu >> 16)]; + + /* Transparency test */ + + if (texel) + { + *(unsigned short *)zptr = pz >> 16; + *ptr = zb.shade_table[((pi >> 8) & 0xff00) + texel]; + } + } + + error += dx; + if (error > 0) + { + error -= dy; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr += zb.row_width; + zptr += zb.depth_row_width; + } + + /* + * Update parameters + */ + pi += di; + pz += dz; + pu += du; + if (pu < 0) + pu += BrIntToFixed(width); + pv += dv; + if (pv < 0) + pv += BrIntToFixed(height); + } + } +} + +/* + * Arbitrary size textured line drawer + */ +void BR_ASM_CALL LineRenderPIZ2T(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1) +{ + br_fixed_ls dx, dy; + br_fixed_ls pm, dm, pz, dz, x0, x1, y0, y1; + br_fixed_ls pu, pv, du, dv; + int error; + int count, offset, base; + int X0, Y0, X1, Y1; + char *ptr, *zptr; + int dptr, dzptr; + int width, height, stride; + + width = zb.material->colour_map->width; + height = zb.material->colour_map->height; + stride = zb.material->colour_map->row_bytes; + + x0 = v0->v[X]; + y0 = v0->v[Y]; + x1 = v1->v[X]; + y1 = v1->v[Y]; + +#if 0 + /* + * Clamp ends of line + * + * XXX - Should not be necessary! + */ + CLAMP_POINT(x0,y0); + CLAMP_POINT(x1,y1); +#endif + + X0 = BrFixedToInt(x0); + Y0 = BrFixedToInt(y0); + X1 = BrFixedToInt(x1); + Y1 = BrFixedToInt(y1); + + CLAMP_LP(X0, Y0); + CLAMP_LP(X1, Y1); + + dx = X1 - X0; + dy = Y1 - Y0; + + error = 0; + + if (ABS(dx) > ABS(dy)) + { + /* + * Major axis is X axis - ensure dx is +ve + */ + + if (dx < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = 1 + (dy > 0 ? zb.row_width : -zb.row_width); + dzptr = 2 + (dy > 0 ? zb.depth_row_width : -zb.depth_row_width); + dy = ABS(dy); + + if (dx < 0) + return; + + pz = v0->v[Z]; + pu = v0->comp[C_U] % BrIntToFixed(width); + if (pu < 0) + pu += BrIntToFixed(width); + pv = v0->comp[C_V] % BrIntToFixed(height); + if (pv < 0) + pv += BrIntToFixed(height); + + if (dx > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dx)); + du = BrFixedDiv((v1->comp[C_U] - v0->comp[C_U]), BrIntToFixed(dx)); + dv = BrFixedDiv((v1->comp[C_V] - v0->comp[C_V]), BrIntToFixed(dx)); + + du = du % BrIntToFixed(width); + if (du > 0) + du -= BrIntToFixed(width); + dv = dv % BrIntToFixed(height); + if (dv > 0) + dv -= BrIntToFixed(height); + } + + ptr = (char *)zb.colour_buffer + X0 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dx; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + char texel; + texel = zb.texture_buffer[(pv >> 16) * stride + (pu >> 16)]; + + /* Transparency test */ + + if (texel) + { + *(unsigned short *)zptr = pz >> 16; + *ptr = texel; + } + } + + error += dy; + if (error > 0) + { + error -= dx; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr++; + zptr += 2; + } + + /* + * Update parameters + */ + pz += dz; + pu += du; + if (pu < 0) + pu += BrIntToFixed(width); + pv += dv; + if (pv < 0) + pv += BrIntToFixed(height); + } + } + else + { + /* + * Major axis is Y axis - ensure dy is +ve + */ + + if (dy < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = zb.row_width + (dx > 0 ? 1 : -1); + dzptr = zb.depth_row_width + (dx > 0 ? 2 : -2); + dx = ABS(dx); + + if (dy < 0) + return; + + pz = v0->v[Z]; + pu = v0->comp[C_U] % BrIntToFixed(width); + if (pu < 0) + pu += BrIntToFixed(width); + pv = v0->comp[C_V] % BrIntToFixed(height); + if (pv < 0) + pv += BrIntToFixed(height); + + if (dy > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dy)); + du = BrFixedDiv((v1->comp[C_U] - v0->comp[C_U]), BrIntToFixed(dy)); + dv = BrFixedDiv((v1->comp[C_V] - v0->comp[C_V]), BrIntToFixed(dy)); + + du = du % BrIntToFixed(width); + if (du > 0) + du -= BrIntToFixed(width); + dv = dv % BrIntToFixed(height); + if (dv > 0) + dv -= BrIntToFixed(height); + } + + ptr = (char *)zb.colour_buffer + X0 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dy; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + char texel; + texel = zb.texture_buffer[(pv >> 16) * stride + (pu >> 16)]; + + /* Transparency test */ + + if (texel) + { + *(unsigned short *)zptr = pz >> 16; + *ptr = texel; + } + } + + error += dx; + if (error > 0) + { + error -= dy; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr += zb.row_width; + zptr += zb.depth_row_width; + } + + /* + * Update parameters + */ + pz += dz; + pu += du; + if (pu < 0) + pu += BrIntToFixed(width); + pv += dv; + if (pv < 0) + pv += BrIntToFixed(height); + } + } +} + +/* + * line drawer + */ +void BR_ASM_CALL LineRenderPIZ2T_RGB_888(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1) +{ + br_fixed_ls dx, dy; + br_fixed_ls pm, dm, pz, dz, x0, x1, y0, y1; + br_fixed_ls pu, pv, du, dv; + int error; + int count, offset, base; + int X0, Y0, X1, Y1; + char *ptr, *zptr; + int dptr, dzptr; + int width, height, stride; + + width = zb.material->colour_map->width; + height = zb.material->colour_map->height; + stride = zb.material->colour_map->row_bytes; + + x0 = v0->v[X]; + y0 = v0->v[Y]; + x1 = v1->v[X]; + y1 = v1->v[Y]; + +#if 0 + /* + * Clamp ends of line + * + * XXX - Should not be necessary! + */ + CLAMP_POINT(x0,y0); + CLAMP_POINT(x1,y1); +#endif + + X0 = BrFixedToInt(x0); + Y0 = BrFixedToInt(y0); + X1 = BrFixedToInt(x1); + Y1 = BrFixedToInt(y1); + + CLAMP_LP(X0, Y0); + CLAMP_LP(X1, Y1); + + dx = X1 - X0; + dy = Y1 - Y0; + + error = 0; + + if (ABS(dx) > ABS(dy)) + { + /* + * Major axis is X axis - ensure dx is +ve + */ + + if (dx < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = 3 + (dy > 0 ? zb.row_width : -zb.row_width); + dzptr = 2 + (dy > 0 ? zb.depth_row_width : -zb.depth_row_width); + dy = ABS(dy); + + if (dx < 0) + return; + + pz = v0->v[Z]; + pu = v0->comp[C_U] % BrIntToFixed(width); + if (pu < 0) + pu += BrIntToFixed(width); + pv = v0->comp[C_V] % BrIntToFixed(height); + if (pv < 0) + pv += BrIntToFixed(height); + + if (dx > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dx)); + du = BrFixedDiv((v1->comp[C_U] - v0->comp[C_U]), BrIntToFixed(dx)); + dv = BrFixedDiv((v1->comp[C_V] - v0->comp[C_V]), BrIntToFixed(dx)); + + du = du % BrIntToFixed(width); + if (du > 0) + du -= BrIntToFixed(width); + dv = dv % BrIntToFixed(height); + if (dv > 0) + dv -= BrIntToFixed(height); + } + + ptr = (char *)zb.colour_buffer + 3 * X0 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dx; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + char *texel; + texel = zb.texture_buffer + (pv >> 16) * stride + 3 * (pu >> 16); + if (texel[0] || texel[1] || texel[2]) + { + *(unsigned short *)zptr = pz >> 16; + ptr[0] = texel[0]; + ptr[1] = texel[1]; + ptr[2] = texel[2]; + } + } + + error += dy; + if (error > 0) + { + error -= dx; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr += 3; + zptr += 2; + } + + /* + * Update parameters + */ + pz += dz; + pu += du; + if (pu < 0) + pu += BrIntToFixed(width); + pv += dv; + if (pv < 0) + pv += BrIntToFixed(height); + } + } + else + { + /* + * Major axis is Y axis - ensure dy is +ve + */ + + if (dy < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = zb.row_width + (dx > 0 ? 3 : -3); + dzptr = zb.depth_row_width + (dx > 0 ? 2 : -2); + dx = ABS(dx); + + if (dy < 0) + return; + + pz = v0->v[Z]; + pu = v0->comp[C_U] % BrIntToFixed(width); + if (pu < 0) + pu += BrIntToFixed(width); + pv = v0->comp[C_V] % BrIntToFixed(height); + if (pv < 0) + pv += BrIntToFixed(height); + + if (dy > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dy)); + du = BrFixedDiv((v1->comp[C_U] - v0->comp[C_U]), BrIntToFixed(dy)); + dv = BrFixedDiv((v1->comp[C_V] - v0->comp[C_V]), BrIntToFixed(dy)); + + du = du % BrIntToFixed(width); + if (du > 0) + du -= BrIntToFixed(width); + dv = dv % BrIntToFixed(height); + if (dv > 0) + dv -= BrIntToFixed(height); + } + + ptr = (char *)zb.colour_buffer + X0 * 3 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dy; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + char *texel; + + /* Transparency test */ + + texel = zb.texture_buffer + (pv >> 16) * stride + 3 * (pu >> 16); + if (texel[0] || texel[1] || texel[2]) + { + *(unsigned short *)zptr = pz >> 16; + ptr[0] = texel[0]; + ptr[1] = texel[1]; + ptr[2] = texel[2]; + } + } + + error += dx; + if (error > 0) + { + error -= dy; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr += zb.row_width; + zptr += zb.depth_row_width; + } + + /* + * Update parameters + */ + pz += dz; + pu += du; + if (pu < 0) + pu += BrIntToFixed(width); + pv += dv; + if (pv < 0) + pv += BrIntToFixed(height); + } + } +} + +/* + * Gouraud shaded 24-bit line drawer + */ +void BR_ASM_CALL LineRenderPIZ2I_RGB_888(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1) +{ + br_fixed_ls dx, dy; + br_fixed_ls pm, dm, pz, dz, x0, x1, y0, y1; + br_fixed_ls pr, pg, pb, dr, dg, db; + int error; + int count, offset, base; + int X0, Y0, X1, Y1; + char *ptr, *zptr; + int dptr, dzptr; + + x0 = v0->v[X]; + y0 = v0->v[Y]; + x1 = v1->v[X]; + y1 = v1->v[Y]; + +#if 0 + /* + * Clamp ends of line + * + * XXX - Should not be necessary! + */ + CLAMP_POINT(x0,y0); + CLAMP_POINT(x1,y1); +#endif + + X0 = BrFixedToInt(x0); + Y0 = BrFixedToInt(y0); + X1 = BrFixedToInt(x1); + Y1 = BrFixedToInt(y1); + + CLAMP_LP(X0, Y0); + CLAMP_LP(X1, Y1); + + dx = X1 - X0; + dy = Y1 - Y0; + + error = 0; + + if (ABS(dx) > ABS(dy)) + { + /* + * Major axis is X axis - ensure dx is +ve + */ + + if (dx < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = 3 + (dy > 0 ? zb.row_width : -zb.row_width); + dzptr = 2 + (dy > 0 ? zb.depth_row_width : -zb.depth_row_width); + dy = ABS(dy); + + if (dx < 0) + return; + + pz = v0->v[Z]; + pr = v0->comp[C_R]; + pg = v0->comp[C_G]; + pb = v0->comp[C_B]; + + if (dx > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dx)); + dr = BrFixedDiv((v1->comp[C_R] - v0->comp[C_R]), BrIntToFixed(dx)); + dg = BrFixedDiv((v1->comp[C_G] - v0->comp[C_G]), BrIntToFixed(dx)); + db = BrFixedDiv((v1->comp[C_B] - v0->comp[C_B]), BrIntToFixed(dx)); + } + + ptr = (char *)zb.colour_buffer + 3 * X0 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dx; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + *(unsigned short *)zptr = pz >> 16; + ptr[0] = pb >> 16; + ptr[1] = pg >> 16; + ptr[2] = pr >> 16; + } + + error += dy; + if (error > 0) + { + error -= dx; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr += 3; + zptr += 2; + } + + /* + * Update parameters + */ + pz += dz; + pr += dr; + pg += dg; + pb += db; + } + } + else + { + /* + * Major axis is Y axis - ensure dy is +ve + */ + + if (dy < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = zb.row_width + (dx > 0 ? 3 : -3); + dzptr = zb.depth_row_width + (dx > 0 ? 2 : -2); + dx = ABS(dx); + + if (dy < 0) + return; + + pz = v0->v[Z]; + pr = v0->comp[C_R]; + pg = v0->comp[C_G]; + pb = v0->comp[C_B]; + + if (dy > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dy)); + dr = BrFixedDiv((v1->comp[C_R] - v0->comp[C_R]), BrIntToFixed(dy)); + dg = BrFixedDiv((v1->comp[C_G] - v0->comp[C_G]), BrIntToFixed(dy)); + db = BrFixedDiv((v1->comp[C_B] - v0->comp[C_B]), BrIntToFixed(dy)); + } + + ptr = (char *)zb.colour_buffer + X0 * 3 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dy; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + *(unsigned short *)zptr = pz >> 16; + ptr[0] = pb >> 16; + ptr[1] = pg >> 16; + ptr[2] = pr >> 16; + } + + error += dx; + if (error > 0) + { + error -= dy; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr += zb.row_width; + zptr += zb.depth_row_width; + } + + /* + * Update parameters + */ + pz += dz; + pr += dr; + pg += dg; + pb += db; + } + } +} + +/* + * line drawer + */ +void BR_ASM_CALL LineRenderPIZ2T_RGB_555(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1) +{ + br_fixed_ls dx, dy; + br_fixed_ls pm, dm, pz, dz, x0, x1, y0, y1; + br_fixed_ls pu, pv, du, dv; + int error; + int count, offset, base; + int X0, Y0, X1, Y1; + char *ptr, *zptr; + int dptr, dzptr; + int width, height, stride; + + width = zb.material->colour_map->width; + height = zb.material->colour_map->height; + stride = zb.material->colour_map->row_bytes; + + x0 = v0->v[X]; + y0 = v0->v[Y]; + x1 = v1->v[X]; + y1 = v1->v[Y]; + +#if 0 + /* + * Clamp ends of line + * + * XXX - Should not be necessary! + */ + CLAMP_POINT(x0,y0); + CLAMP_POINT(x1,y1); +#endif + + X0 = BrFixedToInt(x0); + Y0 = BrFixedToInt(y0); + X1 = BrFixedToInt(x1); + Y1 = BrFixedToInt(y1); + + CLAMP_LP(X0, Y0); + CLAMP_LP(X1, Y1); + + dx = X1 - X0; + dy = Y1 - Y0; + + error = 0; + + if (ABS(dx) > ABS(dy)) + { + /* + * Major axis is X axis - ensure dx is +ve + */ + + if (dx < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = 2 + (dy > 0 ? zb.row_width : -zb.row_width); + dzptr = 2 + (dy > 0 ? zb.depth_row_width : -zb.depth_row_width); + dy = ABS(dy); + + if (dx < 0) + return; + + pz = v0->v[Z]; + pu = v0->comp[C_U] % BrIntToFixed(width); + if (pu < 0) + pu += BrIntToFixed(width); + pv = v0->comp[C_V] % BrIntToFixed(height); + if (pv < 0) + pv += BrIntToFixed(height); + + if (dx > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dx)); + du = BrFixedDiv((v1->comp[C_U] - v0->comp[C_U]), BrIntToFixed(dx)); + dv = BrFixedDiv((v1->comp[C_V] - v0->comp[C_V]), BrIntToFixed(dx)); + + du = du % BrIntToFixed(width); + if (du > 0) + du -= BrIntToFixed(width); + dv = dv % BrIntToFixed(height); + if (dv > 0) + dv -= BrIntToFixed(height); + } + + ptr = (char *)zb.colour_buffer + 2 * X0 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dx; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + unsigned short texel; + texel = *(unsigned short *)(zb.texture_buffer + (pv >> 16) * stride + 2 * (pu >> 16)); + if (texel) + { + *(unsigned short *)zptr = pz >> 16; + *(unsigned short *)ptr = texel; + } + } + + error += dy; + if (error > 0) + { + error -= dx; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr += 2; + zptr += 2; + } + + /* + * Update parameters + */ + pz += dz; + pu += du; + if (pu < 0) + pu += BrIntToFixed(width); + pv += dv; + if (pv < 0) + pv += BrIntToFixed(height); + } + } + else + { + /* + * Major axis is Y axis - ensure dy is +ve + */ + + if (dy < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = zb.row_width + (dx > 0 ? 2 : -2); + dzptr = zb.depth_row_width + (dx > 0 ? 2 : -2); + dx = ABS(dx); + + if (dy < 0) + return; + + pz = v0->v[Z]; + pu = v0->comp[C_U] % BrIntToFixed(width); + if (pu < 0) + pu += BrIntToFixed(width); + pv = v0->comp[C_V] % BrIntToFixed(height); + if (pv < 0) + pv += BrIntToFixed(height); + + if (dy > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dy)); + du = BrFixedDiv((v1->comp[C_U] - v0->comp[C_U]), BrIntToFixed(dy)); + dv = BrFixedDiv((v1->comp[C_V] - v0->comp[C_V]), BrIntToFixed(dy)); + + du = du % BrIntToFixed(width); + if (du > 0) + du -= BrIntToFixed(width); + dv = dv % BrIntToFixed(height); + if (dv > 0) + dv -= BrIntToFixed(height); + } + + ptr = (char *)zb.colour_buffer + X0 * 2 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dy; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + unsigned short texel; + + texel = *(unsigned short *)(zb.texture_buffer + (pv >> 16) * stride + 2 * (pu >> 16)); + if (texel) + { + *(unsigned short *)zptr = pz >> 16; + *(unsigned short *)ptr = texel; + } + } + + error += dx; + if (error > 0) + { + error -= dy; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr += zb.row_width; + zptr += zb.depth_row_width; + } + + /* + * Update parameters + */ + pz += dz; + pu += du; + if (pu < 0) + pu += BrIntToFixed(width); + pv += dv; + if (pv < 0) + pv += BrIntToFixed(height); + } + } +} + +/* + * Gouraud shaded 15-bit line drawer + */ +void BR_ASM_CALL LineRenderPIZ2I_RGB_555(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1) +{ + br_fixed_ls dx, dy; + br_fixed_ls pm, dm, pz, dz, x0, x1, y0, y1; + br_fixed_ls pr, pg, pb, dr, dg, db; + int error; + int count, offset, base; + int X0, Y0, X1, Y1; + char *ptr, *zptr; + int dptr, dzptr; + + x0 = v0->v[X]; + y0 = v0->v[Y]; + x1 = v1->v[X]; + y1 = v1->v[Y]; + +#if 0 + /* + * Clamp ends of line + * + * XXX - Should not be necessary! + */ + CLAMP_POINT(x0,y0); + CLAMP_POINT(x1,y1); +#endif + + X0 = BrFixedToInt(x0); + Y0 = BrFixedToInt(y0); + X1 = BrFixedToInt(x1); + Y1 = BrFixedToInt(y1); + + CLAMP_LP(X0, Y0); + CLAMP_LP(X1, Y1); + + dx = X1 - X0; + dy = Y1 - Y0; + + error = 0; + + if (ABS(dx) > ABS(dy)) + { + /* + * Major axis is X axis - ensure dx is +ve + */ + + if (dx < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = 2 + (dy > 0 ? zb.row_width : -zb.row_width); + dzptr = 2 + (dy > 0 ? zb.depth_row_width : -zb.depth_row_width); + dy = ABS(dy); + + if (dx < 0) + return; + + pz = v0->v[Z]; + pr = v0->comp[C_R]; + pg = v0->comp[C_G]; + pb = v0->comp[C_B]; + + if (dx > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dx)); + dr = BrFixedDiv((v1->comp[C_R] - v0->comp[C_R]), BrIntToFixed(dx)); + dg = BrFixedDiv((v1->comp[C_G] - v0->comp[C_G]), BrIntToFixed(dx)); + db = BrFixedDiv((v1->comp[C_B] - v0->comp[C_B]), BrIntToFixed(dx)); + } + + ptr = (char *)zb.colour_buffer + 2 * X0 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dx; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + *(unsigned short *)zptr = pz >> 16; + *(unsigned short *)ptr = ScalarsToRGB15(pr, pg, pb); + } + + error += dy; + if (error > 0) + { + error -= dx; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr += 2; + zptr += 2; + } + + /* + * Update parameters + */ + pz += dz; + pr += dr; + pg += dg; + pb += db; + } + } + else + { + /* + * Major axis is Y axis - ensure dy is +ve + */ + + if (dy < 0) + { + SWAP(struct temp_vertex_fixed *, v0, v1); + SWAP(int, X0, X1); + SWAP(int, Y0, Y1); + dx = -dx; + dy = -dy; + } + + dptr = zb.row_width + (dx > 0 ? 2 : -2); + dzptr = zb.depth_row_width + (dx > 0 ? 2 : -2); + dx = ABS(dx); + + if (dy < 0) + return; + + pz = v0->v[Z]; + pr = v0->comp[C_R]; + pg = v0->comp[C_G]; + pb = v0->comp[C_B]; + + if (dy > 0) + { + dz = BrFixedDiv((v1->v[Z] - v0->v[Z]), BrIntToFixed(dy)); + dr = BrFixedDiv((v1->comp[C_R] - v0->comp[C_R]), BrIntToFixed(dy)); + dg = BrFixedDiv((v1->comp[C_G] - v0->comp[C_G]), BrIntToFixed(dy)); + db = BrFixedDiv((v1->comp[C_B] - v0->comp[C_B]), BrIntToFixed(dy)); + } + + ptr = (char *)zb.colour_buffer + X0 * 2 + Y0 * zb.row_width; + zptr = (char *)zb.depth_buffer + X0 + X0 + Y0 * zb.depth_row_width; + + count = dy; + + while (count-- >= 0) + { + /* + * plot pixel + */ + + if (*(unsigned short *)zptr > (unsigned short)(pz >> 16)) + { + *(unsigned short *)zptr = pz >> 16; + *(unsigned short *)ptr = ScalarsToRGB15(pr, pg, pb); + } + + error += dx; + if (error > 0) + { + error -= dy; + ptr += dptr; + zptr += dzptr; + } + else + { + ptr += zb.row_width; + zptr += zb.depth_row_width; + } + + /* + * Update parameters + */ + pz += dz; + pr += dr; + pg += dg; + pb += db; + } + } +} + diff --git a/bren/ZB/mesh_agnostic.c b/bren/ZB/mesh_agnostic.c new file mode 100644 index 00000000..4e3a7eb6 --- /dev/null +++ b/bren/ZB/mesh_agnostic.c @@ -0,0 +1,295 @@ +#include +#include +#include "zb.h" + +static inline void __VERTEX_TRANSFORM_PROJECT(br_vertex *vp, struct temp_vertex_fixed *tvp) +{ + br_int_32 w = BrFixedMac3(zb.os_model_to_screen.m[0][3], vp->p.v[0], zb.os_model_to_screen.m[1][3], vp->p.v[1], + zb.os_model_to_screen.m[2][3], vp->p.v[2]) + + zb.os_model_to_screen.m[3][3]; + + br_int_32 x; + { + br_int_64 __x; + __x = ((br_uint_64)zb.os_model_to_screen_hi[0] << 32) | zb.os_model_to_screen.m[3][0]; + __x += (br_int_64)zb.os_model_to_screen.m[0][0] * (br_int_64)vp->p.v[0]; + __x += (br_int_64)zb.os_model_to_screen.m[1][0] * (br_int_64)vp->p.v[1]; + __x += (br_int_64)zb.os_model_to_screen.m[2][0] * (br_int_64)vp->p.v[2]; + __x /= w; + x = __x + fw.vp_ox; + } + + tvp->v[0] = x; + + br_int_32 y; + { + br_int_64 __y; + __y = ((br_uint_64)zb.os_model_to_screen_hi[1] << 32) | zb.os_model_to_screen.m[3][1]; + __y += (br_int_64)zb.os_model_to_screen.m[0][1] * (br_int_64)vp->p.v[0]; + __y += (br_int_64)zb.os_model_to_screen.m[1][1] * (br_int_64)vp->p.v[1]; + __y += (br_int_64)zb.os_model_to_screen.m[2][1] * (br_int_64)vp->p.v[2]; + __y /= w; + y = __y + fw.vp_oy; + } + + tvp->v[1] = y; + + br_uint_32 z; + { + br_uint_64 __z; + __z = ((br_uint_64)zb.os_model_to_screen_hi[2] << 32) | zb.os_model_to_screen.m[3][2]; + __z += (br_int_64)zb.os_model_to_screen.m[0][2] * (br_int_64)vp->p.v[0]; + __z += (br_int_64)zb.os_model_to_screen.m[1][2] * (br_int_64)vp->p.v[1]; + __z += (br_int_64)zb.os_model_to_screen.m[2][2] * (br_int_64)vp->p.v[2]; + __z <<= 15; + __z /= w; + z = __z; + } + + tvp->comp[C_W] = w; + tvp->v[2] = z; +} + +static inline void __VERTEX_TRANSFORM_PROJECT_CHECK(br_vertex *vp, struct temp_vertex_fixed *tvp) +{ + br_int_32 w = BrFixedMac3(zb.os_model_to_screen.m[0][3], vp->p.v[0], zb.os_model_to_screen.m[1][3], vp->p.v[1], + zb.os_model_to_screen.m[2][3], vp->p.v[2]) + + zb.os_model_to_screen.m[3][3]; + + br_int_32 x; + { + br_int_64 __x; + __x = ((br_uint_64)zb.os_model_to_screen_hi[0] << 32) | zb.os_model_to_screen.m[3][0]; + __x += (br_int_64)zb.os_model_to_screen.m[0][0] * (br_int_64)vp->p.v[0]; + __x += (br_int_64)zb.os_model_to_screen.m[1][0] * (br_int_64)vp->p.v[1]; + __x += (br_int_64)zb.os_model_to_screen.m[2][0] * (br_int_64)vp->p.v[2]; + __x /= w; + x = __x + fw.vp_ox; + } + + tvp->v[0] = x; + + if (zb.bounds[0] > x) + { + zb.bounds[0] = x; + } + if (zb.bounds[2] < x) + { + zb.bounds[2] = x; + } + + br_int_32 y; + { + br_int_64 __y; + __y = ((br_uint_64)zb.os_model_to_screen_hi[1] << 32) | zb.os_model_to_screen.m[3][1]; + __y += (br_int_64)zb.os_model_to_screen.m[0][1] * (br_int_64)vp->p.v[0]; + __y += (br_int_64)zb.os_model_to_screen.m[1][1] * (br_int_64)vp->p.v[1]; + __y += (br_int_64)zb.os_model_to_screen.m[2][1] * (br_int_64)vp->p.v[2]; + __y /= w; + y = __y + fw.vp_oy; + } + + tvp->v[1] = y; + + if (zb.bounds[1] > y) + { + zb.bounds[1] = y; + } + if (zb.bounds[3] < y) + { + zb.bounds[3] = y; + } + + br_uint_32 z; + { + br_uint_64 __z; + __z = ((br_uint_64)zb.os_model_to_screen_hi[2] << 32) | zb.os_model_to_screen.m[3][2]; + __z += (br_int_64)zb.os_model_to_screen.m[0][2] * (br_int_64)vp->p.v[0]; + __z += (br_int_64)zb.os_model_to_screen.m[1][2] * (br_int_64)vp->p.v[1]; + __z += (br_int_64)zb.os_model_to_screen.m[2][2] * (br_int_64)vp->p.v[2]; + __z <<= 15; + __z /= w; + z = __z; + } + + tvp->comp[C_W] = w; + tvp->v[2] = z; +} + +br_int_32 BR_ASM_CALL ZbOSFFVGroupCulled_A(br_face *fp, struct temp_face *tfp, int count) +{ + br_uint_32 loop_count = count; + br_uint_32 group_count = 0; + + do + { + br_scalar dot = BrFixedFMac3(fp->n.v[0], fw.eye_m.v[0], fp->n.v[1], fw.eye_m.v[1], fp->n.v[2], fw.eye_m.v[2]); + + if (dot > fp->d) + { + tfp->flag = TFF_VISIBLE; + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + group_count = 1; + } + else + { + tfp->flag = 0; + } + + fp++; + tfp++; + loop_count--; + } while (loop_count > 0); + + return group_count; +} + +br_int_32 BR_ASM_CALL ZbOSFFVGroupCulledLit_A(br_face *fp, struct temp_face *tfp, int count) +{ + br_uint_32 loop_count = count; + br_uint_32 group_count = 0; + + do + { + br_scalar dot = BrFixedFMac3(fp->n.v[0], fw.eye_m.v[0], fp->n.v[1], fw.eye_m.v[1], fp->n.v[2], fw.eye_m.v[2]); + + if (dot > fp->d) + { + tfp->flag = TFF_VISIBLE; + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + group_count = 1; + + tfp->surface = fw.face_surface_fn(&zb.model->prepared_vertices[fp->vertices[0]], fp, 0); + } + else + { + tfp->flag = 0; + } + + fp++; + tfp++; + loop_count--; + } while (loop_count > 0); + + return group_count; +} + +br_uint_32 BR_ASM_CALL ZbOSTVGroup_A(br_vertex *vp, struct temp_vertex_fixed *tvp, int count, br_uint_8 *countp) +{ + br_uint_32 loop_count = count; + while (loop_count > 0) + { + if (*countp != 0) + { + __VERTEX_TRANSFORM_PROJECT(vp, tvp); + } + + vp++; + tvp++; + countp++; + loop_count--; + } + return count; +} + +br_uint_32 BR_ASM_CALL ZbOSTVGroupLit_A(br_vertex *vp, struct temp_vertex_fixed *tvp, int count, br_uint_8 *countp) +{ + br_uint_32 loop_count = count; + + while (loop_count > 0) + { + if (*countp != 0) + { + __VERTEX_TRANSFORM_PROJECT(vp, tvp); + fw.surface_fn(vp, &vp->n, tvp->comp); + } + + vp++; + tvp++; + countp++; + loop_count--; + } + + return count; +} + +br_uint_32 BR_ASM_CALL ZbOSTVGroupBC_A(br_vertex *vp, struct temp_vertex_fixed *tvp, int count, br_uint_8 *countp) +{ + br_uint_32 loop_count = count; + while (loop_count > 0) + { + if (*countp != 0) + { + __VERTEX_TRANSFORM_PROJECT_CHECK(vp, tvp); + } + + vp++; + tvp++; + countp++; + loop_count--; + } + return count; +} + +br_uint_32 BR_ASM_CALL ZbOSTVGroupLitBC_A(br_vertex *vp, struct temp_vertex_fixed *tvp, int count, br_uint_8 *countp) +{ + br_uint_32 loop_count = count; + while (loop_count > 0) + { + if (*countp != 0) + { + __VERTEX_TRANSFORM_PROJECT_CHECK(vp, tvp); + fw.surface_fn(vp, &vp->n, tvp->comp); + } + + vp++; + tvp++; + countp++; + loop_count--; + } + return count; +} + +br_uint_32 BR_ASM_CALL ZbOSCopyModelToScreen_A(void) +{ + int i; + for (i = 0; i < 3; i++) + { + br_uint_64 x = ((br_int_64)fw.model_to_screen.m[i][0] * fw.vp_width); + if ((x >> 32 & 0xFFFF8000) != 0xFFFF8000) + { + return -1; + } + zb.os_model_to_screen.m[i][0] = x >> 16; + + br_uint_64 y = ((br_int_64)fw.model_to_screen.m[i][1] * fw.vp_height); + if ((y >> 32 & 0xFFFF8000) != 0xFFFF8000) + { + return -1; + } + zb.os_model_to_screen.m[i][1] = y >> 16; + + zb.os_model_to_screen.m[i][2] = -fw.model_to_screen.m[i][2]; + zb.os_model_to_screen.m[i][3] = fw.model_to_screen.m[i][3]; + } + + br_uint_64 x = ((br_uint_64)fw.model_to_screen.m[i][0] * fw.vp_width); + zb.os_model_to_screen.m[i][0] = x; + zb.os_model_to_screen_hi[0] = x >> 32; + + br_uint_64 y = ((br_uint_64)fw.model_to_screen.m[i][1] * fw.vp_height); + zb.os_model_to_screen.m[i][1] = y; + zb.os_model_to_screen_hi[1] = y >> 32; + + br_uint_32 z = fw.model_to_screen.m[i][2]; + zb.os_model_to_screen.m[i][2] = -z >> 16; + zb.os_model_to_screen_hi[2] = z << 16; + + zb.os_model_to_screen.m[i][3] = fw.model_to_screen.m[i][3]; + + return 0; +} \ No newline at end of file diff --git a/bren/ZB/p_piz.c b/bren/ZB/p_piz.c new file mode 100644 index 00000000..ae58c655 --- /dev/null +++ b/bren/ZB/p_piz.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: p_piz.c 1.1 1995/08/31 16:52:49 sam Exp $ + * $Locker: $ + * + * Mesh rendering to produce points + */ +#include "zb.h" +#include "shortcut.h" +#include "blockops.h" + +static char rscid[] = "$Id: p_piz.c 1.1 1995/08/31 16:52:49 sam Exp $"; + +#define ScalarsToRGB15(r, g, b) (((r) >> 19) & 0x1f | ((g) >> 14) & 0x3e0 | ((b) >> 9) & 0x7c00) + +#define ScalarsToRGB16(r, g, b) (((r) >> 19) & 0x1f | ((g) >> 14) & 0x7c0 | ((b) >> 8) & 0xf800) + +#define ScalarsToRGB24(r, g, b) (((b) >> 16) & 0xff | ((g) >> 8) & 0xff00 | ((b) >> 8) & 0xff0000) + +#define SETUP_POINT \ + x0 = ScreenToInt(tvp->v[X]); \ + y0 = ScreenToInt(tvp->v[Y]); \ + CLAMP_LP(x0, y0); + +#define SETUP_TEXTURE \ + width = zb.material->colour_map->width; \ + height = zb.material->colour_map->height; \ + stride = zb.material->colour_map->row_bytes; + +/* + * Setup arbitrary width u and v + */ +#define SETUP_UV \ + pu = tvp->comp[C_U] % BrIntToFixed(width); \ + if (pu < 0) \ + pu += BrIntToFixed(width); \ + pv = tvp->comp[C_V] % BrIntToFixed(height); \ + if (pv < 0) \ + pv += BrIntToFixed(height); + +/* + * Set up RGB + */ +#define SETUP_RGB \ + pr = tvp->comp[C_R]; \ + pg = tvp->comp[C_G]; \ + pb = tvp->comp[C_B]; + +/* + * 8 bit z-buffered points + */ +void BR_ASM_CALL PointRenderPIZ2(struct temp_vertex_fixed *tvp) +{ + int o; + int x0, y0; + + SETUP_POINT; + + o = y0 * zb.row_width + x0; + + if (((unsigned short *)zb.depth_buffer)[o] > (unsigned short)(tvp->v[Z] >> 16)) + { + ((unsigned short *)zb.depth_buffer)[o] = (unsigned short)(tvp->v[Z] >> 16); + zb.colour_buffer[o] = BrFixedToInt(tvp->comp[C_I]); + } +} + +void BR_ASM_CALL PointRenderPIZ2TI(struct temp_vertex_fixed *tvp) +{ + int o; + int x0, y0; + br_fixed_ls width, height, stride, pi, pu, pv; + char texel; + + SETUP_POINT; + SETUP_TEXTURE; + SETUP_UV; + + pi = tvp->comp[C_I]; + + o = y0 * zb.row_width + x0; + + if (((unsigned short *)zb.depth_buffer)[o] > (unsigned short)(tvp->v[Z] >> 16)) + { + texel = zb.texture_buffer[(pv >> 16) * width + (pu >> 16)]; + if (texel) + { + ((unsigned short *)zb.depth_buffer)[o] = (unsigned short)(tvp->v[Z] >> 16); + zb.colour_buffer[o] = zb.shade_table[256 * (pi >> 16) + texel]; + } + } +} + +/* + * 8 bit textured points + */ +void BR_ASM_CALL PointRenderPIZ2T(struct temp_vertex_fixed *tvp) +{ + int o; + int x0, y0; + br_fixed_ls width, height, stride, pu, pv; + char texel; + + SETUP_POINT; + SETUP_TEXTURE; + SETUP_UV; + + o = y0 * zb.row_width + x0; + + if (((unsigned short *)zb.depth_buffer)[o] > (unsigned short)(tvp->v[Z] >> 16)) + { + texel = zb.texture_buffer[(pv >> 16) * stride + (pu >> 16)]; + if (texel) + { + ((unsigned short *)zb.depth_buffer)[o] = (unsigned short)(tvp->v[Z] >> 16); + zb.colour_buffer[o] = texel; + } + } +} + +typedef enum +{ + LINE_RGB, + LINE_TEXTURE +} point_type; + +/* + * 24 bit point renderer + */ + +void BR_ASM_CALL PointRenderPIZ2_Generic_RGB_888(point_type mode, struct temp_vertex_fixed *tvp) +{ + int oc, oz; + int x0, y0; + br_fixed_ls width, height, stride, pi, pu, pv, pr, pg, pb; + char *texel; + + SETUP_POINT; + + if (mode == LINE_RGB) + { + SETUP_RGB; + } + + if (mode == LINE_TEXTURE) + { + + /* Textured */ + + SETUP_TEXTURE; + SETUP_UV; + } + + oc = y0 * zb.row_width + 3 * x0; + oz = y0 * zb.depth_row_width + x0 + x0; + + if (*(unsigned short *)((char *)zb.depth_buffer + oz) > (unsigned short)(tvp->v[Z] >> 16)) + { + if (mode == LINE_TEXTURE) + { + texel = zb.texture_buffer + (pv >> 16) * stride + 3 * (pu >> 16); + if (texel[0] || texel[1] || texel[2]) + { + *(unsigned short *)((char *)zb.depth_buffer + oz) = (unsigned short)(tvp->v[Z] >> 16); + zb.colour_buffer[oc] = texel[0]; + zb.colour_buffer[oc + 1] = texel[1]; + zb.colour_buffer[oc + 2] = texel[2]; + } + } + else + { + *(unsigned short *)((char *)zb.depth_buffer + oz) = (unsigned short)(tvp->v[Z] >> 16); + zb.colour_buffer[oc] = pb >> 16; + zb.colour_buffer[oc + 1] = pg >> 16; + zb.colour_buffer[oc + 2] = pr >> 16; + } + } +} + +/* + * 24 bit coloured points + */ + +void BR_ASM_CALL PointRenderPIZ2_RGB_888(struct temp_vertex_fixed *tvp) +{ + PointRenderPIZ2_Generic_RGB_888(LINE_RGB, tvp); +} + +/* + * 24 bit textured points + */ + +void BR_ASM_CALL PointRenderPIZ2T_RGB_888(struct temp_vertex_fixed *tvp) +{ + PointRenderPIZ2_Generic_RGB_888(LINE_TEXTURE, tvp); +} + +/* + * 24 bit points + */ + +void BR_ASM_CALL PointRenderPIZ2_Generic_RGB_555(point_type mode, struct temp_vertex_fixed *tvp) +{ + int oc, oz; + int x0, y0; + br_fixed_ls width, height, stride, pi, pu, pv, pr, pg, pb; + unsigned short texel; + + SETUP_POINT; + + if (mode == LINE_RGB) + { + SETUP_RGB; + } + + if (mode == LINE_TEXTURE) + { + + /* Textured */ + + SETUP_TEXTURE; + SETUP_UV; + } + + oc = y0 * zb.row_width + 2 * x0; + oz = y0 * zb.depth_row_width + x0 + x0; + + if (*(unsigned short *)((char *)zb.depth_buffer + oz) > (unsigned short)(tvp->v[Z] >> 16)) + { + if (mode == LINE_TEXTURE) + { + texel = *(unsigned short *)(zb.texture_buffer + (pv >> 16) * stride + 2 * (pu >> 16)); + if (texel) + { + *(unsigned short *)((char *)zb.depth_buffer + oz) = (unsigned short)(tvp->v[Z] >> 16); + *(unsigned short *)(zb.colour_buffer + oc) = texel; + } + } + else + { + *(unsigned short *)((char *)zb.depth_buffer + oz) = (unsigned short)(tvp->v[Z] >> 16); + *(unsigned short *)(zb.colour_buffer + oc) = ScalarsToRGB15(pr, pg, pb); + } + } +} + +/* + * 24 bit coloured points + */ +void BR_ASM_CALL PointRenderPIZ2_RGB_555(struct temp_vertex_fixed *tvp) +{ + PointRenderPIZ2_Generic_RGB_555(LINE_RGB, tvp); +} + +/* + * 24 bit textured points + */ +void BR_ASM_CALL PointRenderPIZ2T_RGB_555(struct temp_vertex_fixed *tvp) +{ + PointRenderPIZ2_Generic_RGB_555(LINE_TEXTURE, tvp); +} + diff --git a/bren/ZB/persp.c b/bren/ZB/persp.c new file mode 100644 index 00000000..0c9a33be --- /dev/null +++ b/bren/ZB/persp.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: persp.c 1.8 1995/08/31 16:47:37 sam Exp $ + * $Locker: $ + * + * Perspective texture mapper + */ +#include +#include + +#include + +#define FIX 1 + +#include "zb.h" +#include "shortcut.h" + +#define swap(type, a, b) \ + { \ + type _; \ + _ = a; \ + a = b; \ + b = _; \ + } + +#define sar16(num) (br_int_32)(br_int_16)((br_uint_32)(num) >> 16) +#define incv(a, size) ((a) + (size) & (size) * (size)-1); +#define incu(a, size) (((a) + 1 & (size)-1) | ((a) & ~((size)-1))); +#define decv(a, size) ((a) - (size) & (size) * (size)-1); +#define decu(a, size) ((a)-1 & (size)-1) | (a & ~((size)-1)); + +extern void BR_ASM_CALL ScanLinePIZ2TIP256(void); +extern void BR_ASM_CALL ScanLinePIZ2TIP64(void); +extern void BR_ASM_CALL ScanLinePIZ2TP256(void); +extern void BR_ASM_CALL ScanLinePIZ2TP64(void); +extern void BR_ASM_CALL ScanLinePIZ2TP1024(void); + +BR_ASM_CALL_EXTRA(ScanLinePIZ2TIP256) +BR_ASM_CALL_EXTRA(ScanLinePIZ2TIP64) +BR_ASM_CALL_EXTRA(ScanLinePIZ2TP1024) +BR_ASM_CALL_EXTRA(ScanLinePIZ2TP256) +BR_ASM_CALL_EXTRA(ScanLinePIZ2TP64) + +extern int BR_ASM_CALL SafeFixedMac2Div(int, int, int, int, int); +BR_ASM_CALL_EXTRA(SafeFixedMac2Div) + +extern int cutoff = 4; + +int PerspCheat = 1; + +TexturedScanLine BR_ASM_DATA tsl; +BR_ASM_DATA_EXTRA(tsl) + +#define FNAME TriangleRenderPIZ2TIP256 +#define SIZE 256 +#define LIGHT 1 +#include "innerp.inc.c" +#undef LIGHT +#undef SIZE +#undef FNAME + +#define FNAME TriangleRenderPIZ2TP256 +#define SIZE 256 +#define LIGHT 0 +#include "innerp.inc.c" +#undef LIGHT +#undef SIZE +#undef FNAME + +#define FNAME TriangleRenderPIZ2TIP64 +#define SIZE 64 +#define LIGHT 1 +#include "innerp.inc.c" +#undef LIGHT +#undef SIZE +#undef FNAME + +#define FNAME TriangleRenderPIZ2TP64 +#define SIZE 64 +#define LIGHT 0 +#include "innerp.inc.c" +#undef LIGHT +#undef SIZE +#undef FNAME + +#define FNAME TriangleRenderPIZ2TP1024 +#define SIZE 1024 +#define LIGHT 0 +#include "innerp.inc.c" +#undef LIGHT +#undef SIZE +#undef FNAME diff --git a/bren/ZB/persp.h b/bren/ZB/persp.h new file mode 100644 index 00000000..5d817a56 --- /dev/null +++ b/bren/ZB/persp.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: persp.h 1.4 1995/08/31 16:47:38 sam Exp $ + * $Locker: $ + * + * Global scanline workspace for persp. correct texture mapper + */ +#ifndef _PERSP_H_ +#define _PERSP_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct + { + char *start, *end; + char *zstart; + unsigned int denominator; + int u_numerator, v_numerator; + int du_numerator, dv_numerator; + int dWx; + int source; + int x, y; + } TexturedScanLine; + + extern TexturedScanLine BR_ASM_DATA tsl; + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/bren/ZB/perspi.inc.c b/bren/ZB/perspi.inc.c new file mode 100644 index 00000000..77dbac8a --- /dev/null +++ b/bren/ZB/perspi.inc.c @@ -0,0 +1,505 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: perspi.inc.c 1.1 1995/08/31 16:52:49 sam Exp $ + * + * Perspective texture mapped triangle renderer + */ + +#define SHIFT 1 + +/* + * Macros for moving left, right, up and down in texture whose size is + * SIZE*SIZE. + */ + +#if SIZE == 256 && defined __WATCOMC__ + +#define incv(a) inch(a) +#define incu(a) incl(a) +#define decv(a) dech(a) +#define decu(a) decl(a) + +#else + +#define incv(a) (a + SIZE & SIZE * SIZE - 1); +#define incu(a) ((a + 1 & SIZE - 1) | (a & ~(SIZE - 1))); +#define decv(a) (a - SIZE & SIZE * SIZE - 1); +#define decu(a) ((a - 1 & SIZE - 1) | (a & ~(SIZE - 1))); + +#endif + +/* + * Setup and outer loops for perspective texture mappers + */ + +void BR_ASM_CALL FNAME(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, struct temp_vertex_fixed *c) +{ + /* + * In linear texture mapping we interpolate u and v which we then use + * as the texture coordinates. + * + * In perspective texture mapping we linearly interpolate uq, wq and q + * and use uq/q and wq/q as texture coordinates. + * + * q is simply a constant times comp[C_W] chose to scale things for + * maximal accuracy + * + * v[0] and v[1] contain the (fractional) screen coordinates + */ + + /* + * Screen coordinates + */ + int sxa, sxb, sxc, sya, syb, syc; + + /* + * Values of uq,vq and q at vertices + */ + float au, av, bu, bv, cu, cv; + + br_fixed_ls dp1, dp2, g_divisor; + + int du_numerator_nocarry; + int dv_numerator_nocarry; + int u, v; + int offset; + int u_base, v_base; + + int carry, grad; + + float aw, bw, cw, maxuv, d1, d2, g_inverse, zmx, zmy, ztx, zty; + + /* Optimal sort of 3 elements? */ + + if (a->v[1] > b->v[1]) + { + if (b->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, a, c); + } + else + { + if (a->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, a, b); + swap(struct temp_vertex_fixed *, b, c); + } + else + { + swap(struct temp_vertex_fixed *, a, b); + } + } + } + else + { + if (b->v[1] > c->v[1]) + { + if (a->v[1] > c->v[1]) + { + swap(struct temp_vertex_fixed *, b, c); + swap(struct temp_vertex_fixed *, a, b); + } + else + { + swap(struct temp_vertex_fixed *, b, c); + } + } + } + +#define RANGE(min, max, a, b, c) \ + { \ + int middle; \ + min = a; \ + middle = b; \ + max = c; \ + if (min > middle) \ + swap(int, min, middle); \ + if (middle > max) \ + swap(int, middle, max); \ + if (min > middle) \ + min = middle; \ + } + +#if CHEAT + { + br_fixed_ls min, max, range; + + RANGE(min, max, a->v[0], b->v[0], c->v[0]); + + range = max - min; + + if (c->v[1] - a->v[1] > range) + range = c->v[1] - a->v[1]; + + range /= 0x10000; + + RANGE(min, max, a->comp[C_W], b->comp[C_W], c->comp[C_W]); + + while ((min | max) & 0xffff0000) + { + min /= 4; + max /= 4; + } + + if ((max - min) * range < cutoff * min) + { + LINEAR(a, b, c); + return; + } + } +#endif + + /* + * Set up general triangle parameters + */ + sxa = sar16(a->v[0]); + sxb = sar16(b->v[0]); + sxc = sar16(c->v[0]); + sya = sar16(a->v[1]); + syb = sar16(b->v[1]); + syc = sar16(c->v[1]); + + if (sya == syc) + return; + + zb.top.x = sxb - sxa; + zb.top.y = syb - sya; + zb.bot.x = sxc - sxb; + zb.bot.y = syc - syb; + zb.main.x = sxc - sxa; + zb.main.y = syc - sya; + + g_divisor = zb.top.x * zb.main.y - zb.main.x * zb.top.y; + if (g_divisor == 0) + { + return; + } + + if (g_divisor > 0 && g_divisor < 100) + g_inverse = frcp[g_divisor]; + else if (g_divisor < 0 && g_divisor > -100) + g_inverse = -frcp[-g_divisor]; + else + g_inverse = 1.0f / g_divisor; + + /* + * Set up texture specific parameters + */ + + /* + * Eliminate rounding errors by shifting to new base point + */ + u_base = a->comp[C_U] & 0xffff0000; + v_base = a->comp[C_V] & 0xffff0000; + + u = (a->comp[C_U] - u_base) / 0x10000; + v = (a->comp[C_V] - v_base) / 0x10000; + + au = (float)(a->comp[C_U] - u_base) / 0x10000; + bu = (float)(b->comp[C_U] - u_base) / 0x10000; + cu = (float)(c->comp[C_U] - u_base) / 0x10000; + av = (float)(a->comp[C_V] - v_base) / 0x10000; + bv = (float)(b->comp[C_V] - v_base) / 0x10000; + cv = (float)(c->comp[C_V] - v_base) / 0x10000; + + u_base /= 0x10000; + v_base /= 0x10000; + + /* + * Convert texture coordinates u,v to projective coordinates u,v,1/w + */ + aw = (float)b->comp[C_W] * c->comp[C_W]; + bw = (float)c->comp[C_W] * a->comp[C_W]; + cw = (float)b->comp[C_W] * a->comp[C_W]; + + /* + * Normalise u,v,q to maximise accuracy + */ + + maxuv = aw > 0 ? aw : -aw; + maxuv += au > 0 ? au : -au; + maxuv += av > 0 ? av : -av; + + au *= aw; + maxuv += au > 0 ? au : -au; + av *= aw; + maxuv += av > 0 ? av : -av; + bu *= bw; + maxuv += bu > 0 ? bu : -bu; + bv *= bw; + maxuv += bv > 0 ? bv : -bv; + cu *= cw; + maxuv += cu > 0 ? cu : -cu; + cv *= cw; + maxuv += cv > 0 ? cv : -cv; + + maxuv = (1 << 28) / maxuv; + + au *= maxuv; + av *= maxuv; + aw *= maxuv; + bu *= maxuv; + bv *= maxuv; + bw *= maxuv; + cu *= maxuv; + cv *= maxuv; + cw *= maxuv; + + d1 = bu - au; + d2 = cu - au; + + /* + * Convert deltas along edges to deltas along x and y + */ + zmx = zb.main.x * g_inverse; + zmy = zb.main.y * g_inverse; + ztx = zb.top.x * g_inverse; + zty = zb.top.y * g_inverse; + + zb.pu.grad_x = (br_int_32)(d1 * zmy - d2 * zty); + zb.pu.grad_y = (br_int_32)(d2 * ztx - d1 * zmx); + + d1 = bv - av; + d2 = cv - av; + + zb.pv.grad_x = (br_int_32)(d1 * zmy - d2 * zty); + zb.pv.grad_y = (br_int_32)(d2 * ztx - d1 * zmx); + + d1 = bw - aw; + d2 = cw - aw; + + zb.pq.grad_x = (br_int_32)(d1 * zmy - d2 * zty); + zb.pq.grad_y = (br_int_32)(d2 * ztx - d1 * zmx); + + zb.pu.current = (br_int_32)au; + zb.pv.current = (br_int_32)av; + zb.pq.current = (br_int_32)aw; + + if (!zb.pq.current) + { + return; + } + + /* + * Calculate deltas along triangle edges + */ + + zb.main.grad = zb.main.x * _reciprocal[zb.main.y]; + zb.main.d_f = zb.main.grad << 16; + grad = sar16(zb.main.grad); + zb.main.d_i = grad + zb.row_width; + + zb.pu.d_nocarry = grad * zb.pu.grad_x + zb.pu.grad_y; + zb.pv.d_nocarry = grad * zb.pv.grad_x + zb.pv.grad_y; + zb.pq.d_nocarry = grad * zb.pq.grad_x + zb.pq.grad_y; + + zb.top.grad = zb.top.y ? zb.top.x * _reciprocal[zb.top.y] : 0; + zb.top.d_f = zb.top.grad << 16; + zb.top.d_i = sar16(zb.top.grad) + zb.row_width; + zb.top.count = syb - sya; + + zb.bot.grad = zb.bot.y ? zb.bot.x * _reciprocal[zb.bot.y] : 0; + zb.bot.d_f = zb.bot.grad << 16; + zb.bot.d_i = sar16(zb.bot.grad) + zb.row_width; + zb.bot.count = syc - syb; + +#define PARAM_SETUP(param, p) \ + { \ + dp1 = b->p - a->p; \ + dp2 = c->p - a->p; \ + param.grad_x = SafeFixedMac2Div(dp1, zb.main.y, -dp2, zb.top.y, g_divisor); \ + param.grad_y = SafeFixedMac2Div(dp2, zb.top.x, -dp1, zb.main.x, g_divisor); \ + param.current = a->p + (g_divisor >= 0 ? param.grad_x / 2 : -param.grad_x / 2); \ + param.d_nocarry = BrFixedToInt(zb.main.grad) * param.grad_x + param.grad_y; \ + param.d_carry = param.d_nocarry + param.grad_x; \ + } + +#if LIGHT + PARAM_SETUP(zb.pi, comp[C_I]); +#endif + + /* Shift right by half a pixel */ + + zb.main.f = zb.top.f = zb.bot.f = 0x80000000; + + du_numerator_nocarry = u * zb.pq.d_nocarry - zb.pu.d_nocarry; + zb.pu.grad_x = u * zb.pq.grad_x - zb.pu.grad_x; + + dv_numerator_nocarry = v * zb.pq.d_nocarry - zb.pv.d_nocarry; + zb.pv.grad_x = v * zb.pq.grad_x - zb.pv.grad_x; + + /* u_numerator and v_numerator are the 'Bresenham style' error terms */ + + zb.pu.current = zb.pu.current - u * zb.pq.current; + zb.pv.current = zb.pv.current - v * zb.pq.current; + + /* + * Set up pointer into texture taking into account the fact that + * its size may be an arbitrary power of two + */ + + zb.tsl.source = (v + v_base & SIZE - 1) * SIZE | u + u_base & SIZE - 1; + + offset = sar16(a->v[X]) + sar16(a->v[Y]) * zb.row_width - (g_divisor < 0); + zb.tsl.start = zb.tsl.end = zb.colour_buffer + offset; + zb.tsl.zstart = (char *)zb.depth_buffer + (offset << 1); + + PARAM_SETUP(zb.pz, v[Z]); + +#if SHIFT + + /* shift by 1/2 pixel */ + + if (g_divisor >= 0) + { + zb.pq.current += zb.pq.grad_x / 2; + zb.pu.current += -zb.pu.grad_x / 2; + zb.pv.current += -zb.pv.grad_x / 2; + } + else + { + zb.pq.current -= zb.pq.grad_x / 2; + zb.pu.current -= -zb.pu.grad_x / 2; + zb.pv.current -= -zb.pv.grad_x / 2; + } + +#define PDIVIDE \ + while (zb.pu.current >= (signed)zb.pq.current) \ + { \ + zb.pu.current -= zb.pq.current; \ + zb.tsl.source = incu(zb.tsl.source); \ + zb.pu.grad_x += zb.pq.grad_x; \ + du_numerator_nocarry += zb.pq.d_nocarry; \ + } \ + while (zb.pu.current < 0) \ + { \ + zb.pu.current += zb.pq.current; \ + zb.tsl.source = decu(zb.tsl.source); \ + zb.pu.grad_x -= zb.pq.grad_x; \ + du_numerator_nocarry -= zb.pq.d_nocarry; \ + } \ + while (zb.pv.current >= (signed)zb.pq.current) \ + { \ + zb.pv.current -= zb.pq.current; \ + zb.tsl.source = incv(zb.tsl.source); \ + zb.pv.grad_x += zb.pq.grad_x; \ + dv_numerator_nocarry += zb.pq.d_nocarry; \ + } \ + while (zb.pv.current < 0) \ + { \ + zb.pv.current += zb.pq.current; \ + zb.tsl.source = decv(zb.tsl.source); \ + zb.pv.grad_x -= zb.pq.grad_x; \ + dv_numerator_nocarry -= zb.pq.d_nocarry; \ + } +#endif + + zb.tsl.y = sya; + + while (zb.top.count--) + { + /* Start of second innermost loop */ + + /* + * Call scan line renderer + */ + if (zb.tsl.start != zb.tsl.end) + { + PDIVIDE; + SNAME(); + } + + zb.tsl.y++; + + zb.top.f += zb.top.d_f; + carry = (unsigned)zb.top.f < (unsigned)zb.top.d_f; + zb.tsl.end += zb.top.d_i + carry; + zb.main.f += zb.main.d_f; + carry = (unsigned)zb.main.f < (unsigned)zb.main.d_f; + zb.pq.current += zb.pq.d_nocarry; + + zb.pu.current += -du_numerator_nocarry; + zb.pv.current += -dv_numerator_nocarry; + zb.tsl.start += zb.main.d_i + carry; + zb.tsl.zstart += zb.main.d_i + carry << 1; +#if LIGHT + zb.pi.current += zb.pi.d_nocarry; +#endif + zb.pz.current += zb.pz.d_nocarry; + if (carry) + { + zb.pq.current += zb.pq.grad_x; + + zb.pu.current += -zb.pu.grad_x; + zb.pv.current += -zb.pv.grad_x; +#if LIGHT + zb.pi.current += zb.pi.grad_x; +#endif +#if ZB + zb.pz.current += zb.pz.grad_x; +#endif + } + + /* + * The core perspective calculations along the main edge + */ + + /* End of second innermost loop */ + } + + zb.tsl.end = zb.colour_buffer + sar16(b->v[X]) + sar16(b->v[Y]) * zb.row_width - (g_divisor < 0); + + while (zb.bot.count--) + { + /* Start of second innermost loop */ + + /* + * Call scan line renderer + */ + if (zb.tsl.start != zb.tsl.end) + { + PDIVIDE; + SNAME(); + } + + zb.tsl.y++; + + zb.bot.f += zb.bot.d_f; + carry = (unsigned)zb.bot.f < (unsigned)zb.bot.d_f; + zb.tsl.end += zb.bot.d_i + carry; + zb.main.f += zb.main.d_f; + carry = (unsigned)zb.main.f < (unsigned)zb.main.d_f; + zb.pq.current += zb.pq.d_nocarry; + + zb.pu.current += -du_numerator_nocarry; + zb.pv.current += -dv_numerator_nocarry; + zb.tsl.start += zb.main.d_i + carry; + zb.tsl.zstart += zb.main.d_i + carry << 1; +#if LIGHT + zb.pi.current += zb.pi.d_nocarry; +#endif +#if ZB + zb.pz.current += zb.pz.d_nocarry; +#endif + if (carry) + { + zb.pq.current += zb.pq.grad_x; + + zb.pu.current += -zb.pu.grad_x; + zb.pv.current += -zb.pv.grad_x; +#if LIGHT + zb.pi.current += zb.pi.grad_x; +#endif +#if ZB + zb.pz.current += zb.pz.grad_x; +#endif + } + /* End of second innermost loop */ + } +} + +#undef decu +#undef decv +#undef incu +#undef incv \ No newline at end of file diff --git a/bren/ZB/perspz.c b/bren/ZB/perspz.c new file mode 100644 index 00000000..bee274e9 --- /dev/null +++ b/bren/ZB/perspz.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: perspz.c 1.1 1995/08/31 16:52:50 sam Exp $ + * $Locker: $ + * + * Perspective texture mapper + */ +#include +#include +#include + +#include + +#define FIX 1 + +#include "zb.h" +#include "shortcut.h" +#include "brassert.h" + +#define swap(type, a, b) \ + { \ + type _; \ + _ = a; \ + a = b; \ + b = _; \ + } + +extern float frcp[100]; + +extern int dither[4][4]; + +extern void BR_ASM_CALL ScanLinePIZ2TIP256(void); +extern void BR_ASM_CALL ScanLinePIZ2TIP64(void); +extern void BR_ASM_CALL ScanLinePIZ2TIP1024(void); +extern void BR_ASM_CALL ScanLinePIZ2TP256(void); +extern void BR_ASM_CALL ScanLinePIZ2TP64(void); +extern void BR_ASM_CALL ScanLinePIZ2TP1024(void); +extern void BR_ASM_CALL ScanLinePIZ2TPD1024(void); + +extern int BR_ASM_CALL SafeFixedMac2Div(int, int, int, int, int); + +#define cutoff 4.0 + +#ifdef __WATCOMC__ + +extern int sar16(int); + +extern int inch(int); +extern int incl(int); +extern int dech(int); +extern int decl(int); + +#pragma aux sar16 = "sar eax,16" parm[eax] + +#pragma aux inch = "inc ah" parm[eax] +#pragma aux incl = "inc al" parm[eax] +#pragma aux dech = "dec ah" parm[eax] +#pragma aux decl = "dec al" parm[eax] + +#else + +#define sar16(num) (br_int_32)(br_int_16)((br_uint_32)(num) >> 16) + +#endif + +#define ZB 1 + +#define CHEAT 1 +#define FNAME TriangleRenderPIZ2TIP256 +#define SNAME ScanLinePIZ2TIP256 +#define SIZE 256 +#define LIGHT 1 +#define LINEAR TriangleRenderPIZ2TI +#include "perspi.inc.c" +#undef LINEAR +#undef LIGHT +#undef SIZE +#undef SNAME +#undef FNAME + +#define FNAME TriangleRenderPIZ2TP256 +#define SNAME ScanLinePIZ2TP256 +#define SIZE 256 +#define LIGHT 0 +#define LINEAR TriangleRenderPIZ2T +#include "perspi.inc.c" +#undef LINEAR +#undef LIGHT +#undef SIZE +#undef FNAME +#undef SNAME + +#define FNAME TriangleRenderPIZ2TIP64 +#define SNAME ScanLinePIZ2TIP64 +#define SIZE 64 +#define LIGHT 1 +#define LINEAR TriangleRenderPIZ2TIA +#include "perspi.inc.c" +#undef LINEAR +#undef LIGHT +#undef SIZE +#undef SNAME +#undef FNAME + +#define FNAME TriangleRenderPIZ2TP64 +#define SNAME ScanLinePIZ2TP64 +#define SIZE 64 +#define LIGHT 0 +#define LINEAR TriangleRenderPIZ2TA +#include "perspi.inc.c" +#undef LINEAR +#undef LIGHT +#undef SIZE +#undef SNAME +#undef FNAME + +#define FNAME TriangleRenderPIZ2TP1024 +#define SNAME ScanLinePIZ2TP1024 +#define SIZE 1024 +#define LIGHT 0 +#define LINEAR TriangleRenderPIZ2TA +#include "perspi.inc.c" +#undef LINEAR +#undef LIGHT +#undef SIZE +#undef SNAME +#undef FNAME + +#define FNAME TriangleRenderPIZ2TIP1024 +#define SNAME ScanLinePIZ2TIP1024 +#define SIZE 1024 +#define LIGHT 1 +#define LINEAR TriangleRenderPIZ2TIA +#include "perspi.inc.c" +#undef LINEAR +#undef LIGHT +#undef SIZE +#undef SNAME +#undef FNAME +#undef CHEAT + +/* + * Turn off cheating simply because we have no linear + * dithered 1024x1024 renderer + */ +#define CHEAT 0 +#define FNAME TriangleRenderPIZ2TPD1024 +#define SNAME ScanLinePIZ2TPD1024 +#define SIZE 1024 +#define LIGHT 0 +#include "perspi.inc.c" +#undef LINEAR +#undef LIGHT +#undef SIZE +#undef SNAME +#undef FNAME \ No newline at end of file diff --git a/bren/ZB/safediv.c b/bren/ZB/safediv.c new file mode 100644 index 00000000..68c69501 --- /dev/null +++ b/bren/ZB/safediv.c @@ -0,0 +1,50 @@ +#include +#include +#include "zb.h" + +static inline br_int_32 __SafeDiv(br_int_64 a, br_int_32 b) +{ + br_int_32 sign = b ^ (br_uint_32)(a >> 31); + + if (a < 0) + { + a = -a; + } + + if (b < 0) + { + b = -b; + } + else if (b == 0) + { + return 0; + } + + if ((a >> 32) >= b) + { + return 0; + } + + // NOTE(???): div *must* be safe now or I'll eat my hat... NOT! + br_uint_32 result = __BrBuiltinDivU64U32(a, b); + + sign >>= 31; + result ^= sign; + result -= sign; + return result; +} + +int BR_ASM_CALL SafeFixedMac2Div(int a, int b, int c, int d, int e) +{ + br_int_64 ab = (br_int_64)a * (br_int_64)b; + br_int_64 cd = (br_int_64)c * (br_int_64)d; + return __SafeDiv(ab + cd, e); +} + +int BR_ASM_CALL SafeFixedMac3Div(int a, int b, int c, int d, int e, int f, int g) +{ + br_int_64 ab = (br_int_64)a * (br_int_64)b; + br_int_64 cd = (br_int_64)c * (br_int_64)d; + br_int_64 ef = (br_int_64)e * (br_int_64)f; + return __SafeDiv(ab + cd + ef, g); +} \ No newline at end of file diff --git a/bren/ZB/t_piza.asm b/bren/ZB/t_piza.asm new file mode 100644 index 00000000..9491d314 --- /dev/null +++ b/bren/ZB/t_piza.asm @@ -0,0 +1,714 @@ +;; Copyright (c) 1991,1993-1995 Argonaut Technologies Limited. All rights reserved. +;; +;; $Id: t_piza.asm 1.1 1995/08/31 16:52:47 sam Exp $ +;; $Locker: $ +;; +;; Trapezoid rendering for arbitary width texture mapping +;; Transparent Version. +;; See t_piza2.asm for non-transparent version +;; + + .386p + .model c,flat + include zb.inc + +WRAP equ 1 +WRAPROW equ 1 +TRANSP equ 1 + + .data +noffset dd ? + + .code + + ; Macro to increment those parts of the per scan line + ; increment that depend on whether there has been a carry + ; from the fractional part of the current screen x coordinate + +scan_inc macro carry,LIGHT,BPP + local lab2 + + if LIGHT + mov ebx,zb.pi.current + endif ; LIGHT + + if LIGHT + mov ecx,zb.pi.d_&carry& + endif ; LIGHT + + mov esi,zb.pz.current + mov edi,zb.pz.d_&carry& + add esi,edi + mov zb.pz.current,esi + + add ebx,ecx + mov zb.pi.current,ebx + + mov ebx,zb.awsl.u_current + mov ecx,zb.awsl.du_&carry& + mov ebp,zb.awsl.source_current + mov edi,zb.awsl.dsource_&carry& + add ebx,ecx ; zb.awsl.u_current += zb.awsl.dsource_&carry& + sbb ecx,ecx ; Save -carry + add ebp,edi ; zb.awsl.source_current += zb.awsl.dsource_&carry& + mov zb.awsl.u_current,ebx + + if WRAP + mov ebx,dword ptr zb.awsl.u_int_current + add ebx,zb.awsl.du_int_&carry& + sub ebx,ecx ; zb.awsl.u_int_current += carry; + mov dword ptr zb.awsl.u_int_current,ebx + endif ; WRAP + + ifidni ,<2> + shl ecx,1 + elseifidni ,<3> + lea ecx,[ecx+ecx*2] + elseifidni ,<4> + shl ecx,2 + endif ; + + sub ebp,ecx ; zb.awsl.source_current += carry*BPP + + mov ebx,zb.awsl.v_current + mov ecx,zb.awsl.dv_&carry& + add ebx,ecx + mov zb.awsl.v_current,ebx + jnc lab2 + + mov edi,zb.awsl.texture_stride + add ebp,edi +lab2: + + mov zb.awsl.source_current,ebp + endm + + + +TriangleRenderZ2 macro fn,LIGHT,BPP,BUMP + +fn proc uses eax ebx ecx edx esi edi ebp + +outer: + mov eax,zb.awsl.edge + mov ebx,[eax].scan_edge.count + test ebx,ebx + jz exit + dec ebx ; zb.awsl.edge->count-- + mov [eax].scan_edge.count,ebx + + if BUMP + mov ecx,zb.bump_buffer + sub ecx,zb.texture_buffer + mov noffset,ecx + endif + + mov edi,zb.awsl.start + mov ebx,zb.awsl._end + cmp edi,ebx + mov eax,zb.awsl.u_current + mov ebx,zb.awsl.v_current + + mov al,byte ptr zb.awsl.u_int_current + + mov ecx,zb.pz.current + mov zb.pz.currentpix,ecx + + if LIGHT + mov ecx,zb.pi.current + mov zb.pi.currentpix,ecx + endif ; LIGHT + + mov ah,byte ptr zb.awsl.u_int_current+1 + + mov esi,zb.awsl.source_current + mov ebp,zb.awsl.zstart + + jge scan_back + + ; Forward scan +loopf: + mov ecx,zb.awsl._end + cmp edi,ecx + jge next + + if TRANSP + + ifidni ,<1> + mov dl, [esi] + test dl, dl + jz failf ; Skip if transparent + elseifidni ,<2> + mov dl, [esi] + mov dh, 1[esi] + or dl, dh + jz failf + elseifidni ,<3> + mov dl,[esi] + mov dh,1[esi] + or dl,dh + mov dh,2[esi] + or dl,dh + jz failf + endif ; + + endif ; TRANSP + + ; 16 bit z test + + mov bl,byte ptr zb.pz.currentpix+2 + mov dl,[ebp] + mov bh,byte ptr zb.pz.currentpix+3 + mov dh,1[ebp] + cmp dl,bl + sbb dh,bh + jb failf ; Skip if pixel failed z test + + if LIGHT + + xor ecx,ecx + mov [ebp],bl ; Store low byte of z + + mov ch,byte ptr zb.pi.currentpix+2 ; Get lighting index + mov edx,zb.shade_table + mov cl,[esi] ; Get texel + mov 1[ebp],bh ; Store high byte of z + add edx,ecx + mov ecx,zb.pz.currentpix + add ebp,2 ; zptr += 2 + mov bl,[edx] ; Light texel + mov edx,zb.pz.grad_x ; z += dz + mov [edi],bl ; Store texel + + add ecx,edx + + ifidni ,<1> + inc edi ; ptr++ + else ; + add edi,BPP + endif ; + + mov edx,zb.pi.currentpix + mov zb.pz.currentpix,ecx + mov ecx,zb.pi.grad_x ; i += di + add edx,ecx + mov zb.pi.currentpix,edx + + jmp contf + +failf: + add ebp,2 ; zptr += 2 + + ifidni ,<1> + inc edi ; ptr++ + else ; + add edi,BPP + endif ; + + mov ecx,zb.pz.currentpix + mov edx,zb.pz.grad_x ; z += dz + add ecx,edx + mov edx,zb.pi.currentpix + mov zb.pz.currentpix,ecx + mov ecx,zb.pi.grad_x ; i += di + add edx,ecx + mov zb.pi.currentpix,edx + + elseif BUMP + + ; Bump mapping + + mov [ebp],bl ; Store low byte of z + + xor ecx,ecx + mov cl,[esi] ; Get texel + mov edx,noffset + mov dl,[esi+edx] ; Get normal + and edx,0ffh + add edx,zb.lighting_table ; Calculate light level from normal + mov ch,[edx] + mov edx,zb.shade_table + mov cl,[edx+ecx] ; Light texel + mov 1[ebp],bh ; Store high byte of z + mov [edi],cl + + mov ecx,zb.pz.currentpix + add ebp,2 ; zptr += 2 + mov edx,zb.pz.grad_x + + add ecx,edx ; z += dz + + ifidni ,<1> + inc edi ; ptr++ + else ; + add edi,BPP + endif ; + + mov zb.pz.currentpix,ecx + jmp contf + +failf: + add ebp,2 ; zptr += 2 + + ifidni ,<1> + inc edi ; ptr++ + else ; + add edi,BPP + endif ; + + mov ecx,zb.pz.currentpix + mov edx,zb.pz.grad_x ; z += dz + add ecx,edx + mov zb.pz.currentpix,ecx + + else ; LIGHT + + ; No lighting + + mov [ebp],bl ; Store low byte of z + + ifidni ,<1> + + mov cl,[esi] ; Get texel + mov 1[ebp],bh ; Store high byte of z + mov [edi],cl + + elseifidni ,<2> + + mov cl,[esi] + mov 1[ebp],bh ; Store high byte of z + mov ch,1[esi] + mov [edi],cl + mov 1[edi],ch + + elseifidni ,<3> + + mov cl,[esi] ; Get texel + mov 1[ebp],bh ; Store high byte of z + mov [edi],cl + mov ch,1[esi] + mov 1[edi],ch ; Store green + mov cl,2[esi] + mov 2[edi],cl ; Store red + + elseifidni ,<4> + + mov ecx,[esi] + mov 1[ebp],bh + mov [edi],ecx + + endif ; + + mov ecx,zb.pz.currentpix + add ebp,2 ; zptr += 2 + mov edx,zb.pz.grad_x + + add ecx,edx ; z += dz + + ifidni ,<1> + inc edi ; ptr++ + else ; + add edi,BPP + endif ; + + mov zb.pz.currentpix,ecx + jmp contf + +failf: + add ebp,2 ; zptr += 2 + + ifidni ,<1> + inc edi ; ptr++ + else ; + add edi,BPP + endif ; + + mov ecx,zb.pz.currentpix + mov edx,zb.pz.grad_x ; z += dz + add ecx,edx + mov zb.pz.currentpix,ecx + + endif ; LIGHT + +contf: + + ; Redo this with high and low halfwords of du swapped + + mov ecx,zb.awsl.du + add eax,ecx ; u += du + mov ecx,zb.awsl.dsource + + sbb edx,edx ; edx = -carry + add esi,ecx + mov ecx,zb.awsl.du_int + sub eax,edx ; zb.awsl.du += carry + + ifidni ,<2> + shl edx,1 + elseifidni ,<3> + lea edx,[edx+2*edx] + elseifidni ,<4> + shl edx,2 + endif ; + + sub esi,edx ; esi += carry + add eax,ecx ; u_int += du_int + + mov ecx,zb.awsl.dv + mov edx,zb.awsl.texture_stride; + add ebx,ecx + jnc nostridef + + add esi,edx + +nostridef: + test ah,ah + jl nowidthf + + mov ecx,zb.awsl.texture_width + add eax,ecx + + ifidni ,<1> + add esi,ecx + elseifidni ,<2> + lea esi,[esi+2*ecx] + elseifidni ,<3> + lea ecx,[ecx+2*ecx] + add esi,ecx + elseifidni ,<4> + lea esi,[esi+4*ecx] + endif ; + +nowidthf: + mov ecx,zb.awsl.texture_start + cmp esi,ecx ; Have we underrun? + jge nosizef + + mov ecx,zb.awsl.texture_size + add esi,ecx + +nosizef: + + jmp loopf + +scan_back: + ; Backwards scan +loopb: + mov ecx, zb.awsl._end + cmp edi, ecx + jle next + + mov ecx, zb.pz.currentpix + mov edx, zb.pz.grad_x ; z += dz + sub ecx, edx + + if LIGHT + mov edx, zb.pi.currentpix + endif + + mov zb.pz.currentpix,ecx + + if LIGHT + mov ecx,zb.pi.grad_x ; i += di + sub edx,ecx + mov zb.pi.currentpix,edx + endif + + ; Redo this with high and low halfwords of du swapped + + mov ecx,zb.awsl.du + add eax,ecx ; u += du + mov ecx,zb.awsl.dsource + + sbb edx,edx ; edx = -carry + add esi,ecx + mov ecx,zb.awsl.du_int + sub eax,edx + add eax,ecx ; u_int += du_int + + ifidni ,<1> + sub esi,edx + elseifidni ,<2> + shl edx,1 + sub esi,edx + elseifidni ,<3> + lea edx,[edx+edx*2] + sub esi,edx + elseifidni ,<4> + shl edx,2 + sub esi,edx + endif + + mov ecx,zb.awsl.dv + add ebx,ecx + jnc nostrideb + + mov ecx,zb.awsl.texture_stride + add esi,ecx + +nostrideb: + + test ah,ah + jl nowidthb + + mov ecx,zb.awsl.texture_width + add eax,ecx + + ifidni ,<1> + add esi,ecx + elseifidni ,<2> + lea esi,[esi+2*ecx] + elseifidni ,<3> + lea ecx,[ecx+2*ecx] + add esi,ecx + elseifidni ,<4> + lea esi,[esi+4*ecx] + endif ; + +nowidthb: + mov ecx,zb.awsl.texture_start + cmp esi,ecx + jge nosizeb + + mov ecx,zb.awsl.texture_size + add esi,ecx + +nosizeb: + sub ebp,2 ; zptr += 2 + + ifidni ,<1> + dec edi ; ptr += 1 + else ; + sub edi,BPP + endif ; + + if TRANSP + + ifidni ,<1> + mov bl,[esi] + test bl,bl + jz loopb ; Skip if transparent + elseifidni ,<2> + mov bl,[esi] + mov bh,1[esi] + or bl,bh + jz failb + elseifidni ,<3> + mov bl,[esi] + mov bh,1[esi] + or bl,bh + mov bh,2[esi] + or bl,bh + jz failb + endif ; + + endif ; + + mov dl,byte ptr zb.pz.currentpix+2 + mov bl,[ebp] + mov dh,byte ptr zb.pz.currentpix+3 + mov bh,1[ebp] + sub bl,dl + sbb bh,dh + jb loopb ; Skip if pixel failed z test + + mov [ebp],dl ; Store low byte of z + + if LIGHT + xor ecx,ecx + endif ; + + mov 1[ebp],dh ; Store high byte of z + + if LIGHT + mov ch,byte ptr zb.pi.currentpix+2 + mov edx,zb.shade_table + endif ; + + ifidni ,<1> + + mov cl,[esi] ; Get texel + + if LIGHT + mov cl,[ecx+edx] ; Light texel + endif + + if BUMP + and ecx,0ffh + mov edx,noffset + mov dl,[esi+edx] + and edx,0ffh + add edx,zb.lighting_table ; Calculate light level from normal + mov ch,[edx] + mov edx,zb.shade_table + mov cl,[edx+ecx] ; Light texel + endif + + mov [edi],cl + + elseifidni ,<2> + + mov cl,[esi] + mov [edi],cl ; Store texel + mov cl,1[esi] + mov 1[edi],cl ; Store texel + + elseifidni ,<3> + + mov ecx,[esi] + mov 2[edi],cl ; Store texel + mov 1[edi],ch ; Store texel + ror ecx,16 + mov [edi],cl ; Store texel + + elseifidni ,<4> + + mov ecx,[esi] + mov [edi],ecx ; Store texel + + endif ; + +failb: + jmp loopb + +next: + ; Per scan line updates + + assume eax:ptr scan_edge + mov eax,zb.awsl.edge + + mov ebx,[eax].f + mov ecx,[eax].d_f + add ebx,ecx ; edge->f += edge->d_f + mov [eax].f,ebx + mov ecx,[eax].d_i + mov ebx,zb.awsl._end + + ifidni ,<1> + adc ebx,ecx ; zb.awsl._end += edge->d_i+carry + elseifidni ,<2> + adc ecx,0 + shl ecx,1 + add ebx,ecx + elseifidni ,<3> + adc ecx,0 + lea ecx,[ecx+2*ecx] + add ebx,ecx ; zb.awsl._end += 3*(edge->d_i+carry) + elseifidni ,<3> + adc ecx,0 + shl ecx,2 + add ebx,ecx + endif ; + + mov zb.awsl._end,ebx + + mov ebx,zb.main.f + mov ecx,zb.main.d_f + add ebx,ecx + mov zb.main.f,ebx + mov ebx,zb.awsl.start + mov ecx,zb.main.d_i + mov esi,zb.awsl.zstart + jnc noscarry + + ; if (carry) ... + + adc ecx,0 + lea esi,[esi+2*ecx] + + ifidni ,<1> + add ebx,ecx + elseifidni ,<2> + lea ebx,[ebx+2*ecx] + elseifidni ,<3> + lea ecx,[ecx+2*ecx] + add ebx,ecx + elseifidni ,<4> + lea ebx,[ebx+4*ecx] + endif + + mov zb.awsl.start,ebx + mov zb.awsl.zstart,esi + + scan_inc carry,LIGHT,BPP + + jmp cont + + ; ... else ... +noscarry: + + lea esi,[esi+2*ecx] + + ifidni ,<1> + add ebx,ecx + elseifidni ,<2> + lea ebx,[ebx+2*ecx] + elseifidni ,<3> + lea ecx,[ecx+2*ecx] + add ebx,ecx + elseifidni ,<4> + lea ebx,[ebx+4*ecx] + endif + + mov zb.awsl.start,ebx + mov zb.awsl.zstart,esi + + scan_inc nocarry,LIGHT,BPP + + ; ... endif + +cont: + mov ebx,dword ptr zb.awsl.u_int_current + test bh,bh ; Test sign of low halfword + jl lab1 + + mov ecx,zb.awsl.texture_width + add ebx,ecx + mov dword ptr zb.awsl.u_int_current,ebx + mov ebx,zb.awsl.source_current + + ifidni ,<1> + add ebx,ecx + elseifidni ,<2> + lea ebx,[ebx+2*ecx] + elseifidni ,<3> + lea ecx,[ecx+2*ecx] + add ebx,ecx + elseifidni ,<4> + lea ebx,[ebx+4*ecx] + endif + + mov zb.awsl.source_current,ebx + +lab1: + mov ebx,zb.awsl.source_current + mov ecx,zb.awsl.texture_start + cmp ebx,ecx + jge outer + + mov ecx,zb.awsl.texture_size + add ebx,ecx + mov zb.awsl.source_current,ebx + + jmp outer + +exit: + ret + +fn endp + + endm + +TriangleRenderZ2 TrapezoidRenderPIZ2TA, 0, 1, 0 +TriangleRenderZ2 TrapezoidRenderPIZ2TA_RGB_555, 0, 2, 0 +TriangleRenderZ2 TrapezoidRenderPIZ2TA_RGB_888, 0, 3, 0 + +TriangleRenderZ2 TrapezoidRenderPIZ2TAN, 0, 1, 1 +TriangleRenderZ2 TrapezoidRenderPIZ2TAN_RGB_555, 0, 2, 1 +TriangleRenderZ2 TrapezoidRenderPIZ2TAN_RGB_888, 0, 3, 1 + +TriangleRenderZ2 TrapezoidRenderPIZ2TIA, 1, 1, 0 +TriangleRenderZ2 TrapezoidRenderPIZ2TIA_RGB_555, 1, 2, 0 +TriangleRenderZ2 TrapezoidRenderPIZ2TIA_RGB_888, 1, 3, 0 + + end \ No newline at end of file diff --git a/bren/ZB/t_piza.c b/bren/ZB/t_piza.c new file mode 100644 index 00000000..9402b09b --- /dev/null +++ b/bren/ZB/t_piza.c @@ -0,0 +1,82 @@ +#include +#include +#include "fwproto.h" +#include "zb.h" + +br_uint_32 noffset; + +static inline void __TriangleRenderZ2(br_boolean use_light, br_boolean use_bump, br_boolean use_transparency, + br_uint_32 bpp) +{ + // TODO(bjrkk): To be translated + +outer: + if (zb.awsl.edge->count == 0) + { + return; + } + zb.awsl.edge->count--; + + if (use_bump) + { + noffset = zb.bump_buffer - zb.texture_buffer; + } + + zb.pz.currentpix = zb.pz.current; + if (use_light) + { + zb.pi.currentpix = zb.pi.current; + } + + if (zb.awsl.start < zb.awsl.end) + { + } + else + { + } +} + +void BR_ASM_CALL TrapezoidRenderPIZ2TA() +{ + __TriangleRenderZ2(BR_FALSE, BR_FALSE, BR_TRUE, 1); +} + +void BR_ASM_CALL TrapezoidRenderPIZ2TA_RGB_555() +{ + __TriangleRenderZ2(BR_FALSE, BR_FALSE, BR_TRUE, 2); +} + +void BR_ASM_CALL TrapezoidRenderPIZ2TA_RGB_888() +{ + __TriangleRenderZ2(BR_FALSE, BR_FALSE, BR_TRUE, 3); +} + +void BR_ASM_CALL TrapezoidRenderPIZ2TAN() +{ + __TriangleRenderZ2(BR_FALSE, BR_TRUE, BR_TRUE, 1); +} + +void BR_ASM_CALL TrapezoidRenderPIZ2TAN_RGB_555() +{ + __TriangleRenderZ2(BR_FALSE, BR_TRUE, BR_TRUE, 2); +} + +void BR_ASM_CALL TrapezoidRenderPIZ2TAN_RGB_888() +{ + __TriangleRenderZ2(BR_FALSE, BR_TRUE, BR_TRUE, 3); +} + +void BR_ASM_CALL TrapezoidRenderPIZ2TIA() +{ + __TriangleRenderZ2(BR_TRUE, BR_FALSE, BR_TRUE, 1); +} + +void BR_ASM_CALL TrapezoidRenderPIZ2TIA_RGB_555() +{ + __TriangleRenderZ2(BR_TRUE, BR_FALSE, BR_TRUE, 2); +} + +void BR_ASM_CALL TrapezoidRenderPIZ2TIA_RGB_888() +{ + __TriangleRenderZ2(BR_TRUE, BR_FALSE, BR_TRUE, 3); +} \ No newline at end of file diff --git a/bren/ZB/ti8_piz.c b/bren/ZB/ti8_piz.c new file mode 100644 index 00000000..0356446c --- /dev/null +++ b/bren/ZB/ti8_piz.c @@ -0,0 +1,664 @@ +#include +#include +#include "fwproto.h" +#include "zb.h" + +extern int BR_ASM_CALL SafeFixedMac2Div(int, int, int, int, int); + +#define swap(type, a, b) \ + { \ + type _; \ + _ = a; \ + a = b; \ + b = _; \ + } + +static br_uint_32 temp_b = 0; +static br_uint_32 temp_g = 0; +static br_uint_32 temp_r = 0; +static br_uint_32 temp_colour = 0; + +static br_uint_32 p0_offset_x = 0; +static br_uint_32 p0_offset_y = 0; + +static br_uint_32 temp_i = 0; +static br_uint_32 temp_u = 0; +static br_uint_32 temp_v = 0; + +static screen_scalar vertex_0[2]; +static screen_scalar vertex_1[2]; +static screen_scalar vertex_2[2]; + +static br_int_32 g_divisor = 0; + +static inline void __TRAPEZOID_PIZ2(struct scan_edge *edge, br_boolean is_forward, br_fixed_ls *z_val, + br_int_32 *fb_index, br_uint_8 colour) +{ + br_int_32 endptr = edge->i; + + while (edge->count > 0) + { + br_int_32 fb_curr = *fb_index; + br_uint_32 z_curr = *z_val; + br_uint_16 *z_ptr = ((br_uint_16 *)zb.depth_buffer) + fb_curr; + + // pixel loop + if (is_forward) + { + while (fb_curr < endptr) + { + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + zb.colour_buffer[fb_curr] = colour; + } + z_curr += zb.pz.grad_x; + z_ptr++; + fb_curr++; + } + } + else + { + while (endptr < fb_curr) + { + z_curr -= zb.pz.grad_x; + z_ptr--; + fb_curr--; + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + zb.colour_buffer[fb_curr] = colour; + } + } + } + + br_uint_32 carry; + + edge->f += edge->d_f; + carry = (br_uint_32)edge->f < (br_uint_32)edge->d_f; + endptr += edge->d_i + carry; + + zb.main.f += zb.main.d_f; + carry = (br_uint_32)zb.main.f < (br_uint_32)zb.main.d_f; + *fb_index += zb.main.d_i + carry; + if (carry != 0) + { + *z_val += zb.pz.d_carry; + } + else + { + *z_val += zb.pz.d_nocarry; + } + + edge->count--; + } +} + +static inline void __TRAPEZOID_PIZ2I(struct scan_edge *edge, br_boolean is_forward, br_fixed_ls *z_val, + br_int_32 *fb_index) +{ + br_int_32 endptr = edge->i; + + while (edge->count > 0) + { + br_int_32 fb_curr = *fb_index; + br_uint_32 z_curr = *z_val; + br_uint_32 i_curr = zb.pi.current; + br_uint_16 *z_ptr = ((br_uint_16 *)zb.depth_buffer) + fb_curr; + + // pixel loop + if (is_forward) + { + while (fb_curr < endptr) + { + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + zb.colour_buffer[fb_curr] = BrFixedToInt(i_curr); + } + z_curr += zb.pz.grad_x; + i_curr += zb.pi.grad_x; + z_ptr++; + fb_curr++; + } + } + else + { + while (endptr < fb_curr) + { + z_curr -= zb.pz.grad_x; + i_curr -= zb.pi.grad_x; + z_ptr--; + fb_curr--; + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + zb.colour_buffer[fb_curr] = BrFixedToInt(i_curr); + } + } + } + + br_uint_32 carry; + + edge->f += edge->d_f; + carry = (br_uint_32)edge->f < (br_uint_32)edge->d_f; + endptr += edge->d_i + carry; + + zb.main.f += zb.main.d_f; + carry = (br_uint_32)zb.main.f < (br_uint_32)zb.main.d_f; + *fb_index += zb.main.d_i + carry; + if (carry != 0) + { + *z_val += zb.pz.d_carry; + zb.pi.current += zb.pi.d_carry; + } + else + { + *z_val += zb.pz.d_nocarry; + zb.pi.current += zb.pi.d_nocarry; + } + + edge->count--; + } +} + +static inline void __TRAPEZOID_PIZ2T(struct scan_edge *edge, br_boolean is_forward, br_fixed_ls *z_val, + br_int_32 *fb_index) +{ + br_int_32 endptr = edge->i; + + while (edge->count > 0) + { + br_int_32 fb_curr = *fb_index; + br_uint_32 z_curr = *z_val; + br_uint_16 *z_ptr = ((br_uint_16 *)zb.depth_buffer) + fb_curr; + + temp_u = zb.pu.current; + temp_v = zb.pv.current; + + // pixel loop + if (is_forward) + { + while (fb_curr < endptr) + { + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + zb.colour_buffer[fb_curr] = *zb.texture_buffer; + } + + temp_u += zb.pu.grad_x; + temp_v += zb.pv.grad_x; + z_curr += zb.pz.grad_x; + z_ptr++; + fb_curr++; + } + } + else + { + while (endptr < fb_curr) + { + temp_u -= zb.pu.grad_x; + temp_v -= zb.pv.grad_x; + z_curr -= zb.pz.grad_x; + z_ptr--; + fb_curr--; + + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + zb.colour_buffer[fb_curr] = *zb.texture_buffer; + } + } + } + + br_uint_32 carry; + + edge->f += edge->d_f; + carry = (br_uint_32)edge->f < (br_uint_32)edge->d_f; + endptr += edge->d_i + carry; + + zb.main.f += zb.main.d_f; + carry = (br_uint_32)zb.main.f < (br_uint_32)zb.main.d_f; + *fb_index += zb.main.d_i + carry; + if (carry != 0) + { + *z_val += zb.pz.d_carry; + zb.pu.current += zb.pu.d_carry; + zb.pv.current += zb.pv.d_carry; + } + else + { + *z_val += zb.pz.d_nocarry; + zb.pu.current += zb.pu.d_nocarry; + zb.pv.current += zb.pv.d_nocarry; + } + + edge->count--; + } +} + +static inline void __TRAPEZOID_PIZ2TI(struct scan_edge *edge, br_boolean is_forward, br_fixed_ls *z_val, + br_int_32 *fb_index) +{ + br_int_32 endptr = edge->i; + + while (edge->count > 0) + { + br_int_32 fb_curr = *fb_index; + br_uint_32 z_curr = *z_val; + br_uint_16 *z_ptr = ((br_uint_16 *)zb.depth_buffer) + fb_curr; + + temp_u = zb.pu.current; + temp_v = zb.pv.current; + temp_i = zb.pi.current; + + // pixel loop + if (is_forward) + { + while (fb_curr < endptr) + { + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + } + z_curr += zb.pz.grad_x; + temp_u += zb.pu.grad_x; + temp_v += zb.pv.grad_x; + temp_i += zb.pi.grad_x; + z_ptr++; + fb_curr++; + } + } + else + { + while (endptr < fb_curr) + { + z_curr -= zb.pz.grad_x; + temp_u -= zb.pu.grad_x; + temp_v -= zb.pv.grad_x; + temp_i -= zb.pi.grad_x; + z_ptr--; + fb_curr--; + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + } + } + } + + br_uint_32 carry; + + edge->f += edge->d_f; + carry = (br_uint_32)edge->f < (br_uint_32)edge->d_f; + endptr += edge->d_i + carry; + + zb.main.f += zb.main.d_f; + carry = (br_uint_32)zb.main.f < (br_uint_32)zb.main.d_f; + *fb_index += zb.main.d_i + carry; + if (carry != 0) + { + *z_val += zb.pz.d_carry; + zb.pu.current += zb.pu.d_carry; + zb.pv.current += zb.pv.d_carry; + zb.pi.current += zb.pi.d_carry; + } + else + { + *z_val += zb.pz.d_nocarry; + zb.pu.current += zb.pu.d_nocarry; + zb.pv.current += zb.pv.d_nocarry; + zb.pi.current += zb.pi.d_nocarry; + } + + edge->count--; + } +} + +static inline void __SETUP_PI(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, struct temp_vertex_fixed *v2) +{ + // NOTE(???): Should really do this at projection time + vertex_0[0] = v0->v[0] >> 16; + vertex_1[0] = v1->v[0] >> 16; + vertex_2[0] = v2->v[0] >> 16; + + vertex_0[1] = v0->v[1] >> 16; + vertex_1[1] = v1->v[1] >> 16; + vertex_2[1] = v2->v[1] >> 16; + + if (vertex_0[1] == vertex_2[1]) + { + return; + } + + zb.top.x = vertex_1[0] - vertex_0[0]; + zb.top.y = vertex_1[1] - vertex_0[1]; + zb.top.count = zb.top.y; + if (zb.top.count != 0) + { + zb.top.grad = BrFixedDiv(zb.top.x, zb.top.y); + zb.top.d_f = (zb.top.grad << 16); + zb.top.d_i = (zb.top.grad >> 16) + zb.row_width; + } + + // don't need to save deltas + zb.bot.count = vertex_2[1] - vertex_1[1]; + if (zb.bot.count != 0) + { + zb.bot.grad = BrFixedDiv(vertex_2[0] - vertex_1[0], vertex_2[1] - vertex_1[1]); + zb.bot.d_f = (zb.bot.grad << 16); + zb.bot.d_i = (zb.bot.grad >> 16) + zb.row_width; + } + + zb.main.x = vertex_2[0] - vertex_0[0]; + zb.main.y = vertex_2[1] - vertex_0[1]; + zb.main.grad = BrFixedDiv(zb.main.x, zb.main.y); + zb.main.d_f = (zb.main.grad << 16); + zb.main.d_i = (zb.main.grad >> 16) + zb.row_width; + + zb.main.f = 0x80000000; + zb.main.i = (vertex_0[1] * zb.row_width) + vertex_0[0]; + zb.top.f = 0x80000000; + zb.top.i = (vertex_0[1] * zb.row_width) + vertex_0[0]; + zb.bot.f = 0x80000000; + zb.bot.i = (vertex_1[1] * zb.row_width) + vertex_1[0]; + + g_divisor = zb.top.x * zb.main.y - zb.main.x * zb.top.y; +} + +static inline void __PARAM_PI_DIRN(screen_scalar a, screen_scalar b, screen_scalar c, struct scan_parameter *param) +{ + param->grad_x = SafeFixedMac2Div(b - a, zb.main.y, c - a, -zb.top.y, g_divisor); + + param->grad_y = SafeFixedMac2Div(c - a, zb.top.x, b - a, -zb.main.x, g_divisor); + + param->current = a + param->grad_x / 2; + param->d_nocarry = BrFixedToInt(zb.main.grad) * param->grad_x + param->grad_y; + param->d_carry = param->d_nocarry + param->grad_x; +} + +void BR_ASM_CALL RawTriangle_PIZ2(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + struct temp_vertex_fixed *a, *b, *c; + a = v0; + b = v1; + c = v2; + if (v0->v[1] > v1->v[1]) + { + if (v1->v[1] > v2->v[1]) + { + a = v2; + c = v0; + } + else if (v0->v[1] > v2->v[1]) + { + a = v1; + b = v2; + c = v0; + } + else + { + a = v1; + b = v0; + } + } + else if (v1->v[1] > v2->v[1]) + { + if (v0->v[1] > v2->v[1]) + { + a = v2; + b = v0; + c = v1; + } + else + { + b = v2; + c = v1; + } + } + + __SETUP_PI(a, b, c); + + if (g_divisor == 0) + { + return; + } + + __PARAM_PI_DIRN(a->v[2], b->v[2], c->v[2], &zb.pz); + + br_boolean is_forward = g_divisor >= 0; + if (!is_forward) + { + g_divisor = -g_divisor; + } + + temp_r = zb.pr.current; + temp_g = zb.pg.current; + temp_b = zb.pb.current; + + br_fixed_ls z_val = zb.pz.current; + br_int_32 fb_index = zb.main.i; + + __TRAPEZOID_PIZ2(&zb.top, is_forward, &z_val, &fb_index, zb.pi.current >> 16); + __TRAPEZOID_PIZ2(&zb.bot, is_forward, &z_val, &fb_index, zb.pi.current >> 16); +} + +void BR_ASM_CALL RawTriangle_PIZ2I(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + struct temp_vertex_fixed *a, *b, *c; + a = v0; + b = v1; + c = v2; + if (v0->v[1] > v1->v[1]) + { + if (v1->v[1] > v2->v[1]) + { + a = v2; + c = v0; + } + else if (v0->v[1] > v2->v[1]) + { + a = v1; + b = v2; + c = v0; + } + else + { + a = v1; + b = v0; + } + } + else if (v1->v[1] > v2->v[1]) + { + if (v0->v[1] > v2->v[1]) + { + a = v2; + b = v0; + c = v1; + } + else + { + b = v2; + c = v1; + } + } + + __SETUP_PI(a, b, c); + + if (g_divisor == 0) + { + return; + } + + __PARAM_PI_DIRN(a->v[2], b->v[2], c->v[2], &zb.pz); + __PARAM_PI_DIRN(a->comp[C_I], b->comp[C_I], c->comp[C_I], &zb.pi); + + br_boolean is_forward = g_divisor >= 0; + if (!is_forward) + { + g_divisor = -g_divisor; + } + + br_fixed_ls z_val = zb.pz.current; + br_int_32 fb_index = zb.main.i; + + __TRAPEZOID_PIZ2I(&zb.top, is_forward, &z_val, &fb_index); + __TRAPEZOID_PIZ2I(&zb.bot, is_forward, &z_val, &fb_index); +} + +void BR_ASM_CALL RawTriangle_PIZ2T(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + struct temp_vertex_fixed *a, *b, *c; + a = v0; + b = v1; + c = v2; + if (v0->v[1] > v1->v[1]) + { + if (v1->v[1] > v2->v[1]) + { + a = v2; + c = v0; + } + else if (v0->v[1] > v2->v[1]) + { + a = v1; + b = v2; + c = v0; + } + else + { + a = v1; + b = v0; + } + } + else if (v1->v[1] > v2->v[1]) + { + if (v0->v[1] > v2->v[1]) + { + a = v2; + b = v0; + c = v1; + } + else + { + b = v2; + c = v1; + } + } + + __SETUP_PI(a, b, c); + + if (g_divisor == 0) + { + return; + } + + __PARAM_PI_DIRN(a->v[2], b->v[2], c->v[2], &zb.pz); + __PARAM_PI_DIRN(a->comp[C_U], b->comp[C_U], c->comp[C_U], &zb.pu); + __PARAM_PI_DIRN(a->comp[C_V], b->comp[C_V], c->comp[C_V], &zb.pv); + + br_boolean is_forward = g_divisor >= 0; + if (!is_forward) + { + g_divisor = -g_divisor; + } + + br_fixed_ls z_val = zb.pz.current; + br_int_32 fb_index = zb.main.i; + + __TRAPEZOID_PIZ2T(&zb.top, is_forward, &z_val, &fb_index); + __TRAPEZOID_PIZ2T(&zb.bot, is_forward, &z_val, &fb_index); +} + +void BR_ASM_CALL RawTriangle_PIZ2TI(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + struct temp_vertex_fixed *a, *b, *c; + a = v0; + b = v1; + c = v2; + if (v0->v[1] > v1->v[1]) + { + if (v1->v[1] > v2->v[1]) + { + a = v2; + c = v0; + } + else if (v0->v[1] > v2->v[1]) + { + a = v1; + b = v2; + c = v0; + } + else + { + a = v1; + b = v0; + } + } + else if (v1->v[1] > v2->v[1]) + { + if (v0->v[1] > v2->v[1]) + { + a = v2; + b = v0; + c = v1; + } + else + { + b = v2; + c = v1; + } + } + + __SETUP_PI(a, b, c); + + if (g_divisor == 0) + { + return; + } + + __PARAM_PI_DIRN(a->v[2], b->v[2], c->v[2], &zb.pz); + __PARAM_PI_DIRN(a->comp[C_I], b->comp[C_I], c->comp[C_I], &zb.pi); + __PARAM_PI_DIRN(a->comp[C_U], b->comp[C_U], c->comp[C_U], &zb.pu); + __PARAM_PI_DIRN(a->comp[C_V], b->comp[C_V], c->comp[C_V], &zb.pv); + + br_boolean is_forward = g_divisor >= 0; + if (!is_forward) + { + g_divisor = -g_divisor; + } + + br_fixed_ls z_val = zb.pz.current; + br_int_32 fb_index = zb.main.i; + + __TRAPEZOID_PIZ2TI(&zb.top, is_forward, &z_val, &fb_index); + __TRAPEZOID_PIZ2TI(&zb.bot, is_forward, &z_val, &fb_index); +} + +void BR_ASM_CALL TriangleRenderPIZ2(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + RawTriangle_PIZ2(v0, v1, v2); +} + +void BR_ASM_CALL TriangleRenderPIZ2I(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + RawTriangle_PIZ2I(v0, v1, v2); +} + +void BR_ASM_CALL TriangleRenderPIZ2T(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + RawTriangle_PIZ2T(v0, v1, v2); +} + +void BR_ASM_CALL TriangleRenderPIZ2TI(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + RawTriangle_PIZ2TI(v0, v1, v2); +} \ No newline at end of file diff --git a/bren/ZB/ti8_pizp.asm b/bren/ZB/ti8_pizp.asm new file mode 100644 index 00000000..5324242b --- /dev/null +++ b/bren/ZB/ti8_pizp.asm @@ -0,0 +1,1302 @@ +;; Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. +;; +;; $Id: ti8_pizp.asm 1.1 1995/08/31 16:52:50 sam Exp $ +;; $Locker: $ +;; +;; Scanline loop for perpsective correct texture mapping +;; + .386p + .model c,flat + include zb.inc + .data + +z dd ? +i dd ? +du_numerator dd ? +dv_numerator dd ? +u_numerator dd ? +v_numerator dd ? +zdest dd ? +dest dd ? +dest2 dd ? +source dd ? +denominator dd ? +dz dd ? + + align 4 + + .code + + +; Smoothly lit perspective texture mapping + +ScanLinePIZ2TIP macro name,pre,incu,decu,incv,decv,post1,post2 +name proc + + pushad + + ; Copy various parameters into registers + + mov esi,zb.pu.current + mov ebx,zb.pv.current + mov eax,zb.pu.grad_x + mov edi,zb.pv.grad_x + + mov dv_numerator,edi + mov ecx,zb.pi.current + mov edx,zb.pq.current + mov v_numerator,ebx + mov denominator,edx + mov i,ecx + + + mov ecx,zb.pz.current + mov z,ecx + mov ecx,zb.tsl.zstart + mov zdest,ecx + + mov ebp,zb.tsl._end + mov du_numerator,eax + + mov edi,zb.tsl.start + mov eax,zb.tsl.source + + cmp edi,ebp + mov ebp,zdest + ja rtol ; Jump if right to left + + ; Left to right scan + + mov dest,edi +next_pixelb: + jae L50 ; Jump if end of scan + + mov source,eax ; Free up eax + + ; Texel fetch and store section + + ; z buffer test + + mov dl,[ebp] + mov ebx,z ; Get new z value + mov dh,1[ebp] + ror ebx,16 + cmp bx,dx + ja L34 ; Jump if new pixel behind old + + mov edx,zb.texture_buffer + xor ecx,ecx + + ;; Get texel and test for transparency + + mov cl,[eax+edx] +if 1 + test cl,cl + jz L34 +endif + + ;; Store texel and z + + mov eax,zb.shade_table + mov ch,byte ptr i+2 + mov [ebp],bx ; Store new z + mov cl,[ecx+eax] ; Get lit texel + mov [edi],cl ; Store texel + +L34: + ror ebx,16 + mov edx,zb.pz.grad_x ; Get z step + add ebp,2 ; zdest++ + add ebx,edx ; z += dz + mov eax,zb.pi.grad_x + mov edx,i ; Get lighting + add edx,eax ; i += di + mov i,edx + +L34a: + inc edi +if 1 + cmp edi,zb.tsl._end + jae L50 +endif + mov edx,denominator + mov dest,edi + mov edi,dv_numerator + mov z,ebx + mov zdest,ebp + mov ecx,zb.pq.grad_x + mov ebp,du_numerator + mov ebx,v_numerator + mov eax,source ; Restore eax + + ; Perspective calculation section + + pre + sub esi,ebp + add edx,ecx + cmp esi,edx + jge incuf ; Jump if u not too large + +L36: + test esi,esi + jl decuf +L37: + sub ebx,edi + jl decvf + cmp ebx,edx + jge incvf ; Jump if v not too small +L40: + post1 + post2 + mov denominator,edx + mov v_numerator,ebx + mov edi,dest + cmp edi,zb.tsl._end + mov ebp,zdest + jmp next_pixelb + + ; Right to left +rtol: + mov dest,edi +next_pixelbr: + jbe L50 ; Jump if end of scan + + mov source,eax ; Free up eax + + ; z buffer test + + mov dl,[ebp] + mov ebx,z ; Get new z value + mov dh,1[ebp] + ror ebx,16 + cmp bx,dx + ja R34 ; Jump if new pixel behind old + + mov edx,zb.texture_buffer + xor ecx,ecx + + ;; Get texel and test for transparency + + mov cl,[edx+eax] +if 1 + test cl,cl ; Transparent? + jz R34 +endif + + ;; Store texel and z + + mov eax,zb.shade_table + mov ch,byte ptr i+2 + mov [ebp],bx ; Store new z + mov cl,[ecx+eax] ; Get lit texel + mov [edi],cl ; Store texel +R34: + sub ebp,2 ; zdest++ + + ;; Update lighting and z + + ror ebx,16 + mov edx,zb.pz.grad_x ; Get z step + mov eax,zb.pi.grad_x + sub ebx,edx ; z += dz + mov edx,i ; Get lighting + sub edx,eax ; i += di + mov i,edx + +R34a: + dec edi +if 1 + cmp edi,zb.tsl._end + jbe L50 +endif + mov edx,denominator + mov dest,edi + mov edi,dv_numerator + mov z,ebx + mov zdest,ebp + mov ecx,zb.pq.grad_x + mov ebp,du_numerator + mov ebx,v_numerator + mov eax,source ; Restore eax + + ; Core perspective calculations + + pre + add esi,ebp + sub edx,ecx + cmp esi,edx + jge incub ; Jump if u not too large + +R36: + test esi,esi + jl decub +R37: + add ebx,edi + jl decvb + cmp ebx,edx + jge incvb ; Jump if v not too small +R40: + post1 + post2 + mov denominator,edx + mov v_numerator,ebx + mov edi,dest + cmp edi,zb.tsl._end + mov ebp,zdest + jmp next_pixelbr + +L50: + popad + ret + +decuf: + mov ebp,du_numerator +decufloop: + decu + sub ebp,zb.pq.grad_x + add esi,edx + jnc decufloop + + mov du_numerator,ebp + jmp L37 + +incuf: + mov ecx,zb.pq.grad_x + mov ebp,du_numerator + sub esi,edx + +incufloop: + incu ; Increment u + add ebp,ecx + sub esi,edx + jge incufloop + add esi,edx + + mov du_numerator,ebp + jmp L37 + +decvf: + mov ebp,zb.pq.grad_x +decvfloop: + decv ; Decrement v + sub edi,ebp + add ebx,edx + jnc decvfloop + mov dv_numerator,edi + jmp L40 + +incvf: + mov ecx,zb.pq.grad_x + sub ebx,edx + +incvfloop: + incv ; Increment v + add edi,ecx + sub ebx,edx + jge incvfloop + + add ebx,edx + mov dv_numerator,edi + jmp L40 + + ; Back +decub: + mov ebp,du_numerator +decubloop: + decu + sub ebp,zb.pq.grad_x + add esi,edx + jnc decubloop + + mov du_numerator,ebp + jmp R37 + +incub: + mov ecx,zb.pq.grad_x + mov ebp,du_numerator + sub esi,edx + +incubloop: + incu ; Increment u + add ebp,ecx + sub esi,edx + jge incubloop + add esi,edx + + mov du_numerator,ebp + jmp R37 + +decvb: + mov ebp,zb.pq.grad_x +decvbloop: + decv ; Decrement v + sub edi,ebp + add ebx,edx + jnc decvbloop + mov dv_numerator,edi + jmp R40 + +incvb: + mov ecx,zb.pq.grad_x + sub ebx,edx + +incvbloop: + incv ; Increment v + add edi,ecx + sub ebx,edx + jge incvbloop + + add ebx,edx + mov dv_numerator,edi + jmp R40 + +name endp + + endm + +; Unlit version + +ScanLinePIZ2TP macro name,pre,incu,decu,incv,decv,post1,post2 +name proc + + pushad + + mov esi,zb.pu.current + mov ebx,zb.pv.current + mov eax,zb.pu.grad_x + mov edi,zb.pv.grad_x + mov edx,zb.pq.current + mov ecx,zb.pz.current + mov ebp,zb.tsl._end + + mov dv_numerator,edi + mov denominator,edx + mov v_numerator,ebx + mov z,ecx + mov du_numerator,eax + + mov ecx,zb.tsl.zstart + mov zdest,ecx + + mov edi,zb.tsl.start + mov eax,zb.tsl.source + + cmp edi,ebp + mov ebp,zdest + ja rtol ; Jump if right to left + + ; Left to right scan + + mov dest,edi +L33: + jae L50 ; Jump if end of scan + + mov source,eax ; Free up eax + mov ebx,z ; Get new z value + mov dx,[ebp] + ror ebx,16 + cmp bx,dx + ja L34 ; Jump if new pixel behind old + + mov edx,zb.texture_buffer + add eax,edx + + ;; Get and test texel for transparency + + mov cl,[eax] +if 1 + test cl,cl ; Transparent? + jz L34 +endif + + ;; Store texel and z value + + mov [edi],cl ; Store texel + mov [ebp],bx ; Store new z +L34: + add ebp,2 ; zdest++ + ror ebx,16 + mov ecx,zb.pz.grad_x + add ebx,ecx +L34a: + inc edi + cmp edi,zb.tsl._end + jae L50 + mov edx,denominator + mov dest,edi + mov edi,dv_numerator + mov z,ebx + mov zdest,ebp + mov ecx,zb.pq.grad_x + mov ebp,du_numerator + mov ebx,v_numerator + mov eax,source ; Restore eax + pre + sub esi,ebp + add edx,ecx + cmp esi,edx + jl L36 + + mov ecx,zb.pq.grad_x + mov ebp,du_numerator + sub esi,edx +incufloop: + incu + add ebp,ecx + sub esi,edx + jge incufloop + add esi,edx + + mov du_numerator,ebp + jmp L37 + +L36: test esi,esi + jge L37 + + mov ebp,du_numerator + mov ecx,zb.pq.grad_x +decufloop: + decu + sub ebp,ecx + add esi,edx + jnc decufloop + + mov du_numerator,ebp + +L37: + sub ebx,edi + jge skipdecvf + + mov ebp,zb.pq.grad_x +decvfloop: + decv + sub edi,ebp + add ebx,edx + jnc decvfloop + mov dv_numerator,edi + jmp L40 +skipdecvf: + cmp ebx,edx + jl L40 ; Jump if v not too small + + mov ecx,zb.pq.grad_x + sub ebx,edx + +incvfloop: + incv + add edi,ecx + sub ebx,edx + jge incvfloop + + add ebx,edx + mov dv_numerator,edi +L40: + post1 + post2 + mov denominator,edx + mov v_numerator,ebx + mov edi,dest + cmp edi,zb.tsl._end + mov ebp,zdest + jmp L33 + +rtol: + mov dest,edi +R33: + jbe L50 ; Jump if end of scan + + mov source,eax ; Free up eax + mov ebx,z ; Get new z value + mov dx,[ebp] + ror ebx,16 + cmp bx,dx + ja R34 ; Jump if new pixel behind old + + mov edx,zb.texture_buffer + add eax,edx + + ;; Get texel and test for transparency + + mov cl,[eax] +if 1 + test cl,cl ; Transparent? + jz R34 +endif + + ;; Store texel and z value + + mov [edi],cl ; Store texel + mov [ebp],bx ; Store new z + +R34: + ror ebx,16 + mov ecx,zb.pz.grad_x + sub ebp,2 + sub ebx,ecx +R34a: + dec edi + cmp edi,zb.tsl._end + jbe L50 + mov edx,denominator + mov dest,edi + mov edi,dv_numerator + mov z,ebx + mov zdest,ebp + mov ecx,zb.pq.grad_x + mov ebp,du_numerator + mov ebx,v_numerator + mov eax,source ; Restore eax + pre + add esi,ebp + sub edx,ecx + cmp esi,edx + jl R36 + + mov ecx,zb.pq.grad_x + mov ebp,du_numerator + sub esi,edx +incubloop: + incu + add ebp,ecx + sub esi,edx + jge incubloop + + add esi,edx + mov du_numerator,ebp + jmp R37 + +R36: test esi,esi + jge R37 + + mov ebp,du_numerator + mov ecx,zb.pq.grad_x +decubloop: + decu + sub ebp,ecx + add esi,edx + jnc decubloop + + mov du_numerator,ebp +R37: + add ebx,edi + jge skipdecvb + + mov ebp,zb.pq.grad_x +decvbloop: + decv + sub edi,ebp + add ebx,edx + jnc decvbloop + mov dv_numerator,edi + jmp R40 +skipdecvb: + cmp ebx,edx + jl R40 ; Jump if v not too small + + mov ecx,zb.pq.grad_x + sub ebx,edx + +incvbloop: + incv + add edi,ecx + sub ebx,edx + jge incvbloop + + add ebx,edx + mov dv_numerator,edi + +R40: + post1 + post2 + mov denominator,edx + mov v_numerator,ebx + mov edi,dest + cmp edi,zb.tsl._end + mov ebp,zdest + jmp R33 + +L50: + popad + ret + +name endp + endm + + +; a += b*frac/16 + +dither macro a,b,frac + + push b + + ifidni ,<0> + elseifidni ,<1> + sar b,4 + add a,b + elseifidni ,<2> + sar b,3 + add a,b + elseifidni ,<3> + sar b,3 + add a,b + sar b,1 + add a,b + elseifidni ,<4> + sar b,2 + add a,b + elseifidni ,<5> + sar b,2 + add a,b + sar b,2 + add a,b + elseifidni ,<6> + sar b,2 + add a,b + sar b,1 + add a,b + elseifidni ,<7> + sar b,2 + add a,b + sar b,1 + add a,b + sar b,1 + add a,b + elseifidni ,<8> + sar b,1 + add a,b + elseifidni ,<9> + sar b,1 + add a,b + sar b,3 + add a,b + elseifidni ,<10> + sar b,1 + add a,b + sar b,2 + add a,b + elseifidni ,<11> + sar b,1 + add a,b + sar b,2 + add a,b + sar b,1 + add a,b + elseifidni ,<12> + sar b,1 + add a,b + sar b,1 + add a,b + elseifidni ,<13> + sar b,1 + add a,b + sar b,1 + add a,b + sar b,2 + add a,b + elseifidni ,<14> + sar b,1 + add a,b + sar b,1 + add a,b + sar b,1 + add a,b + elseifidni ,<15> + sar b,1 + add a,b + sar b,1 + add a,b + sar b,1 + add a,b + sar b,1 + add a,b + elseifidni ,<16> + add a,b + elseifidni ,<-1> + sar b,4 + sub a,b + elseifidni ,<-2> + sar b,3 + sub a,b + elseifidni ,<-3> + sar b,3 + sub a,b + sar b,1 + sub a,b + elseifidni ,<-4> + sar b,2 + sub a,b + elseifidni ,<-5> + sar b,2 + sub a,b + sar b,2 + sub a,b + elseifidni ,<-6> + sar b,2 + sub a,b + sar b,1 + sub a,b + elseifidni ,<-7> + sar b,2 + sub a,b + sar b,1 + sub a,b + sar b,1 + sub a,b + elseifidni ,<-8> + sar b,1 + sub a,b + elseifidni ,<-9> + sar b,1 + sub a,b + sar b,3 + sub a,b + elseifidni ,<-10> + sar b,1 + sub a,b + sar b,2 + sub a,b + elseifidni ,<-11> + sar b,1 + sub a,b + sar b,2 + sub a,b + sar b,1 + sub a,b + elseifidni ,<-12> + sar b,1 + sub a,b + sar b,1 + sub a,b + elseifidni ,<-13> + sar b,1 + sub a,b + sar b,1 + sub a,b + sar b,2 + sub a,b + elseifidni ,<-14> + sar b,1 + sub a,b + sar b,1 + sub a,b + sar b,1 + sub a,b + elseifidni ,<-15> + sar b,1 + sub a,b + sar b,1 + sub a,b + sar b,1 + sub a,b + sar b,1 + sub a,b + endif + + pop b + + endm + +; Dithered perspective + +ScanLinePIZ2TPDn macro name,pre,incu,decu,incv,decv,post1,post2,\ + d0,d1,d2,d3 +name proc + + pushad + + mov esi,zb.pu.current + mov ebx,zb.pv.current + mov eax,zb.pu.grad_x + mov edi,zb.pv.grad_x + mov edx,zb.pq.current + + mov v_numerator,ebx + mov du_numerator,eax + mov dv_numerator,edi + mov denominator,edx + + mov ecx,zb.pz.current + mov edx,zb.tsl.zstart + + mov z,ecx + mov zdest,edx + + mov eax,zb.tsl.source + mov edi,zb.tsl.start + mov ebp,zb.tsl._end + + mov source,eax + mov dest,edi + + cmp edi,ebp + je L50 + ja rtol ; Jump if right to left + + ; Left to right scan + + and edi,3 + jmp table_f_&name&[edi*4] + + .data +table_f_&name& label ptr dword + dd init_forward0 + dd init_forward1 + dd init_forward2 + dd init_forward3 + .code + + for count,<0,1,2,3> +init_forward&count&: + mov edx,denominator + mov ebx,v_numerator + + if 1 ; Dithering? + +; Initialise forward dither +; For dithering need esi += edx*fraction +; and ebx += edx*fraction + + ifidni ,<0> + dither esi,edx,d0 + dither ebx,edx,d0 + elseifidni ,<1> + dither esi,edx,d1 + dither ebx,edx,d1 + elseifidni ,<2> + dither esi,edx,d2 + dither ebx,edx,d2 + elseifidni ,<3> + dither esi,edx,d3 + dither ebx,edx,d3 + endif + + endif + + jmp forward&count& + endm + +L33: + for count,<0,1,2,3> + local transp2,L34,L34a,L36,L37 + local skipdecvf,L40 + + mov edx,denominator + mov ebx,v_numerator + +forward&count&: + mov ecx,zb.pq.grad_x + mov ebp,du_numerator + mov edi,dv_numerator + mov eax,source + + pre + cmp esi,edx + jl L36 + + sub esi,edx ; u_numerator -= denominator +@@: + incu + add ebp,ecx ; du_numerator += d_denominator + sub esi,edx ; u_numerator -= denominator + jge @B + + add esi,edx ; u_numerator += denominator + + mov du_numerator,ebp + jmp L37 + +L36: test esi,esi + jge L37 + + mov ebp,du_numerator +@@: + decu + sub ebp,ecx ; du_numerator -= d_denominator + add esi,edx ; u_numerator -= denominator + jnc @B + + mov du_numerator,ebp +L37: + test ebx,ebx ; test v_numerator + jge skipdecvf + +@@: + decv + sub edi,ecx ; dv_numerator -= d_denominator + add ebx,edx ; v_numerator -= denominator + jnc @B + + mov dv_numerator,edi + jmp L40 +skipdecvf: + cmp ebx,edx ; Compare v_numerator and denominator + jl L40 ; Jump if proper fraction + + sub ebx,edx + +@@: + incv + add edi,ecx + sub ebx,edx + jge @B + + add ebx,edx + mov dv_numerator,edi +L40: + post1 + post2 + +; U,V and W increments + + sub esi,ebp ; u_numerator -= du_numerator + sub ebx,edi ; v_numerator -= dv_numerator + add edx,ecx ; demominator += d_denominator + + if 1 ; Dithering? + +; Dither forwards +; For dithering need esi (u_numerator) += edx*fraction +; and ebx (v_numerator) += edx*fraction + + ifidni ,<0> + dither esi,edx,%d1-d0 + dither ebx,edx,%d1-d0 + elseifidni ,<1> + dither esi,edx,%d2-d1 + dither ebx,edx,%d2-d1 + elseifidni ,<2> + dither esi,edx,%d3-d2 + dither ebx,edx,%d3-d2 + elseifidni ,<3> + dither esi,edx,%d0-d3 + dither ebx,edx,%d0-d3 + endif + + endif + + mov denominator,edx + mov v_numerator,ebx + +; End of calcs + + mov edi,dest + mov ebp,zb.tsl._end + cmp edi,ebp + jae L50 + + mov ebp,zdest + mov source,eax ; Save source + mov ebx,z ; Get new z value + mov dx,[ebp] + ror ebx,16 + cmp bx,dx + ja @F ; Jump if new pixel behind old + + mov edx,zb.texture_buffer + add eax,edx + + ;; Fetch texel and test for transparency + + mov cl,[eax] +if 1 + test cl,cl ; Transparent? + jz @F +endif + + ;; Store texel and z value + + mov [edi],cl ; Store texel + mov [ebp],bx ; Store new z +@@: + add ebp,2 ; zdest++ + ror ebx,16 + mov ecx,zb.pz.grad_x + add ebx,ecx ; z += dz +L34a: + mov zdest,ebp + mov z,ebx + + inc edi + cmp edi,zb.tsl._end + jae L50 + mov dest,edi + + endm + + jmp L33 + + ; Right to left scan + +rtol: + and edi,3 + jmp table_b_&name&[edi*4] + + .data +table_b_&name& label ptr dword + dd init_backward0 + dd init_backward1 + dd init_backward2 + dd init_backward3 + .code + + for count,<0,1,2,3> +init_backward&count&: + mov edx,denominator + mov ebx,v_numerator + + if 1 ; Dithering? + +; Initialise backward dither +; For dithering need esi += edx*fraction +; and ebx += edx*fraction + + ifidni ,<0> + dither esi,edx,d0 + dither ebx,edx,d0 + elseifidni ,<1> + dither esi,edx,d1 + dither ebx,edx,d1 + elseifidni ,<2> + dither esi,edx,d2 + dither ebx,edx,d2 + elseifidni ,<3> + dither esi,edx,d3 + dither ebx,edx,d3 + endif + + endif + + jmp backward&count& + endm +R33: + for count,<3,2,1,0> + local R33,transp2r,R34,R34a + local R36,R37 + local skipdecvb,R40 + + mov edx,denominator + mov ebx,v_numerator + +backward&count&: + mov ecx,zb.pq.grad_x + mov ebp,du_numerator + mov edi,dv_numerator + mov eax,source + + pre + cmp esi,edx + jl R36 + + sub esi,edx ; u_numerator -= denominator +@@: + incu + add ebp,ecx + sub esi,edx + jge @B + + add esi,edx + + mov du_numerator,ebp + jmp R37 + +R36: test esi,esi + jge R37 + + mov ebp,du_numerator +@@: + decu + sub ebp,ecx ; du_numerator -= d_denominator + add esi,edx ; u_numerator -= denominator + jnc @B + + mov du_numerator,ebp +R37: + test ebx,ebx ; test v_numerator + jge skipdecvb + +@@: + decv + sub edi,ecx + add ebx,edx + jnc @B + + mov dv_numerator,edi + jmp R40 +skipdecvb: + cmp ebx,edx + jl R40 ; Jump if v not too small + + sub ebx,edx + +@@: + incv + add edi,ecx + sub ebx,edx + jge @B + + add ebx,edx + mov dv_numerator,edi + +R40: + post1 + post2 + +; U,V and W increments + + add esi,ebp ; u_numerator += du_numerator + add ebx,edi ; v_numerator += dv_numerator + sub edx,ecx ; demominator -= d_denominator + + if 1 ; Dithering? + +; Dither backwards +; For dithering need esi (u_numerator) += edx*fraction +; and ebx (v_numerator) += edx*fraction + + ifidni ,<0> + dither esi,edx,%d3-d0 + dither ebx,edx,%d3-d0 + elseifidni ,<1> + dither esi,edx,%d0-d1 + dither ebx,edx,%d0-d1 + elseifidni ,<2> + dither esi,edx,%d1-d2 + dither ebx,edx,%d1-d2 + elseifidni ,<3> + dither esi,edx,%d2-d3 + dither ebx,edx,%d2-d3 + endif + + endif + mov denominator,edx + mov v_numerator,ebx + +; End of calcs + + mov edi,dest + mov ebp,zb.tsl._end + cmp edi,ebp + jbe L50 + + mov ebp,zdest + mov source,eax ; Save source + mov ebx,z ; Get new z value + mov dx,[ebp] + ror ebx,16 + cmp bx,dx + ja @F ; Jump if new pixel behind old + + mov edx,zb.texture_buffer + add eax,edx + + ;; Fetch texel and text for transparency + + mov cl,[eax] +if 1 + test cl,cl ; Transparent? + jz @F +endif + + mov [ebp],bx ; Store new z + mov [edi],cl ; Store texel + +@@: + sub ebp,2 ; zdest++ + ror ebx,16 + mov ecx,zb.pz.grad_x + sub ebx,ecx +R34a: + mov zdest,ebp + mov z,ebx + + dec edi + cmp edi,zb.tsl._end + mov dest,edi + jbe L50 + + endm + + jmp R33 + +L50: + popad + ret + +name endp + + endm + + ; Dithered texture mapping + +ScanLinePIZ2TPD macro name,pre,incu,decu,incv,decv,post1,post2 + +ScanLinePIZ2TPDn &name&_0,\ + pre,incu,decu,incv,decv,post1,post2,\ + 13,1,4,16 + +ScanLinePIZ2TPDn &name&_1,\ + pre,incu,decu,incv,decv,post1,post2,\ + 8,12,9,5 + +ScanLinePIZ2TPDn &name&_2,\ + pre,incu,decu,incv,decv,post1,post2,\ + 10,6,7,11 + +ScanLinePIZ2TPDn &name&_3,\ + pre,incu,decu,incv,decv,post1,post2,\ + 3,15,14,2 + + .data +&name&_table label ptr dword + dd &name&_0 + dd &name&_1 + dd &name&_2 + dd &name&_3 + .code + +name proc + + mov eax,zb.tsl.y + and eax,3 + jmp &name&_table[4*eax] + +name endp + + endm + +ScanLinePIZ2TIP ScanLinePIZ2TIP256,\ + <>,\ + ,,,,\ + <>,<> + +ScanLinePIZ2TIP ScanLinePIZ2TIP64,\ + ,\ + ,,,,\ + , + +ScanLinePIZ2TIP ScanLinePIZ2TIP1024,\ + ,\ + ,,,,\ + , + +ScanLinePIZ2TP ScanLinePIZ2TP64,\ + ,\ + ,,,,\ + , + +ScanLinePIZ2TP ScanLinePIZ2TP1024,\ + ,\ + ,,,,\ + , + +ScanLinePIZ2TP ScanLinePIZ2TP256,\ + <>,\ + ,,,,\ + <>,<> + +ScanLinePIZ2TPD ScanLinePIZ2TPD1024,\ + <>,\ + <>,<>,<>,<>,\ + <>,<> + + end diff --git a/bren/ZB/ti8_pizp.c b/bren/ZB/ti8_pizp.c new file mode 100644 index 00000000..fceed971 --- /dev/null +++ b/bren/ZB/ti8_pizp.c @@ -0,0 +1,39 @@ +#include +#include +#include "fwproto.h" +#include "zb.h" + +void BR_ASM_CALL ScanLinePIZ2TIP256(void) +{ + // TODO(bjrkk): To be translated +} + +void BR_ASM_CALL ScanLinePIZ2TIP64(void) +{ + // TODO(bjrkk): To be translated +} + +void BR_ASM_CALL ScanLinePIZ2TIP1024(void) +{ + // TODO(bjrkk): To be translated +} + +void BR_ASM_CALL ScanLinePIZ2TP256(void) +{ + // TODO(bjrkk): To be translated +} + +void BR_ASM_CALL ScanLinePIZ2TP64(void) +{ + // TODO(bjrkk): To be translated +} + +void BR_ASM_CALL ScanLinePIZ2TP1024(void) +{ + // TODO(bjrkk): To be translated +} + +void BR_ASM_CALL ScanLinePIZ2TPD1024(void) +{ + // TODO(bjrkk): To be translated +} diff --git a/bren/ZB/tt15_piz.c b/bren/ZB/tt15_piz.c new file mode 100644 index 00000000..80287592 --- /dev/null +++ b/bren/ZB/tt15_piz.c @@ -0,0 +1,409 @@ +#include +#include +#include "fwproto.h" +#include "zb.h" + +extern int BR_ASM_CALL SafeFixedMac2Div(int, int, int, int, int); + +#define swap(type, a, b) \ + { \ + type _; \ + _ = a; \ + a = b; \ + b = _; \ + } + +static br_int_32 colour_row_width = 0; + +static br_uint_32 temp_b = 0; +static br_uint_32 temp_g = 0; +static br_uint_32 temp_r = 0; +static br_uint_32 temp_colour = 0; + +static br_uint_32 p0_offset_x = 0; +static br_uint_32 p0_offset_y = 0; + +static br_uint_32 temp_i = 0; +static br_uint_32 temp_u = 0; +static br_uint_32 temp_v = 0; + +static screen_scalar vertex_0[2]; +static screen_scalar vertex_1[2]; +static screen_scalar vertex_2[2]; + +static br_int_32 g_divisor = 0; + +static inline void __TRAPEZOID_PIZ2_RGB_555(struct scan_edge *edge, br_boolean is_forward, br_fixed_ls *z_val, + br_int_32 *fb_index) +{ + br_int_32 endptr = edge->i; + + while (edge->count > 0) + { + br_int_32 fb_curr = *fb_index; + br_uint_32 z_curr = *z_val; + br_uint_16 *z_ptr = ((br_uint_16 *)zb.depth_buffer) + fb_curr; + + // pixel loop + if (is_forward) + { + while (fb_curr < endptr) + { + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + + br_uint_16 r = BrFixedToInt(temp_r) >> 3; + br_uint_16 g = BrFixedToInt(temp_g) >> 3; + br_uint_16 b = BrFixedToInt(temp_b) >> 3; + + ((br_uint_16 *)zb.colour_buffer)[fb_curr] = (r << 10) | (g << 5) | b; + } + z_curr += zb.pz.grad_x; + z_ptr++; + fb_curr++; + } + } + else + { + while (endptr < fb_curr) + { + z_curr -= zb.pz.grad_x; + z_ptr--; + fb_curr--; + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + + br_uint_16 r = BrFixedToInt(temp_r) >> 3; + br_uint_16 g = BrFixedToInt(temp_g) >> 3; + br_uint_16 b = BrFixedToInt(temp_b) >> 3; + + ((br_uint_16 *)zb.colour_buffer)[fb_curr] = (r << 10) | (g << 5) | b; + } + } + } + + br_uint_32 carry; + + edge->f += edge->d_f; + carry = (br_uint_32)edge->f < (br_uint_32)edge->d_f; + endptr += edge->d_i + carry; + + zb.main.f += zb.main.d_f; + carry = (br_uint_32)zb.main.f < (br_uint_32)zb.main.d_f; + *fb_index += zb.main.d_i + carry; + if (carry != 0) + { + *z_val += zb.pz.d_carry; + } + else + { + *z_val += zb.pz.d_nocarry; + } + + edge->count--; + } +} + +static inline void __TRAPEZOID_PIZ2I_RGB_555(struct scan_edge *edge, br_boolean is_forward, br_fixed_ls *z_val, + br_int_32 *fb_index) +{ + br_int_32 endptr = edge->i; + + while (edge->count > 0) + { + br_int_32 fb_curr = *fb_index; + br_uint_32 z_curr = *z_val; + br_uint_16 *z_ptr = ((br_uint_16 *)zb.depth_buffer) + fb_curr; + + temp_r = zb.pr.current; + temp_g = zb.pg.current; + temp_b = zb.pb.current; + + // pixel loop + if (is_forward) + { + while (fb_curr < endptr) + { + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + + br_uint_16 r = BrFixedToInt(temp_r) >> 3; + br_uint_16 g = BrFixedToInt(temp_g) >> 3; + br_uint_16 b = BrFixedToInt(temp_b) >> 3; + + ((br_uint_16 *)zb.colour_buffer)[fb_curr] = (r << 10) | (g << 5) | b; + } + z_curr += zb.pz.grad_x; + temp_r += zb.pr.grad_x; + temp_g += zb.pg.grad_x; + temp_b += zb.pb.grad_x; + z_ptr++; + fb_curr++; + } + } + else + { + while (endptr < fb_curr) + { + z_curr -= zb.pz.grad_x; + temp_r -= zb.pr.grad_x; + temp_g -= zb.pg.grad_x; + temp_b -= zb.pb.grad_x; + z_ptr--; + fb_curr--; + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + + br_uint_16 r = BrFixedToInt(temp_r) >> 3; + br_uint_16 g = BrFixedToInt(temp_g) >> 3; + br_uint_16 b = BrFixedToInt(temp_b) >> 3; + + ((br_uint_16 *)zb.colour_buffer)[fb_curr] = (r << 10) | (g << 5) | b; + } + } + } + + br_uint_32 carry; + + edge->f += edge->d_f; + carry = (br_uint_32)edge->f < (br_uint_32)edge->d_f; + endptr += edge->d_i + carry; + + zb.main.f += zb.main.d_f; + carry = (br_uint_32)zb.main.f < (br_uint_32)zb.main.d_f; + *fb_index += zb.main.d_i + carry; + if (carry != 0) + { + *z_val += zb.pz.d_carry; + zb.pr.current += zb.pr.d_carry; + zb.pg.current += zb.pg.d_carry; + zb.pb.current += zb.pb.d_carry; + } + else + { + *z_val += zb.pz.d_nocarry; + zb.pr.current += zb.pr.d_nocarry; + zb.pg.current += zb.pg.d_nocarry; + zb.pb.current += zb.pb.d_nocarry; + } + + edge->count--; + } +} + +static inline void __SETUP_PI(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, struct temp_vertex_fixed *v2) +{ + colour_row_width = zb.row_width / 2; + + /* + * Work out integer vertex values + * XXX Should really do this at projection time + */ + vertex_0[0] = v0->v[0] >> 16; + vertex_1[0] = v1->v[0] >> 16; + vertex_2[0] = v2->v[0] >> 16; + + vertex_0[1] = v0->v[1] >> 16; + vertex_1[1] = v1->v[1] >> 16; + vertex_2[1] = v2->v[1] >> 16; + + if (vertex_0[1] == vertex_2[1]) + { + return; + } + + zb.top.x = vertex_1[0] - vertex_0[0]; + zb.top.y = vertex_1[1] - vertex_0[1]; + zb.top.count = zb.top.y; + if (zb.top.count != 0) + { + zb.top.grad = BrFixedDiv(zb.top.x, zb.top.y); + zb.top.d_f = (zb.top.grad << 16); + zb.top.d_i = (zb.top.grad >> 16) + colour_row_width; + } + + // don't need to save deltas + zb.bot.count = vertex_2[1] - vertex_1[1]; + if (zb.bot.count != 0) + { + zb.bot.grad = BrFixedDiv(vertex_2[0] - vertex_1[0], vertex_2[1] - vertex_1[1]); + zb.bot.d_f = (zb.bot.grad << 16); + zb.bot.d_i = (zb.bot.grad >> 16) + colour_row_width; + } + + zb.main.x = vertex_2[0] - vertex_0[0]; + zb.main.y = vertex_2[1] - vertex_0[1]; + zb.main.grad = BrFixedDiv(zb.main.x, zb.main.y); + zb.main.d_f = (zb.main.grad << 16); + zb.main.d_i = (zb.main.grad >> 16) + colour_row_width; + + zb.main.f = 0x80000000; + zb.main.i = (vertex_0[1] * colour_row_width) + vertex_0[0]; + zb.top.f = 0x80000000; + zb.top.i = (vertex_0[1] * colour_row_width) + vertex_0[0]; + zb.bot.f = 0x80000000; + zb.bot.i = (vertex_1[1] * colour_row_width) + vertex_1[0]; + + g_divisor = zb.top.x * zb.main.y - zb.main.x * zb.top.y; +} + +static inline void __PARAM_PI_DIRN(screen_scalar a, screen_scalar b, screen_scalar c, struct scan_parameter *param) +{ + /* Optimal sort of 3 elements? */ + param->grad_x = SafeFixedMac2Div(b - a, zb.main.y, c - a, -zb.top.y, g_divisor); + + param->grad_y = SafeFixedMac2Div(c - a, zb.top.x, b - a, -zb.main.x, g_divisor); + + param->current = a + param->grad_x / 2; + param->d_nocarry = BrFixedToInt(zb.main.grad) * param->grad_x + param->grad_y; + param->d_carry = param->d_nocarry + param->grad_x; +} + +void BR_ASM_CALL RawTriangle_PIZ2_RGB_555(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + struct temp_vertex_fixed *a, *b, *c; + a = v0; + b = v1; + c = v2; + if (v0->v[1] > v1->v[1]) + { + if (v1->v[1] > v2->v[1]) + { + a = v2; + c = v0; + } + else if (v0->v[1] > v2->v[1]) + { + a = v1; + b = v2; + c = v0; + } + else + { + a = v1; + b = v0; + } + } + else if (v1->v[1] > v2->v[1]) + { + if (v0->v[1] > v2->v[1]) + { + a = v2; + b = v0; + c = v1; + } + else + { + b = v2; + c = v1; + } + } + + __SETUP_PI(a, b, c); + + if (g_divisor == 0) + { + return; + } + + __PARAM_PI_DIRN(a->v[2], b->v[2], c->v[2], &zb.pz); + + br_boolean is_forward = g_divisor >= 0; + if (!is_forward) + { + g_divisor = -g_divisor; + } + + temp_r = zb.pr.current; + temp_g = zb.pg.current; + temp_b = zb.pb.current; + + br_fixed_ls z_val = zb.pz.current; + br_int_32 fb_index = zb.main.i; + + __TRAPEZOID_PIZ2_RGB_555(&zb.top, is_forward, &z_val, &fb_index); + __TRAPEZOID_PIZ2_RGB_555(&zb.bot, is_forward, &z_val, &fb_index); +} + +void BR_ASM_CALL RawTriangle_PIZ2I_RGB_555(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + struct temp_vertex_fixed *a, *b, *c; + a = v0; + b = v1; + c = v2; + if (v0->v[1] > v1->v[1]) + { + if (v1->v[1] > v2->v[1]) + { + a = v2; + c = v0; + } + else if (v0->v[1] > v2->v[1]) + { + a = v1; + b = v2; + c = v0; + } + else + { + a = v1; + b = v0; + } + } + else if (v1->v[1] > v2->v[1]) + { + if (v0->v[1] > v2->v[1]) + { + a = v2; + b = v0; + c = v1; + } + else + { + b = v2; + c = v1; + } + } + + __SETUP_PI(a, b, c); + + if (g_divisor == 0) + { + return; + } + + __PARAM_PI_DIRN(a->v[2], b->v[2], c->v[2], &zb.pz); + __PARAM_PI_DIRN(a->comp[C_R], b->comp[C_R], c->comp[C_R], &zb.pr); + __PARAM_PI_DIRN(a->comp[C_G], b->comp[C_G], c->comp[C_G], &zb.pg); + __PARAM_PI_DIRN(a->comp[C_B], b->comp[C_B], c->comp[C_B], &zb.pb); + + br_boolean is_forward = g_divisor >= 0; + if (!is_forward) + { + g_divisor = -g_divisor; + } + + br_fixed_ls z_val = zb.pz.current; + br_int_32 fb_index = zb.main.i; + + __TRAPEZOID_PIZ2I_RGB_555(&zb.top, is_forward, &z_val, &fb_index); + __TRAPEZOID_PIZ2I_RGB_555(&zb.bot, is_forward, &z_val, &fb_index); +} + +void BR_ASM_CALL TriangleRenderPIZ2_RGB_555(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + RawTriangle_PIZ2_RGB_555(v0, v1, v2); +} + +void BR_ASM_CALL TriangleRenderPIZ2I_RGB_555(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + RawTriangle_PIZ2I_RGB_555(v0, v1, v2); +} \ No newline at end of file diff --git a/bren/ZB/tt24_piz.c b/bren/ZB/tt24_piz.c new file mode 100644 index 00000000..09eea68c --- /dev/null +++ b/bren/ZB/tt24_piz.c @@ -0,0 +1,397 @@ +#include +#include +#include "fwproto.h" +#include "zb.h" + +extern int BR_ASM_CALL SafeFixedMac2Div(int, int, int, int, int); + +#define swap(type, a, b) \ + { \ + type _; \ + _ = a; \ + a = b; \ + b = _; \ + } + +static br_int_32 colour_row_width = 0; + +static br_uint_32 temp_b = 0; +static br_uint_32 temp_g = 0; +static br_uint_32 temp_r = 0; + +static br_uint_32 p0_offset_x = 0; +static br_uint_32 p0_offset_y = 0; + +static br_uint_32 temp_i = 0; +static br_uint_32 temp_u = 0; +static br_uint_32 temp_v = 0; + +static screen_scalar vertex_0[2]; +static screen_scalar vertex_1[2]; +static screen_scalar vertex_2[2]; + +static br_int_32 g_divisor = 0; + +static inline void __TRAPEZOID_PIZ2_RGB_888(struct scan_edge *edge, br_boolean is_forward, br_fixed_ls *z_val, + br_int_32 *fb_index) +{ + br_int_32 endptr = edge->i; + + while (edge->count > 0) + { + br_int_32 fb_curr = *fb_index; + br_uint_32 z_curr = *z_val; + br_uint_16 *z_ptr = ((br_uint_16 *)zb.depth_buffer) + fb_curr; + + // pixel loop + if (is_forward) + { + while (fb_curr < endptr) + { + br_uint_16 z_hi = z_curr >> 16; + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + zb.colour_buffer[fb_curr * 3 + 0] = BrFixedToInt(temp_r); + zb.colour_buffer[fb_curr * 3 + 1] = BrFixedToInt(temp_g); + zb.colour_buffer[fb_curr * 3 + 2] = BrFixedToInt(temp_b); + } + z_curr += zb.pz.grad_x; + z_ptr++; + fb_curr++; + } + } + else + { + while (endptr < fb_curr) + { + z_curr -= zb.pz.grad_x; + z_ptr--; + fb_curr--; + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + zb.colour_buffer[fb_curr * 3 + 0] = BrFixedToInt(temp_r); + zb.colour_buffer[fb_curr * 3 + 1] = BrFixedToInt(temp_g); + zb.colour_buffer[fb_curr * 3 + 2] = BrFixedToInt(temp_b); + } + } + } + + br_uint_32 carry; + + edge->f += edge->d_f; + carry = (br_uint_32)edge->f < (br_uint_32)edge->d_f; + endptr += edge->d_i + carry; + + zb.main.f += zb.main.d_f; + carry = (br_uint_32)zb.main.f < (br_uint_32)zb.main.d_f; + *fb_index += zb.main.d_i + carry; + if (carry != 0) + { + *z_val += zb.pz.d_carry; + } + else + { + *z_val += zb.pz.d_nocarry; + } + + edge->count--; + } +} + +static inline void __TRAPEZOID_PIZ2I_RGB_888(struct scan_edge *edge, br_boolean is_forward, br_fixed_ls *z_val, + br_int_32 *fb_index) +{ + br_int_32 endptr = edge->i; + + while (edge->count > 0) + { + br_int_32 fb_curr = *fb_index; + br_uint_32 z_curr = *z_val; + br_uint_16 *z_ptr = ((br_uint_16 *)zb.depth_buffer) + fb_curr; + + temp_r = zb.pr.current; + temp_g = zb.pg.current; + temp_b = zb.pb.current; + + // pixel loop + if (is_forward) + { + while (fb_curr < endptr) + { + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + zb.colour_buffer[fb_curr * 3 + 0] = BrFixedToInt(temp_r); + zb.colour_buffer[fb_curr * 3 + 1] = BrFixedToInt(temp_g); + zb.colour_buffer[fb_curr * 3 + 2] = BrFixedToInt(temp_b); + } + z_curr += zb.pz.grad_x; + temp_r += zb.pr.grad_x; + temp_g += zb.pg.grad_x; + temp_b += zb.pb.grad_x; + z_ptr++; + fb_curr++; + } + } + else + { + while (endptr < fb_curr) + { + z_curr -= zb.pz.grad_x; + temp_r -= zb.pr.grad_x; + temp_g -= zb.pg.grad_x; + temp_b -= zb.pb.grad_x; + z_ptr--; + fb_curr--; + if (*z_ptr > BrFixedToInt(z_curr)) + { + *z_ptr = BrFixedToInt(z_curr); + zb.colour_buffer[fb_curr * 3 + 0] = BrFixedToInt(temp_r); + zb.colour_buffer[fb_curr * 3 + 1] = BrFixedToInt(temp_g); + zb.colour_buffer[fb_curr * 3 + 2] = BrFixedToInt(temp_b); + } + } + } + + br_uint_32 carry; + + edge->f += edge->d_f; + carry = (br_uint_32)edge->f < (br_uint_32)edge->d_f; + endptr += edge->d_i + carry; + + zb.main.f += zb.main.d_f; + carry = (br_uint_32)zb.main.f < (br_uint_32)zb.main.d_f; + *fb_index += zb.main.d_i + carry; + if (carry != 0) + { + *z_val += zb.pz.d_carry; + zb.pr.current += zb.pr.d_carry; + zb.pg.current += zb.pg.d_carry; + zb.pb.current += zb.pb.d_carry; + } + else + { + *z_val += zb.pz.d_nocarry; + zb.pr.current += zb.pr.d_nocarry; + zb.pg.current += zb.pg.d_nocarry; + zb.pb.current += zb.pb.d_nocarry; + } + + edge->count--; + } +} + +static inline void __SETUP_PI(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, struct temp_vertex_fixed *v2) +{ + colour_row_width = zb.row_width / 3; + + /* + * Work out integer vertex values + * XXX Should really do this at projection time + */ + vertex_0[0] = v0->v[0] >> 16; + vertex_1[0] = v1->v[0] >> 16; + vertex_2[0] = v2->v[0] >> 16; + + vertex_0[1] = v0->v[1] >> 16; + vertex_1[1] = v1->v[1] >> 16; + vertex_2[1] = v2->v[1] >> 16; + + if (vertex_0[1] == vertex_2[1]) + { + return; + } + + zb.top.x = vertex_1[0] - vertex_0[0]; + zb.top.y = vertex_1[1] - vertex_0[1]; + zb.top.count = zb.top.y; + if (zb.top.count != 0) + { + zb.top.grad = BrFixedDiv(zb.top.x, zb.top.y); + zb.top.d_f = (zb.top.grad << 16); + zb.top.d_i = (zb.top.grad >> 16) + colour_row_width; + } + + // don't need to save deltas + zb.bot.count = vertex_2[1] - vertex_1[1]; + if (zb.bot.count != 0) + { + zb.bot.grad = BrFixedDiv(vertex_2[0] - vertex_1[0], vertex_2[1] - vertex_1[1]); + zb.bot.d_f = (zb.bot.grad << 16); + zb.bot.d_i = (zb.bot.grad >> 16) + colour_row_width; + } + + zb.main.x = vertex_2[0] - vertex_0[0]; + zb.main.y = vertex_2[1] - vertex_0[1]; + zb.main.grad = BrFixedDiv(zb.main.x, zb.main.y); + zb.main.d_f = (zb.main.grad << 16); + zb.main.d_i = (zb.main.grad >> 16) + colour_row_width; + + zb.main.f = 0x80000000; + zb.main.i = (vertex_0[1] * colour_row_width) + vertex_0[0]; + zb.top.f = 0x80000000; + zb.top.i = (vertex_0[1] * colour_row_width) + vertex_0[0]; + zb.bot.f = 0x80000000; + zb.bot.i = (vertex_1[1] * colour_row_width) + vertex_1[0]; + + g_divisor = zb.top.x * zb.main.y - zb.main.x * zb.top.y; +} + +static inline void __PARAM_PI_DIRN(screen_scalar a, screen_scalar b, screen_scalar c, struct scan_parameter *param) +{ + /* Optimal sort of 3 elements? */ + param->grad_x = SafeFixedMac2Div(b - a, zb.main.y, c - a, -zb.top.y, g_divisor); + + param->grad_y = SafeFixedMac2Div(c - a, zb.top.x, b - a, -zb.main.x, g_divisor); + + param->current = a + param->grad_x / 2; + param->d_nocarry = BrFixedToInt(zb.main.grad) * param->grad_x + param->grad_y; + param->d_carry = param->d_nocarry + param->grad_x; +} + +void BR_ASM_CALL RawTriangle_PIZ2_RGB_888(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + struct temp_vertex_fixed *a, *b, *c; + a = v0; + b = v1; + c = v2; + if (v0->v[1] > v1->v[1]) + { + if (v1->v[1] > v2->v[1]) + { + a = v2; + c = v0; + } + else if (v0->v[1] > v2->v[1]) + { + a = v1; + b = v2; + c = v0; + } + else + { + a = v1; + b = v0; + } + } + else if (v1->v[1] > v2->v[1]) + { + if (v0->v[1] > v2->v[1]) + { + a = v2; + b = v0; + c = v1; + } + else + { + b = v2; + c = v1; + } + } + + __SETUP_PI(a, b, c); + + if (g_divisor == 0) + { + return; + } + + __PARAM_PI_DIRN(a->v[2], b->v[2], c->v[2], &zb.pz); + + br_boolean is_forward = g_divisor >= 0; + if (!is_forward) + { + g_divisor = -g_divisor; + } + + temp_r = zb.pr.current; + temp_g = zb.pg.current; + temp_b = zb.pb.current; + + br_fixed_ls z_val = zb.pz.current; + br_int_32 fb_index = zb.main.i; + + __TRAPEZOID_PIZ2_RGB_888(&zb.top, is_forward, &z_val, &fb_index); + __TRAPEZOID_PIZ2_RGB_888(&zb.bot, is_forward, &z_val, &fb_index); +} + +void BR_ASM_CALL RawTriangle_PIZ2I_RGB_888(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + struct temp_vertex_fixed *a, *b, *c; + a = v0; + b = v1; + c = v2; + if (v0->v[1] > v1->v[1]) + { + if (v1->v[1] > v2->v[1]) + { + a = v2; + c = v0; + } + else if (v0->v[1] > v2->v[1]) + { + a = v1; + b = v2; + c = v0; + } + else + { + a = v1; + b = v0; + } + } + else if (v1->v[1] > v2->v[1]) + { + if (v0->v[1] > v2->v[1]) + { + a = v2; + b = v0; + c = v1; + } + else + { + b = v2; + c = v1; + } + } + + __SETUP_PI(a, b, c); + + if (g_divisor == 0) + { + return; + } + + __PARAM_PI_DIRN(a->v[2], b->v[2], c->v[2], &zb.pz); + __PARAM_PI_DIRN(a->comp[C_R], b->comp[C_R], c->comp[C_R], &zb.pr); + __PARAM_PI_DIRN(a->comp[C_G], b->comp[C_G], c->comp[C_G], &zb.pg); + __PARAM_PI_DIRN(a->comp[C_B], b->comp[C_B], c->comp[C_B], &zb.pb); + + br_boolean is_forward = g_divisor >= 0; + if (!is_forward) + { + g_divisor = -g_divisor; + } + + br_fixed_ls z_val = zb.pz.current; + br_int_32 fb_index = zb.main.i; + + __TRAPEZOID_PIZ2I_RGB_888(&zb.top, is_forward, &z_val, &fb_index); + __TRAPEZOID_PIZ2I_RGB_888(&zb.bot, is_forward, &z_val, &fb_index); +} + +void BR_ASM_CALL TriangleRenderPIZ2_RGB_888(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + RawTriangle_PIZ2_RGB_888(v0, v1, v2); +} + +void BR_ASM_CALL TriangleRenderPIZ2I_RGB_888(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ + RawTriangle_PIZ2I_RGB_888(v0, v1, v2); +} \ No newline at end of file diff --git a/bren/ZB/zb.fixed.inc b/bren/ZB/zb.fixed.inc new file mode 100644 index 00000000..56ca70a9 --- /dev/null +++ b/bren/ZB/zb.fixed.inc @@ -0,0 +1,3212 @@ + +option expr32 +option casemap:none + +; Begin of file zb.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: zb.h 1.44 1995/08/31 16:47:50 sam Exp $ +; * $Locker: $ +; * +; * Internal types and structures for z-buffer renderer +; +; +; * Pull in all the framework and public definitions +; +; Begin of file ..\fw\fw.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: fw.h 1.39 1995/07/28 19:01:47 sam Exp $ +; * $Locker: sam $ +; * +; * Internal types and structures for framework +; +; +; * Pull in all the public definitions/declarations +; +; Begin of file ..\inc\brender.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brender.h 1.19 1995/08/31 16:36:12 sam Exp $ +; * $Locker: $ +; * +; * Master include file for BRender +; * +; +; Begin of file ..\inc\compiler.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: compiler.h 1.22 1995/08/31 16:36:15 sam Exp $ +; * $Locker: sam $ +; * +; * Misc host compiler configuration (types & special declarators etc.) +; +; +; * Fixed bitsize integers +; +br_int_32 TYPEDEF SDWORD + +br_uint_32 TYPEDEF DWORD + +br_int_16 TYPEDEF SWORD + +br_uint_16 TYPEDEF WORD + +br_int_8 TYPEDEF SBYTE + +br_uint_8 TYPEDEF BYTE + +; +; * Generic size type (in case target environment does not have size_t) +; +br_size_t TYPEDEF DWORD + +; +; * Boolean type +; +br_boolean TYPEDEF SDWORD + +BR_TRUE EQU 1t +BR_FALSE EQU 0t +; * +; ** Compiler specific declarations +; ** +; * +; * BR_PUBLIC_ENTRY are the declarators for public entry points into the library +; * +; * BR_CALLBACK are the declarators for function pointers to callbacks +; * +; * BR_ASM_DATA is the declarator for data that is shared with ASM files +; * +; * BR_ASM_CALL is the declarator for function declarations that are ASM functions +; * called from C +; * +; * BR_ASM_CALLBACK is the declarator for function definitions that are C functions +; * called from ASM +; * +; * BR_SUFFIX_HOST is a string used for banners/titles etc +; * +; * br_framebuffer_ptr is a type used for pointing at the pixels of a frame buffer +; * +; * BR_HAS_FAR is !0 if language supports __far pointers +; +; +; * WATCOM C/C++ 32 +; +BR_HAS_FAR EQU 0t +MEMAVL EQU 0t +; +; * Metaware High-C Version 1 +; +; +; * Avoid some tokens that masm chokes on +; +; +; * Supress compiler specific declarators +; +; +; * Macros for producing banners & copyright messages +; +; +; * Useful macro for sizing an array +; +; End of file ..\inc\compiler.h +; Begin of file ..\inc\brlimits.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brlimits.h 1.5 1995/02/22 21:37:01 sam Exp $ +; * $Locker: $ +; * +; * Various limits imposed by the renderer +; +; +; * Maximum length of an item's name +; +BR_MAX_NAME EQU 256t +; +; * Maximum number of active lights +; +BR_MAX_LIGHTS EQU 16t +; +; * Maximum number of active clip planes +; +BR_MAX_CLIP_PLANES EQU 6t +; +; * Maximum number of resource classes +; +BR_MAX_RESOURCE_CLASSES EQU 256t +; +; * Maximum depth of camera in hierachy +; +MAX_CAMERA_DEPTH EQU 16t +; End of file ..\inc\brlimits.h +; Begin of file ..\inc\fixed.h +; +; * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: fixed.h 1.17 1995/02/22 21:37:06 sam Exp $ +; * $Locker: $ +; +INLINE_FIXED EQU 1t +; +; * Fixed point types +; +br_fixed_ls TYPEDEF SDWORD + +; Long Signed fixed 15.16 +br_fixed_lsf TYPEDEF SWORD + +; Long Signed fraction 0.15 +br_fixed_lu TYPEDEF DWORD + +; Long unsigned fixed 16.16 +br_fixed_luf TYPEDEF WORD + +; Long unsigned fixed fraction 0.16 +br_fixed_ss TYPEDEF SWORD + +; Short Signed fixed 7.8 +br_fixed_ssf TYPEDEF SBYTE + +; Short Signed fraction 0.7 +br_fixed_su TYPEDEF WORD + +; Short unsigned fixed 8.8 +br_fixed_suf TYPEDEF BYTE + +; Short unsigned fixed fraction 0.8 +; +; * 1 in various fixed point forms +; +BR_ONE_LS EQU 000010000h +BR_ONE_LSF EQU 000008000h +BR_ONE_LU EQU 000010000h +BR_ONE_LUF EQU 000010000h +BR_ONE_SS EQU 000000100h +BR_ONE_SSF EQU 000000080h +BR_ONE_SU EQU 000000100h +BR_ONE_SUF EQU 000000100h +; End of file ..\inc\fixed.h +; Begin of file ..\inc\scalar.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: scalar.h 1.21 1995/08/31 16:36:20 sam Exp $ +; * $Locker: $ +; * +; * Scalar type +; * +; * External defines: +; * +; * BASED_FIXED +; * True if system is based on signed 16.16 fixed point +; * +; * BASED_FLOAT +; * True if system is based on 32 bit floating point +; * +; * One of these must be defined and the appropriate libraries must be used +; +BASED_FLOAT EQU 0t +; * +; ** Basic types - either fixed or float +; * +; +; * Reference an external symbol to make sure +; * the right library is linked +; +EXTERNDEF C _BR_Fixed_Point_Scalar:SDWORD + +; +; * Fixed base types +; +br_scalar TYPEDEF br_fixed_ls + +br_fraction TYPEDEF br_fixed_lsf + +br_ufraction TYPEDEF br_fixed_luf + +BR_SCALAR_EPSILON EQU 000000001h +BR_SCALAR_MAX EQU 07fffffffh +BR_SCALAR_MIN EQU 080000000h +; +; * Macros for static initialisation +; +; +; * Macros for type conversion +; +; +; * Various arithmetic operations +; +; +; * Make sure PI is defined +; +; End of file ..\inc\scalar.h +; Begin of file ..\inc\colour.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: colour.h 1.4 1995/08/31 16:36:14 sam Exp $ +; * $Locker: $ +; * +; * Colour type and macros +; * +; +br_colour TYPEDEF DWORD + +; End of file ..\inc\colour.h +; Begin of file ..\inc\matrix.h +; +; * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: matrix.h 1.3 1995/02/22 21:37:13 sam Exp $ +; * $Locker: $ +; * +; * Structrures describing matrices +; +br_matrix4 STRUCT 4t +m br_scalar 4t DUP (4t DUP (?)) +br_matrix4 ENDS + +br_matrix34 STRUCT 4t +m br_scalar 4t DUP (3t DUP (?)) +br_matrix34 ENDS + +br_matrix23 STRUCT 4t +m br_scalar 3t DUP (2t DUP (?)) +br_matrix23 ENDS + +; End of file ..\inc\matrix.h +; Begin of file ..\inc\vector.h +; +; * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: vector.h 1.9 1995/06/30 16:09:07 sam Exp $ +; * $Locker: $ +; * +; * Vector types +; +; +; * Vector types +; +br_vector2 STRUCT 4t +v br_scalar 2t DUP (?) +br_vector2 ENDS + +br_vector3 STRUCT 4t +v br_scalar 3t DUP (?) +br_vector3 ENDS + +br_vector4 STRUCT 4t +v br_scalar 4t DUP (?) +br_vector4 ENDS + +; +; * Integer vectors (used for integer bounding boxes) +; +br_vector2i STRUCT 4t +v br_int_32 2t DUP (?) +br_vector2i ENDS + +br_vector3i STRUCT 4t +v br_int_32 3t DUP (?) +br_vector3i ENDS + +br_vector4i STRUCT 4t +v br_int_32 4t DUP (?) +br_vector4i ENDS + +; +; * Fraction vector types +; +br_fvector2 STRUCT 4t +v br_fraction 2t DUP (?) +br_fvector2 ENDS + +br_fvector3 STRUCT 4t +v br_fraction 3t DUP (?) +br_fvector3 ENDS + +br_fvector4 STRUCT 4t +v br_fraction 4t DUP (?) +br_fvector4 ENDS + +; +; * General structures for describing an axis aligned bounds +; +; Minimum corner +; Maximum corner +br_bounds2 STRUCT 4t +min br_vector2 <> +max br_vector2 <> +br_bounds2 ENDS + +; Minimum corner +; Maximum corner +br_bounds3 STRUCT 4t +min br_vector3 <> +max br_vector3 <> +br_bounds3 ENDS + +; Minimum corner +; Maximum corner +br_bounds4 STRUCT 4t +min br_vector4 <> +max br_vector4 <> +br_bounds4 ENDS + +; +; * Integer bounding boxes +; +; Minimum corner +; Maximum corner +br_bounds2i STRUCT 4t +min br_vector2i <> +max br_vector2i <> +br_bounds2i ENDS + +; Minimum corner +; Maximum corner +br_bounds3i STRUCT 4t +min br_vector3i <> +max br_vector3i <> +br_bounds3i ENDS + +; Minimum corner +; Maximum corner +br_bounds4i STRUCT 4t +min br_vector4i <> +max br_vector4i <> +br_bounds4i ENDS + +; +; * Backwards compatibility +; +br_bounds TYPEDEF br_bounds3 + +; +; * Macros for static initialisation +; +; End of file ..\inc\vector.h +; Begin of file ..\inc\angles.h +; +; * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: angles.h 1.10 1995/08/31 16:36:11 sam Exp $ +; * $Locker: $ +; * +; +; +; * Angles are alway 0.16 fixed point +; +br_angle TYPEDEF br_fixed_luf + +; +; * Fields that go into br_euler.order +; +BR_EULER_FIRST EQU 3t +BR_EULER_FIRST_X EQU 0t +BR_EULER_FIRST_Y EQU 1t +BR_EULER_FIRST_Z EQU 2t +BR_EULER_PARITY EQU 4t +BR_EULER_PARITY_EVEN EQU 0t +BR_EULER_PARITY_ODD EQU 4t +BR_EULER_REPEAT EQU 8t +BR_EULER_REPEAT_NO EQU 0t +BR_EULER_REPEAT_YES EQU 8t +BR_EULER_FRAME EQU 16t +BR_EULER_FRAME_STATIC EQU 0t +BR_EULER_FRAME_ROTATING EQU 16t + +; +; * Various possible orders +; +BR_EULER_XYZ_S EQU 0t +BR_EULER_XYX_S EQU 8t +BR_EULER_XZY_S EQU 4t +BR_EULER_XZX_S EQU 12t +BR_EULER_YZX_S EQU 1t +BR_EULER_YZY_S EQU 9t +BR_EULER_YXZ_S EQU 5t +BR_EULER_YXY_S EQU 13t +BR_EULER_ZXY_S EQU 2t +BR_EULER_ZXZ_S EQU 10t +BR_EULER_ZYX_S EQU 6t +BR_EULER_ZYZ_S EQU 14t +BR_EULER_ZYX_R EQU 16t +BR_EULER_XYX_R EQU 24t +BR_EULER_YZX_R EQU 20t +BR_EULER_XZX_R EQU 28t +BR_EULER_XZY_R EQU 17t +BR_EULER_YZY_R EQU 25t +BR_EULER_ZXY_R EQU 21t +BR_EULER_YXY_R EQU 29t +BR_EULER_YXZ_R EQU 18t +BR_EULER_ZXZ_R EQU 26t +BR_EULER_XYZ_R EQU 22t +BR_EULER_ZYZ_R EQU 30t + +; +; * A triple of euler angles and a description of how they are to +; * be applied - loosely based on - +; * "Euler Angle Convertion" Ken Shoemake, Graphics Gems IV pp. 222 +; +br_euler STRUCT 4t +_a br_angle ? +_b br_angle ? +_c br_angle ? +order br_uint_8 ? +br_euler ENDS + +; End of file ..\inc\angles.h +; Begin of file ..\inc\quat.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: quat.h 1.5 1995/02/22 21:37:21 sam Exp $ +; * $Locker: $ +; * +; * Type descibing a unit quaternion +; +br_quat STRUCT 4t +x br_scalar ? +y br_scalar ? +z br_scalar ? +w br_scalar ? +br_quat ENDS + +; End of file ..\inc\quat.h +; Begin of file ..\inc\transfrm.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: transfrm.h 1.11 1995/02/22 21:37:24 sam Exp $ +; * $Locker: $ +; * +; * Structure describing an affine transform from one coordinate space +; * to another +; +; +; * Type of actor position +; +BR_TRANSFORM_MATRIX34 EQU 0t +BR_TRANSFORM_MATRIX34_LP EQU 1t +BR_TRANSFORM_QUAT EQU 2t +BR_TRANSFORM_EULER EQU 3t +BR_TRANSFORM_LOOK_UP EQU 4t +BR_TRANSFORM_TRANSLATION EQU 5t +BR_TRANSFORM_IDENTITY EQU 6t +BR_TRANSFORM_MAX EQU 7t + +; +; * Type of position +; +; +; * Union of the various means of describing a transform - +; * these are explicity arrranged so that any exlicit transform +; * will always be available as br_transform.t.translate +; +; +; * Affine 3x4 matrix +; +; +; * Euler angles and translation +; +@tag_4 STRUCT 4t +e br_euler <> +_pad br_scalar 7t DUP (?) +t br_vector3 <> +@tag_4 ENDS + +; +; * Unit quaternion and translation +; +@tag_5 STRUCT 4t +q br_quat <> +_pad br_scalar 5t DUP (?) +t br_vector3 <> +@tag_5 ENDS + +; +; * Lookat vector, up vector and translation +; +@tag_6 STRUCT 4t +look br_vector3 <> +up br_vector3 <> +_pad br_scalar 3t DUP (?) +t br_vector3 <> +@tag_6 ENDS + +; +; * Just a translation +; +@tag_7 STRUCT 4t +_pad br_scalar 9t DUP (?) +t br_vector3 <> +@tag_7 ENDS + +@tag_3 UNION +mat br_matrix34 <> +euler @tag_4 <> +quat @tag_5 <> +look_up @tag_6 <> +translate @tag_7 <> +@tag_3 ENDS + +br_transform STRUCT 4t +_type br_uint_16 ? +t @tag_3 <> +br_transform ENDS + +; End of file ..\inc\transfrm.h +; Begin of file ..\inc\order.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: order.h 1.1 1995/08/31 16:37:15 sam Exp $ +; * $Locker: $ +; * +; * Definitons for an order table +; +BR_ORDER_TABLE_NEW_BOUNDS EQU 1t + +; +; * Order table array +; +@t_0 TYPEDEF PTR PTR +; +; * Number of entries in array +; +; +; * Next order table in list +; +@t_1 TYPEDEF PTR br_order_table +; +; * Order table bounds +; +; +; * Flags +; +br_order_table STRUCT 4t +table @t_0 ? +ot_size br_uint_32 ? +next @t_1 ? +min_z br_scalar ? +max_z br_scalar ? +flags br_uint_32 ? +br_order_table ENDS + +; End of file ..\inc\order.h +; Begin of file ..\inc\pixelmap.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: pixelmap.h 1.17 1995/08/31 16:36:19 sam Exp $ +; * $Locker: $ +; * +; * A stopgap 2D pixelmap structure for brender. This should really be the +; * pixelmap data type from the underlying 2D system (whatever that will +; * be) +; * +; * Used for input (maps) and output (render buffer) +; +; +; * Various types of pixel +; +; +; * Each pixel is an index into a colour map +; +BR_PMT_INDEX_1 EQU 0t +BR_PMT_INDEX_2 EQU 1t +BR_PMT_INDEX_4 EQU 2t +BR_PMT_INDEX_8 EQU 3t +; +; * True colour RGB +; +BR_PMT_RGB_555 EQU 4t +; 16 bits per pixel +BR_PMT_RGB_565 EQU 5t +; 16 bits per pixel +BR_PMT_RGB_888 EQU 6t +; 24 bits per pixel +BR_PMT_RGBX_888 EQU 7t +; 32 bits per pixel +BR_PMT_RGBA_8888 EQU 8t +; 32 bits per pixel +; +; * YUV +; +BR_PMT_YUYV_8888 EQU 9t +; YU YV YU YV ... +BR_PMT_YUV_888 EQU 10t +; +; * Depth +; +BR_PMT_DEPTH_16 EQU 11t +BR_PMT_DEPTH_32 EQU 12t +; +; * Opacity +; +BR_PMT_ALPHA_8 EQU 13t +; +; * Opacity + Index +; +BR_PMT_INDEXA_88 EQU 14t +; +; * Bump maps +; +BR_PMT_NORMAL_INDEX_8 EQU 15t +BR_PMT_NORMAL_XYZ EQU 16t +; +; * Wrong way around 15 bit true colour +; +BR_PMT_BGR_555 EQU 17t + +; +; * pixelmap flags +; +; +; * No direct access to pixels +; +BR_PMF_NO_ACCESS EQU 1t +BR_PMF_LINEAR EQU 2t +BR_PMF_ROW_WHOLEPIXELS EQU 4t + +; +; * Optional identifier (when maps used as textures/tables etc.) +; +@t_2 TYPEDEF PTR SBYTE +; +; * pointer to raw pixel data +; +@t_3 TYPEDEF PTR +; +; * Optional pixel map when pixels are indexed. +; +@t_4 TYPEDEF PTR br_pixelmap +; +; * Byte difference between pixels at same column of adjacent rows +; +; +; * Type of pixels +; +; +; * Flags +; +; +; * top left visible region in pixels from pixel at 'pixel' pointer +; +; +; * Width and height of bitmap in pixels +; +; +; * Local origin for any graphics system rendering into map, relative +; * to 'base' +; +; +; * Device pointer - if pixelmap originated from a device +; +@t_5 TYPEDEF PTR +br_pixelmap STRUCT 4t +identifier @t_2 ? +pixels @t_3 ? +_reserved0 br_uint_32 ? +map @t_4 ? +row_bytes br_int_16 ? +_type br_uint_8 ? +flags br_uint_8 ? +base_x br_uint_16 ? +base_y br_uint_16 ? +_width br_uint_16 ? +height br_uint_16 ? +origin_x br_int_16 ? +origin_y br_int_16 ? +context @t_5 ? +br_pixelmap ENDS + +; +; * Flags to BrPixelMapAllocate +; +BR_PMAF_INVERTED EQU 1t +; Setup pixelmap so that 0th scanline is at high memory +; Setup pixelmap so that 0th scanline is at low memory +BR_PMAF_NORMAL EQU 0t + +; +; * Channel flags +; +BR_PMCHAN_INDEX EQU 1t +BR_PMCHAN_RGB EQU 2t +BR_PMCHAN_DEPTH EQU 4t +BR_PMCHAN_ALPHA EQU 8t +BR_PMCHAN_YUV EQU 16t + +; +; * Matching pixelmap types +; +BR_PMMATCH_OFFSCREEN EQU 0t +BR_PMMATCH_DEPTH_16 EQU 1t +BR_PMMATCH_MAX EQU 2t + +; End of file ..\inc\pixelmap.h +; Begin of file ..\inc\brfont.h +; +; * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brfont.h 1.4 1995/03/29 16:42:55 sam Exp $ +; * $Locker: $ +; * +; +@t_6 TYPEDEF PTR br_int_8 +@t_7 TYPEDEF PTR br_uint_16 +@t_8 TYPEDEF PTR br_uint_8 +br_font STRUCT 4t +flags br_uint_32 ? +glyph_x br_uint_16 ? +glyph_y br_uint_16 ? +spacing_x br_int_16 ? +spacing_y br_int_16 ? +_width @t_6 ? +encoding @t_7 ? +glyphs @t_8 ? +br_font ENDS + +; +; * Flags +; +BR_FONTF_PROPORTIONAL EQU 1t +; +; * Default fonts that are available in framework +; +EXTERNDEF C BrFontFixed3x5:PTR br_font + +EXTERNDEF C BrFontProp4x6:PTR br_font + +EXTERNDEF C BrFontProp7x9:PTR br_font + +; End of file ..\inc\brfont.h +; Begin of file ..\inc\material.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: material.h 1.19 1995/05/25 13:37:32 sam Exp $ +; * $Locker: $ +; * +; * Describes the appearance of a material than can be applied to a surface +; +@t_9 TYPEDEF PTR SBYTE +; +; * Specular power +; +; +; * Controls how texture is rendered +; +; +; * 2x3 transform applied to model U,V +; +; +; * The direct index ramp base and range +; +; +; * Pointers to colour map +; +@t_10 TYPEDEF PTR br_pixelmap +; +; * Pointers to tables +; +@t_11 TYPEDEF PTR br_pixelmap +; Screen door opacity +@t_12 TYPEDEF PTR br_pixelmap +; Index shading +@t_13 TYPEDEF PTR br_pixelmap +; Index blending +; +; * Private fields +; +@t_14 TYPEDEF PTR +br_material STRUCT 4t +identifier @t_9 ? +colour br_colour ? +opacity br_uint_8 ? +ka br_ufraction ? +kd br_ufraction ? +ks br_ufraction ? +power br_scalar ? +flags br_uint_32 ? +map_transform br_matrix23 <> +index_base br_uint_8 ? +index_range br_uint_8 ? +colour_map @t_10 ? +screendoor @t_11 ? +index_shade @t_12 ? +index_blend @t_13 ? +prep_flags br_uint_8 ? +rptr @t_14 ? +br_material ENDS + +; +; * Bits for br_material->flags +; +BR_MATF_LIGHT EQU 1t +BR_MATF_PRELIT EQU 2t +BR_MATF_SMOOTH EQU 4t +BR_MATF_ENVIRONMENT_I EQU 8t +BR_MATF_ENVIRONMENT_L EQU 16t +BR_MATF_PERSPECTIVE EQU 32t +BR_MATF_DECAL EQU 64t +BR_MATF_I_FROM_U EQU 128t +BR_MATF_I_FROM_V EQU 256t +BR_MATF_U_FROM_I EQU 512t +BR_MATF_V_FROM_I EQU 1024t +BR_MATF_ALWAYS_VISIBLE EQU 2048t +BR_MATF_TWO_SIDED EQU 4096t +BR_MATF_FORCE_Z_0 EQU 8192t +BR_MATF_DITHER EQU 16384t + +; +; * Backwards compatibility +; +BR_MATF_MAP_COLOUR EQU 0t +; +; * Flags to BrMaterialUpdate() +; +BR_MATU_MAP_TRANSFORM EQU 1t +BR_MATU_RENDERING EQU 2t +BR_MATU_LIGHTING EQU 4t +BR_MATU_COLOURMAP EQU 8t +BR_MATU_ALL EQU 32767t + +; +; * Flags to BrMapUpdate() +; +BR_MAPU_ALL EQU 32767t + +; +; * Flags to BrTableUpdate() +; +BR_TABU_ALL EQU 32767t + +; End of file ..\inc\material.h +; Begin of file ..\inc\model.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: model.h 1.20 1995/08/31 16:36:18 sam Exp $ +; * $Locker: $ +; * +; * In-memory structures for models, both public and private areas +; +; Point in model space +; Mapping coordinates +; +; * Index for prelit models +; +; +; * true colour for pre-lit models +; +; +; * Private fields +; +; Surface normal at vertex +br_vertex STRUCT 4t +p br_vector3 <> +map br_vector2 <> +index br_uint_8 ? +red br_uint_8 ? +grn br_uint_8 ? +blu br_uint_8 ? +r br_uint_16 ? +n br_fvector3 <> +br_vertex ENDS + +; Vertices around face +; Edges around face +@t_15 TYPEDEF PTR br_material +; Face material (or NULL) +; Controls if shared edges are smooth +; Bits 0,1 and 2 denote internal edges +; Plane equation of face +br_face STRUCT 4t +vertices br_uint_16 3t DUP (?) +edges br_uint_16 3t DUP (?) +material @t_15 ? +smoothing br_uint_16 ? +flags br_uint_8 ? +_pad0 br_uint_8 ? +n br_fvector3 <> +d br_scalar ? +br_face ENDS + +; +; * Bits for face flags +; +BR_FACEF_COPLANAR_0 EQU 1t +; The face adjoining edge 0 is coplanar with this face +BR_FACEF_COPLANAR_1 EQU 2t +; "" 1 "" +; "" 1 "" +BR_FACEF_COPLANAR_2 EQU 4t + +@t_16 TYPEDEF PTR br_material +; Group material (or NULL) +@t_17 TYPEDEF PTR br_face +; faces in group +; Number of faces in a group +br_face_group STRUCT 4t +material @t_16 ? +faces @t_17 ? +nfaces br_uint_16 ? +br_face_group ENDS + +@t_18 TYPEDEF PTR br_material +; Group material (or NULL) +@t_19 TYPEDEF PTR br_vertex +; vertices in group +; Number of vertices in a group +br_vertex_group STRUCT 4t +material @t_18 ? +vertices @t_19 ? +nvertices br_uint_16 ? +br_vertex_group ENDS + +; +; * Callback function type for custom models +; +@proto_0 TYPEDEF PROTO C :PTR br_actor, :PTR br_model, :PTR br_material, :PTR , :br_uint_8, :SDWORD, :PTR br_matrix34, :PTR br_matrix4 +br_model_custom_cbfn TYPEDEF @proto_0 + +@t_20 TYPEDEF PTR SBYTE +@t_21 TYPEDEF PTR br_vertex +@t_22 TYPEDEF PTR br_face +; +; * Offset of model's pivot point (where it attaches to parent) +; +; +; * Flags describing what is allowed in ModelPrepare() +; +; +; * Application call +; +@t_23 TYPEDEF PTR br_model_custom_cbfn +; +; * Application defined data - untouched by system +; +@t_24 TYPEDEF PTR +; +; * Generated by ModelUpdate +; +; +; * Bounding radius of model from origin +; +; +; * Axis-aligned box that bound model in model coords +; +; +; * Vertices and faces that have been sorted +; * into groups, removing conflicts at material boundaries +; * and smoothign groups +; +@t_25 TYPEDEF PTR br_face +@t_26 TYPEDEF PTR br_vertex +; +; * Groups of faces and vertices, by material +; +@t_27 TYPEDEF PTR br_face_group +@t_28 TYPEDEF PTR br_vertex_group +; +; * Upper limit on the face->edges[] entries +; +; +; * Pointers to tables that map prepared face and vertex indexes +; * back to original face index +; * +; * Only generated if BR_MODF_GENERATE_TAGS is set +; +@t_29 TYPEDEF PTR br_uint_16 +@t_30 TYPEDEF PTR br_uint_16 +; +; * Private fields +; +@t_31 TYPEDEF PTR br_uint_16 +@t_32 TYPEDEF PTR +br_model STRUCT 4t +identifier @t_20 ? +vertices @t_21 ? +faces @t_22 ? +nvertices br_uint_16 ? +nfaces br_uint_16 ? +pivot br_vector3 <> +flags br_uint_16 ? +custom @t_23 ? +user @t_24 ? +radius br_scalar ? +bounds br_bounds <> +nprepared_vertices br_uint_16 ? +nprepared_faces br_uint_16 ? +prepared_faces @t_25 ? +prepared_vertices @t_26 ? +nface_groups br_uint_16 ? +nvertex_groups br_uint_16 ? +face_groups @t_27 ? +vertex_groups @t_28 ? +nedges br_uint_16 ? +face_tags @t_29 ? +vertex_tags @t_30 ? +prep_flags br_uint_32 ? +smooth_strings @t_31 ? +rptr @t_32 ? +br_model ENDS + +; +; * Bits for br_model->flags +; +BR_MODF_DONT_WELD EQU 1t +; Vertices with same x,y,z cannot be merged +BR_MODF_KEEP_ORIGINAL EQU 2t +; Don't release model->faces/vertices during ModelUpdate() +BR_MODF_GENERATE_TAGS EQU 4t +; Allocate and fill in the face and vertex tag structures +BR_MODF_QUICK_UPDATE EQU 16t +; ModelUpdate is fast - but may produce slower models +BR_MODF_CUSTOM EQU 32t +; Invoke custom callback for this model +; Model structure is pre-prepared - update performs no work +BR_MODF_PREPREPARED EQU 64t + +; +; * Flags to BrModelUpdate() +; +BR_MODU_NORMALS EQU 1t +BR_MODU_EDGES EQU 2t +BR_MODU_RADIUS EQU 4t +BR_MODU_GROUPS EQU 8t +BR_MODU_BOUNDING_BOX EQU 16t +BR_MODU_MATERIALS EQU 32t +BR_MODU_ALL EQU 32767t + +; +; * Backwards compatibility +; +; +; * Values for BrModelApplyMap() +; +BR_APPLYMAP_PLANE EQU 0t +BR_APPLYMAP_SPHERE EQU 1t +BR_APPLYMAP_CYLINDER EQU 2t +BR_APPLYMAP_DISC EQU 3t +BR_APPLYMAP_NONE EQU 4t + +; +; * Axis values for BrModelFitMap() +; +BR_FITMAP_PLUS_X EQU 0t +BR_FITMAP_PLUS_Y EQU 1t +BR_FITMAP_PLUS_Z EQU 2t +BR_FITMAP_MINUS_X EQU 3t +BR_FITMAP_MINUS_Y EQU 4t +BR_FITMAP_MINUS_Z EQU 5t + +; +; * Local Variables: +; * tab-width: 4 +; * End: +; +; End of file ..\inc\model.h +; Begin of file ..\inc\actor.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: actor.h 1.15 1995/08/31 16:36:10 sam Exp $ +; * $Locker: $ +; * +; * Definitons for an Actor +; +; * +; ** Definition of base actor structure +; * +; +; * Basic types of actor +; +BR_ACTOR_NONE EQU 0t +BR_ACTOR_MODEL EQU 1t +BR_ACTOR_LIGHT EQU 2t +BR_ACTOR_CAMERA EQU 3t +_BR_ACTOR_RESERVED EQU 4t +BR_ACTOR_BOUNDS EQU 5t +BR_ACTOR_BOUNDS_CORRECT EQU 6t +BR_ACTOR_CLIP_PLANE EQU 7t +BR_ACTOR_MAX EQU 8t + +; +; * Render styles - an actor inherits it's style from the most _distant_ +; * ancestor included in this traversal that does not have default set +; * (unlike model & material which are inherited from the nearest ancestor) +; +BR_RSTYLE_DEFAULT EQU 0t +BR_RSTYLE_NONE EQU 1t +BR_RSTYLE_POINTS EQU 2t +BR_RSTYLE_EDGES EQU 3t +BR_RSTYLE_FACES EQU 4t +BR_RSTYLE_BOUNDING_POINTS EQU 5t +BR_RSTYLE_BOUNDING_EDGES EQU 6t +BR_RSTYLE_BOUNDING_FACES EQU 7t +BR_RSTYLE_MAX EQU 8t + +; +; * The actor structure +; +; +; * Doubly linked list of siblings +; * br_actor can be used as br_simple_node +; +@t_33 TYPEDEF PTR br_actor +@t_34 TYPEDEF PTR PTR br_actor +; +; * First in list of children, or NULL if none +; * br_actor.children can be used as br_simple_list +; +@t_35 TYPEDEF PTR br_actor +; +; * Parent, or NULL, if no higher parent +; +@t_36 TYPEDEF PTR br_actor +; +; * Depth of actor from furthest ancestor +; +; +; * Type of actor +; +; +; * Optional name of actor +; +@t_37 TYPEDEF PTR SBYTE +; +; * Reference to model associated with this actor, NULL will inherit +; * from parent (root inherits default_model) +; +@t_38 TYPEDEF PTR br_model +; +; * Default material for model - NULL will inherit from parent. Root +; * inherits default material +; +@t_39 TYPEDEF PTR br_material +; +; * Render style for actor, and all it's decendants if not BR_RSTYLE_DEFAULT +; +; +; * Reference to renderer specific data associated with this actor - NULL will +; * inherit from parent (root inherits default data) +; +@t_40 TYPEDEF PTR +; +; * Postiton of this actor within parent space +; +; +; * Reference to any type specific data block +; +@t_41 TYPEDEF PTR +br_actor STRUCT 4t +next @t_33 ? +prev @t_34 ? +children @t_35 ? +parent @t_36 ? +depth br_uint_16 ? +_type br_uint_8 ? +identifier @t_37 ? +model @t_38 ? +material @t_39 ? +render_style br_uint_8 ? +render_data @t_40 ? +t br_transform <> +type_data @t_41 ? +br_actor ENDS + +; End of file ..\inc\actor.h +; Begin of file ..\inc\camera.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: camera.h 1.4 1995/05/25 13:37:27 sam Exp $ +; * $Locker: $ +; * +; * Definitons for a camera +; +BR_CAMERA_PARALLEL EQU 0t +BR_CAMERA_PERSPECTIVE_FOV EQU 1t +BR_CAMERA_PERSPECTIVE_WHD EQU 2t + +; +; * Backwards compatibility +; +; +; * Optional identifier +; +@t_42 TYPEDEF PTR SBYTE +; +; * Type of camera +; +; +; * Field of view +; * (BR_CAMERA_PERSPECTIVE_FOV only) +; +; +; * Front and back of view volume in view coordinates +; +; +; * Aspect ratio of viewport +; * (BR_CAMERA_PERSPECTIVE_FOV only) +; +; +; * Width and height of projection surface +; * (BR_CAMERA_PERSPECTIVE_WHD and BR_CAMERA_PARALLEL only) +; +; +; * Distance of projection plane from center of projection +; * (BR_CAMERA_PERSPECTIVE_WHD only) +; +br_camera STRUCT 4t +identifier @t_42 ? +_type br_uint_8 ? +field_of_view br_angle ? +hither_z br_scalar ? +yon_z br_scalar ? +aspect br_scalar ? +_width br_scalar ? +height br_scalar ? +distance br_scalar ? +br_camera ENDS + +; End of file ..\inc\camera.h +; Begin of file ..\inc\light.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: light.h 1.6 1995/05/25 13:37:32 sam Exp $ +; * $Locker: $ +; * +; * Definitons for a light +; +; +; * Type of light +; +BR_LIGHT_TYPE EQU 3t +BR_LIGHT_POINT EQU 0t +BR_LIGHT_DIRECT EQU 1t +BR_LIGHT_SPOT EQU 2t +; +; * Flag idicating that caluculations are done in view space +; +BR_LIGHT_VIEW EQU 4t + +; +; * Optional identifier +; +@t_43 TYPEDEF PTR SBYTE +; +; * Type of light +; +; +; * Colour of light (if renderer supports it) +; +; +; * Attenuation of light with distance - constant, linear, and quadratic +; * l & q only apply to point and spot lights +; +; +; * Cone angles for spot light +; +br_light STRUCT 4t +identifier @t_43 ? +_type br_uint_8 ? +colour br_colour ? +attenuation_c br_scalar ? +attenuation_l br_scalar ? +attenuation_q br_scalar ? +cone_outer br_angle ? +cone_inner br_angle ? +br_light ENDS + +; End of file ..\inc\light.h +; Begin of file ..\inc\pool.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: pool.h 1.7 1995/02/22 21:37:18 sam Exp $ +; * $Locker: $ +; * +; * Fixed size block pools +; +BR_POOL_DEBUG EQU 0t +BR_POOL_ALIGN EQU 7t +@t_44 TYPEDEF PTR br_pool_block +br_pool_block STRUCT 4t +next @t_44 ? +br_pool_block ENDS + +@t_45 TYPEDEF PTR br_pool_block +br_pool STRUCT 4t +free @t_45 ? +block_size br_uint_32 ? +chunk_size br_uint_32 ? +mem_type SDWORD ? +br_pool ENDS + +; +; * Speedup macros +; +; End of file ..\inc\pool.h +; Begin of file ..\inc\custsupt.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: custsupt.h 1.2 1995/02/22 21:37:05 sam Exp $ +; * $Locker: $ +; * +; * Definitions for support routines available during render callbacks +; * +; +; +; * Outcode bits +; +OUTCODE_LEFT EQU 000000001h +OUTCODE_RIGHT EQU 000000002h +OUTCODE_TOP EQU 000000004h +OUTCODE_BOTTOM EQU 000000008h +OUTCODE_HITHER EQU 000000010h +OUTCODE_YON EQU 000000020h +OUTCODE_USER EQU 000000040h +OUTCODE_USER_ALL EQU 000000fc0h +OUTCODES_ALL EQU 000000fffh +OUTCODE_N_LEFT EQU 000010000h +OUTCODE_N_RIGHT EQU 000020000h +OUTCODE_N_TOP EQU 000040000h +OUTCODE_N_BOTTOM EQU 000080000h +OUTCODE_N_HITHER EQU 000100000h +OUTCODE_N_YON EQU 000200000h +OUTCODE_N_USER EQU 000400000h +OUTCODE_N_USER_ALL EQU 00fc00000h +OUTCODES_NOT EQU 00fff0000h +; +; * Values for on screen test +; +OSC_REJECT EQU 0t +OSC_PARTIAL EQU 1t +OSC_ACCEPT EQU 2t + +; End of file ..\inc\custsupt.h +; Begin of file ..\inc\brfile.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brfile.h 1.7 1995/02/22 21:36:59 sam Exp $ +; * $Locker: $ +; * +; * Brender's interface to file IO +; +@proto_1 TYPEDEF PROTO C :PTR br_uint_8, :br_size_t +br_mode_test_cbfn TYPEDEF @proto_1 + +; +; * Interface to filesystem +; +@proto_2 TYPEDEF PROTO C +brfile_attributes_cbfn TYPEDEF @proto_2 + +@proto_3 TYPEDEF PROTO C :PTR SBYTE, :br_size_t, :PTR br_mode_test_cbfn, :PTR SDWORD +brfile_open_read_cbfn TYPEDEF @proto_3 + +@proto_4 TYPEDEF PROTO C :PTR SBYTE, :SDWORD +brfile_open_write_cbfn TYPEDEF @proto_4 + +@proto_5 TYPEDEF PROTO C :PTR +brfile_close_cbfn TYPEDEF @proto_5 + +@proto_6 TYPEDEF PROTO C :PTR +brfile_eof_cbfn TYPEDEF @proto_6 + +@proto_7 TYPEDEF PROTO C :PTR +brfile_getchr_cbfn TYPEDEF @proto_7 + +@proto_8 TYPEDEF PROTO C :SDWORD, :PTR +brfile_putchr_cbfn TYPEDEF @proto_8 + +@proto_9 TYPEDEF PROTO C :PTR , :br_size_t, :DWORD, :PTR +brfile_read_cbfn TYPEDEF @proto_9 + +@proto_10 TYPEDEF PROTO C :PTR , :br_size_t, :DWORD, :PTR +brfile_write_cbfn TYPEDEF @proto_10 + +@proto_11 TYPEDEF PROTO C :PTR SBYTE, :br_size_t, :PTR +brfile_getline_cbfn TYPEDEF @proto_11 + +@proto_12 TYPEDEF PROTO C :PTR SBYTE, :PTR +brfile_putline_cbfn TYPEDEF @proto_12 + +@proto_13 TYPEDEF PROTO C :br_size_t, :PTR +brfile_advance_cbfn TYPEDEF @proto_13 + +@t_46 TYPEDEF PTR SBYTE +; +; * Inquire about attributes of file system +; +@t_47 TYPEDEF PTR brfile_attributes_cbfn +; +; * Locate and open a file, and then grab 'n_magics' bytes +; * from the front of the file and pass them to a an 'identify' +; * function that returns the mode of the file +; * +; * Returns file handle, or NULL if open failed +; * +; * Stores open mode through mode_result if not NULL +; +@t_48 TYPEDEF PTR brfile_open_read_cbfn +; +; * Open a file for writing, possibly with text translation +; * +; * Returns fil handle, or NULL if open failed +; +@t_49 TYPEDEF PTR brfile_open_write_cbfn +; +; * Close an opened file +; +@t_50 TYPEDEF PTR brfile_close_cbfn +; +; * Find out if at end of file +; +@t_51 TYPEDEF PTR brfile_eof_cbfn +; +; * Read and write single characters +; +@t_52 TYPEDEF PTR brfile_getchr_cbfn +@t_53 TYPEDEF PTR brfile_putchr_cbfn +; +; * Read and write blocks +; +@t_54 TYPEDEF PTR brfile_read_cbfn +@t_55 TYPEDEF PTR brfile_write_cbfn +; +; * Read and write lines of text, excluding any line terminators +; * Will only be used if text translation is in use +; +@t_56 TYPEDEF PTR brfile_getline_cbfn +@t_57 TYPEDEF PTR brfile_putline_cbfn +; +; * Advance bytes through stream +; * +; * Will not be invoked if text translation is in use +; +@t_58 TYPEDEF PTR brfile_advance_cbfn +br_filesystem STRUCT 4t +identifier @t_46 ? +attributes @t_47 ? +open_read @t_48 ? +open_write @t_49 ? +close @t_50 ? +eof @t_51 ? +getchr @t_52 ? +putchr @t_53 ? +read @t_54 ? +write @t_55 ? +getline @t_56 ? +putline @t_57 ? +advance @t_58 ? +br_filesystem ENDS + +; +; * Bitmask returned by fs->attributes +; +BR_FS_ATTR_READABLE EQU 1t +BR_FS_ATTR_WRITEABLE EQU 2t +BR_FS_ATTR_HAS_TEXT EQU 4t +BR_FS_ATTR_HAS_BINARY EQU 8t +BR_FS_ATTR_HAS_ADVANCE EQU 16t + +; +; * Possible values returner by open_read identify callback +; +BR_FS_MODE_BINARY EQU 0t +BR_FS_MODE_TEXT EQU 1t +BR_FS_MODE_UNKNOWN EQU 2t + +; +; * Maximum number of magic bytes that can be requested on open_read +; +BR_MAX_FILE_MAGICS EQU 16t +; +; * Returned by filesys->getchr at end of file +; +BR_EOF EQU 0ffffffffh +; End of file ..\inc\brfile.h +; Begin of file ..\inc\brdiag.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brdiag.h 1.1 1995/07/28 18:57:13 sam Exp $ +; * $Locker: $ +; * +; * Brender's interface to diagnostic handling +; +; +; * Instance of an error handler +; +@proto_14 TYPEDEF PROTO C :PTR SBYTE +br_diag_warning_cbfn TYPEDEF @proto_14 + +@proto_15 TYPEDEF PROTO C :PTR SBYTE +br_diag_failure_cbfn TYPEDEF @proto_15 + +@t_59 TYPEDEF PTR SBYTE +@t_60 TYPEDEF PTR br_diag_warning_cbfn +@t_61 TYPEDEF PTR br_diag_failure_cbfn +br_diaghandler STRUCT 4t +identifier @t_59 ? +warning @t_60 ? +failure @t_61 ? +br_diaghandler ENDS + +; +; * For backwards compatibility +; +@t_62 TYPEDEF PTR SBYTE +@t_63 TYPEDEF PTR br_diag_warning_cbfn +@t_64 TYPEDEF PTR br_diag_failure_cbfn +br_errorhandler STRUCT 4t +identifier @t_62 ? +message @t_63 ? +error @t_64 ? +br_errorhandler ENDS + +; * +; ** Macros for diagnostic generation +; * +; +; * Report message and exit - should not return to application +; +; +; * Report message and continue +; +; +; * Report message and exit, including source file and line number +; +; +; * Backwards compatibility +; +; End of file ..\inc\brdiag.h +; Begin of file ..\inc\brmem.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brmem.h 1.15 1995/08/31 16:36:13 sam Exp $ +; * $Locker: $ +; * +; * Brender's interface to memory allocation +; +; +; * Instance of a memory allocator +; +@proto_16 TYPEDEF PROTO C :br_size_t, :br_uint_8 +brmem_allocate_cbfn TYPEDEF @proto_16 + +@proto_17 TYPEDEF PROTO C :PTR +brmem_free_cbfn TYPEDEF @proto_17 + +@proto_18 TYPEDEF PROTO C :br_uint_8 +brmem_inquire_cbfn TYPEDEF @proto_18 + +@t_65 TYPEDEF PTR SBYTE +; +; * Allocate a new chunk of memory - must return the new pointer +; * or handle the error itself +; +@t_66 TYPEDEF PTR brmem_allocate_cbfn +; +; * Release previously allocated block +; +@t_67 TYPEDEF PTR brmem_free_cbfn +; +; * Inquire as to the amount of memeory available for a given type +; +@t_68 TYPEDEF PTR brmem_inquire_cbfn +br_allocator STRUCT 4t +identifier @t_65 ? +allocate @t_66 ? +free @t_67 ? +inquire @t_68 ? +br_allocator ENDS + +; +; * Classes of resource that brender allocates +; * +; * Valid values are 1 to 255 +; +; +; * System classes +; +BR_MEMORY_SCRATCH EQU 1t +BR_MEMORY_PIXELMAP EQU 2t +BR_MEMORY_PIXELS EQU 3t +BR_MEMORY_VERTICES EQU 4t +BR_MEMORY_FACES EQU 5t +BR_MEMORY_GROUPS EQU 6t +BR_MEMORY_MODEL EQU 7t +BR_MEMORY_MATERIAL EQU 8t +BR_MEMORY_MATERIAL_INDEX EQU 9t +BR_MEMORY_ACTOR EQU 10t +BR_MEMORY_PREPARED_VERTICES EQU 11t +BR_MEMORY_PREPARED_FACES EQU 12t +BR_MEMORY_LIGHT EQU 13t +BR_MEMORY_CAMERA EQU 14t +BR_MEMORY_BOUNDS EQU 15t +BR_MEMORY_CLIP_PLANE EQU 16t +BR_MEMORY_STRING EQU 17t +BR_MEMORY_REGISTRY EQU 18t +BR_MEMORY_TRANSFORM EQU 19t +BR_MEMORY_RESOURCE_CLASS EQU 20t +BR_MEMORY_FILE EQU 21t +BR_MEMORY_ANCHOR EQU 22t +BR_MEMORY_POOL EQU 23t +BR_MEMORY_RENDER_MATERIAL EQU 24t +BR_MEMORY_DATAFILE EQU 25t +BR_MEMORY_IMAGE EQU 26t +BR_MEMORY_IMAGE_ARENA EQU 27t +BR_MEMORY_IMAGE_SECTIONS EQU 28t +BR_MEMORY_IMAGE_NAMES EQU 29t +BR_MEMORY_EXCEPTION_HANDLER EQU 30t +BR_MEMORY_RENDER_DATA EQU 31t +; +; * Application classes +; +BR_MEMORY_APPLICATION EQU 128t +; +; * User defined classed are BR_MEMORY_APPLICATION + 1 ... 127 +; +BR_MEMORY_MAX EQU 256t + +; +; * A resource class structure +; +@proto_19 TYPEDEF PROTO C :PTR , :br_uint_8, :br_size_t +br_resourcefree_cbfn TYPEDEF @proto_19 + +@t_69 TYPEDEF PTR SBYTE +@t_70 TYPEDEF PTR br_resourcefree_cbfn +br_resource_class STRUCT 4t +identifier @t_69 ? +res_class br_uint_8 ? +free_cb @t_70 ? +br_resource_class ENDS + +; End of file ..\inc\brmem.h +; Begin of file ..\inc\brerr.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brerr.h 1.4 1995/07/28 18:57:02 sam Exp $ +; * $Locker: $ +; * +; * Error type +; +; +; * Error types are 32 bit integers, broken into three fields - +; * +; * Class Subclass Number +; * +; * 33222222 22221111 1111110000000000 +; * 10987654 32109876 5432109876543210 +; * +; * A value of zero is reserved to indiciate no error +; +br_error TYPEDEF br_uint_32 + +; End of file ..\inc\brerr.h +; Begin of file ..\inc\fmt.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: fmt.h 1.5 1995/02/22 21:37:06 sam Exp $ +; * $Locker: $ +; * +; * Definitions for foreign file format support +; +; +; * Type of things to load from file +; +BR_FMT_MODELS EQU 1t +; Create model definitions from file +BR_FMT_ACTORS EQU 2t +; Create actor +BR_FMT_LIGHTS EQU 4t +; Create lights instances +BR_FMT_CAMERAS EQU 8t +; Create cameras instances +; Create materials +BR_FMT_MATERIALS EQU 16t + +; +; * Interchange structure for passing to file format loaders +; * +; * XXX Not yet used by anything +; +; +; * pointers to tables of each loaded allocated by BrFMTxxxLoad() +; +@t_71 TYPEDEF PTR br_model +@t_72 TYPEDEF PTR br_model +@t_73 TYPEDEF PTR br_model +@t_74 TYPEDEF PTR br_model +@t_75 TYPEDEF PTR br_model +; +; * Size of each allocated array +; +br_fmt_results STRUCT 4t +models @t_71 ? +materials @t_72 ? +lights @t_73 ? +cameras @t_74 ? +actors @t_75 ? +nmodels SDWORD ? +nmaterials SDWORD ? +nlights SDWORD ? +ncameras SDWORD ? +nactors SDWORD ? +br_fmt_results ENDS + +; Begin of file ..\inc\fmtproto.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: fmtproto.h 1.8 1995/05/30 16:57:38 sam Exp $ +; * $Locker: $ +; * +; * Function prototypes for foreign file format support +; +; +; * Eric Haines' NFF format +; +@proto_20 TYPEDEF PROTO C :PTR SBYTE +BrFmtNFFLoad PROTO @proto_20 + +; +; * 3D Studio .ASC files +; +@proto_21 TYPEDEF PROTO C :PTR SBYTE, :PTR PTR br_model, :br_uint_16 +BrFmtASCLoad PROTO @proto_21 + +; +; * Script files +; +@proto_22 TYPEDEF PROTO C :PTR SBYTE, :PTR PTR br_material, :br_uint_16 +BrFmtScriptMaterialLoadMany PROTO @proto_22 + +@proto_23 TYPEDEF PROTO C :PTR SBYTE +BrFmtScriptMaterialLoad PROTO @proto_23 + +@proto_24 TYPEDEF PROTO C :PTR SBYTE, :PTR PTR br_material, :br_uint_16 +BrFmtScriptMaterialSaveMany PROTO @proto_24 + +@proto_25 TYPEDEF PROTO C :PTR SBYTE, :PTR br_material +BrFmtScriptMaterialSave PROTO @proto_25 + +; +; * Windows .BMP files +; +@proto_26 TYPEDEF PROTO C :PTR SBYTE, :br_uint_32 +BrFmtBMPLoad PROTO @proto_26 + +; +; * .TGA files +; +@proto_27 TYPEDEF PROTO C :PTR SBYTE, :br_uint_32 +BrFmtTGALoad PROTO @proto_27 + +; +; * .GIF files +; +@proto_28 TYPEDEF PROTO C :PTR SBYTE, :br_uint_32 +BrFmtGIFLoad PROTO @proto_28 + +; +; * .IFF/.LBM files +; +@proto_29 TYPEDEF PROTO C :PTR SBYTE, :br_uint_32 +BrFmtIFFLoad PROTO @proto_29 + +; End of file ..\inc\fmtproto.h +; End of file ..\inc\fmt.h +; +; * Function prototypes +; +; Begin of file ..\inc\fwproto.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: fwproto.h 1.44 1995/08/31 16:36:16 sam Exp $ +; * $Locker: sam $ +; * +; * Function prototypes for brender framework +; +; End of file ..\inc\fwproto.h +; Begin of file ..\inc\zbproto.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: zbproto.h 1.9 1995/08/31 16:36:24 sam Exp $ +; * $Locker: $ +; * +; * Function prototypes for Z buffer renderer +; +BR_BOUNDS_MIN_X EQU 0t +BR_BOUNDS_MIN_Y EQU 1t +BR_BOUNDS_MAX_X EQU 2t +BR_BOUNDS_MAX_Y EQU 3t +; +; * Callback function invoked when an actor is +; * rendered +; +@proto_30 TYPEDEF PROTO C :PTR br_actor, :PTR br_model, :PTR br_material, :PTR , :br_uint_8, :PTR br_matrix4, :PTR br_int_32 +br_renderbounds_cbfn TYPEDEF @proto_30 + +; End of file ..\inc\zbproto.h +; Begin of file ..\inc\zsproto.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: zsproto.h 1.1 1995/08/31 16:37:20 sam Exp $ +; * $Locker: $ +; * +; * Function prototypes for bucket Z-sort renderer +; +; +; * Sort types for primitive insertion +; +BR_ZSORT_MIN EQU 1t +BR_ZSORT_MAX EQU 2t +BR_ZSORT_AVERAGE EQU 4t + +; +; * Callback function invoked when primitive is generated +; +@proto_31 TYPEDEF PROTO C :PTR , :PTR br_actor, :PTR br_model, :PTR br_material, :PTR br_order_table, :PTR br_scalar +br_primitive_cbfn TYPEDEF @proto_31 + +; End of file ..\inc\zsproto.h +; Begin of file ..\inc\fwpextra.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * Extra glue for C<->ASM generated via gemasmpr.pl +; +; End of file ..\inc\fwpextra.h +; +; * Inline functions +; +; Begin of file ..\inc\compend.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: compend.h 1.1 1995/08/31 16:36:45 sam Exp $ +; * $Locker: $ +; * +; * Included at end of BRender includes - undoes any compiler specific pragmas +; +; +; * WATCOM C/C++ 32 +; +; +; * Metaware High-C Version 1 +; +; End of file ..\inc\compend.h +; End of file ..\inc\brender.h +; Begin of file ..\fw\brlists.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brlists.h 1.4 1995/02/22 21:41:25 sam Exp $ +; * $Locker: $ +; * +; * Doubly linked list supoprt (Based on Amiga EXEC!) +; +; * +; ** Full featued doubly linked lists +; * +; +; * Anchor structure at front of list entries +; +@t_76 TYPEDEF PTR br_node +@t_77 TYPEDEF PTR br_node +br_node STRUCT 4t +next @t_76 ? +prev @t_77 ? +br_node ENDS + +; +; * Anchor structure for whole list - looks like two nodes overlapping. +; * The _null memeber is always NULL, providing the termination at +; * both ends of the list +; +@t_78 TYPEDEF PTR br_node +@t_79 TYPEDEF PTR br_node +@t_80 TYPEDEF PTR br_node +br_list STRUCT 4t +head @t_78 ? +_null @t_79 ? +tail @t_80 ? +br_list ENDS + +; +; * Walk a pointer forwards along a list +; * +; * eg: +; * BR_FOR_LIST(sprites,sptr) { +; * sptr->x = 10; +; * } +; +; +; * Walk a pointer backwards along a list +; * +; * eg: +; * BR_FOR_LIST_R(sprites,sptr) { +; * sptr->x = 10; +; * } +; +; +; * Macros around exported functions that hide type casting +; +; * +; ** Simple lists that only use a single head pointer +; * +@t_81 TYPEDEF PTR br_simple_node +@t_82 TYPEDEF PTR PTR br_simple_node +br_simple_node STRUCT 4t +next @t_81 ? +prev @t_82 ? +br_simple_node ENDS + +; +; * Anchor structure for whole list - just a single head pointer +; +@t_83 TYPEDEF PTR br_simple_node +br_simple_list STRUCT 4t +head @t_83 ? +br_simple_list ENDS + +; +; * Macros around exported functions that hide type casting +; +; +; * Protoypes in lists.c +; +; End of file ..\fw\brlists.h +; Begin of file ..\fw\brexcept.h +; +; * Copyright (c) 1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brexcept.h 1.2 1995/07/28 19:01:35 sam Exp $ +; * $Locker: $ +; * +; * Simple exception handling +; +; +; * Exception types are the same as error types +; * +; * A value of zero is reserved +; +br_exception TYPEDEF br_error + +; +; * Useful macros for generating types +; +; +; * Exception handler - allocated as a resource +; +@t_84 TYPEDEF PTR br_exception_handler +; +; * setjmp/longjmp context to throw to +; +br_exception_handler STRUCT 4t +prev @t_84 ? +br_exception_handler ENDS + +; +; * Public macros +; +; End of file ..\fw\brexcept.h +; Begin of file ..\fw\brimage.h +; +; * Copyright (c) 1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brimage.h 1.1 1995/07/28 19:03:11 sam Exp $ +; * $Locker: $ +; * +; +; +; * In-memory structure describing a loaded image +; +@t_85 TYPEDEF PTR SBYTE +@t_86 TYPEDEF PTR +br_image_section STRUCT 4t +name @t_85 ? +base @t_86 ? +mem_offset br_size_t ? +mem_size br_size_t ? +data_offset br_uint_32 ? +data_size br_uint_32 ? +br_image_section ENDS + +; +; * Anchor block for list of images +; +; +; * DLL name +; +@t_87 TYPEDEF PTR SBYTE +; +; * Flag, true if DLL is resident +; +; +; * Number of references to this DLL +; +; +; * Table of exported functions +; +@t_88 TYPEDEF PTR PTR +; +; * Name -> ordinal lookup +; +@t_89 TYPEDEF PTR PTR SBYTE +@t_90 TYPEDEF PTR br_uint_16 +; +; * Table of imported image pointers +; +@t_91 TYPEDEF PTR PTR br_image +; +; * Image sections +; +@t_92 TYPEDEF PTR br_image_section +br_image STRUCT 4t +node br_node <> +identifier @t_87 ? +resident br_boolean ? +ref_count SDWORD ? +ordinal_base br_uint_32 ? +n_functions br_uint_32 ? +functions @t_88 ? +n_names br_uint_32 ? +names @t_89 ? +name_ordinals @t_90 ? +n_imports br_uint_16 ? +imports @t_91 ? +n_sections br_uint_16 ? +sections @t_92 ? +br_image ENDS + +; End of file ..\fw\brimage.h +; Begin of file ..\fw\register.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: register.h 1.7 1995/03/16 11:57:08 sam Exp $ +; * $Locker: $ +; * +; * +; +; +; * An entry in a registry - doubly linked list and pointers to data +; * +; * It is assumed that the first thing in the data structure is a pointer +; * to the item's name +; +@t_93 TYPEDEF PTR PTR SBYTE +br_registry_entry STRUCT 4t +node br_node <> +item @t_93 ? +br_registry_entry ENDS + +@proto_32 TYPEDEF PROTO C :PTR SBYTE +br_find_failed_cbfn TYPEDEF @proto_32 + +@proto_33 TYPEDEF PROTO C :PTR , :PTR +br_enum_cbfn TYPEDEF @proto_33 + +; +; * Base structure for registry +; +; +; * Anchor structure +; +; +; * Number of items in list +; +; +; * Hook that is called when RegistryFind fails +; +@t_94 TYPEDEF PTR br_find_failed_cbfn +br_registery STRUCT 4t +list br_list <> +count SDWORD ? +find_failed_hook @t_94 ? +br_registery ENDS + +br_registry TYPEDEF br_registery + +; End of file ..\fw\register.h +; Begin of file ..\fw\device.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: device.h 1.5 1995/07/28 19:01:38 sam Exp $ +; * $Locker: $ +; * +; * Device structure - a function dispatch table for pixelmap operations +; +; +; * function list for pixelmaps->context +; +@proto_34 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_32 +ctx_fill_cbfn TYPEDEF @proto_34 + +@proto_35 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_32 +ctx_rectangle_cbfn TYPEDEF @proto_35 + +@proto_36 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_32, :br_uint_32 +ctx_rectangle2_cbfn TYPEDEF @proto_36 + +@proto_37 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16 +ctx_rectangle_copy_cbfn TYPEDEF @proto_37 + +@proto_38 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_32 +ctx_rectangle_fill_cbfn TYPEDEF @proto_38 + +@proto_39 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16 +ctx_dirty_rectangle_copy_cbfn TYPEDEF @proto_39 + +@proto_40 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_32 +ctx_dirty_rectangle_fill_cbfn TYPEDEF @proto_40 + +@proto_41 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_32 +ctx_pixel_set_cbfn TYPEDEF @proto_41 + +@proto_42 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16 +ctx_pixel_get_cbfn TYPEDEF @proto_42 + +@proto_43 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :PTR br_pixelmap +ctx_copy_cbfn TYPEDEF @proto_43 + +@proto_44 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_int_16, :br_int_16, :br_int_16, :br_int_16, :br_uint_32 +ctx_line_cbfn TYPEDEF @proto_44 + +@proto_45 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_int_16, :br_int_16, :PTR br_uint_8, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_32 +ctx_copy_bits_cbfn TYPEDEF @proto_45 + +@proto_46 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :PTR br_pixelmap +ctx_double_buffer_cbfn TYPEDEF @proto_46 + +@proto_47 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_8 +ctx_match_cbfn TYPEDEF @proto_47 + +@proto_48 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap +ctx_clone_cbfn TYPEDEF @proto_48 + +@proto_49 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap +ctx_free_cbfn TYPEDEF @proto_49 + +; +; * Device context structure +; +; +; * General ID for this structure +; +@t_95 TYPEDEF PTR SBYTE +; +; * Pointer to underlying device +; +@t_96 TYPEDEF PTR br_device +; +; * Font for context +; +@t_97 TYPEDEF PTR br_font +; +; * Default qualifier for display memory +; +; * +; ** Function pointers for all the context operations +; * +; +; * Pixelmap management operations +; +@t_98 TYPEDEF PTR ctx_free_cbfn +@t_99 TYPEDEF PTR ctx_match_cbfn +@t_100 TYPEDEF PTR ctx_clone_cbfn +@t_101 TYPEDEF PTR ctx_double_buffer_cbfn +; +; * Pixelmap copying +; +@t_102 TYPEDEF PTR ctx_copy_cbfn +@t_103 TYPEDEF PTR ctx_copy_cbfn +@t_104 TYPEDEF PTR ctx_copy_cbfn +; +; * Rendering operations +; +@t_105 TYPEDEF PTR ctx_fill_cbfn +@t_106 TYPEDEF PTR ctx_rectangle_cbfn +@t_107 TYPEDEF PTR ctx_rectangle2_cbfn +@t_108 TYPEDEF PTR ctx_rectangle_copy_cbfn +@t_109 TYPEDEF PTR ctx_rectangle_copy_cbfn +@t_110 TYPEDEF PTR ctx_rectangle_copy_cbfn +@t_111 TYPEDEF PTR ctx_rectangle_fill_cbfn +@t_112 TYPEDEF PTR ctx_dirty_rectangle_copy_cbfn +@t_113 TYPEDEF PTR ctx_dirty_rectangle_fill_cbfn +@t_114 TYPEDEF PTR ctx_pixel_set_cbfn +@t_115 TYPEDEF PTR ctx_pixel_get_cbfn +@t_116 TYPEDEF PTR ctx_line_cbfn +@t_117 TYPEDEF PTR ctx_copy_bits_cbfn +br_context STRUCT 4t +identifier @t_95 ? +device @t_96 ? +font @t_97 ? +free @t_98 ? +match @t_99 ? +clone @t_100 ? +double_buffer @t_101 ? +copy @t_102 ? +copy_to @t_103 ? +copy_from @t_104 ? +fill @t_105 ? +rectangle @t_106 ? +rectangle2 @t_107 ? +rectangle_copy @t_108 ? +rectangle_copy_to @t_109 ? +rectangle_copy_from @t_110 ? +rectangle_fill @t_111 ? +dirty_rectangle_copy @t_112 ? +dirty_rectangle_fill @t_113 ? +pixel_set @t_114 ? +pixel_get @t_115 ? +line @t_116 ? +copy_bits @t_117 ? +br_context ENDS + +; +; * Generic device class structure +; +@proto_50 TYPEDEF PROTO C :PTR br_device +dev_load_cbfn TYPEDEF @proto_50 + +@proto_51 TYPEDEF PROTO C :PTR br_device +dev_unload_cbfn TYPEDEF @proto_51 + +@proto_52 TYPEDEF PROTO C :PTR br_device +dev_enquire_cbfn TYPEDEF @proto_52 + +@proto_53 TYPEDEF PROTO C :PTR br_device +dev_create_cbfn TYPEDEF @proto_53 + +; +; * Loaded devices are linked into a list +; +@t_118 TYPEDEF PTR SBYTE +@t_119 TYPEDEF PTR dev_enquire_cbfn +@t_120 TYPEDEF PTR dev_load_cbfn +@t_121 TYPEDEF PTR dev_unload_cbfn +@t_122 TYPEDEF PTR dev_create_cbfn +br_device STRUCT 4t +node br_node <> +identifier @t_118 ? +enquire @t_119 ? +load @t_120 ? +unload @t_121 ? +create @t_122 ? +br_device ENDS + +; +; * Given a pixelmap, returns the context to use +; * +; * XXX Handles NULL context pointer, but that should be sorted out in +; * PixelmapAllocate +; +; End of file ..\fw\device.h +; +; * Per vertex components +; +C_X EQU 0t +C_Y EQU 1t +C_Z EQU 2t +C_W EQU 3t +C_U EQU 4t +C_V EQU 5t +C_I EQU 6t +C_R EQU 7t +C_G EQU 8t +C_B EQU 9t +C_Q EQU 10t +NUM_COMPONENTS EQU 11t + +; +; * Mask bits for selecting which components take part in various operations +; +CM_X EQU 1t +CM_Y EQU 2t +CM_Z EQU 4t +CM_W EQU 8t +CM_U EQU 16t +CM_V EQU 32t +CM_I EQU 64t +CM_R EQU 128t +CM_G EQU 256t +CM_B EQU 512t +CM_Q EQU 1024t + +; +; * Limited set of components used for lighting sub functions +; +L_I EQU 0t +L_R EQU 1t +L_G EQU 2t +L_B EQU 3t +NUM_L_COMPONENTS EQU 4t + +; +; * Private information about a light as it applies to the current model +; +; +; * Light intensity +; +; +; * position and direction of light in view space +; +; +; * Position and direction of light in final space, view or model +; +; +; * Half vector for specular effects +; +; +; * Cosine of spot angles +; +; +; * Function to evaluate this light +; +@proto_54 TYPEDEF PROTO C :PTR br_vector3, :PTR br_fvector3, :PTR br_active_light, :PTR br_scalar +@t_123 TYPEDEF PTR @proto_54 +; +; * Copy of light's type - may vary from original if a model's relationship +; * to light allows optimisation, eg: +; * very far point light -> directional light +; * model compeletely within spot cone -> point light +; +@t_124 TYPEDEF PTR br_light +br_active_light STRUCT 4t +intensity br_scalar ? +view_position br_vector3 <> +view_direction br_vector3 <> +position br_vector3 <> +direction br_vector3 <> +half br_vector3 <> +spot_cosine_outer br_scalar ? +spot_cosine_inner br_scalar ? +light_sub_function @t_123 ? +_type SDWORD ? +light @t_124 ? +br_active_light ENDS + +; +; * Private information about an active clip plane +; +; +; * Planer eqn. in screen space +; +br_active_clip_plane STRUCT 4t +screen_plane br_vector4 <> +br_active_clip_plane ENDS + +; +; * Framework has a table of functions used for lighting - this +; * will be initialised according to what sort of output is required +; * (eg: indexed or RGB) +; +@proto_55 TYPEDEF PROTO C :PTR br_vertex, :PTR br_fvector3, :PTR br_scalar +br_surface_fn TYPEDEF @proto_55 + +@proto_56 TYPEDEF PROTO C :PTR br_vertex, :PTR br_face, :SDWORD +br_face_surface_fn TYPEDEF @proto_56 + +@proto_57 TYPEDEF PROTO C :PTR br_vector3, :PTR br_fvector3, :PTR br_active_light, :PTR br_scalar +br_light_sub_fn TYPEDEF @proto_57 + +@proto_58 TYPEDEF PROTO C :PTR br_model, :br_uint_16 +br_model_update_cbfn TYPEDEF @proto_58 + +@proto_59 TYPEDEF PROTO C :PTR br_material, :br_uint_16 +br_material_update_cbfn TYPEDEF @proto_59 + +@proto_60 TYPEDEF PROTO C :PTR br_pixelmap, :br_uint_16 +br_table_update_cbfn TYPEDEF @proto_60 + +@proto_61 TYPEDEF PROTO C :PTR br_pixelmap, :br_uint_16 +br_map_update_cbfn TYPEDEF @proto_61 + +; +; * Top level surface functions +; +@t_125 TYPEDEF PTR br_surface_fn +; Evauluate lighting +@t_126 TYPEDEF PTR br_surface_fn +; Copy material +@t_127 TYPEDEF PTR br_surface_fn +; Copy vertex +@t_128 TYPEDEF PTR br_surface_fn +; simple light plus simple texture mapping +@t_129 TYPEDEF PTR br_face_surface_fn +; Evauluate surface for a face +; +; * Lighting +; +@t_130 TYPEDEF PTR br_light_sub_fn +@t_131 TYPEDEF PTR br_light_sub_fn +@t_132 TYPEDEF PTR br_light_sub_fn +@t_133 TYPEDEF PTR br_light_sub_fn +@t_134 TYPEDEF PTR br_light_sub_fn +fw_fn_table STRUCT 4t +light @t_125 ? +light_material @t_126 ? +light_vertex @t_127 ? +light_texture @t_128 ? +face_light @t_129 ? +direct @t_130 ? +point @t_131 ? +point_attn @t_132 ? +spot @t_133 ? +spot_attn @t_134 ? +fw_fn_table ENDS + +; +; * Private state of framework +; +; +; * Main surface properties function +; +@t_135 TYPEDEF PTR br_surface_fn +; +; * Called after U,V generation +; +@t_136 TYPEDEF PTR br_surface_fn +; +; * Called after component copying +; +@t_137 TYPEDEF PTR br_surface_fn +; +; * Lighting a face - usually calls vertex function and converts result for faces +; +@t_138 TYPEDEF PTR br_face_surface_fn +; +; * Current mapping coordinate transform +; +; +; * Base and scale for indexes +; +; +; * Current Transforms +; +; +; * List of transforms from camera to root with associated actor address +; +@t_139 TYPEDEF PTR br_actor +@tag_28 STRUCT 4t +m br_matrix34 <> +_a @t_139 ? +@tag_28 ENDS + +; +; * Type of view to screen transform +; +; +; * COP in model space +; +; +; * Material curently in use - used for lighting calcs. +; +@t_140 TYPEDEF PTR br_material +; +; * Information about each active light, the lights that need to be +; * processed in model space are first, followed by those processed +; * in view space +; +; +; * numbers of active lights of each type +; +; +; * Flag that is set if there is only 1 direct light in model space +; +; +; * Eye vector to use for lighting, either in model or view space +; +; +; * A table of active clip planes +; +; +; * A table of pointers to enabled lights +; * +; * If an entry is not NULL then the referenced actor is an enabled light +; +@t_141 TYPEDEF PTR br_actor +; +; * A table of pointers to enabled clip planes +; * +; * If an entry is not NULL then the referenced actor is a clip plane +; +@t_142 TYPEDEF PTR br_actor +; +; * A pointer to the current environment - if NULL, then the model's +; * local frame will be used +; +@t_143 TYPEDEF PTR br_actor +; +; * Output pixelmap +; +@t_144 TYPEDEF PTR br_pixelmap +; +; * Viewport parameters +; +; +; * Flag that is true if rendering is going on +; +; +; * Various lists of registered items +; +; +; * An index of registered resources by class +; +@t_145 TYPEDEF PTR br_resource_class +; +; * Renderer functions for item preperation & update +; +@t_146 TYPEDEF PTR br_model_update_cbfn +@t_147 TYPEDEF PTR br_material_update_cbfn +@t_148 TYPEDEF PTR br_table_update_cbfn +@t_149 TYPEDEF PTR br_map_update_cbfn +; +; * Current filesystem, memory, and error handlers +; +@t_150 TYPEDEF PTR br_filesystem +@t_151 TYPEDEF PTR br_allocator +@t_152 TYPEDEF PTR br_diaghandler +; +; * File write mode +; +; +; * Base resource of which everything else is +; * a descendant +; +@t_153 TYPEDEF PTR +; +; * Default model +; +@t_154 TYPEDEF PTR br_model +; +; * Default material +; +@t_155 TYPEDEF PTR br_material +; +; * Function pointers to current lighting ops. +; +; +; * Global scratch space +; +@t_156 TYPEDEF PTR +br_framework_state STRUCT 4t +surface_fn @t_135 ? +surface_fn_after_map @t_136 ? +surface_fn_after_copy @t_137 ? +face_surface_fn @t_138 ? +map_transform br_matrix23 <> +index_base br_scalar ? +index_range br_scalar ? +model_to_screen br_matrix4 <> +view_to_screen br_matrix4 <> +model_to_view br_matrix34 <> +view_to_model br_matrix34 <> +model_to_environment br_matrix34 <> +camera_path @tag_28 16t DUP (<>) +vtos_type SDWORD ? +eye_m br_vector3 <> +eye_m_normalised br_vector3 <> +material @t_140 ? +active_lights_model br_active_light 16t DUP (<>) +active_lights_view br_active_light 16t DUP (<>) +nactive_lights_model br_uint_16 ? +nactive_lights_view br_uint_16 ? +light_is_1md SDWORD ? +eye_l br_vector3 <> +active_clip_planes br_active_clip_plane 6t DUP (<>) +nactive_clip_planes br_uint_16 ? +enabled_lights @t_141 16t DUP (?) +enabled_clip_planes @t_142 6t DUP (?) +enabled_environment @t_143 ? +output @t_144 ? +vp_width br_scalar ? +vp_height br_scalar ? +vp_ox br_scalar ? +vp_oy br_scalar ? +rendering SDWORD ? +reg_models br_registry <> +reg_materials br_registry <> +reg_textures br_registry <> +reg_tables br_registry <> +reg_resource_classes br_registry <> +resource_class_index @t_145 256t DUP (?) +model_update @t_146 ? +material_update @t_147 ? +table_update @t_148 ? +map_update @t_149 ? +fsys @t_150 ? +mem @t_151 ? +diag @t_152 ? +open_mode SDWORD ? +res @t_153 ? +default_model @t_154 ? +default_material @t_155 ? +fn_table fw_fn_table <> +scratch_ptr @t_156 ? +scratch_size br_size_t ? +scratch_last br_size_t ? +scratch_inuse SDWORD ? +br_framework_state ENDS + +; +; * Global renderer state +; +EXTERNDEF C fw:br_framework_state + +; +; * Minimum scratch space to allocate for render temps. +; +MIN_WORKSPACE EQU 8192t +; +; * Make sure NULL is defined +; +NULL EQU 0t +; +; * Class of view->screen transform +; +BR_VTOS_PARALLEL EQU 0t +BR_VTOS_PERSPECTIVE EQU 1t +BR_VTOS_4X4 EQU 2t + +; +; * Magic value for vertex->r to say that this vertex does not reuse a previous x,y,z +; +NO_REUSE EQU 00000ffffh +; +; * The level below which the fixed specular power function is zero +; +; +; * Material flags generated during MaterialUpdate() +; +MATUF_SURFACE_FACES EQU 000000001h +MATUF_SURFACE_VERTICES EQU 000000002h +MATUF_REGISTERED EQU 000000004h +; +; * Model flags generated during ModelUpdate() +; +; Smoothing group is the same for the whole model +MODUF_SIMPLE_GROUPS EQU 000000001h +; There are the same number of vertex groups, using the same materials +MODUF_VERTEX_GROUPS_MATCH EQU 000000002h +MODUF_REGISTERED EQU 000000004h +; Model has non-zero pivot point +MODUF_HAS_PIVOT EQU 000000008h +; +; * Perspective dive for Z component of vertices +; +; +; * Generates outcodes for a homogenous point +; +; * The 6 planes of the view volume... +; * Any user defined clip planes... +BR_RES_TRACKING EQU 1t +BR_RES_TAGGING EQU 1t +; +; * Pull in private prototypes +; +; End of file ..\fw\fw.h +USER_CLIP EQU 1t +; +; * Type for the on-screen vertex components +; +SCREEN_FIXED EQU 1t +screen_scalar TYPEDEF br_fixed_ls +; +; * Per vertex (in model) structure +; * +; * Some code relies on this structure being 64 bytes long +; +; Projected screen space point +; Outcodes for this vertex +; Shading components for vertex +temp_vertex STRUCT 4t +v screen_scalar 3t DUP (?) +outcode br_uint_32 ? +direction br_uint_32 ? +comp br_scalar 11t DUP (?) +temp_vertex ENDS + +; Projected screen space point +; Outcodes for this vertex +; Shading components for vertex +temp_vertex_fixed STRUCT 4t +v screen_scalar 3t DUP (?) +outcode br_uint_32 ? +direction br_uint_32 ? +comp br_fixed_ls 11t DUP (?) +temp_vertex_fixed ENDS + +; +; * Per edge (in model) structure +; +; +; * Vertices at either end of edge +; +; br_uint_32 surface; +; +; * Edge material +; +@t_157 TYPEDEF PTR br_material +temp_edge STRUCT 4t +vertices br_uint_16 2t DUP (?) +codes br_uint_16 ? +flag br_uint_8 ? +_pad br_uint_8 1t DUP (?) +material @t_157 ? +temp_edge ENDS + +; +; * Per face (in model) structure +; +; +; * Result of face surface call +; * +; * Will either be an index or a true colour +; +; +; * Combined outcodes of face +; +; +; * Flag describing visiblity of face +; +temp_face STRUCT 4t +surface br_uint_32 ? +codes br_uint_16 ? +flag br_uint_8 ? +_pad br_uint_8 1t DUP (?) +temp_face ENDS + +; +; * Values for temp_face.flag +; +TFF_VISIBLE EQU 4t +TFF_CLIPPED EQU 2t +TFF_REVERSED EQU 1t +; +; * Values for temp_vertex.direction +; +TVDIR_FRONT EQU 000000001h +TVDIR_BACK EQU 000000002h +; +; * Components of vertex +; +clip_vertex STRUCT 4t +outcode br_uint_16 ? +base_vertex br_uint_16 ? +comp br_scalar 11t DUP (?) +clip_vertex ENDS + +; +; * Scan convertion details for one edge of triangle +; +; delta x along edge +; delta y along edge +; gradient (x/y) +; Starting value (fraction) +; (integer) +; delta_x per scanline (fraction) +; (integer) +; starting scanline +; total scanlines +scan_edge STRUCT 4t +x br_fixed_ls ? +y br_fixed_ls ? +grad br_fixed_ls ? +f br_int_32 ? +i br_int_32 ? +d_f br_int_32 ? +d_i br_int_32 ? +start br_int_32 ? +count br_int_32 ? +scan_edge ENDS + +; +; * Scan convertion details for one parameter +; +; Parameter (16.16) value at pixel +; Parameter (16.16) value at start of scanline +; Increment per scanline if carry from bit 15 +; "" "" no carry "" +; Gradient of parameter along X axis +; Gradient of parameter along Y axis +scan_parameter STRUCT 4t +currentpix br_fixed_ls ? +current br_fixed_ls ? +d_carry br_fixed_ls ? +d_nocarry br_fixed_ls ? +grad_x br_fixed_ls ? +grad_y br_fixed_ls ? +scan_parameter ENDS + +; +; * Arbitrary width scan line data +; +@t_158 TYPEDEF PTR scan_edge +@t_159 TYPEDEF PTR SBYTE +@t_160 TYPEDEF PTR SBYTE +@t_161 TYPEDEF PTR SBYTE +@t_162 TYPEDEF PTR SBYTE +@t_163 TYPEDEF PTR SBYTE +arbitrary_width_scan STRUCT 4t +edge @t_158 ? +start @t_159 ? +_end @t_160 ? +zstart @t_161 ? +source_current @t_162 ? +u_int_current SWORD ? +pad SWORD ? +u_current DWORD ? +du DWORD ? +du_carry DWORD ? +du_nocarry DWORD ? +du_int SDWORD ? +du_int_nocarry SDWORD ? +du_int_carry SDWORD ? +v_current DWORD ? +dv DWORD ? +dv_carry DWORD ? +dv_nocarry DWORD ? +dsource SDWORD ? +dsource_carry SDWORD ? +dsource_nocarry SDWORD ? +texture_start @t_163 ? +texture_size SDWORD ? +texture_stride SDWORD ? +texture_width SDWORD ? +arbitrary_width_scan ENDS + +; +; * Perspective texture mapper data +; +@t_164 TYPEDEF PTR SBYTE +@t_165 TYPEDEF PTR SBYTE +@t_166 TYPEDEF PTR SBYTE +perspective_scan STRUCT 4t +start @t_164 ? +_end @t_165 ? +zstart @t_166 ? +source SDWORD ? +y SDWORD ? +perspective_scan ENDS + +; +; * Function types for primitives +; +@proto_62 TYPEDEF PROTO C :PTR temp_vertex_fixed, :PTR temp_vertex_fixed, :PTR temp_vertex_fixed +br_triangle_fn TYPEDEF @proto_62 + +@proto_63 TYPEDEF PROTO C :PTR temp_vertex_fixed, :PTR temp_vertex_fixed +br_line_fn TYPEDEF @proto_63 + +@proto_64 TYPEDEF PROTO C :PTR temp_vertex_fixed +br_point_fn TYPEDEF @proto_64 + +; +; * Callback functions for generic trapezoid and pixel plot fns. +; +@proto_65 TYPEDEF PROTO C :PTR scan_edge +br_trapezoid_render_cb TYPEDEF @proto_65 + +@proto_66 TYPEDEF PROTO C :br_int_32, :br_int_32 +br_pixel_render_cb TYPEDEF @proto_66 + +; +; * Private state of renderer +; +; +; * Local copy of model -> screen with viewport factored in +; +; +; * Pointers into scratch area +; +@t_167 TYPEDEF PTR br_int_8 +@t_168 TYPEDEF PTR br_int_32 +@t_169 TYPEDEF PTR br_int_8 +@t_170 TYPEDEF PTR br_int_8 +@t_171 TYPEDEF PTR temp_face +@t_172 TYPEDEF PTR temp_edge +@t_173 TYPEDEF PTR temp_vertex +; +; * Flag to indicate that vertex directions +; * have been initialised +; +; +; * Model and material being rendered +; +@t_174 TYPEDEF PTR br_model +@t_175 TYPEDEF PTR br_material +; +; * Current default material +; +@t_176 TYPEDEF PTR br_material +; +; * Misc. constant parameters for rendering +; +@t_177 TYPEDEF PTR br_uint_8 +; Colour buffer +@t_178 TYPEDEF PTR br_fixed_ls +; Z buffer +; Stride (in bytes) +; Stride (in bytes) +@t_179 TYPEDEF PTR br_uint_8 +; Texture map to use +@t_180 TYPEDEF PTR br_uint_8 +; Bump map to use +@t_181 TYPEDEF PTR br_uint_8 +; Indirection table +@t_182 TYPEDEF PTR br_uint_8 +; Indirection table +@t_183 TYPEDEF PTR br_uint_8 +; Lighting for quantised normals +@t_184 TYPEDEF PTR br_uint_32 +; Screen +; +; * Workspace for triangle scan converter +; +; Long edge of triangle +; Top short edge +; Bottom short edge +; Depth +; Mapping +; Index +; Red +; Green +; Blue +; Perspective divisor +; Current texel +; +; * Per-component mask for scan converter interpolation +; +; Components to interpolate +; Components to apply perspective correction +; Components to clip +; Components to convert scalar->float +; +; * Global arbitrary width scan line data +; +; +; * Perspective texture mapper globals +; +; +; * Current triangle functions +; +@t_185 TYPEDEF PTR br_triangle_fn +; +; * Generic triangle rendering sub-functions +; +@t_186 TYPEDEF PTR br_trapezoid_render_cb +@t_187 TYPEDEF PTR br_pixel_render_cb +; +; * Bounds of rendered actor +; +; +; * Callback for visible actors +; +@t_188 TYPEDEF PTR br_renderbounds_cbfn +; +; * Current output type +; +@t_189 TYPEDEF PTR zb_render_type +; +; * Anchor resource for ZB renderer +; +@t_190 TYPEDEF PTR +br_zbuffer_state STRUCT 4t +os_model_to_screen br_matrix4 <> +os_model_to_screen_hi br_scalar 4t DUP (?) +vertex_counts @t_167 ? +face_group_counts @t_168 ? +face_group_clipped @t_169 ? +edge_counts @t_170 ? +temp_faces @t_171 ? +temp_edges @t_172 ? +temp_vertices @t_173 ? +directions_cleared SDWORD ? +model @t_174 ? +material @t_175 ? +default_material @t_176 ? +colour_buffer @t_177 ? +depth_buffer @t_178 ? +row_width br_int_32 ? +depth_row_width br_int_32 ? +texture_buffer @t_179 ? +bump_buffer @t_180 ? +shade_table @t_181 ? +blend_table @t_182 ? +lighting_table @t_183 ? +screen_table @t_184 ? +main scan_edge <> +top scan_edge <> +bot scan_edge <> +pz scan_parameter <> +pu scan_parameter <> +pv scan_parameter <> +pi scan_parameter <> +pr scan_parameter <> +pg scan_parameter <> +pb scan_parameter <> +pq scan_parameter <> +source scan_parameter <> +component_mask br_uint_32 ? +correct_mask br_uint_32 ? +clip_mask br_uint_32 ? +convert_mask br_uint_32 ? +awsl arbitrary_width_scan <> +tsl perspective_scan <> +triangle_render @t_185 ? +trapezoid_render @t_186 ? +pixel_render @t_187 ? +bounds screen_scalar 4t DUP (?) +bounds_call @t_188 ? +_type @t_189 ? +res @t_190 ? +br_zbuffer_state ENDS + +EXTERNDEF C zb:br_zbuffer_state + +; +; * Transform into screen space - Inline expanded BrMatrix4ApplyP() +; +; +; * Generic macro for projecting a vertex from homogenous coordinates +; +; +; * Alignment for block in scratch area +; +SCRATCH_BOUNDARY EQU 16t +; +; * New line and point clamps +; +; +; * Include bounding rectangle callback +; +BOUNDING_RECTANGLE_CALL EQU 1t +; +; * Update MIN and MAX vertices' x,y +; +@proto_67 TYPEDEF PROTO C :PTR br_face_group, :PTR temp_face +br_face_group_fn TYPEDEF @proto_67 + +; +; * Structure describing one particular sort of material renderer +; +; +; * Descriptive string +; +@t_191 TYPEDEF PTR SBYTE +; +; * If +; * mat->flags & flags_mask) == flags_cmp +; * colour_map->map_type == map_type +; * width != 0 && colour_map->width == width +; * height != 0 && colour_map->height == height +; * +; * material matches this type +; +@t_192 TYPEDEF PTR br_face_group_fn +@t_193 TYPEDEF PTR br_triangle_fn +@t_194 TYPEDEF PTR br_line_fn +@t_195 TYPEDEF PTR br_point_fn +zb_material_type STRUCT 4t +identifier @t_191 ? +flags_mask br_uint_32 ? +flags_cmp br_uint_32 ? +map_type br_uint_8 ? +_width br_uint_16 ? +height br_uint_16 ? +face_group @t_192 ? +triangle @t_193 ? +line @t_194 ? +point @t_195 ? +clip_mask br_uint_32 ? +convert_mask br_uint_32 ? +zb_material_type ENDS + +; +; * Flags used to augment material flags when specifiying +; * material type +; +ZB_MATF_HAS_MAP EQU 080000000h +ZB_MATF_TRANSPARENT EQU 040000000h +ZB_MATF_HAS_SCREEN EQU 020000000h +ZB_MATF_SQUARE_POW2 EQU 010000000h +ZB_MATF_NO_SKIP EQU 008000000h +ZB_MATF_MAP_OPACITY EQU 004000000h +ZB_MATF_MAP_TRANSPARENT EQU 002000000h +ZB_MATF_HAS_SHADE EQU 001000000h +; +; * Structure describing one particular class of renderer +; +; +; * Descriptive string +; +@t_196 TYPEDEF PTR SBYTE +; +; * Type of colour buffer +; +; +; * Type of depth buffer +; +; XXX unused at the moment +; +; * Used to check if the row_width's of the two pixelmaps +; * match - +; * if colour row_width * depth_row_size == depth row_width * colour_row_size +; * then this set of functions match +; +; +; * Flag to indicate true-colour +; +; +; * A table of supported material types +; +@t_197 TYPEDEF PTR zb_material_type +zb_render_type STRUCT 4t +identifier @t_196 ? +colour_type br_uint_8 ? +depth_type br_uint_8 ? +user_type br_uint_16 ? +colour_row_size br_uint_8 ? +depth_row_size br_uint_8 ? +true_colour br_uint_8 ? +material_types @t_197 ? +nmaterial_types SDWORD ? +zb_render_type ENDS + +; +; * Pull in private prototypes +; +; +; #ifndef _ZBIPXTRA_H_ +; #include "zbipxtra.h" +; #endif +; +; End of file zb.h diff --git a/bren/ZB/zb.float.inc b/bren/ZB/zb.float.inc new file mode 100644 index 00000000..64454516 --- /dev/null +++ b/bren/ZB/zb.float.inc @@ -0,0 +1,3217 @@ + +option expr32 +option casemap:none + +; Begin of file zb.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: zb.h 1.44 1995/08/31 16:47:50 sam Exp $ +; * $Locker: $ +; * +; * Internal types and structures for z-buffer renderer +; +; +; * Pull in all the framework and public definitions +; +; Begin of file ..\fw\fw.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: fw.h 1.39 1995/07/28 19:01:47 sam Exp $ +; * $Locker: sam $ +; * +; * Internal types and structures for framework +; +; +; * Pull in all the public definitions/declarations +; +; Begin of file ..\inc\brender.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brender.h 1.19 1995/08/31 16:36:12 sam Exp $ +; * $Locker: $ +; * +; * Master include file for BRender +; * +; +; Begin of file ..\inc\compiler.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: compiler.h 1.22 1995/08/31 16:36:15 sam Exp $ +; * $Locker: sam $ +; * +; * Misc host compiler configuration (types & special declarators etc.) +; +; +; * Fixed bitsize integers +; +br_int_32 TYPEDEF SDWORD + +br_uint_32 TYPEDEF DWORD + +br_int_16 TYPEDEF SWORD + +br_uint_16 TYPEDEF WORD + +br_int_8 TYPEDEF SBYTE + +br_uint_8 TYPEDEF BYTE + +; +; * Generic size type (in case target environment does not have size_t) +; +br_size_t TYPEDEF DWORD + +; +; * Boolean type +; +br_boolean TYPEDEF SDWORD + +BR_TRUE EQU 1t +BR_FALSE EQU 0t +; * +; ** Compiler specific declarations +; ** +; * +; * BR_PUBLIC_ENTRY are the declarators for public entry points into the library +; * +; * BR_CALLBACK are the declarators for function pointers to callbacks +; * +; * BR_ASM_DATA is the declarator for data that is shared with ASM files +; * +; * BR_ASM_CALL is the declarator for function declarations that are ASM functions +; * called from C +; * +; * BR_ASM_CALLBACK is the declarator for function definitions that are C functions +; * called from ASM +; * +; * BR_SUFFIX_HOST is a string used for banners/titles etc +; * +; * br_framebuffer_ptr is a type used for pointing at the pixels of a frame buffer +; * +; * BR_HAS_FAR is !0 if language supports __far pointers +; +; +; * WATCOM C/C++ 32 +; +; +; * Use the current default calling convention +; +BR_HAS_FAR EQU 1t +; +; * Stop unreferenced variables producing a warning +; * Things like "rcsid" and unused fucntion arguments +; +; +; * Zortech C++ +; +; +; * Avoid some tokens that masm chokes on +; +; +; * Supress compiler specific declarators +; +; +; * Macros for producing banners & copyright messages +; +; +; * Useful macro for sizing an array +; +; End of file ..\inc\compiler.h +; Begin of file ..\inc\brlimits.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brlimits.h 1.5 1995/02/22 21:37:01 sam Exp $ +; * $Locker: $ +; * +; * Various limits imposed by the renderer +; +; +; * Maximum length of an item's name +; +BR_MAX_NAME EQU 256t +; +; * Maximum number of active lights +; +BR_MAX_LIGHTS EQU 16t +; +; * Maximum number of active clip planes +; +BR_MAX_CLIP_PLANES EQU 6t +; +; * Maximum number of resource classes +; +BR_MAX_RESOURCE_CLASSES EQU 256t +; +; * Maximum depth of camera in hierachy +; +MAX_CAMERA_DEPTH EQU 16t +; End of file ..\inc\brlimits.h +; Begin of file ..\inc\fixed.h +; +; * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: fixed.h 1.17 1995/02/22 21:37:06 sam Exp $ +; * $Locker: $ +; +INLINE_FIXED EQU 1t +; +; * Fixed point types +; +br_fixed_ls TYPEDEF SDWORD + +; Long Signed fixed 15.16 +br_fixed_lsf TYPEDEF SWORD + +; Long Signed fraction 0.15 +br_fixed_lu TYPEDEF DWORD + +; Long unsigned fixed 16.16 +br_fixed_luf TYPEDEF WORD + +; Long unsigned fixed fraction 0.16 +br_fixed_ss TYPEDEF SWORD + +; Short Signed fixed 7.8 +br_fixed_ssf TYPEDEF SBYTE + +; Short Signed fraction 0.7 +br_fixed_su TYPEDEF WORD + +; Short unsigned fixed 8.8 +br_fixed_suf TYPEDEF BYTE + +; Short unsigned fixed fraction 0.8 +; +; * 1 in various fixed point forms +; +BR_ONE_LS EQU 000010000h +BR_ONE_LSF EQU 000008000h +BR_ONE_LU EQU 000010000h +BR_ONE_LUF EQU 000010000h +BR_ONE_SS EQU 000000100h +BR_ONE_SSF EQU 000000080h +BR_ONE_SU EQU 000000100h +BR_ONE_SUF EQU 000000100h +; End of file ..\inc\fixed.h +; Begin of file ..\inc\scalar.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: scalar.h 1.21 1995/08/31 16:36:20 sam Exp $ +; * $Locker: $ +; * +; * Scalar type +; * +; * External defines: +; * +; * BASED_FIXED +; * True if system is based on signed 16.16 fixed point +; * +; * BASED_FLOAT +; * True if system is based on 32 bit floating point +; * +; * One of these must be defined and the appropriate libraries must be used +; +BASED_FIXED EQU 0t +; * +; ** Basic types - either fixed or float +; * +; +; * Reference an external symbol to make sure +; * the right library is linked +; +EXTERNDEF C _BR_Floating_Point_Scalar:SDWORD + +; +; * Floating point base types +; +br_scalar TYPEDEF REAL4 + +br_fraction TYPEDEF REAL4 + +br_ufraction TYPEDEF REAL4 + +; +; * Macros for static initialisation +; +; +; * Macros for type conversion +; +; +; * Various arithmetic operations +; +; +; * Make sure PI is defined +; +; End of file ..\inc\scalar.h +; Begin of file ..\inc\colour.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: colour.h 1.4 1995/08/31 16:36:14 sam Exp $ +; * $Locker: $ +; * +; * Colour type and macros +; * +; +br_colour TYPEDEF DWORD + +; End of file ..\inc\colour.h +; Begin of file ..\inc\matrix.h +; +; * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: matrix.h 1.3 1995/02/22 21:37:13 sam Exp $ +; * $Locker: $ +; * +; * Structrures describing matrices +; +br_matrix4 STRUCT 4t +m br_scalar 4t DUP (4t DUP (?)) +br_matrix4 ENDS + +br_matrix34 STRUCT 4t +m br_scalar 4t DUP (3t DUP (?)) +br_matrix34 ENDS + +br_matrix23 STRUCT 4t +m br_scalar 3t DUP (2t DUP (?)) +br_matrix23 ENDS + +; End of file ..\inc\matrix.h +; Begin of file ..\inc\vector.h +; +; * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: vector.h 1.9 1995/06/30 16:09:07 sam Exp $ +; * $Locker: $ +; * +; * Vector types +; +; +; * Vector types +; +br_vector2 STRUCT 4t +v br_scalar 2t DUP (?) +br_vector2 ENDS + +br_vector3 STRUCT 4t +v br_scalar 3t DUP (?) +br_vector3 ENDS + +br_vector4 STRUCT 4t +v br_scalar 4t DUP (?) +br_vector4 ENDS + +; +; * Integer vectors (used for integer bounding boxes) +; +br_vector2i STRUCT 4t +v br_int_32 2t DUP (?) +br_vector2i ENDS + +br_vector3i STRUCT 4t +v br_int_32 3t DUP (?) +br_vector3i ENDS + +br_vector4i STRUCT 4t +v br_int_32 4t DUP (?) +br_vector4i ENDS + +; +; * Fraction vector types +; +br_fvector2 STRUCT 4t +v br_fraction 2t DUP (?) +br_fvector2 ENDS + +br_fvector3 STRUCT 4t +v br_fraction 3t DUP (?) +br_fvector3 ENDS + +br_fvector4 STRUCT 4t +v br_fraction 4t DUP (?) +br_fvector4 ENDS + +; +; * General structures for describing an axis aligned bounds +; +; Minimum corner +; Maximum corner +br_bounds2 STRUCT 4t +min br_vector2 <> +max br_vector2 <> +br_bounds2 ENDS + +; Minimum corner +; Maximum corner +br_bounds3 STRUCT 4t +min br_vector3 <> +max br_vector3 <> +br_bounds3 ENDS + +; Minimum corner +; Maximum corner +br_bounds4 STRUCT 4t +min br_vector4 <> +max br_vector4 <> +br_bounds4 ENDS + +; +; * Integer bounding boxes +; +; Minimum corner +; Maximum corner +br_bounds2i STRUCT 4t +min br_vector2i <> +max br_vector2i <> +br_bounds2i ENDS + +; Minimum corner +; Maximum corner +br_bounds3i STRUCT 4t +min br_vector3i <> +max br_vector3i <> +br_bounds3i ENDS + +; Minimum corner +; Maximum corner +br_bounds4i STRUCT 4t +min br_vector4i <> +max br_vector4i <> +br_bounds4i ENDS + +; +; * Backwards compatibility +; +br_bounds TYPEDEF br_bounds3 + +; +; * Macros for static initialisation +; +; End of file ..\inc\vector.h +; Begin of file ..\inc\angles.h +; +; * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: angles.h 1.10 1995/08/31 16:36:11 sam Exp $ +; * $Locker: $ +; * +; +; +; * Angles are alway 0.16 fixed point +; +br_angle TYPEDEF br_fixed_luf + +; +; * Fields that go into br_euler.order +; +BR_EULER_FIRST EQU 3t +BR_EULER_FIRST_X EQU 0t +BR_EULER_FIRST_Y EQU 1t +BR_EULER_FIRST_Z EQU 2t +BR_EULER_PARITY EQU 4t +BR_EULER_PARITY_EVEN EQU 0t +BR_EULER_PARITY_ODD EQU 4t +BR_EULER_REPEAT EQU 8t +BR_EULER_REPEAT_NO EQU 0t +BR_EULER_REPEAT_YES EQU 8t +BR_EULER_FRAME EQU 16t +BR_EULER_FRAME_STATIC EQU 0t +BR_EULER_FRAME_ROTATING EQU 16t + +; +; * Various possible orders +; +BR_EULER_XYZ_S EQU 0t +BR_EULER_XYX_S EQU 8t +BR_EULER_XZY_S EQU 4t +BR_EULER_XZX_S EQU 12t +BR_EULER_YZX_S EQU 1t +BR_EULER_YZY_S EQU 9t +BR_EULER_YXZ_S EQU 5t +BR_EULER_YXY_S EQU 13t +BR_EULER_ZXY_S EQU 2t +BR_EULER_ZXZ_S EQU 10t +BR_EULER_ZYX_S EQU 6t +BR_EULER_ZYZ_S EQU 14t +BR_EULER_ZYX_R EQU 16t +BR_EULER_XYX_R EQU 24t +BR_EULER_YZX_R EQU 20t +BR_EULER_XZX_R EQU 28t +BR_EULER_XZY_R EQU 17t +BR_EULER_YZY_R EQU 25t +BR_EULER_ZXY_R EQU 21t +BR_EULER_YXY_R EQU 29t +BR_EULER_YXZ_R EQU 18t +BR_EULER_ZXZ_R EQU 26t +BR_EULER_XYZ_R EQU 22t +BR_EULER_ZYZ_R EQU 30t + +; +; * A triple of euler angles and a description of how they are to +; * be applied - loosely based on - +; * "Euler Angle Convertion" Ken Shoemake, Graphics Gems IV pp. 222 +; +br_euler STRUCT 4t +_a br_angle ? +_b br_angle ? +_c br_angle ? +order br_uint_8 ? +br_euler ENDS + +; End of file ..\inc\angles.h +; Begin of file ..\inc\quat.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: quat.h 1.5 1995/02/22 21:37:21 sam Exp $ +; * $Locker: $ +; * +; * Type descibing a unit quaternion +; +br_quat STRUCT 4t +x br_scalar ? +y br_scalar ? +z br_scalar ? +w br_scalar ? +br_quat ENDS + +; End of file ..\inc\quat.h +; Begin of file ..\inc\transfrm.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: transfrm.h 1.11 1995/02/22 21:37:24 sam Exp $ +; * $Locker: $ +; * +; * Structure describing an affine transform from one coordinate space +; * to another +; +; +; * Type of actor position +; +BR_TRANSFORM_MATRIX34 EQU 0t +BR_TRANSFORM_MATRIX34_LP EQU 1t +BR_TRANSFORM_QUAT EQU 2t +BR_TRANSFORM_EULER EQU 3t +BR_TRANSFORM_LOOK_UP EQU 4t +BR_TRANSFORM_TRANSLATION EQU 5t +BR_TRANSFORM_IDENTITY EQU 6t +BR_TRANSFORM_MAX EQU 7t + +; +; * Type of position +; +; +; * Union of the various means of describing a transform - +; * these are explicity arrranged so that any exlicit transform +; * will always be available as br_transform.t.translate +; +; +; * Affine 3x4 matrix +; +; +; * Euler angles and translation +; +@tag_4 STRUCT 4t +e br_euler <> +_pad br_scalar 7t DUP (?) +t br_vector3 <> +@tag_4 ENDS + +; +; * Unit quaternion and translation +; +@tag_5 STRUCT 4t +q br_quat <> +_pad br_scalar 5t DUP (?) +t br_vector3 <> +@tag_5 ENDS + +; +; * Lookat vector, up vector and translation +; +@tag_6 STRUCT 4t +look br_vector3 <> +up br_vector3 <> +_pad br_scalar 3t DUP (?) +t br_vector3 <> +@tag_6 ENDS + +; +; * Just a translation +; +@tag_7 STRUCT 4t +_pad br_scalar 9t DUP (?) +t br_vector3 <> +@tag_7 ENDS + +@tag_3 UNION +mat br_matrix34 <> +euler @tag_4 <> +quat @tag_5 <> +look_up @tag_6 <> +translate @tag_7 <> +@tag_3 ENDS + +br_transform STRUCT 4t +_type br_uint_16 ? +t @tag_3 <> +br_transform ENDS + +; End of file ..\inc\transfrm.h +; Begin of file ..\inc\order.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: order.h 1.1 1995/08/31 16:37:15 sam Exp $ +; * $Locker: $ +; * +; * Definitons for an order table +; +BR_ORDER_TABLE_NEW_BOUNDS EQU 1t + +; +; * Order table array +; +@t_0 TYPEDEF PTR PTR +; +; * Number of entries in array +; +; +; * Next order table in list +; +@t_1 TYPEDEF PTR br_order_table +; +; * Order table bounds +; +; +; * Flags +; +br_order_table STRUCT 4t +table @t_0 ? +ot_size br_uint_32 ? +next @t_1 ? +min_z br_scalar ? +max_z br_scalar ? +flags br_uint_32 ? +br_order_table ENDS + +; End of file ..\inc\order.h +; Begin of file ..\inc\pixelmap.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: pixelmap.h 1.17 1995/08/31 16:36:19 sam Exp $ +; * $Locker: $ +; * +; * A stopgap 2D pixelmap structure for brender. This should really be the +; * pixelmap data type from the underlying 2D system (whatever that will +; * be) +; * +; * Used for input (maps) and output (render buffer) +; +; +; * Various types of pixel +; +; +; * Each pixel is an index into a colour map +; +BR_PMT_INDEX_1 EQU 0t +BR_PMT_INDEX_2 EQU 1t +BR_PMT_INDEX_4 EQU 2t +BR_PMT_INDEX_8 EQU 3t +; +; * True colour RGB +; +BR_PMT_RGB_555 EQU 4t +; 16 bits per pixel +BR_PMT_RGB_565 EQU 5t +; 16 bits per pixel +BR_PMT_RGB_888 EQU 6t +; 24 bits per pixel +BR_PMT_RGBX_888 EQU 7t +; 32 bits per pixel +BR_PMT_RGBA_8888 EQU 8t +; 32 bits per pixel +; +; * YUV +; +BR_PMT_YUYV_8888 EQU 9t +; YU YV YU YV ... +BR_PMT_YUV_888 EQU 10t +; +; * Depth +; +BR_PMT_DEPTH_16 EQU 11t +BR_PMT_DEPTH_32 EQU 12t +; +; * Opacity +; +BR_PMT_ALPHA_8 EQU 13t +; +; * Opacity + Index +; +BR_PMT_INDEXA_88 EQU 14t +; +; * Bump maps +; +BR_PMT_NORMAL_INDEX_8 EQU 15t +BR_PMT_NORMAL_XYZ EQU 16t +; +; * Wrong way around 15 bit true colour +; +BR_PMT_BGR_555 EQU 17t + +; +; * pixelmap flags +; +; +; * No direct access to pixels +; +BR_PMF_NO_ACCESS EQU 1t +BR_PMF_LINEAR EQU 2t +BR_PMF_ROW_WHOLEPIXELS EQU 4t + +; +; * Optional identifier (when maps used as textures/tables etc.) +; +@t_2 TYPEDEF PTR SBYTE +; +; * pointer to raw pixel data +; +@t_3 TYPEDEF PTR +; +; * Optional pixel map when pixels are indexed. +; +@t_4 TYPEDEF PTR br_pixelmap +; +; * Byte difference between pixels at same column of adjacent rows +; +; +; * Type of pixels +; +; +; * Flags +; +; +; * top left visible region in pixels from pixel at 'pixel' pointer +; +; +; * Width and height of bitmap in pixels +; +; +; * Local origin for any graphics system rendering into map, relative +; * to 'base' +; +; +; * Device pointer - if pixelmap originated from a device +; +@t_5 TYPEDEF PTR +br_pixelmap STRUCT 4t +identifier @t_2 ? +pixels @t_3 ? +_reserved0 br_uint_32 ? +map @t_4 ? +row_bytes br_int_16 ? +_type br_uint_8 ? +flags br_uint_8 ? +base_x br_uint_16 ? +base_y br_uint_16 ? +_width br_uint_16 ? +height br_uint_16 ? +origin_x br_int_16 ? +origin_y br_int_16 ? +context @t_5 ? +br_pixelmap ENDS + +; +; * Flags to BrPixelMapAllocate +; +BR_PMAF_INVERTED EQU 1t +; Setup pixelmap so that 0th scanline is at high memory +; Setup pixelmap so that 0th scanline is at low memory +BR_PMAF_NORMAL EQU 0t + +; +; * Channel flags +; +BR_PMCHAN_INDEX EQU 1t +BR_PMCHAN_RGB EQU 2t +BR_PMCHAN_DEPTH EQU 4t +BR_PMCHAN_ALPHA EQU 8t +BR_PMCHAN_YUV EQU 16t + +; +; * Matching pixelmap types +; +BR_PMMATCH_OFFSCREEN EQU 0t +BR_PMMATCH_DEPTH_16 EQU 1t +BR_PMMATCH_MAX EQU 2t + +; End of file ..\inc\pixelmap.h +; Begin of file ..\inc\brfont.h +; +; * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brfont.h 1.4 1995/03/29 16:42:55 sam Exp $ +; * $Locker: $ +; * +; +@t_6 TYPEDEF PTR br_int_8 +@t_7 TYPEDEF PTR br_uint_16 +@t_8 TYPEDEF PTR br_uint_8 +br_font STRUCT 4t +flags br_uint_32 ? +glyph_x br_uint_16 ? +glyph_y br_uint_16 ? +spacing_x br_int_16 ? +spacing_y br_int_16 ? +_width @t_6 ? +encoding @t_7 ? +glyphs @t_8 ? +br_font ENDS + +; +; * Flags +; +BR_FONTF_PROPORTIONAL EQU 1t +; +; * Default fonts that are available in framework +; +EXTERNDEF C BrFontFixed3x5:PTR br_font + +EXTERNDEF C BrFontProp4x6:PTR br_font + +EXTERNDEF C BrFontProp7x9:PTR br_font + +; End of file ..\inc\brfont.h +; Begin of file ..\inc\material.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: material.h 1.19 1995/05/25 13:37:32 sam Exp $ +; * $Locker: $ +; * +; * Describes the appearance of a material than can be applied to a surface +; +@t_9 TYPEDEF PTR SBYTE +; +; * Specular power +; +; +; * Controls how texture is rendered +; +; +; * 2x3 transform applied to model U,V +; +; +; * The direct index ramp base and range +; +; +; * Pointers to colour map +; +@t_10 TYPEDEF PTR br_pixelmap +; +; * Pointers to tables +; +@t_11 TYPEDEF PTR br_pixelmap +; Screen door opacity +@t_12 TYPEDEF PTR br_pixelmap +; Index shading +@t_13 TYPEDEF PTR br_pixelmap +; Index blending +; +; * Private fields +; +@t_14 TYPEDEF PTR +br_material STRUCT 4t +identifier @t_9 ? +colour br_colour ? +opacity br_uint_8 ? +ka br_ufraction ? +kd br_ufraction ? +ks br_ufraction ? +power br_scalar ? +flags br_uint_32 ? +map_transform br_matrix23 <> +index_base br_uint_8 ? +index_range br_uint_8 ? +colour_map @t_10 ? +screendoor @t_11 ? +index_shade @t_12 ? +index_blend @t_13 ? +prep_flags br_uint_8 ? +rptr @t_14 ? +br_material ENDS + +; +; * Bits for br_material->flags +; +BR_MATF_LIGHT EQU 1t +BR_MATF_PRELIT EQU 2t +BR_MATF_SMOOTH EQU 4t +BR_MATF_ENVIRONMENT_I EQU 8t +BR_MATF_ENVIRONMENT_L EQU 16t +BR_MATF_PERSPECTIVE EQU 32t +BR_MATF_DECAL EQU 64t +BR_MATF_I_FROM_U EQU 128t +BR_MATF_I_FROM_V EQU 256t +BR_MATF_U_FROM_I EQU 512t +BR_MATF_V_FROM_I EQU 1024t +BR_MATF_ALWAYS_VISIBLE EQU 2048t +BR_MATF_TWO_SIDED EQU 4096t +BR_MATF_FORCE_Z_0 EQU 8192t +BR_MATF_DITHER EQU 16384t + +; +; * Backwards compatibility +; +BR_MATF_MAP_COLOUR EQU 0t +; +; * Flags to BrMaterialUpdate() +; +BR_MATU_MAP_TRANSFORM EQU 1t +BR_MATU_RENDERING EQU 2t +BR_MATU_LIGHTING EQU 4t +BR_MATU_COLOURMAP EQU 8t +BR_MATU_ALL EQU 32767t + +; +; * Flags to BrMapUpdate() +; +BR_MAPU_ALL EQU 32767t + +; +; * Flags to BrTableUpdate() +; +BR_TABU_ALL EQU 32767t + +; End of file ..\inc\material.h +; Begin of file ..\inc\model.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: model.h 1.20 1995/08/31 16:36:18 sam Exp $ +; * $Locker: $ +; * +; * In-memory structures for models, both public and private areas +; +; Point in model space +; Mapping coordinates +; +; * Index for prelit models +; +; +; * true colour for pre-lit models +; +; +; * Private fields +; +; Surface normal at vertex +br_vertex STRUCT 4t +p br_vector3 <> +map br_vector2 <> +index br_uint_8 ? +red br_uint_8 ? +grn br_uint_8 ? +blu br_uint_8 ? +r br_uint_16 ? +n br_fvector3 <> +br_vertex ENDS + +; Vertices around face +; Edges around face +@t_15 TYPEDEF PTR br_material +; Face material (or NULL) +; Controls if shared edges are smooth +; Bits 0,1 and 2 denote internal edges +; Plane equation of face +br_face STRUCT 4t +vertices br_uint_16 3t DUP (?) +edges br_uint_16 3t DUP (?) +material @t_15 ? +smoothing br_uint_16 ? +flags br_uint_8 ? +_pad0 br_uint_8 ? +n br_fvector3 <> +d br_scalar ? +br_face ENDS + +; +; * Bits for face flags +; +BR_FACEF_COPLANAR_0 EQU 1t +; The face adjoining edge 0 is coplanar with this face +BR_FACEF_COPLANAR_1 EQU 2t +; "" 1 "" +; "" 1 "" +BR_FACEF_COPLANAR_2 EQU 4t + +@t_16 TYPEDEF PTR br_material +; Group material (or NULL) +@t_17 TYPEDEF PTR br_face +; faces in group +; Number of faces in a group +br_face_group STRUCT 4t +material @t_16 ? +faces @t_17 ? +nfaces br_uint_16 ? +br_face_group ENDS + +@t_18 TYPEDEF PTR br_material +; Group material (or NULL) +@t_19 TYPEDEF PTR br_vertex +; vertices in group +; Number of vertices in a group +br_vertex_group STRUCT 4t +material @t_18 ? +vertices @t_19 ? +nvertices br_uint_16 ? +br_vertex_group ENDS + +; +; * Callback function type for custom models +; +@proto_0 TYPEDEF PROTO C :PTR br_actor, :PTR br_model, :PTR br_material, :PTR , :br_uint_8, :SDWORD, :PTR br_matrix34, :PTR br_matrix4 +br_model_custom_cbfn TYPEDEF @proto_0 + +@t_20 TYPEDEF PTR SBYTE +@t_21 TYPEDEF PTR br_vertex +@t_22 TYPEDEF PTR br_face +; +; * Offset of model's pivot point (where it attaches to parent) +; +; +; * Flags describing what is allowed in ModelPrepare() +; +; +; * Application call +; +@t_23 TYPEDEF PTR br_model_custom_cbfn +; +; * Application defined data - untouched by system +; +@t_24 TYPEDEF PTR +; +; * Generated by ModelUpdate +; +; +; * Bounding radius of model from origin +; +; +; * Axis-aligned box that bound model in model coords +; +; +; * Vertices and faces that have been sorted +; * into groups, removing conflicts at material boundaries +; * and smoothign groups +; +@t_25 TYPEDEF PTR br_face +@t_26 TYPEDEF PTR br_vertex +; +; * Groups of faces and vertices, by material +; +@t_27 TYPEDEF PTR br_face_group +@t_28 TYPEDEF PTR br_vertex_group +; +; * Upper limit on the face->edges[] entries +; +; +; * Pointers to tables that map prepared face and vertex indexes +; * back to original face index +; * +; * Only generated if BR_MODF_GENERATE_TAGS is set +; +@t_29 TYPEDEF PTR br_uint_16 +@t_30 TYPEDEF PTR br_uint_16 +; +; * Private fields +; +@t_31 TYPEDEF PTR br_uint_16 +@t_32 TYPEDEF PTR +br_model STRUCT 4t +identifier @t_20 ? +vertices @t_21 ? +faces @t_22 ? +nvertices br_uint_16 ? +nfaces br_uint_16 ? +pivot br_vector3 <> +flags br_uint_16 ? +custom @t_23 ? +user @t_24 ? +radius br_scalar ? +bounds br_bounds <> +nprepared_vertices br_uint_16 ? +nprepared_faces br_uint_16 ? +prepared_faces @t_25 ? +prepared_vertices @t_26 ? +nface_groups br_uint_16 ? +nvertex_groups br_uint_16 ? +face_groups @t_27 ? +vertex_groups @t_28 ? +nedges br_uint_16 ? +face_tags @t_29 ? +vertex_tags @t_30 ? +prep_flags br_uint_32 ? +smooth_strings @t_31 ? +rptr @t_32 ? +br_model ENDS + +; +; * Bits for br_model->flags +; +BR_MODF_DONT_WELD EQU 1t +; Vertices with same x,y,z cannot be merged +BR_MODF_KEEP_ORIGINAL EQU 2t +; Don't release model->faces/vertices during ModelUpdate() +BR_MODF_GENERATE_TAGS EQU 4t +; Allocate and fill in the face and vertex tag structures +BR_MODF_QUICK_UPDATE EQU 16t +; ModelUpdate is fast - but may produce slower models +BR_MODF_CUSTOM EQU 32t +; Invoke custom callback for this model +; Model structure is pre-prepared - update performs no work +BR_MODF_PREPREPARED EQU 64t + +; +; * Flags to BrModelUpdate() +; +BR_MODU_NORMALS EQU 1t +BR_MODU_EDGES EQU 2t +BR_MODU_RADIUS EQU 4t +BR_MODU_GROUPS EQU 8t +BR_MODU_BOUNDING_BOX EQU 16t +BR_MODU_MATERIALS EQU 32t +BR_MODU_ALL EQU 32767t + +; +; * Backwards compatibility +; +; +; * Values for BrModelApplyMap() +; +BR_APPLYMAP_PLANE EQU 0t +BR_APPLYMAP_SPHERE EQU 1t +BR_APPLYMAP_CYLINDER EQU 2t +BR_APPLYMAP_DISC EQU 3t +BR_APPLYMAP_NONE EQU 4t + +; +; * Axis values for BrModelFitMap() +; +BR_FITMAP_PLUS_X EQU 0t +BR_FITMAP_PLUS_Y EQU 1t +BR_FITMAP_PLUS_Z EQU 2t +BR_FITMAP_MINUS_X EQU 3t +BR_FITMAP_MINUS_Y EQU 4t +BR_FITMAP_MINUS_Z EQU 5t + +; +; * Local Variables: +; * tab-width: 4 +; * End: +; +; End of file ..\inc\model.h +; Begin of file ..\inc\actor.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: actor.h 1.15 1995/08/31 16:36:10 sam Exp $ +; * $Locker: $ +; * +; * Definitons for an Actor +; +; * +; ** Definition of base actor structure +; * +; +; * Basic types of actor +; +BR_ACTOR_NONE EQU 0t +BR_ACTOR_MODEL EQU 1t +BR_ACTOR_LIGHT EQU 2t +BR_ACTOR_CAMERA EQU 3t +_BR_ACTOR_RESERVED EQU 4t +BR_ACTOR_BOUNDS EQU 5t +BR_ACTOR_BOUNDS_CORRECT EQU 6t +BR_ACTOR_CLIP_PLANE EQU 7t +BR_ACTOR_MAX EQU 8t + +; +; * Render styles - an actor inherits it's style from the most _distant_ +; * ancestor included in this traversal that does not have default set +; * (unlike model & material which are inherited from the nearest ancestor) +; +BR_RSTYLE_DEFAULT EQU 0t +BR_RSTYLE_NONE EQU 1t +BR_RSTYLE_POINTS EQU 2t +BR_RSTYLE_EDGES EQU 3t +BR_RSTYLE_FACES EQU 4t +BR_RSTYLE_BOUNDING_POINTS EQU 5t +BR_RSTYLE_BOUNDING_EDGES EQU 6t +BR_RSTYLE_BOUNDING_FACES EQU 7t +BR_RSTYLE_MAX EQU 8t + +; +; * The actor structure +; +; +; * Doubly linked list of siblings +; * br_actor can be used as br_simple_node +; +@t_33 TYPEDEF PTR br_actor +@t_34 TYPEDEF PTR PTR br_actor +; +; * First in list of children, or NULL if none +; * br_actor.children can be used as br_simple_list +; +@t_35 TYPEDEF PTR br_actor +; +; * Parent, or NULL, if no higher parent +; +@t_36 TYPEDEF PTR br_actor +; +; * Depth of actor from furthest ancestor +; +; +; * Type of actor +; +; +; * Optional name of actor +; +@t_37 TYPEDEF PTR SBYTE +; +; * Reference to model associated with this actor, NULL will inherit +; * from parent (root inherits default_model) +; +@t_38 TYPEDEF PTR br_model +; +; * Default material for model - NULL will inherit from parent. Root +; * inherits default material +; +@t_39 TYPEDEF PTR br_material +; +; * Render style for actor, and all it's decendants if not BR_RSTYLE_DEFAULT +; +; +; * Reference to renderer specific data associated with this actor - NULL will +; * inherit from parent (root inherits default data) +; +@t_40 TYPEDEF PTR +; +; * Postiton of this actor within parent space +; +; +; * Reference to any type specific data block +; +@t_41 TYPEDEF PTR +br_actor STRUCT 4t +next @t_33 ? +prev @t_34 ? +children @t_35 ? +parent @t_36 ? +depth br_uint_16 ? +_type br_uint_8 ? +identifier @t_37 ? +model @t_38 ? +material @t_39 ? +render_style br_uint_8 ? +render_data @t_40 ? +t br_transform <> +type_data @t_41 ? +br_actor ENDS + +; End of file ..\inc\actor.h +; Begin of file ..\inc\camera.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: camera.h 1.4 1995/05/25 13:37:27 sam Exp $ +; * $Locker: $ +; * +; * Definitons for a camera +; +BR_CAMERA_PARALLEL EQU 0t +BR_CAMERA_PERSPECTIVE_FOV EQU 1t +BR_CAMERA_PERSPECTIVE_WHD EQU 2t + +; +; * Backwards compatibility +; +; +; * Optional identifier +; +@t_42 TYPEDEF PTR SBYTE +; +; * Type of camera +; +; +; * Field of view +; * (BR_CAMERA_PERSPECTIVE_FOV only) +; +; +; * Front and back of view volume in view coordinates +; +; +; * Aspect ratio of viewport +; * (BR_CAMERA_PERSPECTIVE_FOV only) +; +; +; * Width and height of projection surface +; * (BR_CAMERA_PERSPECTIVE_WHD and BR_CAMERA_PARALLEL only) +; +; +; * Distance of projection plane from center of projection +; * (BR_CAMERA_PERSPECTIVE_WHD only) +; +br_camera STRUCT 4t +identifier @t_42 ? +_type br_uint_8 ? +field_of_view br_angle ? +hither_z br_scalar ? +yon_z br_scalar ? +aspect br_scalar ? +_width br_scalar ? +height br_scalar ? +distance br_scalar ? +br_camera ENDS + +; End of file ..\inc\camera.h +; Begin of file ..\inc\light.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: light.h 1.6 1995/05/25 13:37:32 sam Exp $ +; * $Locker: $ +; * +; * Definitons for a light +; +; +; * Type of light +; +BR_LIGHT_TYPE EQU 3t +BR_LIGHT_POINT EQU 0t +BR_LIGHT_DIRECT EQU 1t +BR_LIGHT_SPOT EQU 2t +; +; * Flag idicating that caluculations are done in view space +; +BR_LIGHT_VIEW EQU 4t + +; +; * Optional identifier +; +@t_43 TYPEDEF PTR SBYTE +; +; * Type of light +; +; +; * Colour of light (if renderer supports it) +; +; +; * Attenuation of light with distance - constant, linear, and quadratic +; * l & q only apply to point and spot lights +; +; +; * Cone angles for spot light +; +br_light STRUCT 4t +identifier @t_43 ? +_type br_uint_8 ? +colour br_colour ? +attenuation_c br_scalar ? +attenuation_l br_scalar ? +attenuation_q br_scalar ? +cone_outer br_angle ? +cone_inner br_angle ? +br_light ENDS + +; End of file ..\inc\light.h +; Begin of file ..\inc\pool.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: pool.h 1.7 1995/02/22 21:37:18 sam Exp $ +; * $Locker: $ +; * +; * Fixed size block pools +; +BR_POOL_DEBUG EQU 0t +BR_POOL_ALIGN EQU 7t +@t_44 TYPEDEF PTR br_pool_block +br_pool_block STRUCT 4t +next @t_44 ? +br_pool_block ENDS + +@t_45 TYPEDEF PTR br_pool_block +br_pool STRUCT 4t +free @t_45 ? +block_size br_uint_32 ? +chunk_size br_uint_32 ? +mem_type SDWORD ? +br_pool ENDS + +; +; * Speedup macros +; +; End of file ..\inc\pool.h +; Begin of file ..\inc\custsupt.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: custsupt.h 1.2 1995/02/22 21:37:05 sam Exp $ +; * $Locker: $ +; * +; * Definitions for support routines available during render callbacks +; * +; +; +; * Outcode bits +; +OUTCODE_LEFT EQU 000000001h +OUTCODE_RIGHT EQU 000000002h +OUTCODE_TOP EQU 000000004h +OUTCODE_BOTTOM EQU 000000008h +OUTCODE_HITHER EQU 000000010h +OUTCODE_YON EQU 000000020h +OUTCODE_USER EQU 000000040h +OUTCODE_USER_ALL EQU 000000fc0h +OUTCODES_ALL EQU 000000fffh +OUTCODE_N_LEFT EQU 000010000h +OUTCODE_N_RIGHT EQU 000020000h +OUTCODE_N_TOP EQU 000040000h +OUTCODE_N_BOTTOM EQU 000080000h +OUTCODE_N_HITHER EQU 000100000h +OUTCODE_N_YON EQU 000200000h +OUTCODE_N_USER EQU 000400000h +OUTCODE_N_USER_ALL EQU 00fc00000h +OUTCODES_NOT EQU 00fff0000h +; +; * Values for on screen test +; +OSC_REJECT EQU 0t +OSC_PARTIAL EQU 1t +OSC_ACCEPT EQU 2t + +; End of file ..\inc\custsupt.h +; Begin of file ..\inc\brfile.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brfile.h 1.7 1995/02/22 21:36:59 sam Exp $ +; * $Locker: $ +; * +; * Brender's interface to file IO +; +@proto_1 TYPEDEF PROTO C :PTR br_uint_8, :br_size_t +br_mode_test_cbfn TYPEDEF @proto_1 + +; +; * Interface to filesystem +; +@proto_2 TYPEDEF PROTO C +brfile_attributes_cbfn TYPEDEF @proto_2 + +@proto_3 TYPEDEF PROTO C :PTR SBYTE, :br_size_t, :PTR br_mode_test_cbfn, :PTR SDWORD +brfile_open_read_cbfn TYPEDEF @proto_3 + +@proto_4 TYPEDEF PROTO C :PTR SBYTE, :SDWORD +brfile_open_write_cbfn TYPEDEF @proto_4 + +@proto_5 TYPEDEF PROTO C :PTR +brfile_close_cbfn TYPEDEF @proto_5 + +@proto_6 TYPEDEF PROTO C :PTR +brfile_eof_cbfn TYPEDEF @proto_6 + +@proto_7 TYPEDEF PROTO C :PTR +brfile_getchr_cbfn TYPEDEF @proto_7 + +@proto_8 TYPEDEF PROTO C :SDWORD, :PTR +brfile_putchr_cbfn TYPEDEF @proto_8 + +@proto_9 TYPEDEF PROTO C :PTR , :br_size_t, :DWORD, :PTR +brfile_read_cbfn TYPEDEF @proto_9 + +@proto_10 TYPEDEF PROTO C :PTR , :br_size_t, :DWORD, :PTR +brfile_write_cbfn TYPEDEF @proto_10 + +@proto_11 TYPEDEF PROTO C :PTR SBYTE, :br_size_t, :PTR +brfile_getline_cbfn TYPEDEF @proto_11 + +@proto_12 TYPEDEF PROTO C :PTR SBYTE, :PTR +brfile_putline_cbfn TYPEDEF @proto_12 + +@proto_13 TYPEDEF PROTO C :br_size_t, :PTR +brfile_advance_cbfn TYPEDEF @proto_13 + +@t_46 TYPEDEF PTR SBYTE +; +; * Inquire about attributes of file system +; +@t_47 TYPEDEF PTR brfile_attributes_cbfn +; +; * Locate and open a file, and then grab 'n_magics' bytes +; * from the front of the file and pass them to a an 'identify' +; * function that returns the mode of the file +; * +; * Returns file handle, or NULL if open failed +; * +; * Stores open mode through mode_result if not NULL +; +@t_48 TYPEDEF PTR brfile_open_read_cbfn +; +; * Open a file for writing, possibly with text translation +; * +; * Returns fil handle, or NULL if open failed +; +@t_49 TYPEDEF PTR brfile_open_write_cbfn +; +; * Close an opened file +; +@t_50 TYPEDEF PTR brfile_close_cbfn +; +; * Find out if at end of file +; +@t_51 TYPEDEF PTR brfile_eof_cbfn +; +; * Read and write single characters +; +@t_52 TYPEDEF PTR brfile_getchr_cbfn +@t_53 TYPEDEF PTR brfile_putchr_cbfn +; +; * Read and write blocks +; +@t_54 TYPEDEF PTR brfile_read_cbfn +@t_55 TYPEDEF PTR brfile_write_cbfn +; +; * Read and write lines of text, excluding any line terminators +; * Will only be used if text translation is in use +; +@t_56 TYPEDEF PTR brfile_getline_cbfn +@t_57 TYPEDEF PTR brfile_putline_cbfn +; +; * Advance bytes through stream +; * +; * Will not be invoked if text translation is in use +; +@t_58 TYPEDEF PTR brfile_advance_cbfn +br_filesystem STRUCT 4t +identifier @t_46 ? +attributes @t_47 ? +open_read @t_48 ? +open_write @t_49 ? +close @t_50 ? +eof @t_51 ? +getchr @t_52 ? +putchr @t_53 ? +read @t_54 ? +write @t_55 ? +getline @t_56 ? +putline @t_57 ? +advance @t_58 ? +br_filesystem ENDS + +; +; * Bitmask returned by fs->attributes +; +BR_FS_ATTR_READABLE EQU 1t +BR_FS_ATTR_WRITEABLE EQU 2t +BR_FS_ATTR_HAS_TEXT EQU 4t +BR_FS_ATTR_HAS_BINARY EQU 8t +BR_FS_ATTR_HAS_ADVANCE EQU 16t + +; +; * Possible values returner by open_read identify callback +; +BR_FS_MODE_BINARY EQU 0t +BR_FS_MODE_TEXT EQU 1t +BR_FS_MODE_UNKNOWN EQU 2t + +; +; * Maximum number of magic bytes that can be requested on open_read +; +BR_MAX_FILE_MAGICS EQU 16t +; +; * Returned by filesys->getchr at end of file +; +BR_EOF EQU 0ffffffffh +; End of file ..\inc\brfile.h +; Begin of file ..\inc\brdiag.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brdiag.h 1.1 1995/07/28 18:57:13 sam Exp $ +; * $Locker: $ +; * +; * Brender's interface to diagnostic handling +; +; +; * Instance of an error handler +; +@proto_14 TYPEDEF PROTO C :PTR SBYTE +br_diag_warning_cbfn TYPEDEF @proto_14 + +@proto_15 TYPEDEF PROTO C :PTR SBYTE +br_diag_failure_cbfn TYPEDEF @proto_15 + +@t_59 TYPEDEF PTR SBYTE +@t_60 TYPEDEF PTR br_diag_warning_cbfn +@t_61 TYPEDEF PTR br_diag_failure_cbfn +br_diaghandler STRUCT 4t +identifier @t_59 ? +warning @t_60 ? +failure @t_61 ? +br_diaghandler ENDS + +; +; * For backwards compatibility +; +@t_62 TYPEDEF PTR SBYTE +@t_63 TYPEDEF PTR br_diag_warning_cbfn +@t_64 TYPEDEF PTR br_diag_failure_cbfn +br_errorhandler STRUCT 4t +identifier @t_62 ? +message @t_63 ? +error @t_64 ? +br_errorhandler ENDS + +; * +; ** Macros for diagnostic generation +; * +; +; * Report message and exit - should not return to application +; +; +; * Report message and continue +; +; +; * Report message and exit, including source file and line number +; +; +; * Backwards compatibility +; +; End of file ..\inc\brdiag.h +; Begin of file ..\inc\brmem.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brmem.h 1.15 1995/08/31 16:36:13 sam Exp $ +; * $Locker: $ +; * +; * Brender's interface to memory allocation +; +; +; * Instance of a memory allocator +; +@proto_16 TYPEDEF PROTO C :br_size_t, :br_uint_8 +brmem_allocate_cbfn TYPEDEF @proto_16 + +@proto_17 TYPEDEF PROTO C :PTR +brmem_free_cbfn TYPEDEF @proto_17 + +@proto_18 TYPEDEF PROTO C :br_uint_8 +brmem_inquire_cbfn TYPEDEF @proto_18 + +@t_65 TYPEDEF PTR SBYTE +; +; * Allocate a new chunk of memory - must return the new pointer +; * or handle the error itself +; +@t_66 TYPEDEF PTR brmem_allocate_cbfn +; +; * Release previously allocated block +; +@t_67 TYPEDEF PTR brmem_free_cbfn +; +; * Inquire as to the amount of memeory available for a given type +; +@t_68 TYPEDEF PTR brmem_inquire_cbfn +br_allocator STRUCT 4t +identifier @t_65 ? +allocate @t_66 ? +free @t_67 ? +inquire @t_68 ? +br_allocator ENDS + +; +; * Classes of resource that brender allocates +; * +; * Valid values are 1 to 255 +; +; +; * System classes +; +BR_MEMORY_SCRATCH EQU 1t +BR_MEMORY_PIXELMAP EQU 2t +BR_MEMORY_PIXELS EQU 3t +BR_MEMORY_VERTICES EQU 4t +BR_MEMORY_FACES EQU 5t +BR_MEMORY_GROUPS EQU 6t +BR_MEMORY_MODEL EQU 7t +BR_MEMORY_MATERIAL EQU 8t +BR_MEMORY_MATERIAL_INDEX EQU 9t +BR_MEMORY_ACTOR EQU 10t +BR_MEMORY_PREPARED_VERTICES EQU 11t +BR_MEMORY_PREPARED_FACES EQU 12t +BR_MEMORY_LIGHT EQU 13t +BR_MEMORY_CAMERA EQU 14t +BR_MEMORY_BOUNDS EQU 15t +BR_MEMORY_CLIP_PLANE EQU 16t +BR_MEMORY_STRING EQU 17t +BR_MEMORY_REGISTRY EQU 18t +BR_MEMORY_TRANSFORM EQU 19t +BR_MEMORY_RESOURCE_CLASS EQU 20t +BR_MEMORY_FILE EQU 21t +BR_MEMORY_ANCHOR EQU 22t +BR_MEMORY_POOL EQU 23t +BR_MEMORY_RENDER_MATERIAL EQU 24t +BR_MEMORY_DATAFILE EQU 25t +BR_MEMORY_IMAGE EQU 26t +BR_MEMORY_IMAGE_ARENA EQU 27t +BR_MEMORY_IMAGE_SECTIONS EQU 28t +BR_MEMORY_IMAGE_NAMES EQU 29t +BR_MEMORY_EXCEPTION_HANDLER EQU 30t +BR_MEMORY_RENDER_DATA EQU 31t +; +; * Application classes +; +BR_MEMORY_APPLICATION EQU 128t +; +; * User defined classed are BR_MEMORY_APPLICATION + 1 ... 127 +; +BR_MEMORY_MAX EQU 256t + +; +; * A resource class structure +; +@proto_19 TYPEDEF PROTO C :PTR , :br_uint_8, :br_size_t +br_resourcefree_cbfn TYPEDEF @proto_19 + +@t_69 TYPEDEF PTR SBYTE +@t_70 TYPEDEF PTR br_resourcefree_cbfn +br_resource_class STRUCT 4t +identifier @t_69 ? +res_class br_uint_8 ? +free_cb @t_70 ? +br_resource_class ENDS + +; End of file ..\inc\brmem.h +; Begin of file ..\inc\brerr.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brerr.h 1.4 1995/07/28 18:57:02 sam Exp $ +; * $Locker: $ +; * +; * Error type +; +; +; * Error types are 32 bit integers, broken into three fields - +; * +; * Class Subclass Number +; * +; * 33222222 22221111 1111110000000000 +; * 10987654 32109876 5432109876543210 +; * +; * A value of zero is reserved to indiciate no error +; +br_error TYPEDEF br_uint_32 + +; End of file ..\inc\brerr.h +; Begin of file ..\inc\fmt.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: fmt.h 1.5 1995/02/22 21:37:06 sam Exp $ +; * $Locker: $ +; * +; * Definitions for foreign file format support +; +; +; * Type of things to load from file +; +BR_FMT_MODELS EQU 1t +; Create model definitions from file +BR_FMT_ACTORS EQU 2t +; Create actor +BR_FMT_LIGHTS EQU 4t +; Create lights instances +BR_FMT_CAMERAS EQU 8t +; Create cameras instances +; Create materials +BR_FMT_MATERIALS EQU 16t + +; +; * Interchange structure for passing to file format loaders +; * +; * XXX Not yet used by anything +; +; +; * pointers to tables of each loaded allocated by BrFMTxxxLoad() +; +@t_71 TYPEDEF PTR br_model +@t_72 TYPEDEF PTR br_model +@t_73 TYPEDEF PTR br_model +@t_74 TYPEDEF PTR br_model +@t_75 TYPEDEF PTR br_model +; +; * Size of each allocated array +; +br_fmt_results STRUCT 4t +models @t_71 ? +materials @t_72 ? +lights @t_73 ? +cameras @t_74 ? +actors @t_75 ? +nmodels SDWORD ? +nmaterials SDWORD ? +nlights SDWORD ? +ncameras SDWORD ? +nactors SDWORD ? +br_fmt_results ENDS + +; Begin of file ..\inc\fmtproto.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: fmtproto.h 1.8 1995/05/30 16:57:38 sam Exp $ +; * $Locker: $ +; * +; * Function prototypes for foreign file format support +; +; +; * Eric Haines' NFF format +; +@proto_20 TYPEDEF PROTO C :PTR SBYTE +BrFmtNFFLoad PROTO @proto_20 + +; +; * 3D Studio .ASC files +; +@proto_21 TYPEDEF PROTO C :PTR SBYTE, :PTR PTR br_model, :br_uint_16 +BrFmtASCLoad PROTO @proto_21 + +; +; * Script files +; +@proto_22 TYPEDEF PROTO C :PTR SBYTE, :PTR PTR br_material, :br_uint_16 +BrFmtScriptMaterialLoadMany PROTO @proto_22 + +@proto_23 TYPEDEF PROTO C :PTR SBYTE +BrFmtScriptMaterialLoad PROTO @proto_23 + +@proto_24 TYPEDEF PROTO C :PTR SBYTE, :PTR PTR br_material, :br_uint_16 +BrFmtScriptMaterialSaveMany PROTO @proto_24 + +@proto_25 TYPEDEF PROTO C :PTR SBYTE, :PTR br_material +BrFmtScriptMaterialSave PROTO @proto_25 + +; +; * Windows .BMP files +; +@proto_26 TYPEDEF PROTO C :PTR SBYTE, :br_uint_32 +BrFmtBMPLoad PROTO @proto_26 + +; +; * .TGA files +; +@proto_27 TYPEDEF PROTO C :PTR SBYTE, :br_uint_32 +BrFmtTGALoad PROTO @proto_27 + +; +; * .GIF files +; +@proto_28 TYPEDEF PROTO C :PTR SBYTE, :br_uint_32 +BrFmtGIFLoad PROTO @proto_28 + +; +; * .IFF/.LBM files +; +@proto_29 TYPEDEF PROTO C :PTR SBYTE, :br_uint_32 +BrFmtIFFLoad PROTO @proto_29 + +; End of file ..\inc\fmtproto.h +; End of file ..\inc\fmt.h +; +; * Function prototypes +; +; Begin of file ..\inc\fwproto.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: fwproto.h 1.44 1995/08/31 16:36:16 sam Exp $ +; * $Locker: sam $ +; * +; * Function prototypes for brender framework +; +; End of file ..\inc\fwproto.h +; Begin of file ..\inc\zbproto.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: zbproto.h 1.9 1995/08/31 16:36:24 sam Exp $ +; * $Locker: $ +; * +; * Function prototypes for Z buffer renderer +; +BR_BOUNDS_MIN_X EQU 0t +BR_BOUNDS_MIN_Y EQU 1t +BR_BOUNDS_MAX_X EQU 2t +BR_BOUNDS_MAX_Y EQU 3t +; +; * Callback function invoked when an actor is +; * rendered +; +@proto_30 TYPEDEF PROTO C :PTR br_actor, :PTR br_model, :PTR br_material, :PTR , :br_uint_8, :PTR br_matrix4, :PTR br_int_32 +br_renderbounds_cbfn TYPEDEF @proto_30 + +; End of file ..\inc\zbproto.h +; Begin of file ..\inc\zsproto.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: zsproto.h 1.1 1995/08/31 16:37:20 sam Exp $ +; * $Locker: $ +; * +; * Function prototypes for bucket Z-sort renderer +; +; +; * Sort types for primitive insertion +; +BR_ZSORT_MIN EQU 1t +BR_ZSORT_MAX EQU 2t +BR_ZSORT_AVERAGE EQU 4t + +; +; * Callback function invoked when primitive is generated +; +@proto_31 TYPEDEF PROTO C :PTR , :PTR br_actor, :PTR br_model, :PTR br_material, :PTR br_order_table, :PTR br_scalar +br_primitive_cbfn TYPEDEF @proto_31 + +; End of file ..\inc\zsproto.h +; Begin of file ..\inc\fwpextra.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * Extra glue for C<->ASM generated via gemasmpr.pl +; +; End of file ..\inc\fwpextra.h +; +; * Inline functions +; +; Begin of file ..\inc\compend.h +; +; * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: compend.h 1.1 1995/08/31 16:36:45 sam Exp $ +; * $Locker: $ +; * +; * Included at end of BRender includes - undoes any compiler specific pragmas +; +; +; * WATCOM C/C++ 32 +; +; +; * Zortech C++ +; +; End of file ..\inc\compend.h +; End of file ..\inc\brender.h +; Begin of file ..\fw\brlists.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brlists.h 1.4 1995/02/22 21:41:25 sam Exp $ +; * $Locker: $ +; * +; * Doubly linked list supoprt (Based on Amiga EXEC!) +; +; * +; ** Full featued doubly linked lists +; * +; +; * Anchor structure at front of list entries +; +@t_76 TYPEDEF PTR br_node +@t_77 TYPEDEF PTR br_node +br_node STRUCT 4t +next @t_76 ? +prev @t_77 ? +br_node ENDS + +; +; * Anchor structure for whole list - looks like two nodes overlapping. +; * The _null memeber is always NULL, providing the termination at +; * both ends of the list +; +@t_78 TYPEDEF PTR br_node +@t_79 TYPEDEF PTR br_node +@t_80 TYPEDEF PTR br_node +br_list STRUCT 4t +head @t_78 ? +_null @t_79 ? +tail @t_80 ? +br_list ENDS + +; +; * Walk a pointer forwards along a list +; * +; * eg: +; * BR_FOR_LIST(sprites,sptr) { +; * sptr->x = 10; +; * } +; +; +; * Walk a pointer backwards along a list +; * +; * eg: +; * BR_FOR_LIST_R(sprites,sptr) { +; * sptr->x = 10; +; * } +; +; +; * Macros around exported functions that hide type casting +; +; * +; ** Simple lists that only use a single head pointer +; * +@t_81 TYPEDEF PTR br_simple_node +@t_82 TYPEDEF PTR PTR br_simple_node +br_simple_node STRUCT 4t +next @t_81 ? +prev @t_82 ? +br_simple_node ENDS + +; +; * Anchor structure for whole list - just a single head pointer +; +@t_83 TYPEDEF PTR br_simple_node +br_simple_list STRUCT 4t +head @t_83 ? +br_simple_list ENDS + +; +; * Macros around exported functions that hide type casting +; +; +; * Protoypes in lists.c +; +; End of file ..\fw\brlists.h +; Begin of file ..\fw\brexcept.h +; +; * Copyright (c) 1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brexcept.h 1.2 1995/07/28 19:01:35 sam Exp $ +; * $Locker: $ +; * +; * Simple exception handling +; +; +; * Exception types are the same as error types +; * +; * A value of zero is reserved +; +br_exception TYPEDEF br_error + +; +; * Useful macros for generating types +; +; +; * Exception handler - allocated as a resource +; +@t_84 TYPEDEF PTR br_exception_handler +; +; * setjmp/longjmp context to throw to +; +br_exception_handler STRUCT 4t +prev @t_84 ? +br_exception_handler ENDS + +; +; * Public macros +; +; End of file ..\fw\brexcept.h +; Begin of file ..\fw\brimage.h +; +; * Copyright (c) 1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: brimage.h 1.1 1995/07/28 19:03:11 sam Exp $ +; * $Locker: $ +; * +; +; +; * In-memory structure describing a loaded image +; +@t_85 TYPEDEF PTR SBYTE +@t_86 TYPEDEF PTR +br_image_section STRUCT 4t +name @t_85 ? +base @t_86 ? +mem_offset br_size_t ? +mem_size br_size_t ? +data_offset br_uint_32 ? +data_size br_uint_32 ? +br_image_section ENDS + +; +; * Anchor block for list of images +; +; +; * DLL name +; +@t_87 TYPEDEF PTR SBYTE +; +; * Flag, true if DLL is resident +; +; +; * Number of references to this DLL +; +; +; * Table of exported functions +; +@t_88 TYPEDEF PTR PTR +; +; * Name -> ordinal lookup +; +@t_89 TYPEDEF PTR PTR SBYTE +@t_90 TYPEDEF PTR br_uint_16 +; +; * Table of imported image pointers +; +@t_91 TYPEDEF PTR PTR br_image +; +; * Image sections +; +@t_92 TYPEDEF PTR br_image_section +br_image STRUCT 4t +node br_node <> +identifier @t_87 ? +resident br_boolean ? +ref_count SDWORD ? +ordinal_base br_uint_32 ? +n_functions br_uint_32 ? +functions @t_88 ? +n_names br_uint_32 ? +names @t_89 ? +name_ordinals @t_90 ? +n_imports br_uint_16 ? +imports @t_91 ? +n_sections br_uint_16 ? +sections @t_92 ? +br_image ENDS + +; End of file ..\fw\brimage.h +; Begin of file ..\fw\register.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: register.h 1.7 1995/03/16 11:57:08 sam Exp $ +; * $Locker: $ +; * +; * +; +; +; * An entry in a registry - doubly linked list and pointers to data +; * +; * It is assumed that the first thing in the data structure is a pointer +; * to the item's name +; +@t_93 TYPEDEF PTR PTR SBYTE +br_registry_entry STRUCT 4t +node br_node <> +item @t_93 ? +br_registry_entry ENDS + +@proto_32 TYPEDEF PROTO C :PTR SBYTE +br_find_failed_cbfn TYPEDEF @proto_32 + +@proto_33 TYPEDEF PROTO C :PTR , :PTR +br_enum_cbfn TYPEDEF @proto_33 + +; +; * Base structure for registry +; +; +; * Anchor structure +; +; +; * Number of items in list +; +; +; * Hook that is called when RegistryFind fails +; +@t_94 TYPEDEF PTR br_find_failed_cbfn +br_registery STRUCT 4t +list br_list <> +count SDWORD ? +find_failed_hook @t_94 ? +br_registery ENDS + +br_registry TYPEDEF br_registery + +; End of file ..\fw\register.h +; Begin of file ..\fw\device.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * $Id: device.h 1.5 1995/07/28 19:01:38 sam Exp $ +; * $Locker: $ +; * +; * Device structure - a function dispatch table for pixelmap operations +; +; +; * function list for pixelmaps->context +; +@proto_34 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_32 +ctx_fill_cbfn TYPEDEF @proto_34 + +@proto_35 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_32 +ctx_rectangle_cbfn TYPEDEF @proto_35 + +@proto_36 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_32, :br_uint_32 +ctx_rectangle2_cbfn TYPEDEF @proto_36 + +@proto_37 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16 +ctx_rectangle_copy_cbfn TYPEDEF @proto_37 + +@proto_38 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_32 +ctx_rectangle_fill_cbfn TYPEDEF @proto_38 + +@proto_39 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16 +ctx_dirty_rectangle_copy_cbfn TYPEDEF @proto_39 + +@proto_40 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_32 +ctx_dirty_rectangle_fill_cbfn TYPEDEF @proto_40 + +@proto_41 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16, :br_uint_32 +ctx_pixel_set_cbfn TYPEDEF @proto_41 + +@proto_42 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_16, :br_uint_16 +ctx_pixel_get_cbfn TYPEDEF @proto_42 + +@proto_43 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :PTR br_pixelmap +ctx_copy_cbfn TYPEDEF @proto_43 + +@proto_44 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_int_16, :br_int_16, :br_int_16, :br_int_16, :br_uint_32 +ctx_line_cbfn TYPEDEF @proto_44 + +@proto_45 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_int_16, :br_int_16, :PTR br_uint_8, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_16, :br_uint_32 +ctx_copy_bits_cbfn TYPEDEF @proto_45 + +@proto_46 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :PTR br_pixelmap +ctx_double_buffer_cbfn TYPEDEF @proto_46 + +@proto_47 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap, :br_uint_8 +ctx_match_cbfn TYPEDEF @proto_47 + +@proto_48 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap +ctx_clone_cbfn TYPEDEF @proto_48 + +@proto_49 TYPEDEF PROTO C :PTR br_context, :PTR br_pixelmap +ctx_free_cbfn TYPEDEF @proto_49 + +; +; * Device context structure +; +; +; * General ID for this structure +; +@t_95 TYPEDEF PTR SBYTE +; +; * Pointer to underlying device +; +@t_96 TYPEDEF PTR br_device +; +; * Font for context +; +@t_97 TYPEDEF PTR br_font +; +; * Default qualifier for display memory +; +; * +; ** Function pointers for all the context operations +; * +; +; * Pixelmap management operations +; +@t_98 TYPEDEF PTR ctx_free_cbfn +@t_99 TYPEDEF PTR ctx_match_cbfn +@t_100 TYPEDEF PTR ctx_clone_cbfn +@t_101 TYPEDEF PTR ctx_double_buffer_cbfn +; +; * Pixelmap copying +; +@t_102 TYPEDEF PTR ctx_copy_cbfn +@t_103 TYPEDEF PTR ctx_copy_cbfn +@t_104 TYPEDEF PTR ctx_copy_cbfn +; +; * Rendering operations +; +@t_105 TYPEDEF PTR ctx_fill_cbfn +@t_106 TYPEDEF PTR ctx_rectangle_cbfn +@t_107 TYPEDEF PTR ctx_rectangle2_cbfn +@t_108 TYPEDEF PTR ctx_rectangle_copy_cbfn +@t_109 TYPEDEF PTR ctx_rectangle_copy_cbfn +@t_110 TYPEDEF PTR ctx_rectangle_copy_cbfn +@t_111 TYPEDEF PTR ctx_rectangle_fill_cbfn +@t_112 TYPEDEF PTR ctx_dirty_rectangle_copy_cbfn +@t_113 TYPEDEF PTR ctx_dirty_rectangle_fill_cbfn +@t_114 TYPEDEF PTR ctx_pixel_set_cbfn +@t_115 TYPEDEF PTR ctx_pixel_get_cbfn +@t_116 TYPEDEF PTR ctx_line_cbfn +@t_117 TYPEDEF PTR ctx_copy_bits_cbfn +br_context STRUCT 4t +identifier @t_95 ? +device @t_96 ? +font @t_97 ? +free @t_98 ? +match @t_99 ? +clone @t_100 ? +double_buffer @t_101 ? +copy @t_102 ? +copy_to @t_103 ? +copy_from @t_104 ? +fill @t_105 ? +rectangle @t_106 ? +rectangle2 @t_107 ? +rectangle_copy @t_108 ? +rectangle_copy_to @t_109 ? +rectangle_copy_from @t_110 ? +rectangle_fill @t_111 ? +dirty_rectangle_copy @t_112 ? +dirty_rectangle_fill @t_113 ? +pixel_set @t_114 ? +pixel_get @t_115 ? +line @t_116 ? +copy_bits @t_117 ? +br_context ENDS + +; +; * Generic device class structure +; +@proto_50 TYPEDEF PROTO C :PTR br_device +dev_load_cbfn TYPEDEF @proto_50 + +@proto_51 TYPEDEF PROTO C :PTR br_device +dev_unload_cbfn TYPEDEF @proto_51 + +@proto_52 TYPEDEF PROTO C :PTR br_device +dev_enquire_cbfn TYPEDEF @proto_52 + +@proto_53 TYPEDEF PROTO C :PTR br_device +dev_create_cbfn TYPEDEF @proto_53 + +; +; * Loaded devices are linked into a list +; +@t_118 TYPEDEF PTR SBYTE +@t_119 TYPEDEF PTR dev_enquire_cbfn +@t_120 TYPEDEF PTR dev_load_cbfn +@t_121 TYPEDEF PTR dev_unload_cbfn +@t_122 TYPEDEF PTR dev_create_cbfn +br_device STRUCT 4t +node br_node <> +identifier @t_118 ? +enquire @t_119 ? +load @t_120 ? +unload @t_121 ? +create @t_122 ? +br_device ENDS + +; +; * Given a pixelmap, returns the context to use +; * +; * XXX Handles NULL context pointer, but that should be sorted out in +; * PixelmapAllocate +; +; End of file ..\fw\device.h +; +; * Per vertex components +; +C_X EQU 0t +C_Y EQU 1t +C_Z EQU 2t +C_W EQU 3t +C_U EQU 4t +C_V EQU 5t +C_I EQU 6t +C_R EQU 7t +C_G EQU 8t +C_B EQU 9t +C_Q EQU 10t +NUM_COMPONENTS EQU 11t + +; +; * Mask bits for selecting which components take part in various operations +; +CM_X EQU 1t +CM_Y EQU 2t +CM_Z EQU 4t +CM_W EQU 8t +CM_U EQU 16t +CM_V EQU 32t +CM_I EQU 64t +CM_R EQU 128t +CM_G EQU 256t +CM_B EQU 512t +CM_Q EQU 1024t + +; +; * Limited set of components used for lighting sub functions +; +L_I EQU 0t +L_R EQU 1t +L_G EQU 2t +L_B EQU 3t +NUM_L_COMPONENTS EQU 4t + +; +; * Private information about a light as it applies to the current model +; +; +; * Light intensity +; +; +; * position and direction of light in view space +; +; +; * Position and direction of light in final space, view or model +; +; +; * Half vector for specular effects +; +; +; * Cosine of spot angles +; +; +; * Function to evaluate this light +; +@proto_54 TYPEDEF PROTO C :PTR br_vector3, :PTR br_fvector3, :PTR br_active_light, :PTR br_scalar +@t_123 TYPEDEF PTR @proto_54 +; +; * Copy of light's type - may vary from original if a model's relationship +; * to light allows optimisation, eg: +; * very far point light -> directional light +; * model compeletely within spot cone -> point light +; +@t_124 TYPEDEF PTR br_light +br_active_light STRUCT 4t +intensity br_scalar ? +view_position br_vector3 <> +view_direction br_vector3 <> +position br_vector3 <> +direction br_vector3 <> +half br_vector3 <> +spot_cosine_outer br_scalar ? +spot_cosine_inner br_scalar ? +light_sub_function @t_123 ? +_type SDWORD ? +light @t_124 ? +br_active_light ENDS + +; +; * Private information about an active clip plane +; +; +; * Planer eqn. in screen space +; +br_active_clip_plane STRUCT 4t +screen_plane br_vector4 <> +br_active_clip_plane ENDS + +; +; * Framework has a table of functions used for lighting - this +; * will be initialised according to what sort of output is required +; * (eg: indexed or RGB) +; +@proto_55 TYPEDEF PROTO C :PTR br_vertex, :PTR br_fvector3, :PTR br_scalar +br_surface_fn TYPEDEF @proto_55 + +@proto_56 TYPEDEF PROTO C :PTR br_vertex, :PTR br_face, :SDWORD +br_face_surface_fn TYPEDEF @proto_56 + +@proto_57 TYPEDEF PROTO C :PTR br_vector3, :PTR br_fvector3, :PTR br_active_light, :PTR br_scalar +br_light_sub_fn TYPEDEF @proto_57 + +@proto_58 TYPEDEF PROTO C :PTR br_model, :br_uint_16 +br_model_update_cbfn TYPEDEF @proto_58 + +@proto_59 TYPEDEF PROTO C :PTR br_material, :br_uint_16 +br_material_update_cbfn TYPEDEF @proto_59 + +@proto_60 TYPEDEF PROTO C :PTR br_pixelmap, :br_uint_16 +br_table_update_cbfn TYPEDEF @proto_60 + +@proto_61 TYPEDEF PROTO C :PTR br_pixelmap, :br_uint_16 +br_map_update_cbfn TYPEDEF @proto_61 + +; +; * Top level surface functions +; +@t_125 TYPEDEF PTR br_surface_fn +; Evauluate lighting +@t_126 TYPEDEF PTR br_surface_fn +; Copy material +@t_127 TYPEDEF PTR br_surface_fn +; Copy vertex +@t_128 TYPEDEF PTR br_surface_fn +; simple light plus simple texture mapping +@t_129 TYPEDEF PTR br_face_surface_fn +; Evauluate surface for a face +; +; * Lighting +; +@t_130 TYPEDEF PTR br_light_sub_fn +@t_131 TYPEDEF PTR br_light_sub_fn +@t_132 TYPEDEF PTR br_light_sub_fn +@t_133 TYPEDEF PTR br_light_sub_fn +@t_134 TYPEDEF PTR br_light_sub_fn +fw_fn_table STRUCT 4t +light @t_125 ? +light_material @t_126 ? +light_vertex @t_127 ? +light_texture @t_128 ? +face_light @t_129 ? +direct @t_130 ? +point @t_131 ? +point_attn @t_132 ? +spot @t_133 ? +spot_attn @t_134 ? +fw_fn_table ENDS + +; +; * Private state of framework +; +; +; * Main surface properties function +; +@t_135 TYPEDEF PTR br_surface_fn +; +; * Called after U,V generation +; +@t_136 TYPEDEF PTR br_surface_fn +; +; * Called after component copying +; +@t_137 TYPEDEF PTR br_surface_fn +; +; * Lighting a face - usually calls vertex function and converts result for faces +; +@t_138 TYPEDEF PTR br_face_surface_fn +; +; * Current mapping coordinate transform +; +; +; * Base and scale for indexes +; +; +; * Current Transforms +; +; +; * List of transforms from camera to root with associated actor address +; +@t_139 TYPEDEF PTR br_actor +@tag_28 STRUCT 4t +m br_matrix34 <> +_a @t_139 ? +@tag_28 ENDS + +; +; * Type of view to screen transform +; +; +; * COP in model space +; +; +; * Material curently in use - used for lighting calcs. +; +@t_140 TYPEDEF PTR br_material +; +; * Information about each active light, the lights that need to be +; * processed in model space are first, followed by those processed +; * in view space +; +; +; * numbers of active lights of each type +; +; +; * Flag that is set if there is only 1 direct light in model space +; +; +; * Eye vector to use for lighting, either in model or view space +; +; +; * A table of active clip planes +; +; +; * A table of pointers to enabled lights +; * +; * If an entry is not NULL then the referenced actor is an enabled light +; +@t_141 TYPEDEF PTR br_actor +; +; * A table of pointers to enabled clip planes +; * +; * If an entry is not NULL then the referenced actor is a clip plane +; +@t_142 TYPEDEF PTR br_actor +; +; * A pointer to the current environment - if NULL, then the model's +; * local frame will be used +; +@t_143 TYPEDEF PTR br_actor +; +; * Output pixelmap +; +@t_144 TYPEDEF PTR br_pixelmap +; +; * Viewport parameters +; +; +; * Flag that is true if rendering is going on +; +; +; * Various lists of registered items +; +; +; * An index of registered resources by class +; +@t_145 TYPEDEF PTR br_resource_class +; +; * Renderer functions for item preperation & update +; +@t_146 TYPEDEF PTR br_model_update_cbfn +@t_147 TYPEDEF PTR br_material_update_cbfn +@t_148 TYPEDEF PTR br_table_update_cbfn +@t_149 TYPEDEF PTR br_map_update_cbfn +; +; * Current filesystem, memory, and error handlers +; +@t_150 TYPEDEF PTR br_filesystem +@t_151 TYPEDEF PTR br_allocator +@t_152 TYPEDEF PTR br_diaghandler +; +; * File write mode +; +; +; * Base resource of which everything else is +; * a descendant +; +@t_153 TYPEDEF PTR +; +; * Default model +; +@t_154 TYPEDEF PTR br_model +; +; * Default material +; +@t_155 TYPEDEF PTR br_material +; +; * Function pointers to current lighting ops. +; +; +; * Global scratch space +; +@t_156 TYPEDEF PTR +br_framework_state STRUCT 4t +surface_fn @t_135 ? +surface_fn_after_map @t_136 ? +surface_fn_after_copy @t_137 ? +face_surface_fn @t_138 ? +map_transform br_matrix23 <> +index_base br_scalar ? +index_range br_scalar ? +model_to_screen br_matrix4 <> +view_to_screen br_matrix4 <> +model_to_view br_matrix34 <> +view_to_model br_matrix34 <> +model_to_environment br_matrix34 <> +camera_path @tag_28 16t DUP (<>) +vtos_type SDWORD ? +eye_m br_vector3 <> +eye_m_normalised br_vector3 <> +material @t_140 ? +active_lights_model br_active_light 16t DUP (<>) +active_lights_view br_active_light 16t DUP (<>) +nactive_lights_model br_uint_16 ? +nactive_lights_view br_uint_16 ? +light_is_1md SDWORD ? +eye_l br_vector3 <> +active_clip_planes br_active_clip_plane 6t DUP (<>) +nactive_clip_planes br_uint_16 ? +enabled_lights @t_141 16t DUP (?) +enabled_clip_planes @t_142 6t DUP (?) +enabled_environment @t_143 ? +output @t_144 ? +vp_width br_scalar ? +vp_height br_scalar ? +vp_ox br_scalar ? +vp_oy br_scalar ? +rendering SDWORD ? +reg_models br_registry <> +reg_materials br_registry <> +reg_textures br_registry <> +reg_tables br_registry <> +reg_resource_classes br_registry <> +resource_class_index @t_145 256t DUP (?) +model_update @t_146 ? +material_update @t_147 ? +table_update @t_148 ? +map_update @t_149 ? +fsys @t_150 ? +mem @t_151 ? +diag @t_152 ? +open_mode SDWORD ? +res @t_153 ? +default_model @t_154 ? +default_material @t_155 ? +fn_table fw_fn_table <> +scratch_ptr @t_156 ? +scratch_size br_size_t ? +scratch_last br_size_t ? +scratch_inuse SDWORD ? +br_framework_state ENDS + +; +; * Global renderer state +; +EXTERNDEF C fw:br_framework_state + +; +; * Minimum scratch space to allocate for render temps. +; +MIN_WORKSPACE EQU 8192t +; +; * Make sure NULL is defined +; +NULL EQU 0t +; +; * Class of view->screen transform +; +BR_VTOS_PARALLEL EQU 0t +BR_VTOS_PERSPECTIVE EQU 1t +BR_VTOS_4X4 EQU 2t + +; +; * Magic value for vertex->r to say that this vertex does not reuse a previous x,y,z +; +NO_REUSE EQU 00000ffffh +; +; * The level below which the fixed specular power function is zero +; +; +; * Material flags generated during MaterialUpdate() +; +MATUF_SURFACE_FACES EQU 000000001h +MATUF_SURFACE_VERTICES EQU 000000002h +MATUF_REGISTERED EQU 000000004h +; +; * Model flags generated during ModelUpdate() +; +; Smoothing group is the same for the whole model +MODUF_SIMPLE_GROUPS EQU 000000001h +; There are the same number of vertex groups, using the same materials +MODUF_VERTEX_GROUPS_MATCH EQU 000000002h +MODUF_REGISTERED EQU 000000004h +; Model has non-zero pivot point +MODUF_HAS_PIVOT EQU 000000008h +; +; * Perspective dive for Z component of vertices +; +; +; * Generates outcodes for a homogenous point +; +; * The 6 planes of the view volume... +; * Any user defined clip planes... +BR_RES_TRACKING EQU 1t +BR_RES_TAGGING EQU 1t +; +; * Pull in private prototypes +; +; End of file ..\fw\fw.h +USER_CLIP EQU 1t +; +; * Type for the on-screen vertex components +; +SCREEN_FIXED EQU 1t +screen_scalar TYPEDEF br_fixed_ls +; +; * Per vertex (in model) structure +; * +; * Some code relies on this structure being 64 bytes long +; +; Projected screen space point +; Outcodes for this vertex +; Shading components for vertex +temp_vertex STRUCT 4t +v screen_scalar 3t DUP (?) +outcode br_uint_32 ? +direction br_uint_32 ? +comp br_scalar 11t DUP (?) +temp_vertex ENDS + +; Projected screen space point +; Outcodes for this vertex +; Shading components for vertex +temp_vertex_fixed STRUCT 4t +v screen_scalar 3t DUP (?) +outcode br_uint_32 ? +direction br_uint_32 ? +comp br_fixed_ls 11t DUP (?) +temp_vertex_fixed ENDS + +; +; * Per edge (in model) structure +; +; +; * Vertices at either end of edge +; +; br_uint_32 surface; +; +; * Edge material +; +@t_157 TYPEDEF PTR br_material +temp_edge STRUCT 4t +vertices br_uint_16 2t DUP (?) +codes br_uint_16 ? +flag br_uint_8 ? +_pad br_uint_8 1t DUP (?) +material @t_157 ? +temp_edge ENDS + +; +; * Per face (in model) structure +; +; +; * Result of face surface call +; * +; * Will either be an index or a true colour +; +; +; * Combined outcodes of face +; +; +; * Flag describing visiblity of face +; +temp_face STRUCT 4t +surface br_uint_32 ? +codes br_uint_16 ? +flag br_uint_8 ? +_pad br_uint_8 1t DUP (?) +temp_face ENDS + +; +; * Values for temp_face.flag +; +TFF_VISIBLE EQU 4t +TFF_CLIPPED EQU 2t +TFF_REVERSED EQU 1t +; +; * Values for temp_vertex.direction +; +TVDIR_FRONT EQU 000000001h +TVDIR_BACK EQU 000000002h +; +; * Components of vertex +; +clip_vertex STRUCT 4t +outcode br_uint_16 ? +base_vertex br_uint_16 ? +comp br_scalar 11t DUP (?) +clip_vertex ENDS + +; +; * Scan convertion details for one edge of triangle +; +; delta x along edge +; delta y along edge +; gradient (x/y) +; Starting value (fraction) +; (integer) +; delta_x per scanline (fraction) +; (integer) +; starting scanline +; total scanlines +scan_edge STRUCT 4t +x br_fixed_ls ? +y br_fixed_ls ? +grad br_fixed_ls ? +f br_int_32 ? +i br_int_32 ? +d_f br_int_32 ? +d_i br_int_32 ? +start br_int_32 ? +count br_int_32 ? +scan_edge ENDS + +; +; * Scan convertion details for one parameter +; +; Parameter (16.16) value at pixel +; Parameter (16.16) value at start of scanline +; Increment per scanline if carry from bit 15 +; "" "" no carry "" +; Gradient of parameter along X axis +; Gradient of parameter along Y axis +scan_parameter STRUCT 4t +currentpix br_fixed_ls ? +current br_fixed_ls ? +d_carry br_fixed_ls ? +d_nocarry br_fixed_ls ? +grad_x br_fixed_ls ? +grad_y br_fixed_ls ? +scan_parameter ENDS + +; +; * Arbitrary width scan line data +; +@t_158 TYPEDEF PTR scan_edge +@t_159 TYPEDEF PTR SBYTE +@t_160 TYPEDEF PTR SBYTE +@t_161 TYPEDEF PTR SBYTE +@t_162 TYPEDEF PTR SBYTE +@t_163 TYPEDEF PTR SBYTE +arbitrary_width_scan STRUCT 4t +edge @t_158 ? +start @t_159 ? +_end @t_160 ? +zstart @t_161 ? +source_current @t_162 ? +u_int_current SWORD ? +pad SWORD ? +u_current DWORD ? +du DWORD ? +du_carry DWORD ? +du_nocarry DWORD ? +du_int SDWORD ? +du_int_nocarry SDWORD ? +du_int_carry SDWORD ? +v_current DWORD ? +dv DWORD ? +dv_carry DWORD ? +dv_nocarry DWORD ? +dsource SDWORD ? +dsource_carry SDWORD ? +dsource_nocarry SDWORD ? +texture_start @t_163 ? +texture_size SDWORD ? +texture_stride SDWORD ? +texture_width SDWORD ? +arbitrary_width_scan ENDS + +; +; * Perspective texture mapper data +; +@t_164 TYPEDEF PTR SBYTE +@t_165 TYPEDEF PTR SBYTE +@t_166 TYPEDEF PTR SBYTE +perspective_scan STRUCT 4t +start @t_164 ? +_end @t_165 ? +zstart @t_166 ? +source SDWORD ? +y SDWORD ? +perspective_scan ENDS + +; +; * Function types for primitives +; +@proto_62 TYPEDEF PROTO C :PTR temp_vertex_fixed, :PTR temp_vertex_fixed, :PTR temp_vertex_fixed +br_triangle_fn TYPEDEF @proto_62 + +@proto_63 TYPEDEF PROTO C :PTR temp_vertex_fixed, :PTR temp_vertex_fixed +br_line_fn TYPEDEF @proto_63 + +@proto_64 TYPEDEF PROTO C :PTR temp_vertex_fixed +br_point_fn TYPEDEF @proto_64 + +; +; * Callback functions for generic trapezoid and pixel plot fns. +; +@proto_65 TYPEDEF PROTO C :PTR scan_edge +br_trapezoid_render_cb TYPEDEF @proto_65 + +@proto_66 TYPEDEF PROTO C :br_int_32, :br_int_32 +br_pixel_render_cb TYPEDEF @proto_66 + +; +; * Private state of renderer +; +; +; * Local copy of model -> screen with viewport factored in +; +; +; * Pointers into scratch area +; +@t_167 TYPEDEF PTR br_int_8 +@t_168 TYPEDEF PTR br_int_32 +@t_169 TYPEDEF PTR br_int_8 +@t_170 TYPEDEF PTR br_int_8 +@t_171 TYPEDEF PTR temp_face +@t_172 TYPEDEF PTR temp_edge +@t_173 TYPEDEF PTR temp_vertex +; +; * Flag to indicate that vertex directions +; * have been initialised +; +; +; * Model and material being rendered +; +@t_174 TYPEDEF PTR br_model +@t_175 TYPEDEF PTR br_material +; +; * Current default material +; +@t_176 TYPEDEF PTR br_material +; +; * Misc. constant parameters for rendering +; +@t_177 TYPEDEF PTR br_uint_8 +; Colour buffer +@t_178 TYPEDEF PTR br_fixed_ls +; Z buffer +; Stride (in bytes) +; Stride (in bytes) +@t_179 TYPEDEF PTR br_uint_8 +; Texture map to use +@t_180 TYPEDEF PTR br_uint_8 +; Bump map to use +@t_181 TYPEDEF PTR br_uint_8 +; Indirection table +@t_182 TYPEDEF PTR br_uint_8 +; Indirection table +@t_183 TYPEDEF PTR br_uint_8 +; Lighting for quantised normals +@t_184 TYPEDEF PTR br_uint_32 +; Screen +; +; * Workspace for triangle scan converter +; +; Long edge of triangle +; Top short edge +; Bottom short edge +; Depth +; Mapping +; Index +; Red +; Green +; Blue +; Perspective divisor +; Current texel +; +; * Per-component mask for scan converter interpolation +; +; Components to interpolate +; Components to apply perspective correction +; Components to clip +; Components to convert scalar->float +; +; * Global arbitrary width scan line data +; +; +; * Perspective texture mapper globals +; +; +; * Current triangle functions +; +@t_185 TYPEDEF PTR br_triangle_fn +; +; * Generic triangle rendering sub-functions +; +@t_186 TYPEDEF PTR br_trapezoid_render_cb +@t_187 TYPEDEF PTR br_pixel_render_cb +; +; * Bounds of rendered actor +; +; +; * Callback for visible actors +; +@t_188 TYPEDEF PTR br_renderbounds_cbfn +; +; * Current output type +; +@t_189 TYPEDEF PTR zb_render_type +; +; * Anchor resource for ZB renderer +; +@t_190 TYPEDEF PTR +br_zbuffer_state STRUCT 4t +os_model_to_screen br_matrix4 <> +os_model_to_screen_hi br_scalar 4t DUP (?) +vertex_counts @t_167 ? +face_group_counts @t_168 ? +face_group_clipped @t_169 ? +edge_counts @t_170 ? +temp_faces @t_171 ? +temp_edges @t_172 ? +temp_vertices @t_173 ? +directions_cleared SDWORD ? +model @t_174 ? +material @t_175 ? +default_material @t_176 ? +colour_buffer @t_177 ? +depth_buffer @t_178 ? +row_width br_int_32 ? +depth_row_width br_int_32 ? +texture_buffer @t_179 ? +bump_buffer @t_180 ? +shade_table @t_181 ? +blend_table @t_182 ? +lighting_table @t_183 ? +screen_table @t_184 ? +main scan_edge <> +top scan_edge <> +bot scan_edge <> +pz scan_parameter <> +pu scan_parameter <> +pv scan_parameter <> +pi scan_parameter <> +pr scan_parameter <> +pg scan_parameter <> +pb scan_parameter <> +pq scan_parameter <> +source scan_parameter <> +component_mask br_uint_32 ? +correct_mask br_uint_32 ? +clip_mask br_uint_32 ? +convert_mask br_uint_32 ? +awsl arbitrary_width_scan <> +tsl perspective_scan <> +triangle_render @t_185 ? +trapezoid_render @t_186 ? +pixel_render @t_187 ? +bounds screen_scalar 4t DUP (?) +bounds_call @t_188 ? +_type @t_189 ? +res @t_190 ? +br_zbuffer_state ENDS + +EXTERNDEF C zb:br_zbuffer_state + +; +; * Transform into screen space - Inline expanded BrMatrix4ApplyP() +; +; +; * Generic macro for projecting a vertex from homogenous coordinates +; +; +; * Alignment for block in scratch area +; +SCRATCH_BOUNDARY EQU 16t +; +; * New line and point clamps +; +; +; * Include bounding rectangle callback +; +BOUNDING_RECTANGLE_CALL EQU 1t +; +; * Update MIN and MAX vertices' x,y +; +@proto_67 TYPEDEF PROTO C :PTR br_face_group, :PTR temp_face +br_face_group_fn TYPEDEF @proto_67 + +; +; * Structure describing one particular sort of material renderer +; +; +; * Descriptive string +; +@t_191 TYPEDEF PTR SBYTE +; +; * If +; * mat->flags & flags_mask) == flags_cmp +; * colour_map->map_type == map_type +; * width != 0 && colour_map->width == width +; * height != 0 && colour_map->height == height +; * +; * material matches this type +; +@t_192 TYPEDEF PTR br_face_group_fn +@t_193 TYPEDEF PTR br_triangle_fn +@t_194 TYPEDEF PTR br_line_fn +@t_195 TYPEDEF PTR br_point_fn +zb_material_type STRUCT 4t +identifier @t_191 ? +flags_mask br_uint_32 ? +flags_cmp br_uint_32 ? +map_type br_uint_8 ? +_width br_uint_16 ? +height br_uint_16 ? +face_group @t_192 ? +triangle @t_193 ? +line @t_194 ? +point @t_195 ? +clip_mask br_uint_32 ? +convert_mask br_uint_32 ? +zb_material_type ENDS + +; +; * Flags used to augment material flags when specifiying +; * material type +; +ZB_MATF_HAS_MAP EQU 080000000h +ZB_MATF_TRANSPARENT EQU 040000000h +ZB_MATF_HAS_SCREEN EQU 020000000h +ZB_MATF_SQUARE_POW2 EQU 010000000h +ZB_MATF_NO_SKIP EQU 008000000h +ZB_MATF_MAP_OPACITY EQU 004000000h +ZB_MATF_MAP_TRANSPARENT EQU 002000000h +ZB_MATF_HAS_SHADE EQU 001000000h +; +; * Structure describing one particular class of renderer +; +; +; * Descriptive string +; +@t_196 TYPEDEF PTR SBYTE +; +; * Type of colour buffer +; +; +; * Type of depth buffer +; +; XXX unused at the moment +; +; * Used to check if the row_width's of the two pixelmaps +; * match - +; * if colour row_width * depth_row_size == depth row_width * colour_row_size +; * then this set of functions match +; +; +; * Flag to indicate true-colour +; +; +; * A table of supported material types +; +@t_197 TYPEDEF PTR zb_material_type +zb_render_type STRUCT 4t +identifier @t_196 ? +colour_type br_uint_8 ? +depth_type br_uint_8 ? +user_type br_uint_16 ? +colour_row_size br_uint_8 ? +depth_row_size br_uint_8 ? +true_colour br_uint_8 ? +material_types @t_197 ? +nmaterial_types SDWORD ? +zb_render_type ENDS + +; +; * Pull in private prototypes +; +; Begin of file zbipxtra.h +; +; * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. +; * +; * Extra glue for C<->ASM generated via gemasmpr.pl +; +; End of file zbipxtra.h +; End of file zb.h diff --git a/bren/ZB/zb.h b/bren/ZB/zb.h new file mode 100644 index 00000000..b8cfdef0 --- /dev/null +++ b/bren/ZB/zb.h @@ -0,0 +1,589 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: zb.h 1.44 1995/08/31 16:47:50 sam Exp $ + * $Locker: $ + * + * Internal types and structures for z-buffer renderer + */ +#ifndef _ZB_H_ +#define _ZB_H_ + +/* + * Pull in all the framework and public definitions + */ +#ifndef _FW_H_ +#include "fw.h" +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define USER_CLIP 1 + +/* + * Type for the on-screen vertex components + */ +#define SCREEN_FIXED 1 + +#if SCREEN_FIXED + typedef br_fixed_ls screen_scalar; + +#define ScreenToInt(x) BrFixedToInt(x) +#define IntToScreen(x) BrIntToFixed(x) + +#define ScalarToScreen(x) BrScalarToFixed(x) +#define ScreenToScalar(x) BrFixedToScalar(x) + +#define FixedToScreen(x) (x) +#define ScreenToFixed(x) (x) +#else + +typedef int screen_scalar; + +#define ScreenToInt(x) (x) +#define IntToScreen(x) (x) + +#define ScalarToScreen(x) BrScalarToInt(x) +#define ScreenToScalar(x) BrIntToScalar(x) + +#define FixedToScreen(x) BrFixedToInt(x) +#define ScreenToFixed(x) BrIntToFixed(x) + +#endif + + /* + * Per vertex (in model) structure + * + * Some code relies on this structure being 64 bytes long + */ + struct temp_vertex + { + screen_scalar v[3]; /* Projected screen space point */ + br_uint_32 outcode; /* Outcodes for this vertex */ + br_uint_32 direction; + br_scalar comp[NUM_COMPONENTS]; /* Shading components for vertex */ + }; + + struct temp_vertex_fixed + { + screen_scalar v[3]; /* Projected screen space point */ + br_uint_32 outcode; /* Outcodes for this vertex */ + br_uint_32 direction; + br_fixed_ls comp[NUM_COMPONENTS]; /* Shading components for vertex */ + }; + + /* + * Per edge (in model) structure + */ + struct temp_edge + { + /* + * Vertices at either end of edge + */ + br_uint_16 vertices[2]; + br_uint_16 codes; + + br_uint_8 flag; + br_uint_8 _pad[1]; + + // br_uint_32 surface; + + /* + * Edge material + */ + br_material *material; + }; + + /* + * Per face (in model) structure + */ + struct temp_face + { + /* + * Result of face surface call + * + * Will either be an index or a true colour + */ + br_uint_32 surface; + + /* + * Combined outcodes of face + */ + br_uint_16 codes; + + /* + * Flag describing visiblity of face + */ + br_uint_8 flag; + br_uint_8 _pad[1]; + }; + +/* + * Values for temp_face.flag + */ +#define TFF_VISIBLE 4 +#define TFF_CLIPPED 2 +#define TFF_REVERSED 1 + +/* + * Values for temp_vertex.direction + */ +#define TVDIR_FRONT 0x01 +#define TVDIR_BACK 0x02 + + struct clip_vertex + { + + br_uint_16 outcode; + br_uint_16 base_vertex; + + /* + * Components of vertex + */ + br_scalar comp[NUM_COMPONENTS]; + }; + + /* + * Scan convertion details for one edge of triangle + */ + struct scan_edge + { + br_fixed_ls x; /* delta x along edge */ + br_fixed_ls y; /* delta y along edge */ + br_fixed_ls grad; /* gradient (x/y) */ + br_int_32 f; /* Starting value (fraction) */ + br_int_32 i; /* (integer) */ + br_int_32 d_f; /* delta_x per scanline (fraction) */ + br_int_32 d_i; /* (integer) */ + br_int_32 start; /* starting scanline */ + br_int_32 count; /* total scanlines */ + }; + + /* + * Scan convertion details for one parameter + */ + struct scan_parameter + { + br_fixed_ls currentpix; /* Parameter (16.16) value at pixel */ + br_fixed_ls current; /* Parameter (16.16) value at start of scanline */ + br_fixed_ls d_carry; /* Increment per scanline if carry from bit 15 */ + br_fixed_ls d_nocarry; /* "" "" no carry "" */ + br_fixed_ls grad_x; /* Gradient of parameter along X axis */ + br_fixed_ls grad_y; /* Gradient of parameter along Y axis */ + }; + + /* + * Arbitrary width scan line data + */ + struct arbitrary_width_scan + { + struct scan_edge *edge; + + br_uint_8 *start, *end; + br_fixed_ls *zstart; + br_uint_8 *source_current; + + short u_int_current; + + short pad; + + unsigned u_current, du, du_carry, du_nocarry; + int du_int, du_int_nocarry, du_int_carry; + + unsigned v_current, dv, dv_carry, dv_nocarry; + int dsource, dsource_carry, dsource_nocarry; + + br_uint_8 *texture_start; + int texture_size, texture_stride, texture_width; + }; + + /* + * Perspective texture mapper data + */ + struct perspective_scan + { + char *start, *end; + char *zstart; + int source; + int y; + }; + + /* + * Function types for primitives + */ + typedef void BR_ASM_CALL br_triangle_fn(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); + typedef void BR_ASM_CALL br_line_fn(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + typedef void BR_ASM_CALL br_point_fn(struct temp_vertex_fixed *v0); + + /* + * Callback functions for generic trapezoid and pixel plot fns. + */ + typedef void BR_ASM_CALL br_trapezoid_render_cb(struct scan_edge *minor); + typedef void BR_ASM_CALL br_pixel_render_cb(br_int_32 x, br_int_32 y); + + /* + * Private state of renderer + */ + typedef struct br_zbuffer_state + { + /* + * Local copy of model -> screen with viewport factored in + */ + br_matrix4 os_model_to_screen; + br_scalar os_model_to_screen_hi[4]; + + /* + * Pointers into scratch area + */ + br_int_8 *vertex_counts; + br_int_32 *face_group_counts; + br_int_8 *face_group_clipped; + br_int_8 *edge_counts; + struct temp_face *temp_faces; + struct temp_edge *temp_edges; + struct temp_vertex *temp_vertices; + + /* + * Flag to indicate that vertex directions + * have been initialised + */ + int directions_cleared; + + /* + * Model and material being rendered + */ + br_model *model; + br_material *material; + + /* + * Current default material + */ + br_material *default_material; + + /* + * Misc. constant parameters for rendering + */ + br_uint_8 *colour_buffer; /* Colour buffer */ + br_fixed_ls *depth_buffer; /* Z buffer */ + br_int_32 row_width; /* Stride (in bytes) */ + br_int_32 depth_row_width; /* Stride (in bytes) */ + + br_uint_8 *texture_buffer; /* Texture map to use */ + br_uint_8 *bump_buffer; /* Bump map to use */ + br_uint_8 *shade_table; /* Indirection table */ + br_uint_8 *blend_table; /* Indirection table */ + br_uint_8 *lighting_table; /* Lighting for quantised normals */ + br_uint_32 *screen_table; /* Screen */ + +#if 0 + /* + * Table of x * row_width + */ + br_uint_32 row_table[MAX_OUTPUT_HEIGHT]; +#endif + + /* + * Workspace for triangle scan converter + */ + struct scan_edge main; /* Long edge of triangle */ + struct scan_edge top; /* Top short edge */ + struct scan_edge bot; /* Bottom short edge */ + + struct scan_parameter pz; /* Depth */ + + struct scan_parameter pu; /* Mapping */ + struct scan_parameter pv; + + struct scan_parameter pi; /* Index */ + + struct scan_parameter pr; /* Red */ + struct scan_parameter pg; /* Green */ + struct scan_parameter pb; /* Blue */ + + struct scan_parameter pq; /* Perspective divisor */ + + struct scan_parameter source; /* Current texel */ + + /* + * Per-component mask for scan converter interpolation + */ + br_uint_32 component_mask; /* Components to interpolate */ + br_uint_32 correct_mask; /* Components to apply perspective correction */ + + br_uint_32 clip_mask; /* Components to clip */ + br_uint_32 convert_mask; /* Components to convert scalar->float */ + + /* + * Global arbitrary width scan line data + */ + struct arbitrary_width_scan awsl; + + /* + * Perspective texture mapper globals + */ + struct perspective_scan tsl; + + /* + * Current triangle functions + */ + br_triangle_fn *triangle_render; + + /* + * Generic triangle rendering sub-functions + */ + br_trapezoid_render_cb *trapezoid_render; + br_pixel_render_cb *pixel_render; + + /* + * Bounds of rendered actor + */ + screen_scalar bounds[4]; + + /* + * Callback for visible actors + */ + br_renderbounds_cbfn *bounds_call; + + /* + * Current output type + */ + struct zb_render_type *type; + + /* + * Anchor resource for ZB renderer + */ + void *res; + + } br_zbuffer_state; + + extern br_zbuffer_state BR_ASM_DATA zb; + + /* + * Transform into screen space - Inline expanded BrMatrix4ApplyP() + */ +#define TRANSFORM_VERTEX_OS() \ + { \ + screen.v[X] = BR_MAC3(vp->p.v[X], fw.model_to_screen.m[0][0], vp->p.v[Y], fw.model_to_screen.m[1][0], \ + vp->p.v[Z], fw.model_to_screen.m[2][0]) + \ + fw.model_to_screen.m[3][0]; \ + \ + screen.v[Y] = BR_MAC3(vp->p.v[X], fw.model_to_screen.m[0][1], vp->p.v[Y], fw.model_to_screen.m[1][1], \ + vp->p.v[Z], fw.model_to_screen.m[2][1]) + \ + fw.model_to_screen.m[3][1]; \ + \ + screen.v[Z] = BR_MAC3(vp->p.v[X], fw.model_to_screen.m[0][2], vp->p.v[Y], fw.model_to_screen.m[1][2], \ + vp->p.v[Z], fw.model_to_screen.m[2][2]) + \ + fw.model_to_screen.m[3][2]; \ + \ + screen.v[W] = BR_MAC3(vp->p.v[X], fw.model_to_screen.m[0][3], vp->p.v[Y], fw.model_to_screen.m[1][3], \ + vp->p.v[Z], fw.model_to_screen.m[2][3]) + \ + fw.model_to_screen.m[3][3]; \ + } + +/* + * Generic macro for projecting a vertex from homogenous coordinates + */ +#define PROJECT_VERTEX(tvp, sx, sy, sz, sw) \ + { \ + (tvp)->v[X] = ScalarToScreen(fw.vp_ox + BR_MULDIV(fw.vp_width, (sx), (sw))); \ + (tvp)->v[Y] = ScalarToScreen(fw.vp_oy + BR_MULDIV(fw.vp_height, (sy), (sw))); \ + (tvp)->v[Z] = BrScalarToFixed(PERSP_DIV_Z((sz), (sw))); \ + } + +/* + * Alignment for block in scratch area + */ +#define SCRATCH_BOUNDARY 16 +#define SCRATCH_ALIGN(x) (((x) + (SCRATCH_BOUNDARY - 1)) & ~(SCRATCH_BOUNDARY - 1)) + +/* + * New line and point clamps + */ +#define CLAMP_LP(x, y) \ + { \ + if (x < 0) \ + x = 0; \ + if (y < 0) \ + y = 0; \ + if (x >= fw.output->width) \ + x--; \ + if (y >= fw.output->height) \ + y--; \ + } + +/* + * Include bounding rectangle callback + */ +#define BOUNDING_RECTANGLE_CALL 1 + +#if BOUNDING_RECTANGLE_CALL +/* + * Update MIN and MAX vertices' x,y + */ +#define UPDATE_BOUNDS(tv) \ + { \ + if ((tv).v[X] > zb.bounds[BR_BOUNDS_MAX_X]) \ + zb.bounds[BR_BOUNDS_MAX_X] = (tv).v[X]; \ + if ((tv).v[X] < zb.bounds[BR_BOUNDS_MIN_X]) \ + zb.bounds[BR_BOUNDS_MIN_X] = (tv).v[X]; \ + if ((tv).v[Y] > zb.bounds[BR_BOUNDS_MAX_Y]) \ + zb.bounds[BR_BOUNDS_MAX_Y] = (tv).v[Y]; \ + if ((tv).v[Y] < zb.bounds[BR_BOUNDS_MIN_Y]) \ + zb.bounds[BR_BOUNDS_MIN_Y] = (tv).v[Y]; \ + } + +#define CLAMP_POINT(x, y) \ + { \ + if ((x) <= ScalarToScreen(fw.vp_ox - fw.vp_width)) \ + (x) = ScalarToScreen(fw.vp_ox - fw.vp_width) + 1; \ + if ((x) >= ScalarToScreen(fw.vp_ox + fw.vp_width)) \ + (x) = ScalarToScreen(fw.vp_ox + fw.vp_width) - 1; \ + \ + if ((y) <= ScalarToScreen(fw.vp_oy + fw.vp_height)) \ + (y) = ScalarToScreen(fw.vp_oy + fw.vp_height) + 1; \ + if ((y) >= ScalarToScreen(fw.vp_oy - fw.vp_height)) \ + (y) = ScalarToScreen(fw.vp_oy - fw.vp_height) - 1; \ + } + +#define CLAMP_POINT_MIN(x, y) \ + { \ + if ((x) <= ScalarToScreen(fw.vp_ox - fw.vp_width)) \ + (x) = ScalarToScreen(fw.vp_ox - fw.vp_width) + 1; \ + \ + if ((y) <= ScalarToScreen(fw.vp_oy + fw.vp_height)) \ + (y) = ScalarToScreen(fw.vp_oy + fw.vp_height) + 1; \ + } + +#define CLAMP_POINT_MAX(x, y) \ + { \ + if ((x) >= ScalarToScreen(fw.vp_ox + fw.vp_width)) \ + (x) = ScalarToScreen(fw.vp_ox + fw.vp_width) - 1; \ + \ + if ((y) >= ScalarToScreen(fw.vp_oy - fw.vp_height)) \ + (y) = ScalarToScreen(fw.vp_oy - fw.vp_height) - 1; \ + } + +#else +#define UPDATE_BOUNDS(tv) +#endif + + typedef void BR_ASM_CALL br_face_group_fn(struct br_face_group *gp, struct temp_face *tfp); + + /* + * Structure describing one particular sort of material renderer + */ + struct zb_material_type + { + /* + * Descriptive string + */ + char *identifier; + + /* + * If + * mat->flags & flags_mask) == flags_cmp + * colour_map->map_type == map_type + * width != 0 && colour_map->width == width + * height != 0 && colour_map->height == height + * + * material matches this type + */ + br_uint_32 flags_mask; + br_uint_32 flags_cmp; + br_uint_8 map_type; + br_uint_16 width; + br_uint_16 height; + + br_face_group_fn *face_group; + br_triangle_fn *triangle; + + br_line_fn *line; + br_point_fn *point; + + br_uint_32 clip_mask; + br_uint_32 convert_mask; + }; + +/* + * Flags used to augment material flags when specifiying + * material type + */ +#define ZB_MATF_HAS_MAP 0x80000000 +#define ZB_MATF_TRANSPARENT 0x40000000 +#define ZB_MATF_HAS_SCREEN 0x20000000 +#define ZB_MATF_SQUARE_POW2 0x10000000 +#define ZB_MATF_NO_SKIP 0x08000000 +#define ZB_MATF_MAP_OPACITY 0x04000000 +#define ZB_MATF_MAP_TRANSPARENT 0x02000000 +#define ZB_MATF_HAS_SHADE 0x01000000 + + /* + * Structure describing one particular class of renderer + */ + struct zb_render_type + { + /* + * Descriptive string + */ + char *identifier; + + /* + * Type of colour buffer + */ + br_uint_8 colour_type; + + /* + * Type of depth buffer + */ + br_uint_8 depth_type; + + br_uint_16 user_type; /* XXX unused at the moment */ + + /* + * Used to check if the row_width's of the two pixelmaps + * match - + * if colour row_width * depth_row_size == depth row_width * colour_row_size + * then this set of functions match + */ + br_uint_8 colour_row_size; + br_uint_8 depth_row_size; + + /* + * Flag to indicate true-colour + */ + br_uint_8 true_colour; + + /* + * A table of supported material types + */ + struct zb_material_type *material_types; + + int nmaterial_types; + }; + +#ifdef __cplusplus +}; +#endif + +/* + * Pull in private prototypes + */ +#ifndef _NO_PROTOTYPES + +#ifndef _ZBIPROTO_H_ +#include "zbiproto.h" +#endif + +#ifndef _FWIPROTO_H_ +#include "fwiproto.h" +#endif + +#endif + +#endif + + diff --git a/bren/ZB/zb.inc b/bren/ZB/zb.inc new file mode 100644 index 00000000..e2347c20 --- /dev/null +++ b/bren/ZB/zb.inc @@ -0,0 +1,8 @@ +option expr32 +option casemap:none + +if BASED_FIXED eq 1 + include zb.fixed.inc +elseif BASED_FLOAT eq 1 + include zb.float.inc +endif \ No newline at end of file diff --git a/bren/ZB/zbclip.c b/bren/ZB/zbclip.c new file mode 100644 index 00000000..f9e19d61 --- /dev/null +++ b/bren/ZB/zbclip.c @@ -0,0 +1,785 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: zbclip.c 1.4 1995/08/31 16:47:51 sam Exp $ + * $Locker: $ + * + * Mesh rendering to produce faces + */ +#include "zb.h" +#include "shortcut.h" +#include "blockops.h" +#include "brassert.h" + +static char rscid[] = "$Id: zbclip.c 1.4 1995/08/31 16:47:51 sam Exp $"; + +#if USER_CLIP +/* + * Core of 3D homogenous clipper - loosly based on Paul Heckbert's + * implemetationin Graphics Gems I. + * + * Clip a polygon to an arbitary plane eqn. + */ +static int ZbClipFaceToPlane(struct clip_vertex *vp, struct clip_vertex *verts_out, int num_in, br_vector4 *plane, + int cmask) +{ + struct clip_vertex *wp = verts_out; + int num_out = 0; + + struct clip_vertex *up; + br_scalar t, tu, tv; + int m; + br_scalar *usp, *vsp, *wsp; + /* + * Go round face, an edge at a time + */ + up = vp + num_in - 1; + + tu = -BR_MAC4(plane->v[0], up->comp[C_X], plane->v[1], up->comp[C_Y], plane->v[2], up->comp[C_Z], plane->v[3], + up->comp[C_W]); + + for (; num_in--; up = vp, tu = tv, vp++) + { + + tv = -BR_MAC4(plane->v[0], vp->comp[C_X], plane->v[1], vp->comp[C_Y], plane->v[2], vp->comp[C_Z], plane->v[3], + vp->comp[C_W]); + + if (tv <= S0) + { + /* + * This vertex is inside clip space + */ + if (tu <= S0) + { + /* + * last vertex was as well - add this vertex + */ + *wp++ = *vp; + num_out++; + continue; + } + + /* + * Edge crosses out to in, add intersection and this vertex + */ + t = BR_DIVR(tv, (tv - tu)); + + usp = up->comp; + vsp = vp->comp; + wsp = wp->comp; + + for (m = cmask; m; m >>= 1, usp++, vsp++, wsp++) + if (m & 1) + *wsp = *vsp + BR_MUL(t, (*usp - *vsp)); + + wp++; + + /* + * Copy next vertex + */ + *wp++ = *vp; + num_out += 2; + } + else + { + /* + * This vertex is outside clip space + */ + if (tu > S0) + /* + * last vertex was as well - don't do anything + */ + continue; + + /* + * Edge crosses in to out, add intersection + */ + + t = BR_DIVR(tu, (tu - tv)); + + usp = up->comp; + vsp = vp->comp; + wsp = wp->comp; + + for (m = cmask; m; m >>= 1, usp++, vsp++, wsp++) + if (m & 1) + *wsp = *usp + BR_MUL(t, (*vsp - *usp)); + + wp++; + num_out++; + } + } + + return num_out; +} +#endif + +#if 0 /* Unused at the moment - has been special cased even further */ +/* + * Special case for plane that has one of the axes as a normal + */ +static int ZbClipFaceToAxisPlane( + struct clip_vertex *vp, + struct clip_vertex *verts_out, + int num_in, + int sign, + int axis, + br_scalar k, + int cmask) +{ + struct clip_vertex *wp = verts_out; + int num_out = 0; + + struct clip_vertex *up; + br_scalar t,tu,tv; + int m; + br_scalar *usp,*vsp,*wsp; + + /* + * Go round face, an edge at a time + */ + up = vp+num_in-1; + tu = sign*up->comp[axis] - BR_MUL(k,up->comp[C_W]); + + for( ; num_in-- ; up = vp, tu = tv, vp++) { + + tv = sign*vp->comp[axis] - BR_MUL(k,vp->comp[C_W]); + + if(tu <= S0 ^ tv <= S0) { + /* + * Edge crosses plane - add a new vertex + */ + t = BR_DIVR(tv,(tv-tu)); + + wp->comp[axis] = sign * BR_MUL(k,wp->comp[C_W]); + + usp = up->comp; + vsp = vp->comp; + wsp = wp->comp; + + for(m = cmask ; m ; m >>=1, usp++,vsp++,wsp++) + if(m & 1) + *wsp = *vsp + BR_MUL(t,(*usp-*vsp)); + + wp++; + num_out++; + } + + if(tv <= S0) { + /* + * Inside clip space, copy vertex + */ + *wp++ = *vp; + num_out++; + } + } + + return num_out; +} +#endif + +/* + * Special case of sign = 1, k = 1.0 + */ +static int ZbClipFaceToPlus1(struct clip_vertex *vp, struct clip_vertex *verts_out, int num_in, int axis, int cmask) +{ + struct clip_vertex *wp = verts_out; + int num_out = 0; + + struct clip_vertex *up; + br_scalar t, tu, tv; + int m; + br_scalar *usp, *vsp, *wsp; + + /* + * Go round face, an edge at a time + */ + up = vp + num_in - 1; + tu = up->comp[axis] - up->comp[C_W]; + + for (; num_in--; up = vp, tu = tv, vp++) + { + + tv = vp->comp[axis] - vp->comp[C_W]; + + if (tv <= S0) + { + /* + * This vertex is inside clip space + */ + if (tu <= S0) + { + /* + * last vertex was as well - add this vertex + */ + *wp++ = *vp; + num_out++; + continue; + } + + /* + * Edge crosses out to in, add intersection and this vertex + */ + t = BR_DIVR(tv, (tv - tu)); + + usp = up->comp; + vsp = vp->comp; + wsp = wp->comp; + + for (m = cmask; m; m >>= 1, usp++, vsp++, wsp++) + if (m & 1) + *wsp = *vsp + BR_MUL(t, (*usp - *vsp)); + + wp->comp[axis] = wp->comp[C_W]; + + wp++; + + /* + * Copy next vertex + */ + *wp++ = *vp; + num_out += 2; + } + else + { + /* + * This vertex is outside clip space + */ + if (tu > S0) + /* + * last vertex was as well - don't do anything + */ + continue; + + /* + * Edge crosses in to out, add intersection + */ + + t = BR_DIVR(tu, (tu - tv)); + + usp = up->comp; + vsp = vp->comp; + wsp = wp->comp; + + for (m = cmask; m; m >>= 1, usp++, vsp++, wsp++) + if (m & 1) + *wsp = *usp + BR_MUL(t, (*vsp - *usp)); + + wp->comp[axis] = wp->comp[C_W]; + + wp++; + num_out++; + } + } + + return num_out; +} + +/* + * Special case of sign = -1, k = 1.0 + */ +static int ZbClipFaceToMinus1(struct clip_vertex *vp, struct clip_vertex *verts_out, int num_in, int axis, int cmask) +{ + struct clip_vertex *wp = verts_out; + int num_out = 0; + + struct clip_vertex *up; + br_scalar t, tu, tv; + int m; + br_scalar *usp, *vsp, *wsp; + + /* + * Go round face, an edge at a time + */ + up = vp + num_in - 1; + tu = -up->comp[axis] - up->comp[C_W]; + + for (; num_in--; up = vp, tu = tv, vp++) + { + + tv = -vp->comp[axis] - vp->comp[C_W]; + + if (tv <= S0) + { + /* + * This vertex is inside clip space + */ + if (tu <= S0) + { + /* + * last vertex was as well - add this vertex + */ + *wp++ = *vp; + num_out++; + continue; + } + /* + * Edge crosses in to out, add intersection and this vertex + */ + t = BR_DIVR(tv, (tv - tu)); + + usp = up->comp; + vsp = vp->comp; + wsp = wp->comp; + + for (m = cmask; m; m >>= 1, usp++, vsp++, wsp++) + if (m & 1) + *wsp = *vsp + BR_MUL(t, (*usp - *vsp)); + + wp->comp[axis] = -wp->comp[C_W]; + + wp++; + + /* + * Copy next vertex + */ + *wp++ = *vp; + num_out += 2; + } + else + { + /* + * This vertex is outside clip space + */ + if (tu > S0) + /* + * last vertex was as well - don't do anything + */ + continue; + + /* + * Edge crosses in to out, add intersection + */ + + t = BR_DIVR(tu, (tu - tv)); + + usp = up->comp; + vsp = vp->comp; + wsp = wp->comp; + + for (m = cmask; m; m >>= 1, usp++, vsp++, wsp++) + if (m & 1) + *wsp = *usp + BR_MUL(t, (*vsp - *usp)); + + wp->comp[axis] = -wp->comp[C_W]; + + wp++; + num_out++; + } + } + + return num_out; +} + +/* + * Special case of sign = 1, k = 0.0 + */ +static int ZbClipFaceToZero(struct clip_vertex *vp, struct clip_vertex *verts_out, int num_in, int axis, int cmask) +{ + struct clip_vertex *wp = verts_out; + int num_out = 0; + + struct clip_vertex *up; + br_scalar t, tu, tv; + int m; + br_scalar *usp, *vsp, *wsp; + + /* + * Go round face, an edge at a time + */ + up = vp + num_in - 1; + tu = up->comp[axis]; + + for (; num_in--; up = vp, tu = tv, vp++) + { + + tv = vp->comp[axis]; + + if (tv <= S0) + { + /* + * This vertex is inside clip space + */ + if (tu <= S0) + { + /* + * last vertex was as well - add this vertex + */ + *wp++ = *vp; + num_out++; + continue; + } + /* + * Edge crosses in to out, add intersection and this vertex + */ + t = BR_DIVR(tv, (tv - tu)); + + usp = up->comp; + vsp = vp->comp; + wsp = wp->comp; + + for (m = cmask; m; m >>= 1, usp++, vsp++, wsp++) + if (m & 1) + *wsp = *vsp + BR_MUL(t, (*usp - *vsp)); + + wp->comp[axis] = S0; + + wp++; + + /* + * Copy next vertex + */ + *wp++ = *vp; + num_out += 2; + } + else + { + /* + * This vertex is outside clip space + */ + if (tu > S0) + /* + * last vertex was as well - don't do anything + */ + continue; + + /* + * Edge crosses in to out, add intersection + */ + + t = BR_DIVR(tu, (tu - tv)); + + usp = up->comp; + vsp = vp->comp; + wsp = wp->comp; + + for (m = cmask; m; m >>= 1, usp++, vsp++, wsp++) + if (m & 1) + *wsp = *usp + BR_MUL(t, (*vsp - *usp)); + + wp->comp[axis] = S0; + + wp++; + num_out++; + } + } + + return num_out; +} + +#if 0 + +void dprintf(int x, int y, char *fmt,...); + +char *component_names[] = { + "X", + "Y", + "Z", + "W", + "U", + "V", + "I", + "R", + "G", + "B", + "Q", +}; + +#endif + +/* + * Clip a a face to the view volume + */ +struct clip_vertex *ZbFaceClip(br_face *fp, struct temp_face *tfp, int mask, int *n_out) +{ + static struct clip_vertex clip_poly_1[16]; + static struct clip_vertex clip_poly_2[16]; + + struct clip_vertex *cp_in, *cp_out, *cp_temp; + struct temp_vertex *tvp; + int n, i, j, codes, c; + + /* + * Get face vertices into clip array + */ + cp_in = clip_poly_1; + + for (i = 0; i < 3; i++, cp_in++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + for (j = 0; j < NUM_COMPONENTS; j++) + cp_in->comp[j] = tvp->comp[j]; + } + +#if 0 + dprintf(0,0,"In:"); + for(j=0; j < NUM_COMPONENTS-1; j++) { + dprintf(7+j*10,0,"%s",component_names[j]); + } + + cp_temp = clip_poly_1; + for(i=0; i < 3; i++, cp_temp++) { + dprintf(0,i+1,"%2d : "); + for(j=0; j < NUM_COMPONENTS-1; j++) { + dprintf(7+j*10,i+1,"%08X",cp_temp->comp[j]); + } + } +#endif + + n = 3; + cp_in = clip_poly_1; + cp_out = clip_poly_2; + codes = tfp->codes; + + /* + * Clip against each plane - if necessary + * After each plane, swap polygon buffers, and quit if + * polygon is completely clipped away + * + * Could table-drive this (outcode,fn,axis,mask) + */ + if (codes & OUTCODE_HITHER) + { + n = ZbClipFaceToZero(cp_in, cp_out, n, Z, mask & ~CM_Z); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + + if (codes & OUTCODE_YON) + { + n = ZbClipFaceToMinus1(cp_in, cp_out, n, Z, mask & ~CM_Z); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + + if (codes & OUTCODE_LEFT) + { + n = ZbClipFaceToPlus1(cp_in, cp_out, n, X, mask & ~CM_X); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + + if (codes & OUTCODE_RIGHT) + { + n = ZbClipFaceToMinus1(cp_in, cp_out, n, X, mask & ~CM_X); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + + if (codes & OUTCODE_TOP) + { + n = ZbClipFaceToPlus1(cp_in, cp_out, n, Y, mask & ~CM_Y); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + + if (codes & OUTCODE_BOTTOM) + { + n = ZbClipFaceToMinus1(cp_in, cp_out, n, Y, mask & ~CM_Y); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + +#if USER_CLIP + /* + * User-defined clip plane + */ + for (c = 0; c < fw.nactive_clip_planes; c++) + { + + if (!(codes & (OUTCODE_USER << c))) + continue; + + n = ZbClipFaceToPlane(cp_in, cp_out, n, &fw.active_clip_planes[c].screen_plane, mask); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } +#endif + +#if 0 + dprintf(0,10,"Out:"); + for(j=0; j < NUM_COMPONENTS-1; j++) { + dprintf(7+j*10,10,"%s",component_names[j]); + } + + cp_temp = cp_in; + for(i=0; i < n; i++, cp_temp++) { + dprintf(0,i+11,"%2d : "); + for(j=0; j < NUM_COMPONENTS-1; j++) { + dprintf(7+j*10,i+11,"%08X",cp_temp->comp[j]); + } + } +#endif + + *n_out = n; + return cp_in; +} + +/* + * Clip a a face to the view volume + */ +struct clip_vertex *ZbTempClip(struct temp_vertex *tvp, struct temp_face *tfp, int mask, int *n_out) +{ + static struct clip_vertex clip_poly_1[16]; + static struct clip_vertex clip_poly_2[16]; + + struct clip_vertex *cp_in, *cp_out, *cp_temp; + int n, i, j, codes, c; + + /* + * Get face vertices into clip array + */ + cp_in = clip_poly_1; + + for (i = 0; i < 3; i++, cp_in++, tvp++) + { + for (j = 0; j < NUM_COMPONENTS; j++) + cp_in->comp[j] = tvp->comp[j]; + } + +#if 0 + dprintf(0,0,"In:"); + for(j=0; j < NUM_COMPONENTS-1; j++) { + dprintf(7+j*10,0,"%s",component_names[j]); + } + + cp_temp = clip_poly_1; + for(i=0; i < 3; i++, cp_temp++) { + dprintf(0,i+1,"%2d : "); + for(j=0; j < NUM_COMPONENTS-1; j++) { + dprintf(7+j*10,i+1,"%08X",cp_temp->comp[j]); + } + } +#endif + + n = 3; + cp_in = clip_poly_1; + cp_out = clip_poly_2; + codes = tfp->codes; + + /* + * Clip against each plane - if necessary + * After each plane, swap polygon buffers, and quit if + * polygon is completely clipped away + * + * Could table-drive this (outcode,fn,axis,mask) + */ + if (codes & OUTCODE_HITHER) + { + n = ZbClipFaceToZero(cp_in, cp_out, n, Z, mask & ~CM_Z); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + + if (codes & OUTCODE_YON) + { + n = ZbClipFaceToMinus1(cp_in, cp_out, n, Z, mask & ~CM_Z); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + + if (codes & OUTCODE_LEFT) + { + n = ZbClipFaceToPlus1(cp_in, cp_out, n, X, mask & ~CM_X); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + + if (codes & OUTCODE_RIGHT) + { + n = ZbClipFaceToMinus1(cp_in, cp_out, n, X, mask & ~CM_X); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + + if (codes & OUTCODE_TOP) + { + n = ZbClipFaceToPlus1(cp_in, cp_out, n, Y, mask & ~CM_Y); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + + if (codes & OUTCODE_BOTTOM) + { + n = ZbClipFaceToMinus1(cp_in, cp_out, n, Y, mask & ~CM_Y); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } + +#if USER_CLIP + /* + * User-defined clip plane + */ + for (c = 0; c < fw.nactive_clip_planes; c++) + { + + if (!(codes & (OUTCODE_USER << c))) + continue; + + n = ZbClipFaceToPlane(cp_in, cp_out, n, &fw.active_clip_planes[c].screen_plane, mask); + if (n < 3) + return NULL; + cp_temp = cp_in; + cp_in = cp_out; + cp_out = cp_temp; + } +#endif + +#if 0 + dprintf(0,10,"Out:"); + for(j=0; j < NUM_COMPONENTS-1; j++) { + dprintf(7+j*10,10,"%s",component_names[j]); + } + + cp_temp = cp_in; + for(i=0; i < n; i++, cp_temp++) { + dprintf(0,i+11,"%2d : "); + for(j=0; j < NUM_COMPONENTS-1; j++) { + dprintf(7+j*10,i+11,"%08X",cp_temp->comp[j]); + } + } +#endif + + *n_out = n; + return cp_in; +} + diff --git a/bren/ZB/zbiproto.h b/bren/ZB/zbiproto.h new file mode 100644 index 00000000..e26010fa --- /dev/null +++ b/bren/ZB/zbiproto.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: zbiproto.h 1.24 1995/08/31 16:47:52 sam Exp $ + * $Locker: $ + * + * Prototypes for functions internal to z-buffer renderer + */ +#ifndef _ZBIPROTO_H_ +#define _ZBIPROTO_H_ +#ifndef NO_PROTOTYPES + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + * ti8_piz.asm + */ + /* + * 8 bit indexed, perfect, integer, Z buffered (16 bit) + */ + void BR_ASM_CALL TriangleRenderPIZ2(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); + + void BR_ASM_CALL TriangleRenderPIZ2I(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); + + void BR_ASM_CALL TriangleRenderPIZ2T(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); + + void BR_ASM_CALL TriangleRenderPIZ2TI(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); + + void BR_ASM_CALL TriangleRenderPIZ2TD(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); + + void BR_ASM_CALL TriangleRenderPIZ2TID(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); + + /* + * tt24_piz.asm + */ + /* + * 24 bit true colour, perfect, integer, Z buffered (16 bit) + */ + void BR_ASM_CALL TriangleRenderPIZ2_RGB_888(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); + + void BR_ASM_CALL TriangleRenderPIZ2I_RGB_888(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); + + /* + * tt15_piz.asm + */ + /* + * 15 bit true colour, perfect, integer, Z buffered (16 bit) + */ + void BR_ASM_CALL TriangleRenderPIZ2_RGB_555(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); + + void BR_ASM_CALL TriangleRenderPIZ2I_RGB_555(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); + + /* + * perspz.c + */ + void BR_ASM_CALL TriangleRenderPIZ2TIP1024(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + void BR_ASM_CALL TriangleRenderPIZ2TIP256(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + void BR_ASM_CALL TriangleRenderPIZ2TIP64(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + void BR_ASM_CALL TriangleRenderPIZ2TP1024(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + void BR_ASM_CALL TriangleRenderPIZ2TP256(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + void BR_ASM_CALL TriangleRenderPIZ2TP64(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + void BR_ASM_CALL TriangleRenderPIZ2TPD1024(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + + /* + * awtmz.c + */ + void BR_ASM_CALL TriangleRenderPIZ2TA(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + void BR_ASM_CALL TriangleRenderPIZ2TA_RGB_555(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + void BR_ASM_CALL TriangleRenderPIZ2TA_RGB_888(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + + void BR_ASM_CALL TriangleRenderPIZ2TIA(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + void BR_ASM_CALL TriangleRenderPIZ2TIA_RGB_555(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + void BR_ASM_CALL TriangleRenderPIZ2TIA_RGB_888(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + + /* + * mesh386.asm + */ + br_int_32 BR_ASM_CALL ZbOSFFVGroupCulled_A(br_face *fp, struct temp_face *tfp, int count); + br_int_32 BR_ASM_CALL ZbOSFFVGroupCulledLit_A(br_face *fp, struct temp_face *tfp, int count); + + br_uint_32 BR_ASM_CALL ZbOSTVGroup_A(br_vertex *vp, struct temp_vertex_fixed *tvp, int count, br_uint_8 *countp); + br_uint_32 BR_ASM_CALL ZbOSTVGroupLit_A(br_vertex *vp, struct temp_vertex_fixed *tvp, int count, br_uint_8 *countp); + + br_uint_32 BR_ASM_CALL ZbOSTVGroupBC_A(br_vertex *vp, struct temp_vertex_fixed *tvp, int count, br_uint_8 *countp); + br_uint_32 BR_ASM_CALL ZbOSTVGroupLitBC_A(br_vertex *vp, struct temp_vertex_fixed *tvp, int count, + br_uint_8 *countp); + + br_uint_32 BR_ASM_CALL ZbOSCopyModelToScreen_A(void); + + /* + * zbmesh.c + */ + void ZbMeshRender(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen); + + void ZbFindVisibleFaces(void); + void ZbFindVisibleFacesPar(void); + void ZbTransformVertices(void); + void ZbFindFacesAndVertices(void); + void ZbFindVertexParameters(void); + + void BR_ASM_CALL ZbRenderFaceGroup(br_face_group *gp, struct temp_face *tfp); + void BR_ASM_CALL ZbRenderFaceGroup_FaceI(br_face_group *gp, struct temp_face *tfp); + void BR_ASM_CALL ZbRenderFaceGroup_FaceIV(br_face_group *gp, struct temp_face *tfp); + void BR_ASM_CALL ZbRenderFaceGroup_FaceRGB(br_face_group *gp, struct temp_face *tfp); + +#if !BASED_FIXED + void ZbConvertComponents(br_fixed_ls *dest, br_scalar *src, br_uint_32 mask); +#endif + + /* + * zbmeshp.c + */ + void ZbPointFindVertexParameters(void); + void ZbMeshRenderPoints(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen); + + void BR_ASM_CALL PointRenderPIZ2(struct temp_vertex_fixed *v0); + void BR_ASM_CALL PointRenderPIZ2T(struct temp_vertex_fixed *v0); + void BR_ASM_CALL PointRenderPIZ2TI(struct temp_vertex_fixed *v0); + + void BR_ASM_CALL PointRenderPIZ2_RGB_888(struct temp_vertex_fixed *v0); + void BR_ASM_CALL PointRenderPIZ2T_RGB_888(struct temp_vertex_fixed *v0); + + void BR_ASM_CALL PointRenderPIZ2_RGB_555(struct temp_vertex_fixed *v0); + void BR_ASM_CALL PointRenderPIZ2T_RGB_555(struct temp_vertex_fixed *v0); + + /* + * zbmeshe.c + */ + void ZbMeshRenderEdges(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen); + + void BR_ASM_CALL LineRenderPIZ2I(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + void BR_ASM_CALL LineRenderPIZ2T(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + void BR_ASM_CALL LineRenderPIZ2TI(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + + void BR_ASM_CALL LineRenderPFZ2I(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + void BR_ASM_CALL LineRenderPFZ2I555(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + void BR_ASM_CALL LineRenderPFZ2I888(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + void BR_ASM_CALL LineRenderPFZ4I(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + + void BR_ASM_CALL LineRenderPIZ2T_RGB_888(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + void BR_ASM_CALL LineRenderPIZ2I_RGB_888(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + void BR_ASM_CALL LineRenderPIZ2T_RGB_555(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + void BR_ASM_CALL LineRenderPIZ2I_RGB_555(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); + + /* + * zbrendr.c + */ + void ZbNullRender(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen); + + /* + * bbox.c + */ + void ZbBoundingBoxRenderPoints(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, + int on_screen); + + void ZbBoundingBoxRenderEdges(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, + int on_screen); + + void ZbBoundingBoxRenderFaces(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, + int on_screen); + + void StartBoundingBox(int on_screen); + void EndBoundingBox(int on_screen); + + /* + * zbclip.c + */ + struct clip_vertex *ZbFaceClip(br_face *fp, struct temp_face *tfp, int mask, int *n_out); + struct clip_vertex *ZbTempClip(struct temp_vertex *tvp, struct temp_face *tfp, int mask, int *n_out); + + /* + * zbmatl.c + */ + void ZbMaterialUpdate(br_material *mat, br_uint_16 flags); + + /* + * decalz.c + */ + void BR_ASM_CALL TriangleRenderPIZ2TAD(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + void BR_ASM_CALL TriangleRenderPIZ2TIAD(struct temp_vertex_fixed *a, struct temp_vertex_fixed *b, + struct temp_vertex_fixed *c); + +#ifdef __cplusplus +}; +#endif +#endif +#endif + diff --git a/bren/ZB/zbmatl.c b/bren/ZB/zbmatl.c new file mode 100644 index 00000000..901f0027 --- /dev/null +++ b/bren/ZB/zbmatl.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: zbmatl.c 1.4 1995/03/01 15:49:47 sam Exp $ + * $Locker: $ + * + * Material preparation for Z buffer renderer + */ +#include "zb.h" +#include "shortcut.h" +#include "blockops.h" +#include "brassert.h" + +static char rscid[] = "$Id: zbmatl.c 1.4 1995/03/01 15:49:47 sam Exp $"; + +static br_uint_16 PixelmapHasZeros(br_pixelmap *pm); + +/* + * ZB renderer specific processing for a material + * + * Look up the material in the current output set + */ +void ZbMaterialUpdate(br_material *mat, br_uint_16 update_flags) +{ + int i, map_type; + br_uint_32 flags; + struct zb_material_type *zbmt; + struct br_pixelmap *cm; + + map_type = 0; + flags = mat->flags; + +#if 1 + if ((update_flags & (BR_MATU_COLOURMAP | BR_MATU_RENDERING)) == 0) + return; +#endif + + /* + * Augment flags with other info from material + */ + if ((cm = mat->colour_map) != NULL) + { + flags |= ZB_MATF_HAS_MAP; + map_type = cm->type; + + /* + * Look for square maps that are a power of 2 in size + */ + if (cm->width == cm->height && !(cm->width & cm->width - 1)) + flags |= ZB_MATF_SQUARE_POW2; + + /* + * See if the stride is the same as the width + */ + if ((cm->width * BrPixelmapPixelSize(cm)) / 8 == cm->row_bytes) + flags |= ZB_MATF_NO_SKIP; + + /* + * Does the pixelmap have an opacity channel? + */ + if (BrPixelmapChannels(cm) & BR_PMCHAN_ALPHA) + flags |= ZB_MATF_MAP_OPACITY; + //#if 0 + /* + * Does the image have any 0 pixels? + */ + if (PixelmapHasZeros(cm)) + flags |= ZB_MATF_MAP_TRANSPARENT; + //#endif + } + +#if 0 + /* + * Is there any transparency? + */ + if(mat->opacity != 255) + flags |= ZB_MATF_TRANSPARENT; +#endif + + /* + * Is there a screen door lookup table? + */ + if (mat->screendoor) + flags |= ZB_MATF_HAS_SCREEN; + + /* + * Is there a shade table ? + */ + if (mat->index_shade) + flags |= ZB_MATF_HAS_SHADE; + + /* + * Look up material + */ + zbmt = zb.type->material_types; + for (i = 0; i < zb.type->nmaterial_types; i++, zbmt++) + { + if ((flags & zbmt->flags_mask) == zbmt->flags_cmp) + { + /* + * Check map type + */ + if (zbmt->map_type && map_type != zbmt->map_type) + continue; + + /* + * See if there are any size restrictions + */ + if (zbmt->width && zbmt->width != cm->width) + continue; + + if (zbmt->height && zbmt->height != cm->height) + continue; + + break; + } + } + + /* + * Make sure we found a matching type + */ + if (i >= zb.type->nmaterial_types) + BR_ERROR1("ZbMaterialUpdate: Unable to render material '%s'", mat->identifier ? mat->identifier : "???"); + + /* + * Remember pointer to type + */ + + mat->rptr = zbmt; +} + +//#if 0 +/* + * Find out if a pixelmap has any zero pixels + */ +static br_uint_16 PixelmapHasZeros(br_pixelmap *pm) +{ + int x, y, bpp; + char *row_ptr, *pp; + + /* + * if we can't read the pixels, assume the worst + */ + if (pm->flags & BR_PMF_NO_ACCESS) + return 1; + + bpp = BrPixelmapPixelSize(pm); + + /* + * Work out starting address + */ + row_ptr = pm->pixels; + row_ptr = row_ptr + pm->row_bytes * pm->base_y + (pm->base_x * bpp) / 8; + + for (y = 0; y < pm->height; y++) + { + pp = row_ptr; + + switch (bpp) + { + case 8: + for (x = 0; x < pm->width; x++, pp++) + if (*pp == 0) + return 1; + break; + /* + case 16: + for(x=0; x < pm->width; x++, pp+=2) + if(*(br_uint_16 *)pp == 0) + return 1; + break; + + case 24: + for(x=0; x < pm->width; x++, pp+=3) + if((*(br_uint_32 *)pp & 0xFFFFFF) == 0) + return 1; + break; + + case 32: + for(x=0; x < pm->width; x++, pp+=4) + if(*(br_uint_32 *)pp == 0) + return 1; + break; + */ + default: + /* + * Unknown pixel size - assume it does have holes + */ + return 1; + } + row_ptr += pm->row_bytes; + } + + return 0; +} +//#endif + diff --git a/bren/ZB/zbmesh.c b/bren/ZB/zbmesh.c new file mode 100644 index 00000000..221fb515 --- /dev/null +++ b/bren/ZB/zbmesh.c @@ -0,0 +1,1832 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: zbmesh.c 1.67 1995/08/31 16:47:54 sam Exp $ + * $Locker: $ + * + * Mesh rendering to produce faces + */ +#include "zb.h" +#include "shortcut.h" +#include "blockops.h" +#include "brassert.h" + +static char rscid[] = "$Id: zbmesh.c 1.67 1995/08/31 16:47:54 sam Exp $"; + +#define SHOW_REVERSED 0 + +#if BASED_FIXED +#define FAST_PROJECT 1 +#define FAST_CULL 1 +#endif + +#if BASED_FLOAT +#define FAST_PROJECT 0 +#define FAST_CULL 0 +#endif + +static void ClearDirections(void) +{ + int v; + + for (v = 0; v < zb.model->nprepared_vertices; v++) + { + zb.temp_vertices[v].direction = 0; + } + + zb.directions_cleared = 1; +} + +/* + * Find out which faces in mesh are towards eye + * + * Accumulate a count of visible faces per group + */ +void ZbFindVisibleFaces(void) +{ + int f, g, n, df; + br_face *fp = zb.model->prepared_faces; + br_face_group *gp = zb.model->face_groups; + struct temp_face *tfp = zb.temp_faces; + + for (g = 0; g < zb.model->nface_groups; g++, gp++) + { + + /* + * Record the material to use for each group + */ + zb.material = (gp->material ? gp->material : zb.default_material); + + if (zb.material->flags & BR_MATF_TWO_SIDED) + { + /* + * Work out which side of face is visible + */ + if (!zb.directions_cleared) + ClearDirections(); + + for (f = 0, n = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + tfp->flag = TFF_VISIBLE; + df = TVDIR_FRONT; + + /* + * if Plane_Eqn . Eye <= 0, face is away from eye + */ + if (BrFVector3Dot(&fp->n, &fw.eye_m) < fp->d) + { + tfp->flag |= TFF_REVERSED; + df = TVDIR_BACK; + } + + zb.vertex_counts[fp->vertices[0]]++; + zb.vertex_counts[fp->vertices[1]]++; + zb.vertex_counts[fp->vertices[2]]++; + + zb.temp_vertices[fp->vertices[0]].direction |= df; + zb.temp_vertices[fp->vertices[1]].direction |= df; + zb.temp_vertices[fp->vertices[2]].direction |= df; + } + zb.face_group_counts[g] = gp->nfaces; + } + else if (zb.material->flags & BR_MATF_ALWAYS_VISIBLE) + { + /* + * Don't check visibility of face + */ + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + tfp->flag = TFF_VISIBLE; + zb.vertex_counts[fp->vertices[0]]++; + zb.vertex_counts[fp->vertices[1]]++; + zb.vertex_counts[fp->vertices[2]]++; + } + zb.face_group_counts[g] = gp->nfaces; + } + else + { + /* + * Check plane eqn. of every face in group against the eye + */ + for (f = 0, n = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + /* + * if Plane_Eqn . Eye <= 0, face is away from eye + */ + if (BrFVector3Dot(&fp->n, &fw.eye_m) < fp->d) + { + tfp->flag = 0; + continue; + } + + tfp->flag = TFF_VISIBLE; + + zb.vertex_counts[fp->vertices[0]]++; + zb.vertex_counts[fp->vertices[1]]++; + zb.vertex_counts[fp->vertices[2]]++; + + n++; + } + zb.face_group_counts[g] = n; + } + } +} + +void ZbFindVisibleFacesPar(void) +{ + int f, g, n, df; + br_face *fp = zb.model->prepared_faces; + br_face_group *gp = zb.model->face_groups; + struct temp_face *tfp = zb.temp_faces; + + for (g = 0; g < zb.model->nface_groups; g++, gp++) + { + + /* + * Recored the material to use for each group + */ + zb.material = (gp->material ? gp->material : zb.default_material); + + if (zb.material->flags & BR_MATF_TWO_SIDED) + { + /* + * Work out which side of face is visible + */ + if (!zb.directions_cleared) + ClearDirections(); + + for (f = 0, n = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + tfp->flag = TFF_VISIBLE; + df = TVDIR_FRONT; + + /* + * if Plane_Eqn . Eye <= 0, face is away from eye + */ + if (BrFVector3Dot(&fp->n, &fw.eye_m) < S0) + { + tfp->flag |= TFF_REVERSED; + df = TVDIR_BACK; + } + + zb.vertex_counts[fp->vertices[0]]++; + zb.vertex_counts[fp->vertices[1]]++; + zb.vertex_counts[fp->vertices[2]]++; + + zb.temp_vertices[fp->vertices[0]].direction |= df; + zb.temp_vertices[fp->vertices[1]].direction |= df; + zb.temp_vertices[fp->vertices[2]].direction |= df; + } + zb.face_group_counts[g] = gp->nfaces; + } + else if (zb.material->flags & BR_MATF_ALWAYS_VISIBLE) + { + + /* + * Two sided faces always face the eye + */ + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + tfp->flag = TFF_VISIBLE; + + zb.vertex_counts[fp->vertices[0]]++; + zb.vertex_counts[fp->vertices[1]]++; + zb.vertex_counts[fp->vertices[2]]++; + } + zb.face_group_counts[g] = gp->nfaces; + } + else + { + /* + * Check plane eqn. of every face in group against the eye + */ + for (f = 0, n = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + /* + * if Plane_Eqn . Eye <= 0, face is away from eye + */ + if (BrFVector3Dot(&fp->n, &fw.eye_m) < S0) + { + tfp->flag = 0; + continue; + } + + tfp->flag = TFF_VISIBLE; + + zb.vertex_counts[fp->vertices[0]]++; + zb.vertex_counts[fp->vertices[1]]++; + zb.vertex_counts[fp->vertices[2]]++; + + n++; + } + zb.face_group_counts[g] = n; + } + } +} + +/* + * Transform, project & outcode vertices + * + */ +void ZbTransformVertices(void) +{ + int i, c; + struct temp_vertex *tvp; + br_vector4 screen; + + tvp = zb.temp_vertices; + + for (i = 0; i < zb.model->nprepared_vertices; i++, tvp++) + { + + /* + * Ignore if not visible + */ + if (zb.vertex_counts[i] == 0) + continue; + + /* + * Transform into screen space + */ + BrMatrix4ApplyP(&screen, &zb.model->prepared_vertices[i].p, &fw.model_to_screen); + + tvp->comp[C_X] = screen.v[X]; + tvp->comp[C_Y] = screen.v[Y]; + tvp->comp[C_Z] = screen.v[Z]; + tvp->comp[C_W] = screen.v[W]; + + OUTCODE_POINT(tvp->outcode, &screen); + + /* + * Project if inside clip volume + */ + if (!(tvp->outcode & OUTCODES_ALL)) + { + PROJECT_VERTEX(tvp, screen.v[X], screen.v[Y], screen.v[Z], screen.v[W]); + UPDATE_BOUNDS(*tvp); + } + } +} + +/* + * Do per face work - find all the faces that are on screen + */ +void ZbFindFacesAndVertices(void) +{ + int f, g, j; + br_face *fp = zb.model->prepared_faces; + br_face_group *gp = zb.model->face_groups; + struct temp_face *tfp = zb.temp_faces; + br_uint_32 combined_codes; + + for (g = 0; g < zb.model->nface_groups; g++, gp++) + { + + /* + * Skip group if it is not visible + */ + if (zb.face_group_counts[g] == 0) + { + fp += gp->nfaces; + tfp += gp->nfaces; + continue; + } + + zb.material = (gp->material ? gp->material : zb.default_material); + + if (zb.material->prep_flags & MATUF_SURFACE_FACES) + SurfacePerMaterial(zb.material); + + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + if (!tfp->flag) + continue; + + /* + * Work out AND/OR of outcodes + */ + combined_codes = zb.temp_vertices[fp->vertices[0]].outcode | zb.temp_vertices[fp->vertices[1]].outcode | + zb.temp_vertices[fp->vertices[2]].outcode; + /* + * If completely of one edge of view volume (by outcodes) + * mark as not visible + * continue + */ + if ((combined_codes & OUTCODES_NOT) != OUTCODES_NOT) + { + zb.face_group_counts[g]--; + + tfp->flag = 0; + + zb.vertex_counts[fp->vertices[0]]--; + zb.vertex_counts[fp->vertices[1]]--; + zb.vertex_counts[fp->vertices[2]]--; + + continue; + } + + /* + * If any outcode is set - mark as needing clipping and remember combined codes + */ + if (combined_codes & OUTCODES_ALL) + { + tfp->flag |= TFF_CLIPPED; + tfp->codes = combined_codes & OUTCODES_ALL; + zb.face_group_clipped[g] = 1; + } + + /* + * Face will be rendered + */ + + /* + * Do lighting for face if required + */ + if (zb.material->prep_flags & MATUF_SURFACE_FACES) + tfp->surface = + fw.face_surface_fn(zb.model->prepared_vertices + fp->vertices[0], fp, tfp->flag & TFF_REVERSED); + } + } +} + +/* + * Render a clipped face using the indiciated callback for triangle rendering + */ +static void ZbFaceRender(struct clip_vertex *cp_in, int n) +{ + int j; + struct temp_vertex tv[3], *tvp1, *tvp2, *tvpt; + + /* + * Render face + */ + for (j = 0; j < 2; j++, cp_in++) + { + PROJECT_VERTEX(tv + j, cp_in->comp[C_X], cp_in->comp[C_Y], cp_in->comp[C_Z], cp_in->comp[C_W]); + UPDATE_BOUNDS(tv[j]); + +#if !BASED_FIXED + ZbConvertComponents((br_fixed_ls *)tv[j].comp, cp_in->comp, zb.convert_mask); +#else + tv[j].comp[C_W] = cp_in->comp[C_W]; + tv[j].comp[C_I] = cp_in->comp[C_I]; + tv[j].comp[C_U] = cp_in->comp[C_U]; + tv[j].comp[C_V] = cp_in->comp[C_V]; + tv[j].comp[C_R] = cp_in->comp[C_R]; + tv[j].comp[C_G] = cp_in->comp[C_G]; + tv[j].comp[C_B] = cp_in->comp[C_B]; +#endif + } + + tvp1 = tv + 1; + tvp2 = tv + 2; + + for (j = 2; j < n; j++, cp_in++) + { + PROJECT_VERTEX(tvp2, cp_in->comp[C_X], cp_in->comp[C_Y], cp_in->comp[C_Z], cp_in->comp[C_W]); + + UPDATE_BOUNDS(*tvp2); + +#if !BASED_FIXED + ZbConvertComponents((br_fixed_ls *)tvp2->comp, cp_in->comp, zb.convert_mask); +#else + tvp2->comp[C_W] = cp_in->comp[C_W]; + tvp2->comp[C_I] = cp_in->comp[C_I]; + tvp2->comp[C_U] = cp_in->comp[C_U]; + tvp2->comp[C_V] = cp_in->comp[C_V]; + tvp2->comp[C_R] = cp_in->comp[C_R]; + tvp2->comp[C_G] = cp_in->comp[C_G]; + tvp2->comp[C_B] = cp_in->comp[C_B]; +#endif + + zb.triangle_render((struct temp_vertex_fixed *)tv, (struct temp_vertex_fixed *)tvp1, + (struct temp_vertex_fixed *)tvp2); + + tvpt = tvp1; + tvp1 = tvp2; + tvp2 = tvpt; + } +} + +/* + * Render visible faces with clipping + */ +static void ZbRenderFaces(void) +{ + br_face_group *gp = zb.model->face_groups; + struct temp_face *tfp = zb.temp_faces; + struct clip_vertex *clipped; + int g; + struct zb_material_type *zbmt; + + /* + * Loop for each group + */ + for (g = 0; g < zb.model->nface_groups; g++, gp++) + { + + /* + * Skip group if it is not visible + */ + if (zb.face_group_counts[g] == 0) + { + tfp += gp->nfaces; + continue; + } + + zb.material = (gp->material ? gp->material : zb.default_material); + + /* + * Extract various bits of info from material type + */ + ASSERT(zb.material->rptr != NULL); + + zbmt = zb.material->rptr; + + zb.triangle_render = zbmt->triangle; + zb.clip_mask = zbmt->clip_mask; +#if !BASED_FIXED + zb.convert_mask = zbmt->convert_mask; +#endif + + if (zb.material->colour_map) + zb.texture_buffer = zb.material->colour_map->pixels; + + if (zb.material->index_shade) + zb.shade_table = zb.material->index_shade->pixels; + + /* + * Call the face group render function + */ + zbmt->face_group(gp, tfp); + tfp += gp->nfaces; + } +} + +/* + * Render a group of faces + */ +void BR_ASM_CALL ZbRenderFaceGroup(br_face_group *gp, struct temp_face *tfp) +{ + br_face *fp; + struct clip_vertex *clipped; + int f, g, nclipped; + struct zb_material_type *zbmt; + int i; + struct temp_vertex *tvp, tv[3]; + br_vertex *vp; + br_fvector3 rev_normal; + + if ((zb.material->flags & BR_MATF_TWO_SIDED) && (zb.material->prep_flags & MATUF_SURFACE_VERTICES)) + { + SurfacePerMaterial(zb.material); + } + + /* + * Go through each face in loop + */ + for (f = 0, fp = gp->faces; f < gp->nfaces; f++, fp++, tfp++) + { + + switch (tfp->flag) + { + /* + * Face is not on screen at all + */ + case 0: + continue; + + /* + * Back of face is visible + */ + case TFF_VISIBLE | TFF_REVERSED: + + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES) + { + + /* + * If any ov the vertices are used in both directions - + * relight them with corect normal + */ + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + + tv[i] = *tvp; + if (tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) + { + vp = zb.model->vertices + fp->vertices[i]; + + BrFVector3Negate(&rev_normal, &vp->n); + fw.surface_fn(vp, &rev_normal, tv[i].comp); + } +#if !BASED_FIXED + ZbConvertComponents((br_fixed_ls *)tv[i].comp, tvp->comp, zb.convert_mask); +#endif + } + + zb.triangle_render((struct temp_vertex_fixed *)tv + 0, (struct temp_vertex_fixed *)tv + 1, + (struct temp_vertex_fixed *)tv + 2); + + break; + } + + /* ELSE FALL THROUGH */ + + /* + * Face is fully on screen + */ + case TFF_VISIBLE: + /* + * Render face + */ +#if !BASED_FIXED + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + tv[i].v[X] = tvp->v[X]; + tv[i].v[Y] = tvp->v[Y]; + tv[i].v[Z] = tvp->v[Z]; + + ZbConvertComponents((br_fixed_ls *)tv[i].comp, tvp->comp, zb.convert_mask); + } + zb.triangle_render((struct temp_vertex_fixed *)tv + 0, (struct temp_vertex_fixed *)tv + 1, + (struct temp_vertex_fixed *)tv + 2); +#else + zb.triangle_render((struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[0], + (struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[1], + (struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[2]); +#endif + break; + + case TFF_VISIBLE | TFF_CLIPPED | TFF_REVERSED: + + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES) + { + + /* + * If any ov the vertices are used in both directions - + * relight them with corect normal + */ + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + + tv[i] = *tvp; + if (tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) + { + vp = zb.model->vertices + fp->vertices[i]; + + BrFVector3Negate(&rev_normal, &vp->n); + fw.surface_fn(vp, &rev_normal, tv[i].comp); + } + } + + if ((clipped = ZbTempClip(tv, tfp, zb.clip_mask, &nclipped))) + { + ZbFaceRender(clipped, nclipped); + } + + break; + } + + /* ELSE FALL THROUGH */ + + /* + * Face is partially on screen + */ + case TFF_VISIBLE | TFF_CLIPPED: + + if ((clipped = ZbFaceClip(fp, tfp, zb.clip_mask, &nclipped))) + { + ZbFaceRender(clipped, nclipped); + } + break; + } + } +} + +/* + * Render a group of faces - Set the current I value from the face + */ +void BR_ASM_CALL ZbRenderFaceGroup_FaceI(br_face_group *gp, struct temp_face *tfp) +{ + br_face *fp; + struct clip_vertex *clipped; + int f, g, nclipped; + struct zb_material_type *zbmt; + int i; + struct temp_vertex tv[3], *tvp; + br_vertex *vp; + br_fvector3 rev_normal; + + if ((zb.material->flags & BR_MATF_TWO_SIDED) && (zb.material->prep_flags & MATUF_SURFACE_VERTICES)) + { + SurfacePerMaterial(zb.material); + } + + /* + * Go through each face in loop + */ + for (f = 0, fp = gp->faces; f < gp->nfaces; f++, fp++, tfp++) + { + + switch (tfp->flag) + { + /* + * Face is not on screen at all + */ + case 0: + continue; + + case TFF_VISIBLE | TFF_REVERSED: + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES) + { + + zb.pi.current = BrIntToFixed(tfp->surface); + + /* + * If any ov the vertices are used in both directions - + * relight them with corect normal + */ + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + + tv[i] = *tvp; + if (tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) + { + vp = zb.model->vertices + fp->vertices[i]; + + BrFVector3Negate(&rev_normal, &vp->n); + fw.surface_fn(vp, &rev_normal, tv[i].comp); + } +#if !BASED_FIXED + ZbConvertComponents((br_fixed_ls *)tv[i].comp, tvp->comp, zb.convert_mask); +#endif + } + + zb.triangle_render((struct temp_vertex_fixed *)tv + 0, (struct temp_vertex_fixed *)tv + 1, + (struct temp_vertex_fixed *)tv + 2); + + break; + } + + /* ELSE FALL THROUGH */ + + /* + * Face is fully on screen + */ + case TFF_VISIBLE: + + /* + * Render face + */ + zb.pi.current = BrIntToFixed(tfp->surface); +#if !BASED_FIXED + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + tv[i].v[X] = tvp->v[X]; + tv[i].v[Y] = tvp->v[Y]; + tv[i].v[Z] = tvp->v[Z]; + + ZbConvertComponents((br_fixed_ls *)tv[i].comp, tvp->comp, zb.convert_mask); + } + zb.triangle_render((struct temp_vertex_fixed *)tv + 0, (struct temp_vertex_fixed *)tv + 1, + (struct temp_vertex_fixed *)tv + 2); +#else + zb.triangle_render((struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[0], + (struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[1], + (struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[2]); +#endif + break; + + case TFF_VISIBLE | TFF_CLIPPED | TFF_REVERSED: + + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES) + { + + /* + * If any ov the vertices are used in both directions - + * relight them with corect normal + */ + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + + tv[i] = *tvp; + if (tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) + { + vp = zb.model->vertices + fp->vertices[i]; + + BrFVector3Negate(&rev_normal, &vp->n); + fw.surface_fn(vp, &rev_normal, tv[i].comp); + } + } + + if ((clipped = ZbTempClip(tv, tfp, zb.clip_mask, &nclipped))) + { + zb.pi.current = BrIntToFixed(tfp->surface); + ZbFaceRender(clipped, nclipped); + } + + break; + } + + /* ELSE FALL THROUGH */ + + /* + * Face is partially on screen + */ + case TFF_VISIBLE | TFF_CLIPPED: + + if ((clipped = ZbFaceClip(fp, tfp, zb.clip_mask, &nclipped))) + { + + zb.pi.current = BrIntToFixed(tfp->surface); + + ZbFaceRender(clipped, nclipped); + } + break; + } + } +} + +/* + * Render a group of faces - Set the current I value for each + * vertex from the face + */ +void BR_ASM_CALL ZbRenderFaceGroup_FaceIV(br_face_group *gp, struct temp_face *tfp) +{ + br_face *fp; + struct clip_vertex *clipped; + int f, g, nclipped; + struct zb_material_type *zbmt; + br_scalar ci; + int i; + struct temp_vertex tv[3], *tvp; + br_vertex *vp; + br_fvector3 rev_normal; + + /* + * Go through each face in loop + */ + for (f = 0, fp = gp->faces; f < gp->nfaces; f++, fp++, tfp++) + { + + switch (tfp->flag) + { + /* + * Face is not on screen at all + */ + case 0: + continue; + + case TFF_VISIBLE | TFF_REVERSED: + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES) + { + + ci = BrIntToScalar(tfp->surface); + zb.temp_vertices[fp->vertices[0]].comp[C_I] = ci; + zb.temp_vertices[fp->vertices[1]].comp[C_I] = ci; + zb.temp_vertices[fp->vertices[2]].comp[C_I] = ci; + + /* + * If any ov the vertices are used in both directions - + * relight them with corect normal + */ + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + + tv[i] = *tvp; + if (tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) + { + vp = zb.model->vertices + fp->vertices[i]; + + BrFVector3Negate(&rev_normal, &vp->n); + fw.surface_fn(vp, &rev_normal, tv[i].comp); + } +#if !BASED_FIXED + ZbConvertComponents((br_fixed_ls *)tv[i].comp, tvp->comp, zb.convert_mask); +#endif + } + + zb.triangle_render((struct temp_vertex_fixed *)tv + 0, (struct temp_vertex_fixed *)tv + 1, + (struct temp_vertex_fixed *)tv + 2); + + break; + } + + /* ELSE FALL THROUGH */ + + /* + * Face is fully on screen + */ + case TFF_VISIBLE: + + /* + * Render face + */ + ci = BrIntToScalar(tfp->surface); + zb.temp_vertices[fp->vertices[0]].comp[C_I] = ci; + zb.temp_vertices[fp->vertices[1]].comp[C_I] = ci; + zb.temp_vertices[fp->vertices[2]].comp[C_I] = ci; + +#if !BASED_FIXED + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + tv[i].v[X] = tvp->v[X]; + tv[i].v[Y] = tvp->v[Y]; + tv[i].v[Z] = tvp->v[Z]; + + ZbConvertComponents((br_fixed_ls *)tv[i].comp, tvp->comp, zb.convert_mask); + } + zb.triangle_render((struct temp_vertex_fixed *)tv + 0, (struct temp_vertex_fixed *)tv + 1, + (struct temp_vertex_fixed *)tv + 2); +#else + zb.triangle_render((struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[0], + (struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[1], + (struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[2]); +#endif + break; + + case TFF_VISIBLE | TFF_CLIPPED | TFF_REVERSED: + + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES) + { + + ci = BrIntToScalar(tfp->surface); + zb.temp_vertices[fp->vertices[0]].comp[C_I] = ci; + zb.temp_vertices[fp->vertices[1]].comp[C_I] = ci; + zb.temp_vertices[fp->vertices[2]].comp[C_I] = ci; + + /* + * If any ov the vertices are used in both directions - + * relight them with corect normal + */ + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + + tv[i] = *tvp; + if (tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) + { + vp = zb.model->vertices + fp->vertices[i]; + + BrFVector3Negate(&rev_normal, &vp->n); + fw.surface_fn(vp, &rev_normal, tv[i].comp); + } + } + + if ((clipped = ZbTempClip(tv, tfp, zb.clip_mask, &nclipped))) + { + ZbFaceRender(clipped, nclipped); + } + + break; + } + + /* ELSE FALL THROUGH */ + + /* + * Face is partially on screen + */ + case TFF_VISIBLE | TFF_CLIPPED: + + ci = BrIntToScalar(tfp->surface); + zb.temp_vertices[fp->vertices[0]].comp[C_I] = ci; + zb.temp_vertices[fp->vertices[1]].comp[C_I] = ci; + zb.temp_vertices[fp->vertices[2]].comp[C_I] = ci; + + if ((clipped = ZbFaceClip(fp, tfp, zb.clip_mask, &nclipped))) + { + + ZbFaceRender(clipped, nclipped); + } + break; + } + } +} + +/* + * Render a group of faces - get the current R,G,B values from the face + */ +void BR_ASM_CALL ZbRenderFaceGroup_FaceRGB(br_face_group *gp, struct temp_face *tfp) +{ + br_face *fp; + struct clip_vertex *clipped; + int f, g, nclipped; + struct zb_material_type *zbmt; + int i; + struct temp_vertex tv[3], *tvp; + br_vertex *vp; + br_fvector3 rev_normal; + + /* + * Go through each face in loop + */ + for (f = 0, fp = gp->faces; f < gp->nfaces; f++, fp++, tfp++) + { + + switch (tfp->flag) + { + /* + * Face is not on screen at all + */ + case 0: + continue; + + case TFF_VISIBLE | TFF_REVERSED: + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES) + { + + zb.pr.current = BrIntToFixed(BR_RED(tfp->surface)); + zb.pg.current = BrIntToFixed(BR_GRN(tfp->surface)); + zb.pb.current = BrIntToFixed(BR_BLU(tfp->surface)); + + /* + * If any ov the vertices are used in both directions - + * relight them with corect normal + */ + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + + tv[i] = *tvp; + if (tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) + { + vp = zb.model->vertices + fp->vertices[i]; + + BrFVector3Negate(&rev_normal, &vp->n); + fw.surface_fn(vp, &rev_normal, tv[i].comp); + } +#if !BASED_FIXED + ZbConvertComponents((br_fixed_ls *)tv[i].comp, tvp->comp, zb.convert_mask); +#endif + } + + zb.triangle_render((struct temp_vertex_fixed *)tv + 0, (struct temp_vertex_fixed *)tv + 1, + (struct temp_vertex_fixed *)tv + 2); + + break; + } + + /* ELSE FALL THROUGH */ + + /* + * Face is fully on screen + */ + case TFF_VISIBLE: + + /* + * Render face + */ + zb.pr.current = BrIntToFixed(BR_RED(tfp->surface)); + zb.pg.current = BrIntToFixed(BR_GRN(tfp->surface)); + zb.pb.current = BrIntToFixed(BR_BLU(tfp->surface)); + +#if !BASED_FIXED + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + tv[i].v[X] = tvp->v[X]; + tv[i].v[Y] = tvp->v[Y]; + tv[i].v[Z] = tvp->v[Z]; + + ZbConvertComponents((br_fixed_ls *)tv[i].comp, tvp->comp, zb.convert_mask); + } + zb.triangle_render((struct temp_vertex_fixed *)tv + 0, (struct temp_vertex_fixed *)tv + 1, + (struct temp_vertex_fixed *)tv + 2); +#else + zb.triangle_render((struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[0], + (struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[1], + (struct temp_vertex_fixed *)zb.temp_vertices + fp->vertices[2]); +#endif + break; + + case TFF_VISIBLE | TFF_CLIPPED | TFF_REVERSED: + + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES) + { + + /* + * If any ov the vertices are used in both directions - + * relight them with corect normal + */ + for (i = 0; i < 3; i++) + { + tvp = zb.temp_vertices + fp->vertices[i]; + + tv[i] = *tvp; + if (tv[i].direction == (TVDIR_FRONT | TVDIR_BACK)) + { + vp = zb.model->vertices + fp->vertices[i]; + + BrFVector3Negate(&rev_normal, &vp->n); + fw.surface_fn(vp, &rev_normal, tv[i].comp); + } + } + + if ((clipped = ZbTempClip(tv, tfp, zb.clip_mask, &nclipped))) + { + zb.pr.current = BrIntToFixed(BR_RED(tfp->surface)); + zb.pg.current = BrIntToFixed(BR_GRN(tfp->surface)); + zb.pb.current = BrIntToFixed(BR_BLU(tfp->surface)); + ZbFaceRender(clipped, nclipped); + } + + break; + } + + /* ELSE FALL THROUGH */ + + /* + * Face is partially on screen + */ + case TFF_VISIBLE | TFF_CLIPPED: + + if ((clipped = ZbFaceClip(fp, tfp, zb.clip_mask, &nclipped))) + { + + zb.pr.current = BrIntToFixed(BR_RED(tfp->surface)); + zb.pg.current = BrIntToFixed(BR_GRN(tfp->surface)); + zb.pb.current = BrIntToFixed(BR_BLU(tfp->surface)); + + ZbFaceRender(clipped, nclipped); + } + break; + } + } +} + +/* + * Do per-vertex paramter calculations (intensity, u & v) + */ +void ZbFindVertexParameters(void) +{ + int gv, g, v; + struct temp_vertex *avp; + br_vertex *vp; + br_vertex_group *gp = zb.model->vertex_groups; + + /* + * Base vertices + */ + avp = zb.temp_vertices; + v = 0; + + for (g = 0; g < zb.model->nvertex_groups; g++, gp++) + { + + zb.material = (gp->material ? gp->material : zb.default_material); + + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES && + !((zb.model->prep_flags & MODUF_VERTEX_GROUPS_MATCH) && zb.face_group_counts[g] == 0)) + { + + SurfacePerMaterial(zb.material); + + if (zb.material->flags & BR_MATF_TWO_SIDED) + { + /* + * Two sided material - do lighting calculations + * with forward facing normals unless the vertex + * is only used reversed, then use the negated + * normal + */ + for (gv = 0, vp = gp->vertices; gv < gp->nvertices; gv++, v++, avp++, vp++) + { + if (zb.vertex_counts[v]) + { + if (avp->direction & TVDIR_FRONT) + fw.surface_fn(vp, &vp->n, avp->comp); + else + { + br_fvector3 rev_normal; + BrFVector3Negate(&rev_normal, &vp->n); + fw.surface_fn(vp, &rev_normal, avp->comp); + } + } + } + } + else + { + for (gv = 0, vp = gp->vertices; gv < gp->nvertices; gv++, v++, avp++, vp++) + if (zb.vertex_counts[v]) + fw.surface_fn(vp, &vp->n, avp->comp); + } + } + else + { + avp += gp->nvertices; + v += gp->nvertices; + } + + /* + * Handle FORCE_Z_0 + */ + if (zb.material->flags & BR_MATF_FORCE_Z_0) + { + avp -= gp->nvertices; + for (gv = 0; gv < gp->nvertices; gv++, avp++) + { + avp->v[Z] = 0; + avp->comp[C_Z] = BR_SCALAR(0.0); + } + } + } +} + +/* + * On Screen version of geometry + */ + +/* + * Go through model's face list - find forward facing faces and light them + */ + +static void ZbOnScreenFindFacesVerts(void) +{ + int f, g, j, v, vt, df; + br_face *fp = zb.model->prepared_faces; + br_face_group *gp = zb.model->face_groups; + struct temp_face *tfp = zb.temp_faces; + + /* + * Go through each group + */ + for (g = 0; g < zb.model->nface_groups; g++, gp++) + { + + zb.material = (gp->material ? gp->material : zb.default_material); + + if (zb.material->prep_flags & MATUF_SURFACE_FACES) + SurfacePerMaterial(zb.material); + + zb.face_group_counts[g] = 0; + + if (zb.material->flags & BR_MATF_TWO_SIDED) + { + + if (!zb.directions_cleared) + ClearDirections(); + + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + tfp->flag = TFF_VISIBLE; + df = TVDIR_FRONT; + + if (BrFVector3Dot(&fp->n, &fw.eye_m) < fp->d) + { + tfp->flag |= TFF_REVERSED; + df = TVDIR_BACK; + } + + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + + zb.temp_vertices[fp->vertices[0]].direction |= df; + zb.temp_vertices[fp->vertices[1]].direction |= df; + zb.temp_vertices[fp->vertices[2]].direction |= df; + + if (zb.material->prep_flags & MATUF_SURFACE_FACES) + tfp->surface = + fw.face_surface_fn(zb.model->prepared_vertices + fp->vertices[0], fp, tfp->flag & TFF_REVERSED); + } + + zb.face_group_counts[g] = gp->nfaces; + } + else if (zb.material->flags & BR_MATF_ALWAYS_VISIBLE) + { + + if (zb.material->prep_flags & MATUF_SURFACE_FACES) + { + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + tfp->flag = TFF_VISIBLE; + tfp->surface = fw.face_surface_fn(zb.model->prepared_vertices + fp->vertices[0], fp, 0); + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + } + } + else + { + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + tfp->flag = TFF_VISIBLE; + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + } + } + + zb.face_group_counts[g] = gp->nfaces; + } + else + { + + /* + * Single sided faces + */ + if (zb.material->prep_flags & MATUF_SURFACE_FACES) + { +#if FAST_CULL + zb.face_group_counts[g] = ZbOSFFVGroupCulledLit_A(fp, tfp, gp->nfaces); + tfp += gp->nfaces; + fp += gp->nfaces; +#else + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + if (BrFVector3Dot(&fp->n, &fw.eye_m) < fp->d) + { + tfp->flag = 0; + } + else + { + tfp->flag = TFF_VISIBLE; + zb.face_group_counts[g]++; + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + + tfp->surface = fw.face_surface_fn(zb.model->prepared_vertices + fp->vertices[0], fp, 0); + } + } +#endif + } + else + { +#if FAST_CULL + zb.face_group_counts[g] = ZbOSFFVGroupCulled_A(fp, tfp, gp->nfaces); + tfp += gp->nfaces; + fp += gp->nfaces; +#else + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + if (BrFVector3Dot(&fp->n, &fw.eye_m) < fp->d) + { + tfp->flag = 0; + } + else + { + tfp->flag = TFF_VISIBLE; + zb.face_group_counts[g]++; + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + } + } +#endif + } + } + } +} + +static void ZbOnScreenFindFacesVertsPar(void) +{ + int f, g, j, v, vt, df; + br_face *fp = zb.model->prepared_faces; + br_face_group *gp = zb.model->face_groups; + struct temp_face *tfp = zb.temp_faces; + + /* + * Go through each group + */ + for (g = 0; g < zb.model->nface_groups; g++, gp++) + { + + zb.material = (gp->material ? gp->material : zb.default_material); + + if (zb.material->prep_flags & MATUF_SURFACE_FACES) + SurfacePerMaterial(zb.material); + + zb.face_group_counts[g] = 0; + + if (zb.material->flags & BR_MATF_TWO_SIDED) + { + + if (!zb.directions_cleared) + ClearDirections(); + + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + tfp->flag = TFF_VISIBLE; + df = TVDIR_FRONT; + + if (BrFVector3Dot(&fp->n, &fw.eye_m) < S0) + { + tfp->flag |= TFF_REVERSED; + df = TVDIR_BACK; + } + + zb.face_group_counts[g]++; + + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + + zb.temp_vertices[fp->vertices[0]].direction |= df; + zb.temp_vertices[fp->vertices[1]].direction |= df; + zb.temp_vertices[fp->vertices[2]].direction |= df; + + if (zb.material->prep_flags & MATUF_SURFACE_FACES) + tfp->surface = + fw.face_surface_fn(zb.model->prepared_vertices + fp->vertices[0], fp, tfp->flag & TFF_REVERSED); + } + } + else if (zb.material->flags & BR_MATF_ALWAYS_VISIBLE) + { + /* + * Two sided faces are always visible + */ + if (zb.material->prep_flags & MATUF_SURFACE_FACES) + { + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + tfp->flag = TFF_VISIBLE; + tfp->surface = fw.face_surface_fn(zb.model->prepared_vertices + fp->vertices[0], fp, 0); + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + } + } + else + { + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + tfp->flag = TFF_VISIBLE; + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + } + } + + zb.face_group_counts[g] = gp->nfaces; + } + else + { + + /* + * Single sided faces + */ + if (zb.material->prep_flags & MATUF_SURFACE_FACES) + { + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + if (BrFVector3Dot(&fp->n, &fw.eye_m) < S0) + { + tfp->flag = 0; + } + else + { + tfp->flag = TFF_VISIBLE; + zb.face_group_counts[g]++; + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + + tfp->surface = fw.face_surface_fn(zb.model->prepared_vertices + fp->vertices[0], fp, 0); + } + } + } + else + { + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + if (BrFVector3Dot(&fp->n, &fw.eye_m) <= S0) + { + tfp->flag = 0; + } + else + { + tfp->flag = TFF_VISIBLE; + zb.face_group_counts[g]++; + zb.vertex_counts[fp->vertices[0]] = 1; + zb.vertex_counts[fp->vertices[1]] = 1; + zb.vertex_counts[fp->vertices[2]] = 1; + } + } + } + } + } +} + +/* + * For all the active vertices, transform them and work out + * the per vertex parameters + */ +static void ZbOnScreenTransformVertices(void) +{ + int v, g, gv; + struct temp_vertex *avp; + br_vertex *vp; + br_vertex_group *gp = zb.model->vertex_groups; + br_vector4 screen; + + /* + * Base vertices + */ + v = 0; + avp = zb.temp_vertices; + + for (g = 0; g < zb.model->nvertex_groups; g++, gp++) + { + + zb.material = (gp->material ? gp->material : zb.default_material); + + /* + * Skip if group is not visible + */ + if ((zb.model->prep_flags & MODUF_VERTEX_GROUPS_MATCH) && zb.face_group_counts[g] == 0) + { + avp += gp->nvertices; + v += gp->nvertices; + continue; + } + + /* + * Select a transform according to current situation + */ + + if (zb.material->flags & BR_MATF_TWO_SIDED) + { + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES) + SurfacePerMaterial(zb.material); + + /* + * Do surface function and bounds update per vertex + */ + for (gv = 0, vp = gp->vertices; gv < gp->nvertices; gv++, v++, avp++, vp++) + { + if (zb.vertex_counts[v] == 0) + continue; + + TRANSFORM_VERTEX_OS(); + avp->comp[C_W] = screen.v[W]; + PROJECT_VERTEX(avp, screen.v[X], screen.v[Y], screen.v[Z], screen.v[W]); + UPDATE_BOUNDS(*avp); + + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES) + { + if (avp->direction & TVDIR_FRONT) + fw.surface_fn(vp, &vp->n, avp->comp); + else + { + br_fvector3 rev_normal; + BrFVector3Negate(&rev_normal, &vp->n); + fw.surface_fn(vp, &rev_normal, avp->comp); + } + } + } + + continue; + } + + if (zb.material->prep_flags & MATUF_SURFACE_VERTICES) + { + + SurfacePerMaterial(zb.material); + + if (zb.bounds_call) + { + +#if FAST_PROJECT + ZbOSTVGroupLitBC_A(gp->vertices, (struct temp_vertex_fixed *)avp, gp->nvertices, + (br_uint_8 *)zb.vertex_counts + v); + avp += gp->nvertices; + v += gp->nvertices; +#else + /* + * Do surface function and bounds update per vertex + */ + for (gv = 0, vp = gp->vertices; gv < gp->nvertices; gv++, v++, avp++, vp++) + { + if (zb.vertex_counts[v] == 0) + continue; + + TRANSFORM_VERTEX_OS(); + avp->comp[C_W] = screen.v[W]; + PROJECT_VERTEX(avp, screen.v[X], screen.v[Y], screen.v[Z], screen.v[W]); + UPDATE_BOUNDS(*avp); + + fw.surface_fn(vp, &vp->n, avp->comp); + } +#endif + } + else + { + + /* + * Do surface function per vertex + */ +#if FAST_PROJECT + ZbOSTVGroupLit_A(gp->vertices, (struct temp_vertex_fixed *)avp, gp->nvertices, + (br_uint_8 *)zb.vertex_counts + v); + avp += gp->nvertices; + v += gp->nvertices; +#else + for (gv = 0, vp = gp->vertices; gv < gp->nvertices; gv++, v++, avp++, vp++) + { + if (zb.vertex_counts[v] == 0) + continue; + + TRANSFORM_VERTEX_OS(); + avp->comp[C_W] = screen.v[W]; + PROJECT_VERTEX(avp, screen.v[X], screen.v[Y], screen.v[Z], screen.v[W]); + + fw.surface_fn(vp, &vp->n, avp->comp); + } +#endif + } + } + else + { + if (zb.bounds_call) + { + /* + * Do bounds update per vertex + */ +#if FAST_PROJECT + ZbOSTVGroupBC_A(gp->vertices, (struct temp_vertex_fixed *)avp, gp->nvertices, + (br_uint_8 *)zb.vertex_counts + v); + avp += gp->nvertices; + v += gp->nvertices; +#else + for (gv = 0, vp = gp->vertices; gv < gp->nvertices; gv++, v++, avp++, vp++) + { + if (zb.vertex_counts[v] == 0) + continue; + + TRANSFORM_VERTEX_OS(); + avp->comp[C_W] = screen.v[W]; + PROJECT_VERTEX(avp, screen.v[X], screen.v[Y], screen.v[Z], screen.v[W]); + UPDATE_BOUNDS(*avp); + } +#endif + } + else + { + /* + * Just transform + */ +#if FAST_PROJECT + ZbOSTVGroup_A(gp->vertices, (struct temp_vertex_fixed *)avp, gp->nvertices, + (br_uint_8 *)zb.vertex_counts + v); + avp += gp->nvertices; + v += gp->nvertices; +#else + for (gv = 0, vp = gp->vertices; gv < gp->nvertices; gv++, v++, avp++, vp++) + { + if (zb.vertex_counts[v] == 0) + continue; + + TRANSFORM_VERTEX_OS(); + avp->comp[C_W] = screen.v[W]; + PROJECT_VERTEX(avp, screen.v[X], screen.v[Y], screen.v[Z], screen.v[W]); + } +#endif + } + } + + /* + * Handle FORCE_Z_0 + */ + if (zb.material->flags & BR_MATF_FORCE_Z_0) + { + avp -= gp->nvertices; + for (gv = 0; gv < gp->nvertices; gv++, avp++) + { + avp->v[Z] = 0; + avp->comp[C_Z] = BR_SCALAR(0.0); + } + } + } +} + +/* + * Render a model to the screen through the current transform + */ +void ZbMeshRender(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen) +{ + void *scratch; + int scratch_size; + char *sp, *clear_end; + + /* + * Remember model and material in renderer info. + */ + zb.model = model; + zb.default_material = material; + +#if 0 + { + extern br_material test_materials[]; + + if(on_screen == OSC_ACCEPT) + zb.default_material = test_materials+2; + } +#endif + +#if 0 + on_screen = OSC_PARTIAL; +#endif + + zb.directions_cleared = 0; + + /* + * Work out amount of scratch space needed for this model + */ + scratch_size = SCRATCH_ALIGN(model->nprepared_faces * sizeof(*zb.temp_faces)); + scratch_size += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.vertex_counts)); + scratch_size += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.temp_vertices)); + scratch_size += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_counts)); + scratch_size += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_clipped)); + + /* + * Make sure current scratch buffer is big enough + */ + scratch = BrScratchAllocate(scratch_size + SCRATCH_BOUNDARY); + + /* + * Allocate scratch areas + */ + sp = scratch; + + zb.vertex_counts = (void *)sp; + sp += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.vertex_counts)); + + zb.face_group_clipped = (void *)sp; + + sp += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_clipped)); + + clear_end = sp; + + zb.face_group_counts = (void *)sp; + sp += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_counts)); + + zb.temp_faces = (void *)sp; + sp += SCRATCH_ALIGN(model->nprepared_faces * sizeof(*zb.temp_faces)); + + zb.temp_vertices = (void *)sp; + + /* + * Clear vertex counts and vertex materials + */ + BrBlockFill(scratch, 0, ((clear_end - (char *)scratch) + 3) / 4); + +#if FAST_PROJECT + /* + * If on_screen, then let the fast project code pre process the model->screen + * matrix + * + * If there was an overflow, revert back to OSC_PARTIAL + */ + if (on_screen == OSC_ACCEPT) + if (ZbOSCopyModelToScreen_A()) + on_screen = OSC_PARTIAL; +#endif + + /* + * Build view_to_model + * + * Record a flag to say if model is inside out (det of Xfrm is < 0) + */ + BrMatrix34Inverse(&fw.view_to_model, &fw.model_to_view); + + /* + * Transform eye point into model space + */ + BrVector3EyeInModel(&fw.eye_m); + + /* + * Normalised version for environment mapping + */ + BrVector3Normalise(&fw.eye_m_normalised, &fw.eye_m); + + /* + * Process lighting for this model + */ + SurfacePerModel(); + + /* + * Initialise bounds + */ +#if BOUNDING_RECTANGLE_CALL + zb.bounds[BR_BOUNDS_MIN_X] = zb.bounds[BR_BOUNDS_MIN_Y] = 0x7fffffff; + zb.bounds[BR_BOUNDS_MAX_X] = zb.bounds[BR_BOUNDS_MAX_Y] = 0x80000001; +#endif + + /* + * Process this model + */ + if (on_screen == OSC_ACCEPT) + { + + switch (fw.vtos_type) + { + case BR_VTOS_PERSPECTIVE: + ZbOnScreenFindFacesVerts(); + break; + + case BR_VTOS_PARALLEL: + ZbOnScreenFindFacesVertsPar(); + break; + } + ZbOnScreenTransformVertices(); + ZbRenderFaces(); + } + else + { + switch (fw.vtos_type) + { + case BR_VTOS_PERSPECTIVE: + ZbFindVisibleFaces(); + break; + + case BR_VTOS_PARALLEL: + ZbFindVisibleFacesPar(); + break; + } + + ZbTransformVertices(); + ZbFindFacesAndVertices(); + ZbFindVertexParameters(); + ZbRenderFaces(); + } + + /* + * Release scratch + */ + BrScratchFree(scratch); + +#if BOUNDING_RECTANGLE_CALL + + /* + * Invoke a callback for bounding rectangle + */ + if (zb.bounds_call) + { + br_int_32 int_bounds[4]; + + int_bounds[0] = ScreenToInt(zb.bounds[0]); + int_bounds[1] = ScreenToInt(zb.bounds[1]) + fw.output->base_y; + int_bounds[2] = ScreenToInt(zb.bounds[2]) - 1; + int_bounds[3] = ScreenToInt(zb.bounds[3]) + fw.output->base_y - 1; + + if ((int_bounds[0] <= int_bounds[2]) && (int_bounds[1] <= int_bounds[3])) + { + zb.bounds_call(actor, model, material, NULL, style, &fw.model_to_screen, int_bounds); + } + } +#endif +} + +/* + * Attempt to shrink scratch space if current usage is well + * bellow that allocated + * + * If max usage is l.t. 1/2 allocated space for 50 tests, then + * resize buffer + */ + +void ZbScratchShrink(void) +{ + /* XXX Add Water */ +} + +#if !BASED_FIXED +/* + * Convert component from scalar to fixed + */ +void ZbConvertComponents(br_fixed_ls *dest, br_scalar *src, br_uint_32 mask) +{ + for (; mask; mask >>= 1, dest++, src++) + if (mask & 1) + *dest = BrScalarToFixed(*src); +} +#endif + +/* + * Local Variables: + * tab-width: 4 + * End: + */ + + diff --git a/bren/ZB/zbmeshe.c b/bren/ZB/zbmeshe.c new file mode 100644 index 00000000..34178b1b --- /dev/null +++ b/bren/ZB/zbmeshe.c @@ -0,0 +1,665 @@ +/* + * Copyright (c) 1993 Argonaut Software Ltd. All rights reserved. + * + * $Id: zbmeshe.c 1.19 1995/08/31 16:47:57 sam Exp $ + * $Locker: $ + * + * Mesh rendering to produce points + */ +#include "zb.h" +#include "shortcut.h" +#include "blockops.h" +#include "brassert.h" + +static char rscid[] = "$Id: zbmeshe.c 1.19 1995/08/31 16:47:57 sam Exp $"; + +/* + * Clip a line to an arbitary plane eqn. Return true if any part + * of the line remains + */ +static int ClipLineToPlane(struct temp_vertex *in, struct temp_vertex *out, br_vector4 *plane, int cmask) +{ + br_scalar t, tu, tv; + int m; + br_scalar *usp, *vsp, *wsp; + + tu = -BR_MAC4(plane->v[0], in[0].comp[C_X], plane->v[1], in[0].comp[C_Y], plane->v[2], in[0].comp[C_Z], plane->v[3], + in[0].comp[C_W]); + + tv = -BR_MAC4(plane->v[0], in[1].comp[C_X], plane->v[1], in[1].comp[C_Y], plane->v[2], in[1].comp[C_Z], plane->v[3], + in[1].comp[C_W]); + + if (tu <= S0) + { + /* + * First vertex is inside clip space + */ + out[0] = in[0]; + + if (tv <= S0) + { + /* + * last vertex was as well - return whole line + */ + out[1] = in[1]; + return 1; + } + + /* + * Line crosses in to out, truncate to intersection + */ + t = BR_DIVR(tu, (tu - tv)); + + usp = in[0].comp; + vsp = in[1].comp; + wsp = out[1].comp; + + for (m = cmask; m; m >>= 1, usp++, vsp++, wsp++) + if (m & 1) + *wsp = *usp + BR_MUL(t, (*vsp - *usp)); + } + else + { + /* + * First vertex is outside clip space + */ + if (tv > S0) + /* + * last vertex was as well - return false + */ + return 0; + + out[1] = in[1]; + + /* + * Line crosses out to in, truncate to intersection + */ + + t = BR_DIVR(tv, (tv - tu)); + + usp = in[0].comp; + vsp = in[1].comp; + wsp = out[0].comp; + + for (m = cmask; m; m >>= 1, usp++, vsp++, wsp++) + if (m & 1) + *wsp = *vsp + BR_MUL(t, (*usp - *vsp)); + } + + return 1; +} + +/* + * Find out which faces in mesh are towards eye + * + * Accumulate visiblity counts for edges and vertices, mark + * materials, and fill in vertices for edges + */ +static void ZbEdgeFindVisibleFaces(void) +{ + int f, g; + br_face *fp = zb.model->prepared_faces; + br_face_group *gp = zb.model->face_groups; + br_material *group_material; + + for (g = 0; g < zb.model->nface_groups; g++, gp++) + { + group_material = gp->material ? gp->material : zb.default_material; + + if (group_material->flags & BR_MATF_TWO_SIDED) + { + /* + * Two sided faces always face the eye + */ + for (f = 0; f < gp->nfaces; f++, fp++) + { + + if (!(fp->flags & 1)) + { + zb.edge_counts[fp->edges[0]]++; + zb.temp_edges[fp->edges[0]].material = group_material; + zb.temp_edges[fp->edges[0]].vertices[0] = fp->vertices[0]; + zb.temp_edges[fp->edges[0]].vertices[1] = fp->vertices[1]; + zb.vertex_counts[fp->vertices[0]]++; + zb.vertex_counts[fp->vertices[1]]++; + } + + if (!(fp->flags & 2)) + { + zb.edge_counts[fp->edges[1]]++; + zb.temp_edges[fp->edges[1]].material = group_material; + zb.temp_edges[fp->edges[1]].vertices[0] = fp->vertices[1]; + zb.temp_edges[fp->edges[1]].vertices[1] = fp->vertices[2]; + zb.vertex_counts[fp->vertices[1]]++; + zb.vertex_counts[fp->vertices[2]]++; + } + + if (!(fp->flags & 4)) + { + zb.edge_counts[fp->edges[2]]++; + zb.temp_edges[fp->edges[2]].material = group_material; + zb.temp_edges[fp->edges[2]].vertices[0] = fp->vertices[2]; + zb.temp_edges[fp->edges[2]].vertices[1] = fp->vertices[0]; + zb.vertex_counts[fp->vertices[2]]++; + zb.vertex_counts[fp->vertices[0]]++; + } + } + zb.face_group_counts[g] = gp->nfaces; + } + else + { + /* + * Check plane eqn. of every face in group against the eye + */ + zb.face_group_counts[g] = 0; + for (f = 0; f < gp->nfaces; f++, fp++) + { + + /* + * if Plane_Eqn . Eye <= 0, face is away from eye + */ + if (fw.vtos_type == BR_VTOS_PERSPECTIVE) + { + if (BrFVector3Dot(&fp->n, &fw.eye_m) <= fp->d) + continue; + } + else + { + if (BrFVector3Dot(&fp->n, &fw.eye_m) <= S0) + continue; + } + + if (!(fp->flags & 1)) + { + zb.edge_counts[fp->edges[0]]++; + zb.temp_edges[fp->edges[0]].material = group_material; + zb.temp_edges[fp->edges[0]].vertices[0] = fp->vertices[0]; + zb.temp_edges[fp->edges[0]].vertices[1] = fp->vertices[1]; + zb.vertex_counts[fp->vertices[0]]++; + zb.vertex_counts[fp->vertices[1]]++; + } + + if (!(fp->flags & 2)) + { + zb.edge_counts[fp->edges[1]]++; + zb.temp_edges[fp->edges[1]].material = group_material; + zb.temp_edges[fp->edges[1]].vertices[0] = fp->vertices[1]; + zb.temp_edges[fp->edges[1]].vertices[1] = fp->vertices[2]; + zb.vertex_counts[fp->vertices[1]]++; + zb.vertex_counts[fp->vertices[2]]++; + } + + if (!(fp->flags & 4)) + { + zb.edge_counts[fp->edges[2]]++; + zb.temp_edges[fp->edges[2]].material = group_material; + zb.temp_edges[fp->edges[2]].vertices[0] = fp->vertices[2]; + zb.temp_edges[fp->edges[2]].vertices[1] = fp->vertices[0]; + zb.vertex_counts[fp->vertices[2]]++; + zb.vertex_counts[fp->vertices[0]]++; + } + + zb.face_group_counts[g]++; + } + } + } +} + +/* + * For each edge, check outcodes, fill in edges and allocate temp_vertices + */ +static void ZbEdgeFindEdgesAndVertices(void) +{ + int e, j, v, vt; + struct temp_edge *tep = zb.temp_edges; + br_uint_32 combined_codes; + + for (e = 0; e < zb.model->nedges; e++, tep++) + { + + tep->flag = 0; + + if (zb.edge_counts[e] == 0) + continue; + + /* + * Work out AND/OR of outcodes + */ + combined_codes = zb.temp_vertices[tep->vertices[0]].outcode | zb.temp_vertices[tep->vertices[1]].outcode; + /* + * If completely of one edge of view volume (by outcodes) + * mark as not visible + * continue + */ + if ((combined_codes & OUTCODES_NOT) != OUTCODES_NOT) + { + zb.vertex_counts[tep->vertices[0]]--; + zb.vertex_counts[tep->vertices[1]]--; + continue; + } + + tep->flag = TFF_VISIBLE; + + /* + * If any outcode is set - mark as needing clipping and remember combined codes + */ + if (combined_codes & OUTCODES_ALL) + { + tep->flag |= TFF_CLIPPED; + tep->codes = combined_codes & OUTCODES_ALL; + } + /* + * Edge will be rendered + */ + } +} + +#if 0 +/* + * Do per-vertex paramter calculations (intensity, u & v) + */ +static void ZbEdgeFindVertexParameters(void) +{ + int i; + struct temp_vertex *avp; + br_vertex *mvp; + br_material *matp; + + /* + * Base vertices + */ + avp = zb.temp_vertices; + mvp = zb.model->prepared_vertices; + + for(i=0; i < zb.model->nprepared_vertices; i++, avp++, mvp++) { + /* + * Ignore if not visible + */ + if(zb.vertex_counts[i] == 0) + continue; + +// matp = zb.vertex_materials[i]; + +#if 1 + /* + * I am not sure this is necessary + */ + if(zb.material == NULL) + continue; +#else + ASSERT(zb.material != NULL); +#endif + + fw.surface_fn(mvp, &mvp->n, avp->comp); + + if(zb.material->flags & BR_MATF_FORCE_Z_0) { + avp->v[Z] = 0; + avp->comp[C_Z] = BR_SCALAR(0.0); + } + } +} +#endif + +/* + * Do per-vertex paramter calculations (intensity, u & v) + */ +static void ZbEdgeFindVertexParameters(void) +{ + int gv, g, v; + struct temp_vertex *avp; + br_vertex *vp; + br_vertex_group *gp = zb.model->vertex_groups; + + /* + * Base vertices + */ + avp = zb.temp_vertices; + v = 0; + + for (g = 0; g < zb.model->nvertex_groups; g++, gp++) + { + + zb.material = gp->material ? gp->material : zb.default_material; + + if ((zb.model->prep_flags & MODUF_VERTEX_GROUPS_MATCH) && (zb.face_group_counts[g] == 0)) + { + avp += gp->nvertices; + v += gp->nvertices; + } + else + { + SurfacePerMaterial(zb.material); + + for (gv = 0, vp = gp->vertices; gv < gp->nvertices; gv++, v++, avp++, vp++) + { + + /* + * Ignore if not visible + */ + if (zb.vertex_counts[v] == 0) + continue; + + fw.surface_fn(vp, &vp->n, avp->comp); + } + } + + /* + * Handle FORCE_Z_0 + */ + if (zb.material->flags & BR_MATF_FORCE_Z_0) + { + avp -= gp->nvertices; + for (gv = 0; gv < gp->nvertices; gv++, avp++) + { + avp->v[Z] = 0; + avp->comp[C_Z] = BR_SCALAR(0.0); + } + } + } +} + +static void ZbLineClipRender(struct temp_edge *tep, int mask, br_line_fn *renderfn, br_uint_32 convert_mask) +{ + static br_vector4 plane_px = BR_VECTOR4(-1, 0, 0, 1); + static br_vector4 plane_nx = BR_VECTOR4(1, 0, 0, 1); + static br_vector4 plane_py = BR_VECTOR4(0, -1, 0, 1); + static br_vector4 plane_ny = BR_VECTOR4(0, 1, 0, 1); + static br_vector4 plane_pz = BR_VECTOR4(0, 0, -1, 0); + static br_vector4 plane_nz = BR_VECTOR4(0, 0, 1, 1); + + struct temp_vertex cv0[2], cv1[2]; + struct temp_vertex *cp_in = cv0, *cp_out = cv1, *cp_tmp; + struct temp_vertex tv[2]; + int i, c; + + cp_in[0] = zb.temp_vertices[tep->vertices[0]]; + cp_in[1] = zb.temp_vertices[tep->vertices[1]]; + + if (tep->codes & OUTCODE_LEFT) + { + if (ClipLineToPlane(cp_in, cp_out, &plane_px, mask) == 0) + return; + + cp_tmp = cp_in; + cp_in = cp_out; + cp_out = cp_tmp; + } + + if (tep->codes & OUTCODE_RIGHT) + { + if (ClipLineToPlane(cp_in, cp_out, &plane_nx, mask) == 0) + return; + + cp_tmp = cp_in; + cp_in = cp_out; + cp_out = cp_tmp; + } + + if (tep->codes & OUTCODE_TOP) + { + if (ClipLineToPlane(cp_in, cp_out, &plane_py, mask) == 0) + return; + + cp_tmp = cp_in; + cp_in = cp_out; + cp_out = cp_tmp; + } + + if (tep->codes & OUTCODE_BOTTOM) + { + if (ClipLineToPlane(cp_in, cp_out, &plane_ny, mask) == 0) + return; + + cp_tmp = cp_in; + cp_in = cp_out; + cp_out = cp_tmp; + } + + if (tep->codes & OUTCODE_HITHER) + { + if (ClipLineToPlane(cp_in, cp_out, &plane_pz, mask) == 0) + return; + + cp_tmp = cp_in; + cp_in = cp_out; + cp_out = cp_tmp; + } + + if (tep->codes & OUTCODE_YON) + { + if (ClipLineToPlane(cp_in, cp_out, &plane_nz, mask) == 0) + return; + + cp_tmp = cp_in; + cp_in = cp_out; + cp_out = cp_tmp; + } + +#if USER_CLIP + /* + * User-defined clip plane + */ + for (c = 0; c < fw.nactive_clip_planes; c++) + { + + if (!(tep->codes & (OUTCODE_USER << c))) + continue; + + if (ClipLineToPlane(cp_in, cp_out, &fw.active_clip_planes[c].screen_plane, mask) == 0) + return; + + cp_tmp = cp_in; + cp_in = cp_out; + cp_out = cp_tmp; + } +#endif + + /* + * Re-project vertices + */ + for (i = 0; i < 2; i++) + { + PROJECT_VERTEX(tv + i, cp_in[i].comp[C_X], cp_in[i].comp[C_Y], cp_in[i].comp[C_Z], cp_in[i].comp[C_W]); + UPDATE_BOUNDS(tv[i]); +#if !BASED_FIXED + ZbConvertComponents((br_fixed_ls *)tv[i].comp, cp_in[i].comp, convert_mask); +#else + tv[i].comp[C_W] = cp_in[i].comp[C_W]; + tv[i].comp[C_I] = cp_in[i].comp[C_I]; + tv[i].comp[C_U] = cp_in[i].comp[C_U]; + tv[i].comp[C_V] = cp_in[i].comp[C_V]; + tv[i].comp[C_R] = cp_in[i].comp[C_R]; + tv[i].comp[C_G] = cp_in[i].comp[C_G]; + tv[i].comp[C_B] = cp_in[i].comp[C_B]; +#endif + } + + renderfn((struct temp_vertex_fixed *)(tv + 0), (struct temp_vertex_fixed *)(tv + 1)); +} + +static void ZbRenderEdges(void) +{ + br_uint_32 e, i; + struct temp_edge *tep = zb.temp_edges; + struct zb_material_type *zbmt; + struct temp_vertex *tvp; + struct temp_vertex_fixed tv[2]; + + for (e = 0; e < zb.model->nedges; e++, tep++) + { + + switch (tep->flag) + { + + case TFF_VISIBLE: + + if (tep->material->colour_map) + zb.texture_buffer = tep->material->colour_map->pixels; + + if (tep->material->index_shade) + zb.shade_table = tep->material->index_shade->pixels; + + zbmt = tep->material->rptr; + +#if !BASED_FIXED + for (i = 0; i < 2; i++) + { + tvp = zb.temp_vertices + tep->vertices[i]; + tv[i].v[X] = tvp->v[X]; + tv[i].v[Y] = tvp->v[Y]; + tv[i].v[Z] = tvp->v[Z]; + ZbConvertComponents(tv[i].comp, tvp->comp, zbmt->convert_mask); + } + zbmt->line(tv + 0, tv + 1); +#else + zbmt->line((struct temp_vertex_fixed *)zb.temp_vertices + tep->vertices[0], + (struct temp_vertex_fixed *)zb.temp_vertices + tep->vertices[1]); +#endif + break; + + case TFF_VISIBLE | TFF_CLIPPED: + + if (tep->material->colour_map) + zb.texture_buffer = tep->material->colour_map->pixels; + + if (tep->material->index_shade) + zb.shade_table = tep->material->index_shade->pixels; + + zbmt = tep->material->rptr; + ZbLineClipRender(tep, zbmt->clip_mask | CM_U | CM_V | CM_I | CM_R | CM_G | CM_B, zbmt->line, + zbmt->convert_mask); + break; + } + } +} + +/* + * Render a models points to the screen through the current transform + */ +void ZbMeshRenderEdges(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen) +{ + void *scratch; + int scratch_size; + char *sp, *clear_end; + int inside_out; + + /* + * Remember model and material in renderer info. + */ + zb.model = model; + zb.default_material = material; + + /* + * Work out amount of scratch space needed for this model + */ + + scratch_size = SCRATCH_ALIGN(model->nedges * sizeof(*zb.temp_edges)); + scratch_size += SCRATCH_ALIGN(model->nedges * sizeof(*zb.edge_counts)); + scratch_size += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_counts)); + scratch_size += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.vertex_counts)); + scratch_size += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.temp_vertices)); + + scratch = BrScratchAllocate(scratch_size + SCRATCH_BOUNDARY); + + /* + * Allocate scratch areas + */ + sp = scratch; + + zb.vertex_counts = (void *)sp; + sp += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.vertex_counts)); + + zb.face_group_counts = (void *)sp; + sp += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_counts)); + + zb.edge_counts = (void *)sp; + sp += SCRATCH_ALIGN(model->nedges * sizeof(*zb.edge_counts)); + + clear_end = sp; + + zb.temp_edges = (void *)sp; + sp += SCRATCH_ALIGN(model->nedges * sizeof(*zb.temp_edges)); + + zb.temp_vertices = (void *)sp; + + /* + * Clear vertex and edge counts + */ + BrBlockFill(scratch, 0, ((clear_end - (char *)scratch) + 3) / 4); + + /* + * Build view_to_model + * + * Record a flag to say if model is inside out (det of Xfrm is < 0) + * + * This should be done in traversal so that special cases can be + * exploited + */ + inside_out = BrMatrix34Inverse(&fw.view_to_model, &fw.model_to_view) < S0; + + /* + * Transform eye point into model space + */ + BrVector3EyeInModel(&fw.eye_m); + + /* + * Process lighting for this model + */ + SurfacePerModel(); + + /* + * Initialise bounds + */ +#if BOUNDING_RECTANGLE_CALL + zb.bounds[BR_BOUNDS_MIN_X] = zb.bounds[BR_BOUNDS_MIN_Y] = 0x7fffffff; + zb.bounds[BR_BOUNDS_MAX_X] = zb.bounds[BR_BOUNDS_MAX_Y] = 0x80000001; +#endif + + /* + * Process this model + */ + ZbEdgeFindVisibleFaces(); + ZbTransformVertices(); + ZbEdgeFindEdgesAndVertices(); + ZbEdgeFindVertexParameters(); + + ZbRenderEdges(); + + BrScratchFree(scratch); + +#if BOUNDING_RECTANGLE_CALL + + /* + * Invoke a callback for bounding rectangle + */ + if (zb.bounds_call) + { + br_int_32 int_bounds[4]; + + zb.bounds[0] -= BR_SCALAR(0.5); + zb.bounds[1] -= BR_SCALAR(0.5); + zb.bounds[2] += BR_SCALAR(0.5); + zb.bounds[3] += BR_SCALAR(0.5); + + CLAMP_POINT_MIN(zb.bounds[0], zb.bounds[1]); + CLAMP_POINT_MAX(zb.bounds[2], zb.bounds[3]); + + int_bounds[0] = ScreenToInt(zb.bounds[0]); + int_bounds[1] = ScreenToInt(zb.bounds[1]) + fw.output->base_y; + // int_bounds[2] = ScreenToInt(zb.bounds[2])-1; + // int_bounds[3] = ScreenToInt(zb.bounds[3])+fw.output->base_y-1; + + // Hawkeye - Add 1 pixel to make sure the narrow lines + // give a rect. (1 pixel high or wide.) + + int_bounds[2] = ScreenToInt(zb.bounds[2]); + int_bounds[3] = ScreenToInt(zb.bounds[3]) + fw.output->base_y; + + if ((int_bounds[0] <= int_bounds[2]) && (int_bounds[1] <= int_bounds[3])) + { + zb.bounds_call(actor, model, material, NULL, style, &fw.model_to_screen, int_bounds); + } + } +#endif +} + diff --git a/bren/ZB/zbmeshp.c b/bren/ZB/zbmeshp.c new file mode 100644 index 00000000..d7825640 --- /dev/null +++ b/bren/ZB/zbmeshp.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: zbmeshp.c 1.20 1995/08/31 16:48:00 sam Exp $ + * $Locker: $ + * + * Mesh rendering to produce points + */ +#include "zb.h" +#include "shortcut.h" +#include "blockops.h" + +static char rscid[] = "$Id: zbmeshp.c 1.20 1995/08/31 16:48:00 sam Exp $"; + +/* + * Render visible points + */ +static void ZbPointsRender(void) +{ + int g, v, gv; + br_vertex_group *gp = zb.model->vertex_groups; + struct temp_vertex *tvp; + struct temp_vertex_fixed tv[1]; + struct zb_material_type *zbmt; + br_material *group_material; + + tvp = zb.temp_vertices; + + for (v = 0, g = 0; g < zb.model->nvertex_groups; g++, gp++) + { + + if ((zb.model->prep_flags & MODUF_VERTEX_GROUPS_MATCH) && (zb.face_group_counts[g] == 0)) + { + tvp += gp->nvertices; + v += gp->nvertices; + continue; + } + + zb.material = group_material = (gp->material ? gp->material : zb.default_material); + + if (group_material->colour_map) + zb.texture_buffer = group_material->colour_map->pixels; + + if (group_material->index_shade) + zb.shade_table = group_material->index_shade->pixels; + + zbmt = group_material->rptr; + + for (gv = 0; gv < gp->nvertices; gv++, tvp++, v++) + { + + if ((zb.vertex_counts[v] <= 0) || tvp->outcode != OUTCODES_NOT) + continue; + +#if !BASED_FIXED + tv[0].v[X] = tvp->v[X]; + tv[0].v[Y] = tvp->v[Y]; + tv[0].v[Z] = tvp->v[Z]; + ZbConvertComponents(tv[0].comp, tvp->comp, zbmt->convert_mask); + zbmt->point(tv); +#else + zbmt->point((struct temp_vertex_fixed *)tvp); +#endif + } + } +} + +/* + * Do per-vertex parameter calculations (intensity, u & v) + */ +void ZbPointFindVertexParameters(void) +{ + int gv, g, v; + struct temp_vertex *avp; + br_vertex *vp; + br_vertex_group *gp = zb.model->vertex_groups; + + /* + * Base vertices + */ + avp = zb.temp_vertices; + v = 0; + + for (g = 0; g < zb.model->nvertex_groups; g++, gp++) + { + zb.material = (gp->material ? gp->material : zb.default_material); + + if ((zb.model->prep_flags & MODUF_VERTEX_GROUPS_MATCH) && (zb.face_group_counts[g] == 0)) + { + avp += gp->nvertices; + v += gp->nvertices; + } + else + { + SurfacePerMaterial(zb.material); + + for (gv = 0, vp = gp->vertices; gv < gp->nvertices; gv++, v++, avp++, vp++) + { + + /* + * Ignore if not visible + */ + if (zb.vertex_counts[v] == 0) + continue; + + fw.surface_fn(vp, &vp->n, avp->comp); + } + } + + /* + * Handle FORCE_Z_0 + */ + if (zb.material->flags & BR_MATF_FORCE_Z_0) + { + avp -= gp->nvertices; + for (gv = 0; gv < gp->nvertices; gv++, avp++) + { + avp->v[Z] = 0; + avp->comp[C_Z] = BR_SCALAR(0.0); + } + } + } +} + +/* + * Do per face work - find all the faces that are on screen and + * allocate temp_vertex structures + */ +static void ZbPointFindFacesAndVertices(void) +{ + int f, g, j; + br_face *fp = zb.model->prepared_faces; + br_face_group *gp = zb.model->face_groups; + struct temp_face *tfp = zb.temp_faces; + br_uint_32 combined_codes; + br_material *group_material; + + for (g = 0; g < zb.model->nface_groups; g++, gp++) + { + /* + * Skip group if it is not visible + */ + if (zb.face_group_counts[g] == 0) + { + fp += gp->nfaces; + tfp += gp->nfaces; + continue; + } + + group_material = gp->material ? gp->material : zb.default_material; + + for (f = 0; f < gp->nfaces; f++, fp++, tfp++) + { + + if (tfp->flag == 0) + continue; + + /* + * Work out AND/OR of outcodes + */ + combined_codes = zb.temp_vertices[fp->vertices[0]].outcode | zb.temp_vertices[fp->vertices[1]].outcode | + zb.temp_vertices[fp->vertices[2]].outcode; + /* + * If completely of one edge of view volume (by outcodes) + * mark as not visible + * continue + */ + if ((combined_codes & OUTCODES_NOT) != OUTCODES_NOT) + { + zb.face_group_counts[g]--; + + tfp->flag = 0; + + zb.vertex_counts[fp->vertices[0]]--; + zb.vertex_counts[fp->vertices[1]]--; + zb.vertex_counts[fp->vertices[2]]--; + continue; + } + + /* + * Face is a least partially visible + */ + } + } +} + +/* + * Render a models points to the screen through the current transform + */ +void ZbMeshRenderPoints(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen) +{ + void *scratch; + int scratch_size; + char *sp, *clear_end; + int inside_out; + + /* + * Remember model and material in renderer info. + */ + zb.model = model; + zb.default_material = material; + + /* + * Work out amount of scratch space needed for this model + */ + scratch_size = SCRATCH_ALIGN(model->nprepared_faces * sizeof(*zb.temp_faces)); + scratch_size += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_counts)); + scratch_size += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.vertex_counts)); + scratch_size += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.temp_vertices)); + + /* + * Make sure current scratch buffer is big enough + */ + scratch = BrScratchAllocate(scratch_size + SCRATCH_BOUNDARY); + + /* + * Allocate scratch areas + */ + sp = scratch; + + zb.vertex_counts = (void *)sp; + sp += SCRATCH_ALIGN(model->nprepared_vertices * sizeof(*zb.vertex_counts)); + + zb.face_group_counts = (void *)sp; + sp += SCRATCH_ALIGN(model->nface_groups * sizeof(*zb.face_group_counts)); + + clear_end = sp; + + zb.temp_faces = (void *)sp; + sp += SCRATCH_ALIGN(model->nprepared_faces * sizeof(*zb.temp_faces)); + + zb.temp_vertices = (void *)sp; + + /* + * Clear vertex counts + */ + BrBlockFill(scratch, 0, ((clear_end - (char *)scratch) + 3) / 4); + + /* + * Build view_to_model + * + * Record a flag to say if model is inside out (det of Xfrm is < 0) + */ + inside_out = BrMatrix34Inverse(&fw.view_to_model, &fw.model_to_view) < S0; + + /* + * Transform eye point into model space + */ + BrVector3EyeInModel(&fw.eye_m); + + /* + * Process lighting for this model + */ + SurfacePerModel(); + + /* + * Process this model + */ + /* + * Initialise bounds + */ +#if BOUNDING_RECTANGLE_CALL + zb.bounds[BR_BOUNDS_MIN_X] = zb.bounds[BR_BOUNDS_MIN_Y] = 0x7fffffff; + zb.bounds[BR_BOUNDS_MAX_X] = zb.bounds[BR_BOUNDS_MAX_Y] = 0x80000001; +#endif + + switch (fw.vtos_type) + { + case BR_VTOS_PERSPECTIVE: + ZbFindVisibleFaces(); + break; + + case BR_VTOS_PARALLEL: + ZbFindVisibleFacesPar(); + break; + } + + ZbTransformVertices(); + ZbPointFindFacesAndVertices(); + ZbPointFindVertexParameters(); + + ZbPointsRender(); + + /* + * Release scratch + */ + BrScratchFree(scratch); + +#if BOUNDING_RECTANGLE_CALL + + /* + * Invoke a callback for bounding rectangle + */ + if (zb.bounds_call) + { + br_int_32 int_bounds[4]; + + zb.bounds[0] -= BR_SCALAR(0.5); + zb.bounds[1] -= BR_SCALAR(0.5); + zb.bounds[2] += BR_SCALAR(0.5); + zb.bounds[3] += BR_SCALAR(0.5); + + CLAMP_POINT_MIN(zb.bounds[0], zb.bounds[1]); + CLAMP_POINT_MAX(zb.bounds[2], zb.bounds[3]); + + int_bounds[0] = ScreenToInt(zb.bounds[0]); + int_bounds[1] = ScreenToInt(zb.bounds[1]) + fw.output->base_y; + int_bounds[2] = ScreenToInt(zb.bounds[2]) - 1; + int_bounds[3] = ScreenToInt(zb.bounds[3]) + fw.output->base_y - 1; + + if ((int_bounds[0] <= int_bounds[2]) && (int_bounds[1] <= int_bounds[3])) + { + zb.bounds_call(actor, model, material, NULL, style, &fw.model_to_screen, int_bounds); + } + } +#endif +} diff --git a/bren/ZB/zbrendr.c b/bren/ZB/zbrendr.c new file mode 100644 index 00000000..b1bb8c05 --- /dev/null +++ b/bren/ZB/zbrendr.c @@ -0,0 +1,519 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: zbrendr.c 1.36 1995/08/31 16:48:02 sam Exp $ + * $Locker: sam $ + * + * Given world, a camera, a vieport and a pixmap - perform the rendering + */ + +#include "zb.h" +#include "shortcut.h" +#include "brassert.h" + +static char rscid[] = "$Id: zbrendr.c 1.36 1995/08/31 16:48:02 sam Exp $"; + +/* + * System defaults + */ +extern br_model default_model; +extern br_material default_material; + +static void ZbActorRenderOnScreen(br_actor *ap, br_model *model, br_material *material, br_uint_8 style); + +/* + * Table of functions to call for each render style + */ + +static void (*ZbRenderStyleCalls[])(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, + int on_screen) = { + ZbMeshRender, /* BR_RSTYLE_DEFAULT */ + ZbNullRender, /* BR_RSTYLE_NONE */ + ZbMeshRenderPoints, /* BR_RSTYLE_POINTS */ + ZbMeshRenderEdges, /* BR_RSTYLE_EDGES */ + ZbMeshRender, /* BR_RSTYLE_FACES */ + ZbBoundingBoxRenderPoints, /* BR_RSTYLE_BOUNDING_POINTS */ + ZbBoundingBoxRenderEdges, /* BR_RSTYLE_BOUNDING_EDGES */ + ZbBoundingBoxRenderFaces, /* BR_RSTYLE_BOUNDING_FACES */ +}; + +/* + * Renders a model with current settings + */ +void BR_PUBLIC_ENTRY BrZbModelRender(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, + int on_screen, int use_custom) +{ + UASSERT(fw.rendering); + UASSERT(model != NULL); + UASSERT(material != NULL); + UASSERT(actor != NULL); + + UASSERT(model->prep_flags & MODUF_REGISTERED); + + /* + * If model has custom callback, invoke that + */ + if (use_custom && (model->flags & BR_MODF_CUSTOM)) + model->custom(actor, model, material, NULL, style, on_screen, &fw.model_to_view, &fw.model_to_screen); + else + ZbRenderStyleCalls[style](actor, model, material, style, on_screen); +} + +/* + * Rendering traversal for the given actor + * + */ +static void ZbActorRender(br_actor *ap, br_model *model, br_material *material, br_uint_8 style) +{ + /* + * Saved state + */ + br_matrix4 m_to_s; + br_matrix34 m_to_v; + br_matrix34 m_to_e; + br_material *this_material; + br_model *this_model; + br_actor *a; + + int s; + + /* + * Ignore actors with no children that are not models, and actors with renderstyle = NONE + */ + if (ap->children == NULL && ap->type != BR_ACTOR_MODEL) + return; + + if (ap->render_style == BR_RSTYLE_NONE) + return; + + /* + * See if this actor overrides default material, model or style + */ + this_material = ap->material ? ap->material : material; + this_model = ap->model ? ap->model : model; + if (ap->render_style != BR_RSTYLE_DEFAULT) + style = ap->render_style; + + /* + * Catch special case of identity transforms + */ + if (ap->t.type == BR_TRANSFORM_IDENTITY) + { + /** + ** Actor has no transform + **/ + switch (ap->type) + { + + case BR_ACTOR_MODEL: + /* + * This is a model - see if model's bounding box is on screen + */ + if ((s = BrOnScreenCheck(&this_model->bounds)) != OSC_REJECT) + BrZbModelRender(ap, this_model, this_material, style, s, 1); + break; + + case BR_ACTOR_BOUNDS: + /* + * A bounding box - truncate whole tree if rejected + */ + if (BrOnScreenCheck(ap->type_data) == OSC_REJECT) + /* DONT PROCESS CHILDREN */ + return; + break; + + case BR_ACTOR_BOUNDS_CORRECT: + /* + * A garuanteed bounding box - test to see if it is on screen + */ + switch (BrOnScreenCheck(ap->type_data)) + { + + case OSC_ACCEPT: + /* + * Bounding box is completely on screen - process children with special loop + */ + BR_FOR_SIMPLELIST(&ap->children, a) + ZbActorRenderOnScreen(a, this_model, this_material, style); + /* FALL THROUGH */ + + case OSC_REJECT: + /* DONT PROCESS CHILDREN */ + return; + } + } + + /* + * Recurse for children + */ + BR_FOR_SIMPLELIST(&ap->children, a) + ZbActorRender(a, this_model, this_material, style); + } + else + { + /** + ** Actor has a transform + **/ + + /* + * Save the current transforms + */ + m_to_s = fw.model_to_screen; + m_to_v = fw.model_to_view; + m_to_e = fw.model_to_environment; + + /* + * See if this actor is on the camera path - if so, generate a new transform + */ + if (ap == fw.camera_path[ap->depth].a) + { + BrMatrix34Inverse(&fw.model_to_view, &fw.camera_path[ap->depth].m); + + BrMatrix4Copy(&fw.model_to_screen, &fw.view_to_screen); + BrMatrix4Pre34(&fw.model_to_screen, &fw.model_to_view); + } + else + { + BrMatrix4PreTransform(&fw.model_to_screen, &ap->t); + BrMatrix34PreTransform(&fw.model_to_view, &ap->t); + } + + if (fw.enabled_environment) + BrMatrix34PreTransform(&fw.model_to_environment, &ap->t); + + switch (ap->type) + { + + case BR_ACTOR_MODEL: + /* + * This is a model - see if model's bounding box is on screen + */ + if ((s = BrOnScreenCheck(&this_model->bounds)) != OSC_REJECT) + BrZbModelRender(ap, this_model, this_material, style, s, 1); + break; + + case BR_ACTOR_BOUNDS: + /* + * A bounding box - truncate whole tree if rejected + */ + if (BrOnScreenCheck(ap->type_data) == OSC_REJECT) + { + fw.model_to_view = m_to_v; + fw.model_to_screen = m_to_s; + fw.model_to_environment = m_to_e; + return; + } + break; + + case BR_ACTOR_BOUNDS_CORRECT: + /* + * A garuanteed bounding box - test to see if it is on screen + */ + switch (BrOnScreenCheck(ap->type_data)) + { + + case OSC_ACCEPT: + /* + * Bounding box is completely on screen - process children with special loop + */ + BR_FOR_SIMPLELIST(&ap->children, a) + ZbActorRenderOnScreen(a, this_model, this_material, style); + /* FALL THROUGH */ + + case OSC_REJECT: + /* + * Don't process children + */ + fw.model_to_view = m_to_v; + fw.model_to_screen = m_to_s; + fw.model_to_environment = m_to_e; + return; + } + } + + /* + * Recurse for children + */ + BR_FOR_SIMPLELIST(&ap->children, a) + ZbActorRender(a, this_model, this_material, style); + + /* + * Restore transforms + */ + fw.model_to_view = m_to_v; + fw.model_to_screen = m_to_s; + fw.model_to_environment = m_to_e; + } +} + +/* + * Rendering traversal for an actor that is completely on screen, along + * with any children + */ +static void ZbActorRenderOnScreen(br_actor *ap, br_model *model, br_material *material, br_uint_8 style) +{ + /* + * Saved state + */ + br_matrix4 m_to_s; + br_matrix34 m_to_v; + br_matrix34 m_to_e; + br_material *this_material; + br_model *this_model; + br_actor *a; + + /* + * Ignore actors with no children that are not models, and actors with renderstyle = NONE + */ + if (ap->children == NULL && ap->type != BR_ACTOR_MODEL) + return; + + if (ap->render_style == BR_RSTYLE_NONE) + return; + + /* + * See if this actor overrides default material, model or style + */ + this_material = ap->material ? ap->material : material; + this_model = ap->model ? ap->model : model; + if (ap->render_style != BR_RSTYLE_DEFAULT) + style = ap->render_style; + + /* + * Catch special case of identity transforms + */ + if (ap->t.type == BR_TRANSFORM_IDENTITY) + { + /* + * This actor has an no transform + */ + if (ap->type == BR_ACTOR_MODEL) + BrZbModelRender(ap, this_model, this_material, style, OSC_ACCEPT, 1); + + BR_FOR_SIMPLELIST(&ap->children, a) + ZbActorRenderOnScreen(a, this_model, this_material, style); + return; + } + else + { + /* + * Actor has a transform + */ + m_to_s = fw.model_to_screen; + m_to_v = fw.model_to_view; + m_to_e = fw.model_to_environment; + + /* + * See if this actor is on the camera path - if so, generate a new transform + */ + if (ap == fw.camera_path[ap->depth].a) + { + /* + * Save model_to_screen and model_to_view + */ + BrMatrix34Inverse(&fw.model_to_view, &fw.camera_path[ap->depth].m); + + BrMatrix4Copy(&fw.model_to_screen, &fw.view_to_screen); + BrMatrix4Pre34(&fw.model_to_screen, &fw.model_to_view); + } + else + { + BrMatrix4PreTransform(&fw.model_to_screen, &ap->t); + BrMatrix34PreTransform(&fw.model_to_view, &ap->t); + } + + if (fw.enabled_environment) + BrMatrix34PreTransform(&fw.model_to_environment, &ap->t); + + if (ap->type == BR_ACTOR_MODEL) + BrZbModelRender(ap, this_model, this_material, style, OSC_ACCEPT, 1); + + BR_FOR_SIMPLELIST(&ap->children, a) + ZbActorRenderOnScreen(a, this_model, this_material, style); + + /* + * Restore transforms + */ + fw.model_to_view = m_to_v; + fw.model_to_screen = m_to_s; + fw.model_to_environment = m_to_e; + return; + } +} + +/* + * BrZbSceneRenderBegin() + * + * Setup a new scene to be rendered - processes the camera, lights + * and environment + */ +void BR_PUBLIC_ENTRY BrZbSceneRenderBegin(br_actor *world, br_actor *camera, br_pixelmap *colour_buffer, + br_pixelmap *depth_buffer) +{ + br_camera *camera_type; + br_matrix34 camera_tfm; + br_actor *a; + int i, j; + + UASSERT(zb.type != NULL); + UASSERT(zb.type->colour_type == colour_buffer->type); + UASSERT(zb.type->depth_type == depth_buffer->type); + + UASSERT(fw.rendering == 0); + + /* + * Set flag to say we are rendering + */ + fw.rendering = 1; + + /* + * Constant parameters for renderer + */ + fw.output = colour_buffer; + + if (depth_buffer->row_bytes * zb.type->colour_row_size != colour_buffer->row_bytes * zb.type->depth_row_size) + BR_ERROR0("Colour and depth strides do not match"); + +#if 0 + /* + * Work out y*row_width table + */ + if(zb.row_width != colour_buffer->row_bytes) { + for(i=0, j=0; i < MAX_OUTPUT_HEIGHT; i++, j+= zb.row_width) + zb.row_table[i] = j; + } +#endif + + zb.row_width = colour_buffer->row_bytes; + zb.depth_row_width = depth_buffer->row_bytes; + + zb.colour_buffer = (br_uint_8 *)colour_buffer->pixels + colour_buffer->base_y * colour_buffer->row_bytes; + zb.depth_buffer = (br_fixed_ls *)depth_buffer->pixels + depth_buffer->base_y * depth_buffer->row_bytes; + + /* + * Parameters of viewport (origin is at pixel centre, so add [0.5,0.5]) + */ + fw.vp_ox = BR_SCALAR(colour_buffer->base_x + colour_buffer->width / 2) + BR_SCALAR(0.5); + fw.vp_width = BR_SCALAR(colour_buffer->width / 2); + + fw.vp_oy = BR_SCALAR(colour_buffer->height / 2) + BR_SCALAR(0.5); + fw.vp_height = -BR_SCALAR(colour_buffer->height / 2); + + /* + * Work out View Transform from info. in camera actor + */ + fw.vtos_type = BrCameraToScreenMatrix4(&fw.view_to_screen, camera); + + /* + * Collect transforms from camera to root + * + * Make a stack of cumulative transforms for each level between + * the camera and the root - this is so that model->view + * transforms can use the shortest route, rather than via the root + */ + for (i = 0; i < MAX_CAMERA_DEPTH; i++) + { + fw.camera_path[i].a = NULL; + } + + i = camera->depth; + a = camera; + BrMatrix34Identity(&fw.camera_path[i].m); + +#if 0 + if(i > 0) { + fw.camera_path[i].a = a; + BrMatrix34Transform(&fw.camera_path[i].m,&a->t); + a =a->parent; + i --; + } +#endif + + for (; i > 0; a = a->parent, i--) + { + ASSERT(a != NULL); + BrMatrix34Transform(&camera_tfm, &a->t); + BrMatrix34Mul(&fw.camera_path[i - 1].m, &fw.camera_path[i].m, &camera_tfm); + fw.camera_path[i].a = a; + } + + if (world != a) + { + BR_ERROR0("camera is not in world hierachy"); + } + + /* + * Make world->view as initial model->view + */ + BrMatrix34Inverse(&fw.model_to_view, &fw.camera_path[0].m); + + BrMatrix4Copy(&fw.model_to_screen, &fw.view_to_screen); + BrMatrix4Pre34(&fw.model_to_screen, &fw.model_to_view); + + /* + * Preprocess active lights, and environment + */ + SurfacePerScene(world, zb.type->true_colour); +} + +/* + * BrZbSceneRenderAdd() + * + * Add a sub-tree of actors to the current rendering + * + */ +void BR_PUBLIC_ENTRY BrZbSceneRenderAdd(br_actor *tree) +{ + UASSERT(tree); + UASSERT(fw.rendering); + + /* + * Walk the provided world and add transformed models to scene + */ + ZbActorRender(tree, fw.default_model, fw.default_material, BR_RSTYLE_DEFAULT); +} + +/* + * BrZbSceneRenderEnd() + * + * Finish rendering a scene - does nothing, but exists in case we + * ever need a flush of some sort + */ +void BR_PUBLIC_ENTRY BrZbSceneRenderEnd(void) +{ + UASSERT(fw.rendering); + fw.rendering = 0; +} + +/* + * BrZbSceneRender() + * + * Wrapper that sets up, renders and flushes a scene + * + */ +void BR_PUBLIC_ENTRY BrZbSceneRender(br_actor *world, br_actor *camera, br_pixelmap *colour_buffer, + br_pixelmap *depth_buffer) +{ + BrZbSceneRenderBegin(world, camera, colour_buffer, depth_buffer); + BrZbSceneRenderAdd(world); + BrZbSceneRenderEnd(); +} + +/* + * Render function for BR_RSTYLE_NONE + */ +void ZbNullRender(br_actor *actor, br_model *model, br_material *material, br_uint_8 style, int on_screen) +{ +} + +/* + * Set a callback function for bounding rectangles + */ +br_renderbounds_cbfn *BR_PUBLIC_ENTRY BrZbSetRenderBoundsCallback(br_renderbounds_cbfn *new_cbfn) +{ + br_renderbounds_cbfn *old_cbfn = zb.bounds_call; + + zb.bounds_call = new_cbfn; + + return old_cbfn; +} diff --git a/bren/ZB/zbsetup.c b/bren/ZB/zbsetup.c new file mode 100644 index 00000000..b409f60a --- /dev/null +++ b/bren/ZB/zbsetup.c @@ -0,0 +1,544 @@ +/* + * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. + * + * $Id: zbsetup.c 1.18 1995/08/31 16:48:03 sam Exp $ + * $Locker: $ + * + */ + +// Hawkeye. Set all non-used types to the NULL render. + +#include "zb.h" +#include + +static char rscid[] = "$Id: zbsetup.c 1.18 1995/08/31 16:48:03 sam Exp $"; + +/* + * Global renderer state + */ +br_zbuffer_state BR_ASM_DATA zb; + +void BR_ASM_CALL TriangleRender_Null(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2); +void BR_ASM_CALL LineRender_Null(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1); +void BR_ASM_CALL PointRender_Null(struct temp_vertex_fixed *v0); + +/* + * Material types for INDEX_8, DEPTH_16 + */ +#define MT_MASK (BR_MATF_SMOOTH | ZB_MATF_HAS_MAP | ZB_MATF_TRANSPARENT) + +#define MT_MASK_T (BR_MATF_SMOOTH | BR_MATF_DECAL | ZB_MATF_HAS_MAP | ZB_MATF_TRANSPARENT) + +#define MT_MASK_TP (BR_MATF_SMOOTH | BR_MATF_PERSPECTIVE | BR_MATF_DECAL | ZB_MATF_HAS_MAP | ZB_MATF_TRANSPARENT) + +#define CM_COORDS (CM_X | CM_Y | CM_Z | CM_W) + +/* + * Only include identifiers in debug code + */ +#if DEBUG +#define IDENT(x) x +#else +#define IDENT(x) x +#endif + +static struct zb_material_type mat_types_index_8[] = { + + // /* + // * Perspective texture mapping + // */ + // { + // IDENT("Texture mapped (perspective, dithered) 1024x1024"), + // MT_MASK_TP | ZB_MATF_NO_SKIP | BR_MATF_LIGHT | BR_MATF_PRELIT | BR_MATF_DITHER, ZB_MATF_HAS_MAP | + //ZB_MATF_NO_SKIP | BR_MATF_DITHER | BR_MATF_PERSPECTIVE, + // BR_PMT_INDEX_8, 1024, 1024, + //// ZbRenderFaceGroup, TriangleRenderPIZ2TPD1024, LineRenderPIZ2T, PointRenderPIZ2T, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V, CM_W | CM_U | CM_V, + // }, + // { + // IDENT("Texture mapped (perspective) 1024x1024"), + // MT_MASK_TP | ZB_MATF_NO_SKIP | BR_MATF_LIGHT | BR_MATF_PRELIT, ZB_MATF_HAS_MAP | ZB_MATF_NO_SKIP | + //BR_MATF_PERSPECTIVE, + // BR_PMT_INDEX_8, 1024, 1024, + //// ZbRenderFaceGroup, TriangleRenderPIZ2TP1024, LineRenderPIZ2T, PointRenderPIZ2T, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V, CM_W | CM_U | CM_V, + // }, + // { + // IDENT("Texture mapped (perspective) 256x256"), + // MT_MASK_TP | ZB_MATF_NO_SKIP | BR_MATF_LIGHT | BR_MATF_PRELIT, ZB_MATF_HAS_MAP | ZB_MATF_NO_SKIP | + //BR_MATF_PERSPECTIVE, + // BR_PMT_INDEX_8, 256, 256, + //// ZbRenderFaceGroup, TriangleRenderPIZ2TP256, LineRenderPIZ2T, PointRenderPIZ2T, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V, CM_W | CM_U | CM_V, + // }, + // { + // IDENT("Texture mapped (perspective) 64x64"), + // MT_MASK_TP | ZB_MATF_NO_SKIP | BR_MATF_LIGHT | BR_MATF_PRELIT, ZB_MATF_HAS_MAP | ZB_MATF_NO_SKIP | + //BR_MATF_PERSPECTIVE, + // BR_PMT_INDEX_8, 64, 64, + //// ZbRenderFaceGroup, TriangleRenderPIZ2TP64, LineRenderPIZ2T, PointRenderPIZ2T, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V, CM_W | CM_U | CM_V, + // }, + // { + // IDENT("Lit smooth texture mapped (perspective) 1024x1024"), + // MT_MASK_TP | ZB_MATF_NO_SKIP | BR_MATF_LIGHT, BR_MATF_SMOOTH | BR_MATF_LIGHT | ZB_MATF_HAS_MAP | + //ZB_MATF_NO_SKIP | BR_MATF_PERSPECTIVE, + // BR_PMT_INDEX_8, 1024, 1024, + //// ZbRenderFaceGroup, TriangleRenderPIZ2TIP1024, LineRenderPIZ2TI, PointRenderPIZ2TI, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V | CM_I, CM_W | CM_U | CM_V | CM_I, + // }, + // { + // IDENT("Lit smooth texture mapped (perspective) 256x256"), + // MT_MASK_TP | ZB_MATF_NO_SKIP | BR_MATF_LIGHT, BR_MATF_SMOOTH | BR_MATF_LIGHT | ZB_MATF_HAS_MAP | + //ZB_MATF_NO_SKIP | BR_MATF_PERSPECTIVE, + // BR_PMT_INDEX_8, 256, 256, + //// ZbRenderFaceGroup, TriangleRenderPIZ2TIP256, LineRenderPIZ2TI, PointRenderPIZ2TI, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V | CM_I, CM_W | CM_U | CM_V | CM_I, + // }, + // { + // IDENT("Lit smooth texture mapped (perspective) 64x64"), + // MT_MASK_TP | ZB_MATF_NO_SKIP | BR_MATF_LIGHT, BR_MATF_SMOOTH | BR_MATF_LIGHT | ZB_MATF_HAS_MAP | + //ZB_MATF_NO_SKIP | BR_MATF_PERSPECTIVE, + // BR_PMT_INDEX_8, 64, 64, + //// ZbRenderFaceGroup, TriangleRenderPIZ2TIP64, LineRenderPIZ2TI, PointRenderPIZ2TI, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V | CM_I, CM_W | CM_U | CM_V | CM_I, + // }, + // + // /* + // * Special case 256x256 linear texture mapping + // */ + // { + // IDENT("Texture mapped (linear, dithered) 256x256"), + // MT_MASK_TP | ZB_MATF_NO_SKIP | BR_MATF_LIGHT | BR_MATF_PRELIT | BR_MATF_DITHER, ZB_MATF_HAS_MAP | + //ZB_MATF_NO_SKIP | BR_MATF_DITHER, + // BR_PMT_INDEX_8, 256, 256, + //// ZbRenderFaceGroup, TriangleRenderPIZ2TD, LineRenderPIZ2T, PointRenderPIZ2T, + // ZbRenderFaceGroup_FaceIV, TriangleRenderPIZ2TIA, LineRenderPIZ2TI, PointRenderPIZ2TI, + //// ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V, CM_W | CM_U | CM_V, + // }, + // { + // IDENT("Lit smooth texture mapped (linear, dithered) 256x256"), + // MT_MASK_TP | ZB_MATF_NO_SKIP | BR_MATF_LIGHT | BR_MATF_DITHER, BR_MATF_SMOOTH | BR_MATF_LIGHT | + //ZB_MATF_HAS_MAP | ZB_MATF_NO_SKIP | BR_MATF_DITHER, + // BR_PMT_INDEX_8, 256, 256, + //// ZbRenderFaceGroup, TriangleRenderPIZ2TID, LineRenderPIZ2TI, PointRenderPIZ2TI, + // ZbRenderFaceGroup_FaceIV, TriangleRenderPIZ2TIA, LineRenderPIZ2TI, PointRenderPIZ2TI, + //// ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V | CM_I, CM_W | CM_U | CM_V | CM_I, + // }, + // { + // IDENT("Texture mapped (linear) 256x256"), + // MT_MASK_T | ZB_MATF_NO_SKIP | BR_MATF_LIGHT | BR_MATF_PRELIT, ZB_MATF_HAS_MAP | ZB_MATF_NO_SKIP, + // BR_PMT_INDEX_8, 256, 256, + //// ZbRenderFaceGroup, TriangleRenderPIZ2T, LineRenderPIZ2T, PointRenderPIZ2T, + // ZbRenderFaceGroup_FaceIV, TriangleRenderPIZ2TIA, LineRenderPIZ2TI, PointRenderPIZ2TI, + //// ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V , CM_U | CM_V, + // }, + // { + // IDENT("Lit flat texture mapped (linear) 256x256"), + // MT_MASK_T | ZB_MATF_NO_SKIP | BR_MATF_LIGHT, BR_MATF_LIGHT | ZB_MATF_HAS_MAP | ZB_MATF_NO_SKIP, + // BR_PMT_INDEX_8, 256, 256, + //// ZbRenderFaceGroup, TriangleRenderPIZ2I, LineRenderPIZ2I, PointRenderPIZ2, + // ZbRenderFaceGroup_FaceIV, TriangleRenderPIZ2TIA, LineRenderPIZ2TI, PointRenderPIZ2TI, + //// ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V | CM_I, CM_U | CM_V | CM_I, + // }, + // { + // IDENT("Lit smooth texture mapped (linear) 256x256"), + // MT_MASK_T | ZB_MATF_NO_SKIP | BR_MATF_LIGHT, BR_MATF_SMOOTH | BR_MATF_LIGHT | ZB_MATF_HAS_MAP | + //ZB_MATF_NO_SKIP, + // BR_PMT_INDEX_8, 256, 256, + //// ZbRenderFaceGroup, TriangleRenderPIZ2I, LineRenderPIZ2I, PointRenderPIZ2, + // ZbRenderFaceGroup_FaceIV, TriangleRenderPIZ2TIA, LineRenderPIZ2TI, PointRenderPIZ2TI, + //// ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V | CM_I, CM_U | CM_V | CM_I, + // }, + + /* + * Arbitary width general texture mapping + */ + { + IDENT("Texture mapped (linear) AW"), + MT_MASK_T | BR_MATF_LIGHT | BR_MATF_PRELIT | ZB_MATF_MAP_TRANSPARENT, + ZB_MATF_HAS_MAP | ZB_MATF_MAP_TRANSPARENT, + BR_PMT_INDEX_8, + 0, + 0, + // ZbRenderFaceGroup, TriangleRenderPIZ2TA, LineRenderPIZ2T, PointRenderPIZ2T, + ZbRenderFaceGroup_FaceIV, + TriangleRenderPIZ2TIA, + LineRenderPIZ2TI, + PointRenderPIZ2TI, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + CM_COORDS | CM_U | CM_V, + CM_U | CM_V, + }, + { + IDENT("Lit flat texture mapped (linear) AW"), + MT_MASK_T | BR_MATF_LIGHT | ZB_MATF_MAP_TRANSPARENT, + BR_MATF_LIGHT | ZB_MATF_HAS_MAP | ZB_MATF_MAP_TRANSPARENT, + BR_PMT_INDEX_8, + 0, + 0, + ZbRenderFaceGroup_FaceIV, + TriangleRenderPIZ2TIA, + LineRenderPIZ2TI, + PointRenderPIZ2TI, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + CM_COORDS | CM_U | CM_V | CM_I, + CM_U | CM_V | CM_I, + }, + { + IDENT("Lit smooth texture mapped (linear) AW"), + MT_MASK_T | BR_MATF_LIGHT | ZB_MATF_MAP_TRANSPARENT, + BR_MATF_SMOOTH | BR_MATF_LIGHT | ZB_MATF_HAS_MAP | ZB_MATF_MAP_TRANSPARENT, + BR_PMT_INDEX_8, + 0, + 0, + ZbRenderFaceGroup, + TriangleRenderPIZ2TIA, + LineRenderPIZ2TI, + PointRenderPIZ2TI, + CM_COORDS | CM_U | CM_V | CM_I, + CM_U | CM_V | CM_I, + }, + + // /* + // * Arbitary width general texture mapping + decal + // */ + // { + // IDENT("Texture mapped decal (linear) AW"), + // MT_MASK_T | BR_MATF_LIGHT | BR_MATF_PRELIT, ZB_MATF_HAS_MAP | BR_MATF_DECAL, + // BR_PMT_INDEX_8, 0, 0, + //// ZbRenderFaceGroup, TriangleRenderPIZ2TAD, LineRenderPIZ2I, PointRenderPIZ2, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V , CM_U | CM_V, + // }, + // { + // IDENT("Lit flat texture mapped decal (linear) AW"), + // MT_MASK_T | BR_MATF_LIGHT, BR_MATF_LIGHT | ZB_MATF_HAS_MAP | BR_MATF_DECAL, + // BR_PMT_INDEX_8, 0, 0, + //// ZbRenderFaceGroup_FaceIV, TriangleRenderPIZ2TIAD, LineRenderPIZ2I, PointRenderPIZ2, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V | CM_I, CM_U | CM_V | CM_I, + // }, + // { + // IDENT("Lit smooth texture mapped decal (linear) AW"), + // MT_MASK_T | BR_MATF_LIGHT, BR_MATF_SMOOTH | BR_MATF_LIGHT | ZB_MATF_HAS_MAP | BR_MATF_DECAL, + // BR_PMT_INDEX_8, 0, 0, + //// ZbRenderFaceGroup, TriangleRenderPIZ2TIAD, LineRenderPIZ2I, PointRenderPIZ2, + // ZbRenderFaceGroup, TriangleRender_Null, LineRender_Null, PointRender_Null, + // CM_COORDS | CM_U | CM_V | CM_I, CM_U | CM_V | CM_I, + // }, + // + { + IDENT("Smooth shading"), + BR_MATF_SMOOTH, + BR_MATF_SMOOTH, + 0, + 0, + 0, + // ZbRenderFaceGroup_FaceIV, TriangleRenderPIZ2TIA, LineRenderPIZ2TI, PointRenderPIZ2TI, + ZbRenderFaceGroup, + TriangleRenderPIZ2I, + LineRenderPIZ2I, + PointRenderPIZ2, + CM_COORDS | CM_I, + CM_I, + }, + { + IDENT("Flat shading"), + 0, + 0, + 0, + 0, + 0, + // ZbRenderFaceGroup_FaceI, TriangleRenderPIZ2, LineRenderPIZ2I, PointRenderPIZ2, + // ZbRenderFaceGroup_FaceIV, TriangleRenderPIZ2TIA, LineRenderPIZ2TI, PointRenderPIZ2TI, + ZbRenderFaceGroup, + TriangleRender_Null, + LineRender_Null, + PointRender_Null, + CM_COORDS, + 0, + }, +}; + +/* + * Material types for RGB_555, DEPTH_16 + */ +static struct zb_material_type mat_types_rgb_555[] = { + { + IDENT("Texture mapped (linear) AW"), + MT_MASK_T | BR_MATF_LIGHT | BR_MATF_PRELIT, + ZB_MATF_HAS_MAP, + BR_PMT_RGB_555, + 0, + 0, + ZbRenderFaceGroup_FaceIV, + TriangleRenderPIZ2TIA_RGB_555, + LineRenderPIZ2T_RGB_555, + PointRenderPIZ2T_RGB_555, + CM_COORDS | CM_U | CM_V, + CM_U | CM_V, + }, + { + IDENT("Lit flat texture mapped (linear) AW"), + MT_MASK_T | BR_MATF_LIGHT | ZB_MATF_MAP_TRANSPARENT, + BR_MATF_LIGHT | ZB_MATF_HAS_MAP | ZB_MATF_MAP_TRANSPARENT, + BR_PMT_RGB_555, + 0, + 0, + ZbRenderFaceGroup_FaceIV, + TriangleRenderPIZ2TIA_RGB_555, + LineRenderPIZ2T_RGB_555, + PointRenderPIZ2T_RGB_555, + CM_COORDS | CM_U | CM_V | CM_I, + CM_U | CM_V | CM_I, + }, + { + IDENT("Lit smooth texture mapped (linear) AW"), + MT_MASK_T | BR_MATF_LIGHT | ZB_MATF_MAP_TRANSPARENT, + BR_MATF_SMOOTH | BR_MATF_LIGHT | ZB_MATF_HAS_MAP | ZB_MATF_MAP_TRANSPARENT, + BR_PMT_RGB_555, + 0, + 0, + ZbRenderFaceGroup, + TriangleRenderPIZ2TIA_RGB_555, + LineRenderPIZ2T_RGB_555, + PointRenderPIZ2T_RGB_555, + CM_COORDS | CM_U | CM_V | CM_I, + CM_U | CM_V | CM_I, + }, + + { + IDENT("Smooth shading"), + MT_MASK, + BR_MATF_SMOOTH, + 0, + 0, + 0, + ZbRenderFaceGroup, + TriangleRenderPIZ2I_RGB_555, + LineRenderPIZ2I_RGB_555, + PointRenderPIZ2_RGB_555, + CM_COORDS | CM_R | CM_G | CM_B, + CM_R | CM_G | CM_B, + }, + { + IDENT("Flat shading"), + 0, + 0, + 0, + 0, + 0, + ZbRenderFaceGroup_FaceRGB, + TriangleRenderPIZ2_RGB_555, + LineRenderPIZ2I_RGB_555, + PointRenderPIZ2_RGB_555, + CM_COORDS, + CM_R | CM_G | CM_B, + }, +}; + +/* + * Material types for RGB_888, DEPTH_16 + */ +static struct zb_material_type mat_types_rgb_888[] = { + { + IDENT("Texture mapped (linear) AW"), + MT_MASK_T | BR_MATF_LIGHT | BR_MATF_PRELIT, + ZB_MATF_HAS_MAP, + BR_PMT_RGB_888, + 0, + 0, + ZbRenderFaceGroup_FaceIV, + TriangleRenderPIZ2TIA_RGB_888, + LineRenderPIZ2T_RGB_888, + PointRenderPIZ2T_RGB_888, + CM_COORDS | CM_U | CM_V, + CM_U | CM_V, + }, + { + IDENT("Lit flat texture mapped (linear) AW"), + MT_MASK_T | BR_MATF_LIGHT | ZB_MATF_MAP_TRANSPARENT, + BR_MATF_LIGHT | ZB_MATF_HAS_MAP | ZB_MATF_MAP_TRANSPARENT, + BR_PMT_RGB_888, + 0, + 0, + ZbRenderFaceGroup_FaceIV, + TriangleRenderPIZ2TIA_RGB_888, + LineRenderPIZ2T_RGB_888, + PointRenderPIZ2T_RGB_888, + CM_COORDS | CM_U | CM_V | CM_I, + CM_U | CM_V | CM_I, + }, + { + IDENT("Lit smooth texture mapped (linear) AW"), + MT_MASK_T | BR_MATF_LIGHT | ZB_MATF_MAP_TRANSPARENT, + BR_MATF_SMOOTH | BR_MATF_LIGHT | ZB_MATF_HAS_MAP | ZB_MATF_MAP_TRANSPARENT, + BR_PMT_RGB_888, + 0, + 0, + ZbRenderFaceGroup, + TriangleRenderPIZ2TIA_RGB_888, + LineRenderPIZ2T_RGB_888, + PointRenderPIZ2T_RGB_888, + CM_COORDS | CM_U | CM_V | CM_I, + CM_U | CM_V | CM_I, + }, + + { + IDENT("Smooth shading"), + BR_MATF_SMOOTH, + BR_MATF_SMOOTH, + 0, + 0, + 0, + ZbRenderFaceGroup, + TriangleRenderPIZ2I_RGB_888, + LineRenderPIZ2I_RGB_888, + PointRenderPIZ2_RGB_888, + CM_COORDS | CM_R | CM_G | CM_B, + CM_R | CM_G | CM_B, + }, + { + IDENT("Flat shading"), + 0, + 0, + 0, + 0, + 0, + ZbRenderFaceGroup_FaceRGB, + TriangleRenderPIZ2_RGB_888, + LineRenderPIZ2I_RGB_888, + PointRenderPIZ2_RGB_888, + CM_COORDS, + CM_R | CM_G | CM_B, + }, +}; + +/* + * Table of valid render types + */ +static struct zb_render_type rtype_table[] = { + { + IDENT("8 bit indexed, 16 bit Z"), + BR_PMT_INDEX_8, + BR_PMT_DEPTH_16, + 0, + 1, + 2, + 0, + mat_types_index_8, + BR_ASIZE(mat_types_index_8), + }, + { + IDENT("15 bit true colour, 16 bit Z"), + BR_PMT_RGB_555, + BR_PMT_DEPTH_16, + 0, + 2, + 2, + 1, + mat_types_rgb_555, + BR_ASIZE(mat_types_rgb_555), + }, + { + IDENT("24 true colour, 16 bit Z"), + BR_PMT_RGB_888, + BR_PMT_DEPTH_16, + 0, + 3, + 2, + 1, + mat_types_rgb_888, + BR_ASIZE(mat_types_rgb_888), + }, +}; + +void BR_PUBLIC_ENTRY BrZbBegin(br_uint_8 colour_type, br_uint_8 depth_type) +{ + int i; + + /* + * See if we can support pixelmap types provided + */ + for (i = 0; i < BR_ASIZE(rtype_table); i++) + if (colour_type == rtype_table[i].colour_type && depth_type == rtype_table[i].depth_type) + break; + + if (i >= BR_ASIZE(rtype_table)) + BR_ERROR("BrZbBegin: invalid types for rendering"); + + /* + * Remember the renderer type structure + */ + zb.type = rtype_table + i; + + /* + * Setup anchor block for resources associated with ZB renderer + */ + zb.res = BrResAllocate(NULL, 0, BR_MEMORY_ANCHOR); + + zb.row_width = 0; + + /* + * Hook update functions + */ + fw.material_update = ZbMaterialUpdate; + + /* + * Update the default material and model + */ + BrMaterialUpdate(fw.default_material, BR_MATU_ALL); + BrModelUpdate(fw.default_model, BR_MODU_ALL); +} + +void BR_PUBLIC_ENTRY BrZbEnd(void) +{ + if (zb.res) + BrResFree(zb.res); + + /* + * Clear out zb structure + */ + memset(&zb, 0, sizeof(zb)); +} + +//#if 0 // Hawkeye +/* + * Dummy triangle renderer for unimplemented ops. + */ +void BR_ASM_CALL TriangleRender_Null(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1, + struct temp_vertex_fixed *v2) +{ +} + +/* + * Dummy line renderer for unimplemented ops. + */ +void BR_ASM_CALL LineRender_Null(struct temp_vertex_fixed *v0, struct temp_vertex_fixed *v1) +{ +} + +/* + * Dummy point renderer for unimplemented ops. + */ +void BR_ASM_CALL PointRender_Null(struct temp_vertex_fixed *v0) +{ +} +//#endif + + + diff --git a/bren/bwld.cpp b/bren/bwld.cpp index 670d3ff8..be1c61d8 100644 --- a/bren/bwld.cpp +++ b/bren/bwld.cpp @@ -616,7 +616,7 @@ void BWLD::_CleanWorkingBuffers(void) Callback for when a BACT is rendered. Need to union with dirty region. ***************************************************************************/ -void BWLD::_ActorRendered(PBACT pbact, PBMDL pbmdl, PBMTL pbmtl, br_uint_8 bStyle, br_matrix4 *pbmat4ModelToScreen, +void BWLD::_ActorRendered(PBACT pbact, PBMDL pbmdl, PBMTL pbmtl, void* render_data, br_uint_8 bStyle, br_matrix4 *pbmat4ModelToScreen, br_int_32 bounds[4]) { AssertVarMem(pbact); diff --git a/bren/inc/actor.h b/bren/inc/actor.h index d39cb7cb..d6c7ffaf 100644 --- a/bren/inc/actor.h +++ b/bren/inc/actor.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: actor.h 1.14 1995/05/25 13:37:23 sam Exp $ + * $Id: actor.h 1.15 1995/08/31 16:36:10 sam Exp $ * $Locker: $ * * Definitons for an Actor @@ -107,6 +107,12 @@ extern "C" */ br_uint_8 render_style; + /* + * Reference to renderer specific data associated with this actor - NULL will + * inherit from parent (root inherits default data) + */ + void *render_data; + /* * Postiton of this actor within parent space */ diff --git a/bren/inc/angles.h b/bren/inc/angles.h index de171caa..0af24eec 100644 --- a/bren/inc/angles.h +++ b/bren/inc/angles.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: angles.h 1.9 1995/05/25 13:37:24 sam Exp $ + * $Id: angles.h 1.10 1995/08/31 16:36:11 sam Exp $ * $Locker: $ * */ @@ -18,8 +18,8 @@ extern "C" */ typedef br_fixed_luf br_angle; -#define BR_ANGLE_DEG(deg) ((br_angle)((deg)*182)) -#define BR_ANGLE_RAD(rad) ((br_angle)((rad)*10430)) +#define BR_ANGLE_DEG(deg) ((br_angle)(long)((deg)*182)) +#define BR_ANGLE_RAD(rad) ((br_angle)(long)((rad)*10430)) #if BASED_FIXED @@ -31,7 +31,7 @@ extern "C" #define BrRadianToDegree(r) (BR_MUL((r), BR_SCALAR(180.0 / PI))) #define BrAngleToScalar(a) ((br_scalar)(a)) -#define BrScalarToAngle(s) ((br_angle)(s)) +#define BrScalarToAngle(s) ((br_angle)(long)(s)) #define BR_SIN(a) BrFixedSin(a) #define BR_COS(a) BrFixedCos(a) @@ -44,22 +44,22 @@ extern "C" #if BASED_FLOAT -#define BrAngleToDegree(a) ((a) * (180.0 / 32768.0)) -#define BrDegreeToAngle(d) ((br_angle)((d) * (32768.0 / 180.0))) -#define BrAngleToRadian(a) ((a) * (PI / 32768.0)) -#define BrRadianToAngle(r) ((br_angle)((r) * (32768.0 / PI))) -#define BrDegreeToRadian(d) ((d) * (PI / 180.0)) -#define BrRadianToDegree(r) ((r) * (180.0 / PI)) +#define BrAngleToDegree(a) ((br_scalar)((a) * (180.0 / 32768.0))) +#define BrDegreeToAngle(d) ((br_angle)(long)((d) * (32768.0 / 180.0))) +#define BrAngleToRadian(a) ((br_scalar)((a) * (PI / 32768.0))) +#define BrRadianToAngle(r) ((br_angle)(long)((r) * (32768.0 / PI))) +#define BrDegreeToRadian(d) ((br_scalar)((d) * (PI / 180.0))) +#define BrRadianToDegree(r) ((br_scalar)((r) * (180.0 / PI))) -#define BrAngleToScalar(a) ((a) * (1.0 / (float)BR_ONE_LS)) -#define BrScalarToAngle(s) ((br_angle)((s) * (float)BR_ONE_LS)) +#define BrAngleToScalar(a) ((br_scalar)((a) * (1.0 / (float)BR_ONE_LS))) +#define BrScalarToAngle(s) ((br_angle)(long)((s) * (float)BR_ONE_LS)) -#define BR_SIN(a) sin(BrAngleToRadian(a)) -#define BR_COS(a) cos(BrAngleToRadian(a)) +#define BR_SIN(a) ((br_scalar)sin(BrAngleToRadian(a))) +#define BR_COS(a) ((br_scalar)cos(BrAngleToRadian(a))) #define BR_ASIN(a) BrRadianToAngle(asin(a)) #define BR_ACOS(a) BrRadianToAngle(acos(a)) #define BR_ATAN2(a, b) BrRadianToAngle(atan2((a), (b))) -#define BR_ATAN2FAST(a, b) RBradianToAngle(atan2((a), (b))) +#define BR_ATAN2FAST(a, b) BrRadianToAngle(atan2((a), (b))) #endif diff --git a/bren/inc/brbithax.h b/bren/inc/brbithax.h new file mode 100644 index 00000000..b5d78972 --- /dev/null +++ b/bren/inc/brbithax.h @@ -0,0 +1,16 @@ +/* + * NOTE(bjrkk): All of these are taken from either the BRender source code + * or from https://graphics.stanford.edu/~seander/bithacks.html + */ + +#include + +#ifndef _BRBITHAX_H_ +#define _BRBITHAX_H_ + +static inline br_boolean __BrBitHaxIsPow2(br_uint_32 num) +{ + return num && !(num & (num - 1)); +} + +#endif diff --git a/bren/inc/brbuiltin.h b/bren/inc/brbuiltin.h new file mode 100644 index 00000000..da058eb3 --- /dev/null +++ b/bren/inc/brbuiltin.h @@ -0,0 +1,312 @@ +/* + * NOTE(bjrkk): this is needed for the assembly translation, as there's some + * things you can't do as easily in C and are rather implemented as compiler + * built-ins, so this seeks out to remedy this issue in some "portable" way. + * + * basically we try to find if we can use a specific builtin, and if we can't, + * we instead resort to a naive implementation that might either hopefully get + * optimized out by the compiler or atleast run well enough. + */ + +#include +#include + +#ifndef _BRBUILTIN_H_ +#define _BRBUILTIN_H_ + +#if defined(__GNUC__) + +#if __has_builtin(__builtin_clz) +#define __BR_BUILTIN_CLZ +#endif +#if __has_builtin(__builtin_add_overflow) +#define __BR_BUILTIN_ADD_OVERFLOW +#endif +#if __has_builtin(__builtin_constant_p) +#define __BR_BUILTIN_CONSTANT_P +#endif +#if __has_builtin(__builtin_unreachable) +#define __BR_BUILTIN_UNREACHABLE +#endif + +#elif defined(_MSC_VER) + +#include + +#if _MSC_VER >= 1400 +#define __BR_BITSCANREVERSE +#endif + +#if _MSC_VER >= 1920 +#define __BR_DIV64 +#endif + +#define __BR_ASSUME + +#endif + +#if defined(__BR_BUILTIN_CLZ) + +static inline br_uint_32 __BrBuiltinCLZ(br_uint_32 num) +{ + if (num == 0) + { + return 0; + } + return __builtin_clz(num) ^ (sizeof(num) * CHAR_BIT - 1); +} + +#elif defined(__BR_BITSCANREVERSE) + +#pragma intrinsic(_BitScanReverse) + +static inline br_uint_32 __BrBuiltinCLZ(br_uint_32 num) +{ + unsigned long index = 0; + if (_BitScanReverse(&index, num) != 0) + { + return (sizeof(num) * CHAR_BIT - 1) - index; + } + else + { + return (sizeof(num) * CHAR_BIT - 1); + } +} + +#else + +static inline br_uint_32 __BrBuiltinCLZ(br_uint_32 num) +{ + static br_uint_8 const debrujin_bit_pos[] = {0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31}; + + num |= num >> 1; + num |= num >> 2; + num |= num >> 4; + num |= num >> 8; + num |= num >> 16; + + return debrujin_bit_pos[(num * 0x07c4acddu) >> 27]; +} + +#endif + +#if defined(__BR_BUILTIN_ADD_OVERFLOW) + +static inline br_boolean __BrBuiltinAddI32Overflow(br_int_32 a, br_int_32 b, br_int_32 *result) +{ + return __builtin_add_overflow(a, b, result); +} + +static inline br_boolean __BrBuiltinAddI16Overflow(br_int_16 a, br_int_16 b, br_int_16 *result) +{ + return __builtin_add_overflow(a, b, result); +} + +static inline br_boolean __BrBuiltinAddI8Overflow(br_int_8 a, br_int_8 b, br_int_8 *result) +{ + return __builtin_add_overflow(a, b, result); +} + +static inline br_boolean __BrBuiltinMulI32Overflow(br_int_32 a, br_int_32 b, br_int_32 *result) +{ + return __builtin_mul_overflow(a, b, result); +} + +static inline br_boolean __BrBuiltinMulI16Overflow(br_int_16 a, br_int_16 b, br_int_16 *result) +{ + return __builtin_mul_overflow(a, b, result); +} + +static inline br_boolean __BrBuiltinMulI8Overflow(br_int_8 a, br_int_8 b, br_int_8 *result) +{ + return __builtin_mul_overflow(a, b, result); +} + +static inline br_boolean __BrBuiltinAddU32Overflow(br_uint_32 a, br_uint_32 b, br_uint_32 *result) +{ + return __builtin_add_overflow(a, b, result); +} + +static inline br_boolean __BrBuiltinAddU16Overflow(br_uint_16 a, br_uint_16 b, br_uint_16 *result) +{ + return __builtin_add_overflow(a, b, result); +} + +static inline br_boolean __BrBuiltinAddU8Overflow(br_uint_8 a, br_uint_8 b, br_uint_8 *result) +{ + return __builtin_add_overflow(a, b, result); +} + +static inline br_boolean __BrBuiltinMulU32Overflow(br_uint_32 a, br_uint_32 b, br_uint_32 *result) +{ + return __builtin_add_overflow(a, b, result); +} + +static inline br_boolean __BrBuiltinMulU16Overflow(br_uint_16 a, br_uint_16 b, br_uint_16 *result) +{ + return __builtin_add_overflow(a, b, result); +} + +static inline br_boolean __BrBuiltinMulU8Overflow(br_uint_8 a, br_uint_8 b, br_uint_8 *result) +{ + return __builtin_add_overflow(a, b, result); +} + +#else + +static inline br_boolean __BrBuiltinAddI32Overflow(br_int_32 a, br_int_32 b, br_int_32 *result) +{ + br_int_64 add = (br_int_64)a + (br_int_64)b; + *result = add; + return add > INT_MAX || add < INT_MIN; +} + +static inline br_boolean __BrBuiltinAddI16Overflow(br_int_16 a, br_int_16 b, br_int_16 *result) +{ + br_int_32 add = (br_int_32)a + (br_int_32)b; + *result = add; + return add > SHRT_MAX || add < SHRT_MIN; +} + +static inline br_boolean __BrBuiltinAddI8Overflow(br_int_8 a, br_int_8 b, br_int_8 *result) +{ + br_int_16 add = (br_int_16)a + (br_int_16)b; + *result = add; + return add > SCHAR_MAX || add < SCHAR_MIN; +} + +static inline br_boolean __BrBuiltinMulI32Overflow(br_int_32 a, br_int_32 b, br_int_32 *result) +{ + br_int_64 add = (br_int_64)a * (br_int_64)b; + *result = add; + return add > INT_MAX || add < INT_MIN; +} + +static inline br_boolean __BrBuiltinMulI16Overflow(br_int_16 a, br_int_16 b, br_int_16 *result) +{ + br_int_32 add = (br_int_32)a * (br_int_32)b; + *result = add; + return add > SHRT_MAX || add < SHRT_MIN; +} + +static inline br_boolean __BrBuiltinMulI8Overflow(br_int_8 a, br_int_8 b, br_int_8 *result) +{ + br_int_16 add = (br_int_16)a * (br_int_16)b; + *result = add; + return add > SCHAR_MAX || add < SCHAR_MIN; +} + +static inline br_boolean __BrBuiltinAddU32Overflow(br_uint_32 a, br_uint_32 b, br_uint_32 *result) +{ + br_uint_64 add = (br_uint_64)a + (br_uint_64)b; + *result = add; + return add > UINT_MAX; +} + +static inline br_boolean __BrBuiltinAddU16Overflow(br_uint_16 a, br_uint_16 b, br_uint_16 *result) +{ + br_uint_32 add = (br_uint_32)a + (br_uint_32)b; + *result = add; + return add > USHRT_MAX; +} + +static inline br_boolean __BrBuiltinAddU8Overflow(br_uint_8 a, br_uint_8 b, br_uint_8 *result) +{ + br_uint_16 add = (br_uint_16)a + (br_uint_16)b; + *result = add; + return add > UCHAR_MAX; +} + +static inline br_boolean __BrBuiltinMulU32Overflow(br_uint_32 a, br_uint_32 b, br_uint_32 *result) +{ + br_uint_64 add = (br_uint_64)a * (br_uint_64)b; + *result = add; + return add > UINT_MAX; +} + +static inline br_boolean __BrBuiltinMulU16Overflow(br_uint_16 a, br_uint_16 b, br_uint_16 *result) +{ + br_uint_32 add = (br_uint_32)a * (br_uint_32)b; + *result = add; + return add > USHRT_MAX; +} + +static inline br_boolean __BrBuiltinMulU8Overflow(br_uint_8 a, br_uint_8 b, br_uint_8 *result) +{ + br_uint_16 add = (br_uint_16)a * (br_uint_16)b; + *result = add; + return add > UCHAR_MAX; +} + +#endif + +// NOTE(bjrkk): This exists purely because apparently no compiler can +// properly optimize divisions with a 64-bit dividend and 32-bit divisor +// into an idiv r/m32. +#if defined(__BR_BUILTIN_CONSTANT_P) && (defined(__i386__) || defined(__x86_64__)) + +static inline br_int_32 __BrBuiltinDivI64I32(br_int_64 a, br_int_32 b) +{ + if (__builtin_constant_p(b)) + { + return a / b; + } + br_int_32 lo = a; + br_int_32 hi = a >> 32; + __asm__("idivl %2" : "+a"(lo), "+d"(hi) : "rm"(b)); + return lo; +} + +static inline br_uint_32 __BrBuiltinDivU64U32(br_uint_64 a, br_uint_32 b) +{ + if (__builtin_constant_p(b)) + { + return a / b; + } + br_uint_32 lo = a; + br_uint_32 hi = a >> 32; + __asm__("divl %2" : "+a"(lo), "+d"(hi) : "rm"(b)); + return lo; +} + +#elif defined(__BR_DIV64) + +static inline br_int_32 __BrBuiltinDivI64I32(br_int_64 a, br_int_32 b) +{ + return _div64(a, b, NULL); +} + +static inline br_uint_32 __BrBuiltinDivU64U32(br_uint_64 a, br_uint_32 b) +{ + return _udiv64(a, b, NULL); +} + +#else + +static inline br_int_32 __BrBuiltinDivI64I32(br_int_64 a, br_int_32 b) +{ + return a / b; +} + +static inline br_uint_32 __BrBuiltinDivU64U32(br_uint_64 a, br_uint_32 b) +{ + return a / b; +} + +#endif + +#if defined(__BR_BUILTIN_UNREACHABLE) +#define __BrBuiltinUnreachable() __builtin_unreachable() +#elif defined(__BR_ASSUME) +#define __BrBuiltinUnreachable() __assume(0) +#else +#define __BrBuiltinUnreachable() +#endif + +static inline br_uint_32 __BrBuiltinROR(br_uint_32 num, br_uint_32 count) +{ + return (num >> count | num << (sizeof(num) * CHAR_BIT - count)); +} + +#endif // _BRBUILTINS_H_ \ No newline at end of file diff --git a/bren/inc/brender.h b/bren/inc/brender.h index 69fbb89c..d0864f74 100644 --- a/bren/inc/brender.h +++ b/bren/inc/brender.h @@ -1,8 +1,8 @@ /* * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: brender.h 1.17 1995/03/01 16:08:11 sam Exp $ - * $Locker: sam $ + * $Id: brender.h 1.19 1995/08/31 16:36:12 sam Exp $ + * $Locker: $ * * Master include file for BRender * @@ -15,9 +15,7 @@ extern "C" { #endif -#ifndef _COMPILER_H_ #include "compiler.h" -#endif #ifndef _BRLIMITS_H_ #include "brlimits.h" @@ -55,6 +53,10 @@ extern "C" #include "transfrm.h" #endif +#ifndef _ORDER_H_ +#include "order.h" +#endif + #ifndef _PIXELMAP_H_ #include "pixelmap.h" #endif @@ -95,14 +97,14 @@ extern "C" #include "brfile.h" #endif -#ifndef _BRMEM_H_ -#include "brmem.h" -#endif - #ifndef _BRDIAG_H_ #include "brdiag.h" #endif +#ifndef _BRMEM_H_ +#include "brmem.h" +#endif + #ifndef _BRERR_H_ #include "brerr.h" #endif @@ -123,8 +125,8 @@ extern "C" #include "zbproto.h" #endif -#ifndef _FWPEXTRA_H_ -#include "fwpextra.h" +#ifndef _ZSPROTO_H_ +#include "zsproto.h" #endif /* @@ -139,7 +141,11 @@ extern "C" #endif #endif +#include "compend.h" + #ifdef __cplusplus }; #endif #endif + + diff --git a/bren/inc/brerr.h b/bren/inc/brerr.h index 03005ee6..8ee920ee 100644 --- a/bren/inc/brerr.h +++ b/bren/inc/brerr.h @@ -1,8 +1,8 @@ /* * Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved. * - * $Id: fwiproto.h 1.27 1995/06/30 16:01:14 sam Exp $ - * $Locker: sam $ + * $Id: brerr.h 1.4 1995/07/28 18:57:02 sam Exp $ + * $Locker: $ * * Error type */ diff --git a/bren/inc/brhton.h b/bren/inc/brhton.h index 49e137a8..ae74ef88 100644 --- a/bren/inc/brhton.h +++ b/bren/inc/brhton.h @@ -25,7 +25,7 @@ extern "C" * XXX SANE format */ -#if defined(__MPW__) || defined(__THINKC__) +#if BR_ENDIAN_BIG typedef float br_float; @@ -37,15 +37,12 @@ extern "C" #define BrHtoNF(x) (x) #define BrNtoHF(x) (x) -#define BR_ENDIAN_BIG 1 -#define BR_ENDIAN_LITTLE 0 #endif /* * PC is little-endian */ -#if defined(__GNUC__) || defined(__WATCOMC__) || defined(__ZTC__) || defined(__PROTONC__) || defined(__HIGHC__) || \ - defined(__BORLANDC__) || defined(__IBMC__) || defined(_MSC_VER) +#if BR_ENDIAN_LITTLE #define BrNtoHL(x) BrSwap32(x) #define BrHtoNL(x) BrSwap32(x) @@ -55,9 +52,6 @@ extern "C" #define BrHtoNF(x) BrSwapFloat(x) #define BrNtoHF(x) BrSwapFloat(x) -#define BR_ENDIAN_BIG 0 -#define BR_ENDIAN_LITTLE 1 - #endif #ifdef __cplusplus diff --git a/bren/inc/brmem.h b/bren/inc/brmem.h index e17249de..91ca727d 100644 --- a/bren/inc/brmem.h +++ b/bren/inc/brmem.h @@ -1,8 +1,8 @@ /* * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: brmem.h 1.13 1995/05/25 13:37:26 sam Exp $ - * $Locker: sam $ + * $Id: brmem.h 1.15 1995/08/31 16:36:13 sam Exp $ + * $Locker: $ * * Brender's interface to memory allocation */ @@ -84,6 +84,7 @@ extern "C" BR_MEMORY_IMAGE_SECTIONS, BR_MEMORY_IMAGE_NAMES, BR_MEMORY_EXCEPTION_HANDLER, + BR_MEMORY_RENDER_DATA, /* * Application classes diff --git a/bren/inc/bwld.h b/bren/inc/bwld.h index da6db159..deeac6ca 100644 --- a/bren/inc/bwld.h +++ b/bren/inc/bwld.h @@ -75,7 +75,7 @@ class BWLD : public BWLD_PAR void _CleanWorkingBuffers(void); static int BR_CALLBACK _FFilter(BACT *pbact, PBMDL pbmdl, PBMTL pbmtl, BVEC3 *pbvec3RayPos, BVEC3 *pbvec3RayDir, BRS dzpNear, BRS dzpFar, void *pbwld); - static void BR_CALLBACK _ActorRendered(PBACT pbact, PBMDL pbmdl, PBMTL pbmtl, br_uint_8 bStyle, + static void BR_CALLBACK _ActorRendered(PBACT pbact, PBMDL pbmdl, PBMTL pbmtl, void* render_data, br_uint_8 bStyle, br_matrix4 *pbmat4ModelToScreen, br_int_32 bounds[4]); public: diff --git a/bren/inc/colour.h b/bren/inc/colour.h index 99acebc1..1bbb51a9 100644 --- a/bren/inc/colour.h +++ b/bren/inc/colour.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: colour.h 1.3 1995/02/22 21:37:03 sam Exp $ + * $Id: colour.h 1.4 1995/08/31 16:36:14 sam Exp $ * $Locker: $ * * Colour type and macros @@ -20,10 +20,7 @@ extern "C" #define BR_COLOUR_RGB(r, g, b) ((((unsigned int)(r)) << 16) | (((unsigned int)(g)) << 8) | ((unsigned int)(b))) #define BR_COLOUR_RGBA(r, g, b, a) \ - ((((unsigned int)(a))<<24) |\ - ((((unsigned int)(r))<<16) |\ - (((unsigned int)(g))<<8) |\ - ((unsigned int)(b))) + ((((unsigned int)(a)) << 24) | (((unsigned int)(r)) << 16) | (((unsigned int)(g)) << 8) | ((unsigned int)(b))) #define BR_ALPHA(c) ((c >> 24) & 0xFF) #define BR_RED(c) ((c >> 16) & 0xFF) diff --git a/bren/inc/compend.h b/bren/inc/compend.h new file mode 100644 index 00000000..c2a67e84 --- /dev/null +++ b/bren/inc/compend.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. + * + * $Id: compend.h 1.1 1995/08/31 16:36:45 sam Exp $ + * $Locker: $ + * + * Included at end of BRender includes - undoes any compiler specific pragmas + */ +#ifndef _COMPEND_H_ +#define _COMPEND_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * WATCOM C/C++ 32 + */ +#if defined(__WATCOMC__) + +#ifndef __H2INC__ +#pragma pack() +#endif + +/* + * Zortech C++ + */ +#elif defined(__ZTC__) + +/* + * GNU C + */ +#elif defined(__GNUC__) + +/* + * Apple MPW C + */ +#elif defined(__MPW__) + +/* + * Intel Proton + */ +#elif defined(__PROTONC__) + +/* + * Microsoft Visual C++ + */ +#elif defined(_MSC_VER) + +#ifndef __H2INC__ +#pragma pack() +#endif + +/* + * Metaware High-C Version 1 + */ +#elif defined(__HIGHC_V1__) + +/* + * Metaware High-C Version 3 + */ +#elif defined(__HIGHC__) + +/* + * Borland BC 4 + */ +#elif defined(__BORLANDC__) + +/* + * IBM CSet++ + */ +#elif defined(__IBMC__) + +#endif + +#ifdef __cplusplus +}; +#endif +#endif diff --git a/bren/inc/compiler.h b/bren/inc/compiler.h index 78309e91..d9b75d16 100644 --- a/bren/inc/compiler.h +++ b/bren/inc/compiler.h @@ -1,11 +1,15 @@ /* * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: compiler.h 1.20 1995/05/25 13:37:28 sam Exp $ + * $Id: compiler.h 1.22 1995/08/31 16:36:15 sam Exp $ * $Locker: sam $ * * Misc host compiler configuration (types & special declarators etc.) */ + +#include +#include + #ifndef _COMPILER_H_ #define _COMPILER_H_ @@ -17,19 +21,23 @@ extern "C" /* * Fixed bitsize integers */ - typedef signed long br_int_32; - typedef unsigned long br_uint_32; - - typedef signed short br_int_16; - typedef unsigned short br_uint_16; - typedef signed char br_int_8; - typedef unsigned char br_uint_8; + typedef int64_t br_int_64; + typedef uint64_t br_uint_64; + typedef int32_t br_int_32; + typedef uint32_t br_uint_32; + typedef int16_t br_int_16; + typedef uint16_t br_uint_16; + typedef int8_t br_int_8; + typedef uint8_t br_uint_8; /* * Generic size type (in case target environment does not have size_t) */ - typedef unsigned int br_size_t; + typedef size_t br_size_t; + + typedef uintptr_t br_uint_ptr; + typedef intptr_t br_int_ptr; /* * Boolean type @@ -39,7 +47,7 @@ extern "C" #define BR_TRUE 1 #define BR_FALSE 0 -#define BR_BOOLEAN(a) ((a) != 0) +#define BR_BOOLEAN(a) ((a) != BR_FALSE) /** ** Compiler specific declarations @@ -77,12 +85,16 @@ extern "C" #define stricmp _stricmp #define strnicmp _strnicmp #define memccpy _memccpy +#define MEMAVL 0 #pragma aux __cdecl "_*" parm caller[] modify[eax ecx edx]; #define BR_PUBLIC_ENTRY __cdecl #define BR_CALLBACK __cdecl + #else + +#define MEMAVL _memavl() #define BR_PUBLIC_ENTRY #define BR_CALLBACK #endif @@ -100,12 +112,16 @@ extern "C" #define BR_SUFFIX_HOST "-WTC" #define BR_HAS_FAR 1 + /* * Stop unreferenced variables producing a warning * Things like "rcsid" and unused fucntion arguments */ #pragma off(unreferenced); +#ifndef __H2INC__ +#pragma pack(4); +#endif /* * Zortech C++ */ @@ -120,6 +136,7 @@ extern "C" #define BR_SUFFIX_HOST "-ZTC" #define BR_HAS_FAR 1 +#define MEMAVL 0 /* * GNU C @@ -136,6 +153,8 @@ extern "C" #define BR_SUFFIX_HOST "-GCC" #define BR_HAS_FAR 0 +#define MEMAVL 0 + /* * Apple MPW C @@ -151,6 +170,7 @@ extern "C" #define BR_SUFFIX_HOST "-MPW" #define BR_HAS_FAR 0 +#define MEMAVL 0 /* * Intel Proton @@ -166,21 +186,29 @@ extern "C" #define BR_SUFFIX_HOST "-PROTON" #define BR_HAS_FAR 1 +#define MEMAVL 0 /* * Microsoft Visual C++ */ #elif defined(_MSC_VER) + #define BR_PUBLIC_ENTRY __cdecl #define BR_CALLBACK __cdecl -#define BR_ASM_DATA __cdecl +#define BR_ASM_DATA #define BR_ASM_CALL __cdecl #define BR_ASM_CALLBACK __cdecl #define BR_SUFFIX_HOST "-VISUALC" #define BR_HAS_FAR 0 +#define MEMAVL 0 + +#ifndef __H2INC__ +#pragma warning(disable : 4103) +#pragma pack(4) +#endif /* * Metaware High-C Version 1 @@ -199,6 +227,7 @@ extern "C" #define BR_SUFFIX_HOST "-HIGHC1" #define BR_HAS_FAR 0 +#define MEMAVL 0 #define stricmp _stricmp @@ -219,6 +248,7 @@ extern "C" #define BR_SUFFIX_HOST "-HIGHC3" #define BR_HAS_FAR 0 +#define MEMAVL 0 #define stricmp _stricmp @@ -237,6 +267,12 @@ extern "C" #define BR_HAS_FAR 0 +#define MEMAVL 0 + +#ifndef __H2INC__ +#pragma option -a4 +#endif + /* * IBM CSet++ */ @@ -251,6 +287,7 @@ extern "C" #define BR_SUFFIX_HOST "-CSET" #define BR_HAS_FAR 0 +#define MEMAVL 0 #endif @@ -290,13 +327,12 @@ extern "C" * Macros for producing banners & copyright messages */ #define BR_BANNER(title, year, revision) \ - do \ { \ static char _revision[] = revision; \ fprintf(stderr, title); \ fwrite(_revision + 10, 1, sizeof(_revision) - 12, stderr); \ fprintf(stderr, "Copyright (C) " year " by Argonaut Technologies Limited\n"); \ - } while (0); + } /* * Useful macro for sizing an array diff --git a/bren/inc/fixed.h b/bren/inc/fixed.h index 23e39333..76ab7e91 100644 --- a/bren/inc/fixed.h +++ b/bren/inc/fixed.h @@ -19,18 +19,18 @@ extern "C" /* * Fixed point types */ - typedef long br_fixed_ls; /* Long Signed fixed 15.16 */ - typedef short br_fixed_lsf; /* Long Signed fraction 0.15 */ + typedef br_int_32 br_fixed_ls; /* Long Signed fixed 15.16 */ + typedef br_int_16 br_fixed_lsf; /* Long Signed fraction 0.15 */ - typedef unsigned long br_fixed_lu; /* Long unsigned fixed 16.16 */ - typedef unsigned short br_fixed_luf; /* Long unsigned fixed fraction 0.16 */ + typedef br_uint_32 br_fixed_lu; /* Long unsigned fixed 16.16 */ + typedef br_uint_16 br_fixed_luf; /* Long unsigned fixed fraction 0.16 */ - typedef short br_fixed_ss; /* Short Signed fixed 7.8 */ + typedef br_int_16 br_fixed_ss; /* Short Signed fixed 7.8 */ - typedef char br_fixed_ssf; /* Short Signed fraction 0.7 */ + typedef br_int_8 br_fixed_ssf; /* Short Signed fraction 0.7 */ - typedef unsigned short br_fixed_su; /* Short unsigned fixed 8.8 */ - typedef unsigned char br_fixed_suf; /* Short unsigned fixed fraction 0.8 */ + typedef br_uint_16 br_fixed_su; /* Short unsigned fixed 8.8 */ + typedef br_uint_8 br_fixed_suf; /* Short unsigned fixed fraction 0.8 */ /* * 1 in various fixed point forms @@ -45,8 +45,8 @@ extern "C" #define BR_ONE_SU (1 << 8) #define BR_ONE_SUF (1 << 8) -#define BrIntToFixed(i) ((i) << 16) -#define BrFixedToInt(i) ((i) >> 16) +#define BrIntToFixed(i) (br_fixed_ls)((int)(i) << 16) +#define BrFixedToInt(i) (int)((br_fixed_ls)(i) >> 16) #define BrFloatToFixed(f) ((br_scalar)((f) * (float)BR_ONE_LS)) #define BrFixedToFloat(s) ((s) * (1.0 / (float)BR_ONE_LS)) diff --git a/bren/inc/fwproto.h b/bren/inc/fwproto.h index 5330af26..50f71f13 100644 --- a/bren/inc/fwproto.h +++ b/bren/inc/fwproto.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: fwproto.h 1.42 1995/06/30 16:08:49 sam Exp $ + * $Id: fwproto.h 1.44 1995/08/31 16:36:16 sam Exp $ * $Locker: sam $ * * Function prototypes for brender framework @@ -128,8 +128,8 @@ extern "C" /* result = a*b + c*d + e*f + g*h (a,c,e,g are fractions) */ - br_fixed_ls BR_ASM_CALL BrFixedFMac4(br_fixed_ls a, br_fixed_ls b, br_fixed_ls c, br_fixed_ls d, br_fixed_ls e, - br_fixed_ls f, br_fixed_ls g, br_fixed_ls h); + br_fixed_ls BR_ASM_CALL BrFixedFMac4(br_fixed_lsf a, br_fixed_ls b, br_fixed_lsf c, br_fixed_ls d, br_fixed_lsf e, + br_fixed_ls f, br_fixed_lsf g, br_fixed_ls h); /* * Misc. support functions @@ -341,6 +341,11 @@ extern "C" void BR_PUBLIC_ENTRY BrPixelmapDirtyRectangleFill(br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_16 w, br_uint_16 h, br_uint_32 colour); +/* + * Backwards compat. + */ +#define BrPixelmapDirtyRectangleClear BrPixelmapDirtyRectangleFill + void BR_PUBLIC_ENTRY BrPixelmapPixelSet(br_pixelmap *dst, br_int_16 x, br_int_16 y, br_uint_32 colour); br_uint_32 BR_PUBLIC_ENTRY BrPixelmapPixelGet(br_pixelmap *dst, br_int_16 x, br_int_16 y); void BR_PUBLIC_ENTRY BrPixelmapCopy(br_pixelmap *dst, br_pixelmap *src); @@ -358,7 +363,7 @@ extern "C" br_uint_16 BR_PUBLIC_ENTRY BrPixelmapTextWidth(br_pixelmap *dst, br_font *font, char *text); br_uint_16 BR_PUBLIC_ENTRY BrPixelmapTextHeight(br_pixelmap *dst, br_font *font); - void BR_PUBLIC_ENTRY BrPixelmapDoubleBuffer(br_pixelmap *dst, br_pixelmap *src); + br_pixelmap *BR_PUBLIC_ENTRY BrPixelmapDoubleBuffer(br_pixelmap *dst, br_pixelmap *src); /* * Backwards compatibility @@ -512,7 +517,7 @@ extern "C" /** ** 3D VECTORS **/ - void BR_PUBLIC_ENTRY BrVector3Copy(br_vector3 *v1, br_vector2 *v2); + void BR_PUBLIC_ENTRY BrVector3Copy(br_vector3 *v1, br_vector3 *v2); void BR_PUBLIC_ENTRY BrVector3Set(br_vector3 *v1, br_scalar s1, br_scalar s2, br_scalar s3); void BR_PUBLIC_ENTRY BrVector3SetInt(br_vector3 *v1, int i1, int i2, int i3); void BR_PUBLIC_ENTRY BrVector3SetFloat(br_vector3 *v1, float f1, float f2, float f3); diff --git a/bren/inc/model.h b/bren/inc/model.h index ca64cc31..1f46f501 100644 --- a/bren/inc/model.h +++ b/bren/inc/model.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: model.h 1.19 1995/05/25 13:37:34 sam Exp $ + * $Id: model.h 1.20 1995/08/31 16:36:18 sam Exp $ * $Locker: $ * * In-memory structures for models, both public and private areas @@ -83,8 +83,9 @@ extern "C" struct br_material; typedef void BR_CALLBACK br_model_custom_cbfn(struct br_actor *actor, struct br_model *model, - struct br_material *material, br_uint_8 style, int on_screen, - br_matrix34 *model_to_view, br_matrix4 *model_to_screen); + struct br_material *material, void *render_data, br_uint_8 style, + int on_screen, br_matrix34 *model_to_view, + br_matrix4 *model_to_screen); typedef struct br_model { diff --git a/bren/inc/order.h b/bren/inc/order.h new file mode 100644 index 00000000..b476236c --- /dev/null +++ b/bren/inc/order.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. + * + * $Id: order.h 1.1 1995/08/31 16:37:15 sam Exp $ + * $Locker: $ + * + * Definitons for an order table + */ +#ifndef _ORDER_H_ +#define _ORDER_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + enum + { + BR_ORDER_TABLE_NEW_BOUNDS = 0x0001, + }; + + typedef struct br_order_table + { + + /* + * Order table array + */ + void **table; + + /* + * Number of entries in array + */ + br_uint_32 ot_size; + + /* + * Next order table in list + */ + struct br_order_table *next; + + /* + * Order table bounds + */ + br_scalar min_z; + br_scalar max_z; + + /* + * Flags + */ + br_uint_32 flags; + + } br_order_table; + +#ifdef __cplusplus +}; +#endif +#endif + diff --git a/bren/inc/pixelmap.h b/bren/inc/pixelmap.h index 3ce71336..252d2a0e 100644 --- a/bren/inc/pixelmap.h +++ b/bren/inc/pixelmap.h @@ -1,8 +1,8 @@ /* * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: pixelmap.h 1.15 1995/06/30 16:08:58 sam Exp $ - * $Locker: sam $ + * $Id: pixelmap.h 1.17 1995/08/31 16:36:19 sam Exp $ + * $Locker: $ * * A stopgap 2D pixelmap structure for brender. This should really be the * pixelmap data type from the underlying 2D system (whatever that will @@ -71,7 +71,7 @@ extern "C" /* * Wrong way around 15 bit true colour */ - BR_PMT_BGR_555, + BR_PMT_BGR_555 }; /* diff --git a/bren/inc/poolmac.inc b/bren/inc/poolmac.inc new file mode 100644 index 00000000..d9224adc --- /dev/null +++ b/bren/inc/poolmac.inc @@ -0,0 +1,37 @@ +;; Copyright (c) 1992,1993 Argonaut Software Ltd. All rights reserved. +;; +;; $Id: poolmac.inc 1.2 1994/07/01 18:55:27 sam Exp $ +;; $Locker: $ +;; +;; ASM support for pool allcoation +;; + +; Allocate a block form the given pool, leaving the pointer in a given +; register. +; +; Trashes AX +; +BR_POOL_ALLOCATE macro reg,pool + local alloc_ok + + mov edi,pool.free + and edi,edi + jne alloc_ok + + push ecx + push ebx + push edx + push offset pool + call BrPoolAddChunk + add sp,4 + pop edx + pop ebx + pop ecx + + mov edi,pool.free + +alloc_ok: mov eax,[edi].br_pool_block.next + mov pool.free,eax + + endm + diff --git a/bren/inc/scalar.h b/bren/inc/scalar.h index a5d9d1f7..e175812f 100644 --- a/bren/inc/scalar.h +++ b/bren/inc/scalar.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: scalar.h 1.20 1995/05/25 13:37:37 sam Exp $ + * $Id: scalar.h 1.21 1995/08/31 16:36:20 sam Exp $ * $Locker: $ * * Scalar type @@ -96,6 +96,7 @@ extern "C" #define BR_SQR(a) BrFixedSqr(a) #define BR_ABS(a) BrFixedAbs(a) +#define BR_NEG(a) (-(a)) #define BR_DIV(a, b) BrFixedDiv(a, b) #define BR_DIVR(a, b) BrFixedDivR(a, b) @@ -203,12 +204,13 @@ extern "C" #define BR_MUL(a, b) ((a) * (b)) #define BR_SQR(a) ((a) * (a)) -#define BR_ABS(a) fabs(a) +#define BR_ABS(a) ((br_scalar)fabs(a)) +#define BR_NEG(a) (-(a)) #define BR_DIV(a, b) ((a) / (b)) #define BR_DIVR(a, b) ((a) / (b)) #define BR_MULDIV(a, b, c) ((a) * (b) / (c)) -#define BR_RCP(a) (1.0 / (a)) +#define BR_RCP(a) ((br_scalar)(1.0 / (a))) #define BR_CONST_MUL(a, b) ((a) * (b)) #define BR_CONST_DIV(a, b) ((a) / (b)) @@ -229,16 +231,16 @@ extern "C" #define BR_FMAC3(a, b, c, d, e, f) ((a) * (b) + (c) * (d) + (e) * (f)) #define BR_FMAC4(a, b, c, d, e, f, g, h) ((a) * (b) + (c) * (d) + (e) * (f) + (g) * (h)) -#define BR_LENGTH2(a, b) sqrt((a) * (a) + (b) * (b)) -#define BR_LENGTH3(a, b, c) sqrt((a) * (a) + (b) * (b) + (c) * (c)) -#define BR_LENGTH4(a, b, c, d) sqrt((a) * (a) + (b) * (b) + (c) * (c) + (d) * (d)) +#define BR_LENGTH2(a, b) ((br_scalar)sqrt((a) * (a) + (b) * (b))) +#define BR_LENGTH3(a, b, c) ((br_scalar)sqrt((a) * (a) + (b) * (b) + (c) * (c))) +#define BR_LENGTH4(a, b, c, d) ((br_scalar)sqrt((a) * (a) + (b) * (b) + (c) * (c) + (d) * (d))) -#define BR_RLENGTH2(a, b) (1.0 / sqrt((a) * (a) + (b) * (b))) -#define BR_RLENGTH3(a, b, c) (1.0 / sqrt((a) * (a) + (b) * (b) + (c) * (c))) -#define BR_RLENGTH4(a, b, c, d) (1.0 / sqrt((a) * (a) + (b) * (b) + (c) * (c) + (d) * (d))) +#define BR_RLENGTH2(a, b) ((br_scalar)(1.0 / sqrt((a) * (a) + (b) * (b)))) +#define BR_RLENGTH3(a, b, c) ((br_scalar)(1.0 / sqrt((a) * (a) + (b) * (b) + (c) * (c)))) +#define BR_RLENGTH4(a, b, c, d) ((br_scalar)(1.0 / sqrt((a) * (a) + (b) * (b) + (c) * (c) + (d) * (d)))) -#define BR_POW(a, b) pow((a), (b)) -#define BR_SQRT(a) sqrt(a) +#define BR_POW(a, b) ((br_scalar)pow((a), (b))) +#define BR_SQRT(a) ((br_scalar)sqrt(a)) #endif diff --git a/bren/inc/vecfns.h b/bren/inc/vecfns.h index feb9a60f..c8bd6bb5 100644 --- a/bren/inc/vecfns.h +++ b/bren/inc/vecfns.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1992,1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: vecfns.h 1.11 1995/06/30 16:09:04 sam Exp $ + * $Id: vecfns.h 1.12 1995/08/31 16:36:22 sam Exp $ * $Locker: $ * * Inline versions of the vector operations (could do compiler specific @@ -293,9 +293,9 @@ extern "C" } \ else \ { \ - (v1)->v[0] = BR_FRACTION(1.0); \ - (v1)->v[1] = BR_FRACTION(0.0); \ - (v1)->v[2] = BR_FRACTION(0.0); \ + (v1)->v[0] = BR_SCALAR(1.0); \ + (v1)->v[1] = BR_SCALAR(0.0); \ + (v1)->v[2] = BR_SCALAR(0.0); \ } \ } while (0) @@ -358,8 +358,8 @@ extern "C" } \ else \ { \ - (v1)->v[0] = BR_FRACTION(1.0); \ - (v1)->v[1] = BR_FRACTION(0.0); \ + (v1)->v[0] = BR_SCALAR(1.0); \ + (v1)->v[1] = BR_SCALAR(0.0); \ } \ } while (0) diff --git a/bren/inc/zbproto.h b/bren/inc/zbproto.h index 9f4513dc..9bf6242e 100644 --- a/bren/inc/zbproto.h +++ b/bren/inc/zbproto.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. * - * $Id: zbproto.h 1.8 1995/02/22 21:37:28 sam Exp $ + * $Id: zbproto.h 1.9 1995/08/31 16:36:24 sam Exp $ * $Locker: $ * * Function prototypes for Z buffer renderer @@ -24,7 +24,8 @@ extern "C" * rendered */ typedef void BR_CALLBACK br_renderbounds_cbfn(br_actor *actor, br_model *model, br_material *material, - br_uint_8 style, br_matrix4 *model_to_screen, br_int_32 bounds[4]); + void *render_data, br_uint_8 style, br_matrix4 *model_to_screen, + br_int_32 bounds[4]); #ifndef _NO_PROTOTYPES @@ -38,7 +39,7 @@ extern "C" void BR_PUBLIC_ENTRY BrZbSceneRenderEnd(void); /* - * Wrapper that inokes above therr calls in order + * Wrapper that invokes above three calls in order */ void BR_PUBLIC_ENTRY BrZbSceneRender(br_actor *world, br_actor *camera, br_pixelmap *colour_buffer, br_pixelmap *depth_buffer); @@ -56,3 +57,4 @@ extern "C" #endif #endif #endif + diff --git a/bren/inc/zsproto.h b/bren/inc/zsproto.h new file mode 100644 index 00000000..200801d6 --- /dev/null +++ b/bren/inc/zsproto.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1993-1995 by Argonaut Technologies Limited. All rights reserved. + * + * $Id: zsproto.h 1.1 1995/08/31 16:37:20 sam Exp $ + * $Locker: $ + * + * Function prototypes for bucket Z-sort renderer + */ +#ifndef _ZSPROTO_H_ +#define _ZSPROTO_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + * Sort types for primitive insertion + */ + enum + { + BR_ZSORT_MIN = 0x0001, + BR_ZSORT_MAX = 0x0002, + BR_ZSORT_AVERAGE = 0x0004, + }; + +#if 0 + +#define BR_BOUNDS_MIN_X 0 +#define BR_BOUNDS_MIN_Y 1 +#define BR_BOUNDS_MAX_X 2 +#define BR_BOUNDS_MAX_Y 3 + +/* + * Callback function invoked when an actor is + * rendered + */ +typedef void BR_CALLBACK br_renderbounds_cbfn( + br_actor *actor, + br_model *model, + br_material *material, + void *render_data, + br_uint_8 style, + br_matrix4 *model_to_screen, + br_int_32 bounds[4]); + +#endif + + /* + * Callback function invoked when primitive is generated + */ + typedef void BR_CALLBACK br_primitive_cbfn(void *primitive, br_actor *actor, br_model *model, br_material *material, + br_order_table *order_table, br_scalar z[3]); + +#ifndef _NO_PROTOTYPES + + void BR_PUBLIC_ENTRY BrZsBegin(br_uint_8 colour_type, void *primitive, br_uint_32 size); + void BR_PUBLIC_ENTRY BrZsEnd(void); + + void BR_PUBLIC_ENTRY BrZsSceneRenderBegin(br_actor *world, br_actor *camera, br_pixelmap *colour_buffer, + br_uint_8 db_index, br_uint_32 flags); + + void BR_PUBLIC_ENTRY BrZsSceneRenderAdd(br_actor *tree); + void BR_PUBLIC_ENTRY BrZsSceneRenderEnd(void); + + /* + * Wrapper that invokes above three calls in order + */ + void BR_PUBLIC_ENTRY BrZsSceneRender(br_actor *world, br_actor *camera, br_pixelmap *colour_buffer, + br_uint_8 db_index, br_uint_32 flags); + + /* + * Used within custom model callbacks to render other models + */ + void BR_PUBLIC_ENTRY BrZsModelRender(br_actor *actor, br_model *model, br_material *material, + br_order_table *order_table, br_uint_8 style, int on_screen, int use_custom); + + br_primitive_cbfn *BR_PUBLIC_ENTRY BrZsSetPrimitiveCallback(br_primitive_cbfn *new_cbfn); + + br_order_table *BR_PUBLIC_ENTRY BrZsSetActorOrderTable(br_actor *actor, br_order_table *order_table); + br_order_table *BR_PUBLIC_ENTRY BrZsGetActorOrderTable(br_actor *actor); + br_order_table *BR_PUBLIC_ENTRY BrZsGetDefaultOrderTable(void); + + void BR_PUBLIC_ENTRY BrZsClearOrderTable(br_order_table *order_table); + void BR_PUBLIC_ENTRY BrZsClearDefaultOrderTable(void); + +#ifdef __cplusplus +}; +#endif +#endif +#endif + diff --git a/inc/portf.h b/inc/portf.h index 8179f742..9b53d6b6 100644 --- a/inc/portf.h +++ b/inc/portf.h @@ -19,7 +19,7 @@ bool FPortGetFniOpen(FNI *pfni, LPTSTR lpstrFilter, LPTSTR lpstrTitle, FNI *pfni bool FPortGetFniSave(FNI *pfni, LPTSTR lpstrFilter, LPTSTR lpstrTitle, LPTSTR lpstrDefExt, PSTN pstnDefFileName, ulong grfPrevType, CNO cnoWave); -UINT CALLBACK OpenHookProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam); +UINT_PTR CALLBACK OpenHookProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); void OpenPreview(HWND hwnd, PGNV pgnvOff, RCS *prcsPreview); void RepaintPortfolio(HWND hwndCustom); diff --git a/inc/srec.h b/inc/srec.h index 169cb128..027224f2 100644 --- a/inc/srec.h +++ b/inc/srec.h @@ -111,7 +111,7 @@ class SREC : public SREC_PAR bool _FOpenRecord(); bool _FCloseRecord(); - static void _WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2); + static void CALLBACK _WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2); protected: bool _FInit(long csampSec, long cchan, long cbSample, ulong dtsMax); diff --git a/inc/tagman.h b/inc/tagman.h index 30045c68..19327f79 100644 --- a/inc/tagman.h +++ b/inc/tagman.h @@ -44,6 +44,10 @@ const long ksidInvalid = -1; // negative SIDs imply an invalid TAG const long sidNil = 0; const long ksidUseCrf = 0; // chunk is in ptag->pcrf +PCRF RefToPcrf(ulong ref); +ulong PcrfToRef(PCRF pcrf); +void ReleasePpoPcrfRef(ulong* ref); + typedef struct TAG *PTAG; struct TAG { @@ -54,7 +58,8 @@ struct TAG #endif // DEBUG long sid; // Source ID (or ksidUseCrf) - PCRF pcrf; // File to look in for this chunk if sid is ksidUseCrf + //PCRF pcrf; // File to look in for this chunk if sid is ksidUseCrf + ulong pcrfRef; // An 8-byte pointer cannot be stored here, so use a ulong reference instead. CTG ctg; // CTG of chunk CNO cno; // CNO of chunk }; diff --git a/kauai/src/appb.cpp b/kauai/src/appb.cpp index 5d386b18..d9fcd534 100644 --- a/kauai/src/appb.cpp +++ b/kauai/src/appb.cpp @@ -512,7 +512,7 @@ bool APPB::FEnableAppCmd(PCMD pcmd, ulong *pgrfeds) break; case cidChooseWnd: - if ((HWND)pcmd->rglw[0] == GOB::HwndMdiActive()) + if ((HWND)pcmd->rglp[0] == GOB::HwndMdiActive()) *pgrfeds |= fedsCheck; else *pgrfeds |= fedsUncheck; @@ -536,7 +536,7 @@ bool APPB::FCmdChooseWnd(PCMD pcmd) AssertThis(0); AssertVarMem(pcmd); - GOB::MakeHwndActive((HWND)pcmd->rglw[0]); + GOB::MakeHwndActive((HWND)pcmd->rglp[0]); return fTrue; } diff --git a/kauai/src/appbwin.cpp b/kauai/src/appbwin.cpp index 96ea2d28..47fd858e 100644 --- a/kauai/src/appbwin.cpp +++ b/kauai/src/appbwin.cpp @@ -436,17 +436,18 @@ bool APPB::_FFrameWndProc(HWND hwnd, uint wm, WPARAM wParam, LPARAM lw, long *pl pmmi = (MINMAXINFO *)lw; - *plwRet = DefFrameProc(hwnd, vwig.hwndClient, wm, wParam, (long)pmmi); + *plwRet = DefFrameProc(hwnd, vwig.hwndClient, wm, wParam, (LPARAM)pmmi); dypFrame = GetSystemMetrics(SM_CYFRAME); dypScreen = GetSystemMetrics(SM_CYSCREEN); dypExtra = 0; - FGetProp(kpridFullScreen, &lw); - if (lw) + long fullscreen = 0; + FGetProp(kpridFullScreen, &fullscreen); + if (fullscreen) dypExtra = GetSystemMetrics(SM_CYCAPTION); pmmi->ptMaxPosition.y = -dypFrame - dypExtra; pmmi->ptMaxSize.y = pmmi->ptMaxTrackSize.y = dypScreen + 2 * dypFrame + dypExtra; - _FCommonWndProc(hwnd, wm, wParam, (long)pmmi, &lw); + _FCommonWndProc(hwnd, wm, wParam, (LPARAM)pmmi, &fullscreen); } return fTrue; @@ -803,7 +804,7 @@ STN *_rgpstn[3]; /*************************************************************************** Dialog proc for assert. ***************************************************************************/ -BOOL CALLBACK _FDlgAssert(HWND hdlg, UINT msg, WPARAM w, LPARAM lw) +INT_PTR CALLBACK _FDlgAssert(HWND hdlg, UINT msg, WPARAM w, LPARAM lw) { switch (msg) { @@ -874,6 +875,7 @@ bool APPB::FAssertProcApp(PSZS pszsFile, long lwLine, PSZS pszsMsg, void *pv, lo stn1 = PszLit("Some Header file"); stn0.FFormatSz(psz, &stn1, lwLine, &stn2); +#ifdef IN_80386 // call stack - follow the EBP chain.... __asm { mov plw,ebp } for (ilw = 0; ilw < kclwChain; ilw++) @@ -889,6 +891,12 @@ bool APPB::FAssertProcApp(PSZS pszsFile, long lwLine, PSZS pszsMsg, void *pv, lo plw = (long *)*plw; } } +#else + for (ilw = 0; ilw < kclwChain; ilw++) + { + rglw[ilw] = 0; + } +#endif // !IN_80386 for (cact = 0; cact < 2; cact++) { diff --git a/kauai/src/base.cpp b/kauai/src/base.cpp index 12f45126..8d34af0f 100644 --- a/kauai/src/base.cpp +++ b/kauai/src/base.cpp @@ -227,6 +227,7 @@ void *BASE::operator new(size_t cb) long *plw; long ilw; +#ifdef IN_80386 __asm { mov plw,ebp } for (ilw = 0; ilw < kclwStackDoi; ilw++) { @@ -241,6 +242,12 @@ void *BASE::operator new(size_t cb) plw = (long *)*plw; } } +#else + for (ilw = 0; ilw < kclwStackDoi; ilw++) + { + pdoi->rglwStack[ilw] = 0; + } +#endif // !IN_80386 #endif // WIN // update statistics diff --git a/kauai/src/cmd.h b/kauai/src/cmd.h index aa8aca50..34c7562a 100644 --- a/kauai/src/cmd.h +++ b/kauai/src/cmd.h @@ -46,7 +46,11 @@ struct CMD PCMH pcmh; // the target of the command - may be nil long cid; // the command id PGG pgg; // additional parameters for the command - long rglw[kclwCmd]; // standard parameters + union + { + long rglw[kclwCmd]; // standard parameters + LONG_PTR rglp[kclwCmd]; // standard parameters (pointer sized) + }; }; typedef CMD *PCMD; diff --git a/kauai/src/codkauai.cpp b/kauai/src/codkauai.cpp index ec79ced3..c74102fe 100644 --- a/kauai/src/codkauai.cpp +++ b/kauai/src/codkauai.cpp @@ -473,6 +473,12 @@ bool KCDC::_FDecode(void *pvSrc, long cbSrc, void *pvDst, long cbDst, long *pcbD #else //! IN_80386 +#include "kcdc_c.h" + + *pcbDst = cbTot; + return fTrue; + +#if 0 // BROKEN; KEPT FOR REFERENCE long cb, dib, ibit, cbit; register ulong luCur; byte *pbT; @@ -560,6 +566,7 @@ bool KCDC::_FDecode(void *pvSrc, long cbSrc, void *pvDst, long cbDst, long *pcbD #undef _FTest #undef _Advance +#endif // 0 #endif //! IN_80386 @@ -835,6 +842,12 @@ bool KCDC::_FDecode2(void *pvSrc, long cbSrc, void *pvDst, long cbDst, long *pcb #else //! IN_80386 +#include "kcd2_c.h" + + *pcbDst = cbTot; + return fTrue; + +#if 0 // BROKEN; KEPT FOR REFERENCE long cb, dib, ibit, cbit; register ulong luCur; byte bT; @@ -936,6 +949,8 @@ bool KCDC::_FDecode2(void *pvSrc, long cbSrc, void *pvDst, long cbDst, long *pcb #undef _FTest #undef _Advance +#endif // 0 + #endif //! IN_80386 LFail: diff --git a/kauai/src/debug.h b/kauai/src/debug.h index 525efe2f..72802e6f 100644 --- a/kauai/src/debug.h +++ b/kauai/src/debug.h @@ -19,7 +19,7 @@ #ifdef WIN inline void Debugger(void) { - __asm { int 3 } + DebugBreak(); } #endif // WIN diff --git a/kauai/src/dlg.h b/kauai/src/dlg.h index 5fc17fd8..e135b2f8 100644 --- a/kauai/src/dlg.h +++ b/kauai/src/dlg.h @@ -61,7 +61,7 @@ class DLG : public DLG_PAR void *_pv; #ifdef WIN - friend BOOL CALLBACK _FDlgCore(HWND hdlg, UINT msg, WPARAM w, LPARAM lw); + friend INT_PTR CALLBACK _FDlgCore(HWND hdlg, UINT msg, WPARAM w, LPARAM lw); #endif // WIN DLG(long rid); diff --git a/kauai/src/dlgwin.cpp b/kauai/src/dlgwin.cpp index f33ec158..2a14e2c3 100644 --- a/kauai/src/dlgwin.cpp +++ b/kauai/src/dlgwin.cpp @@ -111,7 +111,7 @@ bool DLG::_FInit(void) for (csit = dtm.cdit, idit = 0; csit > 0; csit--) { // align to dword - if ((long)psw & 2) + if ((LONG_PTR)psw & 2) psw++; // get and skip the ditm @@ -238,7 +238,7 @@ bool DLG::_FInit(void) /*************************************************************************** Windows dialog proc. ***************************************************************************/ -BOOL CALLBACK _FDlgCore(HWND hdlg, UINT msg, WPARAM w, LPARAM lw) +INT_PTR CALLBACK _FDlgCore(HWND hdlg, UINT msg, WPARAM w, LPARAM lw) { PDLG pdlg; DIT dit; @@ -272,7 +272,7 @@ BOOL CALLBACK _FDlgCore(HWND hdlg, UINT msg, WPARAM w, LPARAM lw) goto LFail; // create a timer so we can do idle processing - if (SetTimer(hdlg, (uint)hdlg, 10, pvNil) == 0) + if (SetTimer(hdlg, (UINT_PTR)hdlg, 10, pvNil) == 0) goto LFail; // create a container gob and attach the hdlg @@ -361,7 +361,7 @@ BOOL CALLBACK _FDlgCore(HWND hdlg, UINT msg, WPARAM w, LPARAM lw) // remove the pdlg property and kill the timer RemoveProp(hdlg, _szDlgProp); - KillTimer(hdlg, (uint)hdlg); + KillTimer(hdlg, (UINT_PTR)hdlg); EndDialog(hdlg, idit); return fTrue; @@ -384,7 +384,7 @@ long DLG::IditDo(long iditFocus) dlgi.pdlg = this; dlgi.iditFocus = iditFocus; - idit = DialogBoxParam(vwig.hinst, MIR(_rid), vwig.hwndApp, &_FDlgCore, (long)&dlgi); + idit = DialogBoxParam(vwig.hinst, MIR(_rid), vwig.hwndApp, &_FDlgCore, (LPARAM)&dlgi); return idit; } diff --git a/kauai/src/gobwin.cpp b/kauai/src/gobwin.cpp index a910918a..eb56f7d9 100644 --- a/kauai/src/gobwin.cpp +++ b/kauai/src/gobwin.cpp @@ -131,7 +131,7 @@ HWND GOB::_HwndNewMdi(PSTN pstnTitle) hwnd = CreateMDIWindow(PszLit("MDI"), pstnTitle->Psz(), lwStyle, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, vwig.hwndClient, vwig.hinst, 0L); if (hNil != hwnd && pvNil != vpmubCur) - vpmubCur->FAddListCid(cidChooseWnd, (long)hwnd, pstnTitle); + vpmubCur->FAddListCid(cidChooseWnd, (LONG_PTR)hwnd, pstnTitle); return hwnd; } @@ -148,7 +148,7 @@ void GOB::_DestroyHwnd(HWND hwnd) if (GetParent(hwnd) == vwig.hwndClient && vwig.hwndClient != hNil) { if (pvNil != vpmubCur) - vpmubCur->FRemoveListCid(cidChooseWnd, (long)hwnd); + vpmubCur->FRemoveListCid(cidChooseWnd, (LONG_PTR)hwnd); SendMessage(vwig.hwndClient, WM_MDIDESTROY, (WPARAM)hwnd, 0); } else @@ -218,7 +218,7 @@ void GOB::SetHwndName(PSTN pstn) } if (pvNil != vpmubCur) { - vpmubCur->FChangeListCid(cidChooseWnd, (long)_hwnd, pvNil, (long)_hwnd, pstn); + vpmubCur->FChangeListCid(cidChooseWnd, (LONG_PTR)_hwnd, pvNil, (LONG_PTR)_hwnd, pstn); } SetWindowText(_hwnd, pstn->Psz()); } diff --git a/kauai/src/kcd2_c.c b/kauai/src/kcd2_c.c new file mode 100644 index 00000000..55771086 --- /dev/null +++ b/kauai/src/kcd2_c.c @@ -0,0 +1,392 @@ +/* Copyright (c) Microsoft Corporation. + Licensed under the MIT License. */ + +/*************************************************************************** +This c file is compiled to a command-line exe which when run produces +the 80386 asm version of the KCD2 decompression code. + +Register usage: + eax: source bytes + ebx: source address + edi: destination address + edx: working space + ecx: for rep movsb + esi: for rep movsb +***************************************************************************/ +#include +#include +#include +#include +#include "codkpri.h" + +const int kcbitMinMoveByDword = 3; + +const bool fFalse = 0; +const bool fTrue = 1; +static FILE *output = NULL; + +void Setup(void); +void End(void); +void Advance(long cb); +void Test(long ibit); +void Block(long ibit); +void Literal(long ibit, bool fSingle); +void Offset(long ibit, long cbit, long cbitOH, long dibBase, long cbBase); +void Copy(long ibit); + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + fprintf(stderr, "usage: %s ", argv[0]); + return EXIT_FAILURE; + } + + output = fopen(argv[1], "w"); + if (output == NULL) + { + fprintf(stderr, "could not open %s", argv[1]); + return EXIT_FAILURE; + } + + long ibit; + + Setup(); + + for (ibit = 0; ibit < 8; ibit++) + { + Literal(ibit, fTrue); + Literal(ibit, fFalse); + Offset(ibit, kcbitKcd2_0, 2, kdibMinKcd2_0, 1); + Offset(ibit, kcbitKcd2_1, 3, kdibMinKcd2_1, 1); + Offset(ibit, kcbitKcd2_2, 4, kdibMinKcd2_2, 1); + Offset(ibit, kcbitKcd2_3, 4, kdibMinKcd2_3, 2); + Copy(ibit); + Block(ibit); + } + + End(); + return 0; +} + +void Setup(void) +{ + // fprintf(output, " // Setup\n" + // " long cbTot;\n" + // " byte *pbLimDst = (byte *)pvDst + cbDst;\n" + // " byte *pbLimSrc = (byte *)pvSrc + cbSrc - kcbTailKcd2;\n\n" + // "__asm\n" + // " {\n" + // " mov edi,pvDst\n" + // " mov ebx,pvSrc\n" + // " inc ebx\n"); + + fprintf(output, "// clang-format off\n" + " // Setup\n" + " long cbTot;\n" + " byte *pbLimDst = (byte *)pvDst + cbDst;\n" + " byte *pbLimSrc = (byte *)pvSrc + cbSrc - kcbTailKcd2;\n\n" + " ulong eax = 0;\n" + " byte *ebx = 0;\n" + " ulong ecx = 0;\n" + " ulong edx = 0;\n" + " byte *edi = 0;\n" + " byte *esi = 0;\n" + " ulong esi_u = 0;\n" + " bool tst = false;\n\n" + " edi = (byte*)pvDst;\n" + " ebx = (byte*)pvSrc + 1;\n"); + + Advance(4); + + // fprintf(output, " jmp LBlock0\n"); + fprintf(output, " goto LBlock0;\n"); +} + +void Copy(long ibit) +{ + fprintf(output, "\n // Copy Byte %d\nLCopyByte%d:\n", ibit, ibit); + + // fprintf(output, "#ifdef SAFETY\n" + // " push edx\n" + // " lea edx,[edi+ecx]\n" + // " cmp edx,pbLimDst\n" + // " pop edx\n" + // " ja LFail\n" + // "#endif //SAFETY\n"); + fprintf(output, "#ifdef SAFETY\n" + " if ((edi + ecx) > pbLimDst) goto LFail;\n" + "#endif //SAFETY\n"); + + // fprintf(output, " neg esi\n" + // " add esi,edi\n"); + fprintf(output, " esi = edi - esi_u;\n"); + + // fprintf(output, "#ifdef SAFETY\n" + // " cmp esi,pvDst\n" + // " jb LFail\n" + // "#endif //SAFETY\n"); + fprintf(output, "#ifdef SAFETY\n" + " if (esi < pvDst) goto LFail;\n" + "#endif //SAFETY\n"); + + // if (fDword) + // { + // fprintf(output, " mov edx,ecx\n" + // " shr ecx,2\n" + // " and edx,3\n" + // " rep movsd\n" + // " mov ecx,edx\n" + // " rep movsb\n"); + // } + // else + // fprintf(output, " rep movsb\n"); + fprintf(output, " for (; ecx > 0; ecx--) *edi++ = *esi++;\n"); +} + +void End(void) +{ + // fprintf(output, "\nLDone:\n" + // " sub edi,pvDst\n" + // " mov cbTot,edi\n" + // " }\n\n"); + fprintf(output, "\nLDone:\n" + " cbTot = edi - pvDst;\n" + "// clang-format on\n\n"); +} + +void Advance(long cb) +{ + switch (cb) + { + case 0: + break; + case 1: + // fprintf(output, " mov eax,[ebx-3]\n" + // " inc ebx\n"); + fprintf(output, " eax = *(ulong*)(ebx - 3);\n" + " ebx++;\n"); + break; + case 2: + // fprintf(output, " mov eax,[ebx-2]\n" + // " add ebx,2\n"); + fprintf(output, " eax = *(ulong*)(ebx - 2);\n" + " ebx += 2;\n"); + break; + case 3: + // fprintf(output, " mov eax,[ebx-1]\n" + // " add ebx,3\n"); + fprintf(output, " eax = *(ulong*)(ebx - 1);\n" + " ebx += 3;\n"); + break; + case 4: + // fprintf(output, " mov eax,[ebx]\n" + // " add ebx,4\n"); + fprintf(output, " eax = *(ulong*)ebx;\n" + " ebx += 4;\n"); + break; + default: + fprintf(output, "*** BUG\n"); + break; + } +} + +void Test(long ibit) +{ + fprintf(output, " tst = eax & %d;\n", 1 << ibit); +} + +void Block(long ibit) +{ + long cbit, ibitT; + + fprintf(output, "\n // Block %d\n", ibit); + fprintf(output, "LBlock%d:\n", ibit); + + for (cbit = 0; cbit <= kcbitMaxLenKcd2; cbit++) + { + Test(ibit + cbit); + // fprintf(output, " jz LLen%d_%d\n", ibit, cbit); + fprintf(output, " if (!tst) goto LLen%d_%d;\n", ibit, cbit); + } + // fprintf(output, " jmp LDone\n"); + fprintf(output, " goto LDone;\n"); + + for (cbit = 0; cbit <= kcbitMaxLenKcd2; cbit++) + { + fprintf(output, "LLen%d_%d:\n", ibit, cbit); + if (cbit == 0) + // fprintf(output, " mov ecx,1\n"); + fprintf(output, " ecx = 1;\n"); + else + { + // fprintf(output, " mov ecx,eax\n"); + // fprintf(output, " shr ecx,%d\n", ibit + cbit + 1); + // fprintf(output, " and ecx,%d\n", (1 << cbit) - 1); + // fprintf(output, " or ecx,%d\n", (1 << cbit)); + fprintf(output, " ecx = ((eax >> %d) & %d) | %d;\n", ibit + cbit + 1, (1 << cbit) - 1, (1 << cbit)); + } + + ibitT = ibit + cbit + cbit + 1; + Advance(ibitT / 8); + ibitT &= 0x07; + Test(ibitT); + if (cbit == 0) + // fprintf(output, " jz LLitSingle%d\n", ibitT); + fprintf(output, " if (!tst) goto LLitSingle%d;\n", ibitT); + else + // fprintf(output, " jz LLitByte%d\n", ibitT); + fprintf(output, " if (!tst) goto LLitByte%d;\n", ibitT); + + Test(ibitT + 1); + // fprintf(output, " jz L%dBitOffByte%d\n", kcbitKcd2_0, ibitT); + fprintf(output, " if (!tst) goto L%dBitOffByte%d;\n", kcbitKcd2_0, ibitT); + Test(ibitT + 2); + // fprintf(output, " jz L%dBitOffByte%d\n", kcbitKcd2_1, ibitT); + fprintf(output, " if (!tst) goto L%dBitOffByte%d;\n", kcbitKcd2_1, ibitT); + Test(ibitT + 3); + // fprintf(output, " jz L%dBitOffByte%d\n", kcbitKcdc2, ibitT); + // fprintf(output, " jmp L%dBitOffByte%d\n", kcbitKcdc3, ibitT); + fprintf(output, " if (!tst) goto L%dBitOffByte%d;\n", kcbitKcdc2, ibitT); + fprintf(output, " goto L%dBitOffByte%d;\n", kcbitKcdc3, ibitT); + } +} + +void Offset(long ibit, long cbit, long cbitOH, long dibBase, long cbBase) +{ + ibit = (ibit - cbit - cbitOH) & 0x07; + fprintf(output, "\nL%dBitOffByte%d:\n", cbit, ibit); + + // fprintf(output, " mov esi,eax\n"); + fprintf(output, " esi_u = ((eax >> %d) & %d) + %d;\n", ibit + cbitOH, (1 << cbit) - 1, dibBase); + // if (cbBase == 1) + // fprintf(output, " inc ecx\n"); + // else + // fprintf(output, " add ecx,%d\n", cbBase); + fprintf(output, " ecx += %d;\n", cbBase); + // fprintf(output, " shr esi,%d\n", ibit + cbitOH); + // fprintf(output, " and esi,%d\n", (1 << cbit) - 1); + // if (1 == dibBase) + // fprintf(output, " inc esi\n"); + // else + // fprintf(output, " add esi,%d\n", dibBase); + + ibit += cbitOH + cbit; + Advance(ibit / 8); + ibit &= 0x07; + + fprintf(output, " goto LCopyByte%d;\n", ibit); +} + +void Literal(long ibit, bool fSingle) +{ + ibit = (ibit - 1) & 0x07; + if (fSingle) + fprintf(output, "\nLLitSingle%d:\n", ibit); + else + fprintf(output, "\nLLitByte%d:\n", ibit); + + ibit++; + if (fSingle) + { + // fprintf(output, "#ifdef SAFETY\n" + // " cmp edi,pbLimDst\n" + // " jae LFail\n" + // "#endif //SAFETY\n"); + fprintf(output, "#ifdef SAFETY\n" + " if (edi >= pbLimDst) goto LFail;\n" + "#endif //SAFETY\n"); + + if (ibit == 8) + { + // fprintf(output, " mov [edi],ah\n" + // " inc edi\n"); + fprintf(output, " *edi++ = eax >> 8;\n"); + } + else + { + // fprintf(output, + // " mov edx,eax\n" + // " shr edx,%d\n" + // " mov [edi],dl\n" + // " inc edi\n", + // ibit); + fprintf(output, " *edi++ = eax >> %d;\n", ibit); + } + + ibit += 8; + Advance(ibit / 8); + // fprintf(output, " jmp LBlock%d\n", ibit & 0x07); + fprintf(output, " goto LBlock%d;\n", ibit & 0x07); + return; + } + + // fprintf(output, "#ifdef SAFETY\n" + // " lea edx,[edi+ecx]\n" + // " cmp edx,pbLimDst\n" + // " ja LFail\n" + // "#endif //SAFETY\n"); + fprintf(output, "#ifdef SAFETY\n" + " if ((edi + ecx) > pbLimDst) goto LFail;\n" + "#endif //SAFETY\n"); + + if (ibit != 8) + { + // get the low bits of the last byte + // fprintf(output, " dec ecx\n"); + // fprintf(output, " mov edx,eax\n"); + // fprintf(output, " shr edx,%d\n", ibit); + // fprintf(output, " and edx,%d\n", (1 << (8 - ibit)) - 1); + fprintf(output, " ecx--;\n"); + fprintf(output, " edx = (eax >> %d) & %d;\n", ibit, (1 << (8 - ibit)) - 1); + } + + // fprintf(output, "#ifdef SAFETY\n" + // " lea esi,[ebx-3+ecx]\n" + // " cmp esi,pbLimSrc\n" + // " ja LFail\n" + // " sub esi,ecx\n" + // "#else //!SAFETY\n" + // " lea esi,[ebx-3]\n" + // "#endif //!SAFETY\n"); + fprintf(output, "#ifdef SAFETY\n" + " esi = ebx - 3 + ecx;\n" + " if (esi > pbLimSrc) goto LFail;\n" + " esi -= ecx;\n" + "#else //!SAFETY\n" + " esi = ebx - 3;\n" + "#endif //!SAFETY\n"); + + // if (fDword) + // { + // fprintf(output, " mov eax,ecx\n" + // " shr ecx,2\n" + // " and eax,3\n" + // " rep movsd\n" + // " mov ecx,eax\n" + // " rep movsb\n"); + // } + // else + // fprintf(output, " rep movsb\n"); + fprintf(output, " for (; ecx > 0; ecx--) *edi++ = *esi++;\n"); + + // fprintf(output, " lea ebx,[esi+4]\n" + // " mov eax,[esi]\n"); + fprintf(output, " ebx = esi + 4;\n" + " eax = *(ulong*)esi;\n"); + + if (ibit != 8) + { + // fprintf(output, " mov esi,eax\n"); + // fprintf(output, " shl esi,%d\n", 8 - ibit); + // fprintf(output, " or edx,esi\n" + // " mov [edi],dl\n" + // " inc edi\n"); + fprintf(output, " esi_u = eax << %d;\n", 8 - ibit); + fprintf(output, " edx |= esi_u;\n" + " *edi++ = edx;\n"); + } + + // fprintf(output, " jmp LBlock%d\n", ibit & 0x07); + fprintf(output, " goto LBlock%d;\n", ibit & 0x07); +} diff --git a/kauai/src/kcd2_c.h b/kauai/src/kcd2_c.h new file mode 100644 index 00000000..ee59ce83 --- /dev/null +++ b/kauai/src/kcd2_c.h @@ -0,0 +1,2012 @@ +// clang-format off + // Setup + long cbTot; + byte *pbLimDst = (byte *)pvDst + cbDst; + byte *pbLimSrc = (byte *)pvSrc + cbSrc - kcbTailKcd2; + + ulong eax = 0; + byte *ebx = 0; + ulong ecx = 0; + ulong edx = 0; + byte *edi = 0; + byte *esi = 0; + ulong esi_u = 0; + bool tst = false; + + edi = (byte*)pvDst; + ebx = (byte*)pvSrc + 1; + eax = *(ulong*)ebx; + ebx += 4; + goto LBlock0; + +LLitSingle7: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 8; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LBlock0; + +LLitByte7: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY +#ifdef SAFETY + esi = ebx - 3 + ecx; + if (esi > pbLimSrc) goto LFail; + esi -= ecx; +#else //!SAFETY + esi = ebx - 3; +#endif //!SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + ebx = esi + 4; + eax = *(ulong*)esi; + goto LBlock0; + +L6BitOffByte0: + esi_u = ((eax >> 2) & 63) + 1; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte0; + +L9BitOffByte4: + esi_u = ((eax >> 7) & 511) + 65; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte0; + +L12BitOffByte0: + esi_u = ((eax >> 4) & 4095) + 577; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte0; + +L20BitOffByte0: + esi_u = ((eax >> 4) & 1048575) + 4673; + ecx += 2; + eax = *(ulong*)(ebx - 1); + ebx += 3; + goto LCopyByte0; + + // Copy Byte 0 +LCopyByte0: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 0 +LBlock0: + tst = eax & 1; + if (!tst) goto LLen0_0; + tst = eax & 2; + if (!tst) goto LLen0_1; + tst = eax & 4; + if (!tst) goto LLen0_2; + tst = eax & 8; + if (!tst) goto LLen0_3; + tst = eax & 16; + if (!tst) goto LLen0_4; + tst = eax & 32; + if (!tst) goto LLen0_5; + tst = eax & 64; + if (!tst) goto LLen0_6; + tst = eax & 128; + if (!tst) goto LLen0_7; + tst = eax & 256; + if (!tst) goto LLen0_8; + tst = eax & 512; + if (!tst) goto LLen0_9; + tst = eax & 1024; + if (!tst) goto LLen0_10; + tst = eax & 2048; + if (!tst) goto LLen0_11; + goto LDone; +LLen0_0: + ecx = 1; + tst = eax & 2; + if (!tst) goto LLitSingle1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; +LLen0_1: + ecx = ((eax >> 2) & 1) | 2; + tst = eax & 8; + if (!tst) goto LLitByte3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; +LLen0_2: + ecx = ((eax >> 3) & 3) | 4; + tst = eax & 32; + if (!tst) goto LLitByte5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; +LLen0_3: + ecx = ((eax >> 4) & 7) | 8; + tst = eax & 128; + if (!tst) goto LLitByte7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; +LLen0_4: + ecx = ((eax >> 5) & 15) | 16; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 2; + if (!tst) goto LLitByte1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; +LLen0_5: + ecx = ((eax >> 6) & 31) | 32; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 8; + if (!tst) goto LLitByte3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; +LLen0_6: + ecx = ((eax >> 7) & 63) | 64; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 32; + if (!tst) goto LLitByte5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; +LLen0_7: + ecx = ((eax >> 8) & 127) | 128; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 128; + if (!tst) goto LLitByte7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; +LLen0_8: + ecx = ((eax >> 9) & 255) | 256; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 2; + if (!tst) goto LLitByte1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; +LLen0_9: + ecx = ((eax >> 10) & 511) | 512; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 8; + if (!tst) goto LLitByte3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; +LLen0_10: + ecx = ((eax >> 11) & 1023) | 1024; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 32; + if (!tst) goto LLitByte5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; +LLen0_11: + ecx = ((eax >> 12) & 2047) | 2048; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 128; + if (!tst) goto LLitByte7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; + +LLitSingle0: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock1; + +LLitByte0: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + ecx--; + edx = (eax >> 1) & 127; +#ifdef SAFETY + esi = ebx - 3 + ecx; + if (esi > pbLimSrc) goto LFail; + esi -= ecx; +#else //!SAFETY + esi = ebx - 3; +#endif //!SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + ebx = esi + 4; + eax = *(ulong*)esi; + esi_u = eax << 7; + edx |= esi_u; + *edi++ = edx; + goto LBlock1; + +L6BitOffByte1: + esi_u = ((eax >> 3) & 63) + 1; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte1; + +L9BitOffByte5: + esi_u = ((eax >> 8) & 511) + 65; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte1; + +L12BitOffByte1: + esi_u = ((eax >> 5) & 4095) + 577; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte1; + +L20BitOffByte1: + esi_u = ((eax >> 5) & 1048575) + 4673; + ecx += 2; + eax = *(ulong*)(ebx - 1); + ebx += 3; + goto LCopyByte1; + + // Copy Byte 1 +LCopyByte1: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 1 +LBlock1: + tst = eax & 2; + if (!tst) goto LLen1_0; + tst = eax & 4; + if (!tst) goto LLen1_1; + tst = eax & 8; + if (!tst) goto LLen1_2; + tst = eax & 16; + if (!tst) goto LLen1_3; + tst = eax & 32; + if (!tst) goto LLen1_4; + tst = eax & 64; + if (!tst) goto LLen1_5; + tst = eax & 128; + if (!tst) goto LLen1_6; + tst = eax & 256; + if (!tst) goto LLen1_7; + tst = eax & 512; + if (!tst) goto LLen1_8; + tst = eax & 1024; + if (!tst) goto LLen1_9; + tst = eax & 2048; + if (!tst) goto LLen1_10; + tst = eax & 4096; + if (!tst) goto LLen1_11; + goto LDone; +LLen1_0: + ecx = 1; + tst = eax & 4; + if (!tst) goto LLitSingle2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; +LLen1_1: + ecx = ((eax >> 3) & 1) | 2; + tst = eax & 16; + if (!tst) goto LLitByte4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; +LLen1_2: + ecx = ((eax >> 4) & 3) | 4; + tst = eax & 64; + if (!tst) goto LLitByte6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; +LLen1_3: + ecx = ((eax >> 5) & 7) | 8; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 1; + if (!tst) goto LLitByte0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; +LLen1_4: + ecx = ((eax >> 6) & 15) | 16; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 4; + if (!tst) goto LLitByte2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; +LLen1_5: + ecx = ((eax >> 7) & 31) | 32; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 16; + if (!tst) goto LLitByte4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; +LLen1_6: + ecx = ((eax >> 8) & 63) | 64; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 64; + if (!tst) goto LLitByte6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; +LLen1_7: + ecx = ((eax >> 9) & 127) | 128; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 1; + if (!tst) goto LLitByte0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; +LLen1_8: + ecx = ((eax >> 10) & 255) | 256; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 4; + if (!tst) goto LLitByte2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; +LLen1_9: + ecx = ((eax >> 11) & 511) | 512; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 16; + if (!tst) goto LLitByte4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; +LLen1_10: + ecx = ((eax >> 12) & 1023) | 1024; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 64; + if (!tst) goto LLitByte6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; +LLen1_11: + ecx = ((eax >> 13) & 2047) | 2048; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 1; + if (!tst) goto LLitByte0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; + +LLitSingle1: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 2; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock2; + +LLitByte1: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + ecx--; + edx = (eax >> 2) & 63; +#ifdef SAFETY + esi = ebx - 3 + ecx; + if (esi > pbLimSrc) goto LFail; + esi -= ecx; +#else //!SAFETY + esi = ebx - 3; +#endif //!SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + ebx = esi + 4; + eax = *(ulong*)esi; + esi_u = eax << 6; + edx |= esi_u; + *edi++ = edx; + goto LBlock2; + +L6BitOffByte2: + esi_u = ((eax >> 4) & 63) + 1; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte2; + +L9BitOffByte6: + esi_u = ((eax >> 9) & 511) + 65; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte2; + +L12BitOffByte2: + esi_u = ((eax >> 6) & 4095) + 577; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte2; + +L20BitOffByte2: + esi_u = ((eax >> 6) & 1048575) + 4673; + ecx += 2; + eax = *(ulong*)(ebx - 1); + ebx += 3; + goto LCopyByte2; + + // Copy Byte 2 +LCopyByte2: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 2 +LBlock2: + tst = eax & 4; + if (!tst) goto LLen2_0; + tst = eax & 8; + if (!tst) goto LLen2_1; + tst = eax & 16; + if (!tst) goto LLen2_2; + tst = eax & 32; + if (!tst) goto LLen2_3; + tst = eax & 64; + if (!tst) goto LLen2_4; + tst = eax & 128; + if (!tst) goto LLen2_5; + tst = eax & 256; + if (!tst) goto LLen2_6; + tst = eax & 512; + if (!tst) goto LLen2_7; + tst = eax & 1024; + if (!tst) goto LLen2_8; + tst = eax & 2048; + if (!tst) goto LLen2_9; + tst = eax & 4096; + if (!tst) goto LLen2_10; + tst = eax & 8192; + if (!tst) goto LLen2_11; + goto LDone; +LLen2_0: + ecx = 1; + tst = eax & 8; + if (!tst) goto LLitSingle3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; +LLen2_1: + ecx = ((eax >> 4) & 1) | 2; + tst = eax & 32; + if (!tst) goto LLitByte5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; +LLen2_2: + ecx = ((eax >> 5) & 3) | 4; + tst = eax & 128; + if (!tst) goto LLitByte7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; +LLen2_3: + ecx = ((eax >> 6) & 7) | 8; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 2; + if (!tst) goto LLitByte1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; +LLen2_4: + ecx = ((eax >> 7) & 15) | 16; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 8; + if (!tst) goto LLitByte3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; +LLen2_5: + ecx = ((eax >> 8) & 31) | 32; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 32; + if (!tst) goto LLitByte5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; +LLen2_6: + ecx = ((eax >> 9) & 63) | 64; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 128; + if (!tst) goto LLitByte7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; +LLen2_7: + ecx = ((eax >> 10) & 127) | 128; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 2; + if (!tst) goto LLitByte1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; +LLen2_8: + ecx = ((eax >> 11) & 255) | 256; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 8; + if (!tst) goto LLitByte3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; +LLen2_9: + ecx = ((eax >> 12) & 511) | 512; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 32; + if (!tst) goto LLitByte5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; +LLen2_10: + ecx = ((eax >> 13) & 1023) | 1024; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 128; + if (!tst) goto LLitByte7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; +LLen2_11: + ecx = ((eax >> 14) & 2047) | 2048; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 2; + if (!tst) goto LLitByte1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; + +LLitSingle2: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 3; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock3; + +LLitByte2: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + ecx--; + edx = (eax >> 3) & 31; +#ifdef SAFETY + esi = ebx - 3 + ecx; + if (esi > pbLimSrc) goto LFail; + esi -= ecx; +#else //!SAFETY + esi = ebx - 3; +#endif //!SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + ebx = esi + 4; + eax = *(ulong*)esi; + esi_u = eax << 5; + edx |= esi_u; + *edi++ = edx; + goto LBlock3; + +L6BitOffByte3: + esi_u = ((eax >> 5) & 63) + 1; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte3; + +L9BitOffByte7: + esi_u = ((eax >> 10) & 511) + 65; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte3; + +L12BitOffByte3: + esi_u = ((eax >> 7) & 4095) + 577; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte3; + +L20BitOffByte3: + esi_u = ((eax >> 7) & 1048575) + 4673; + ecx += 2; + eax = *(ulong*)(ebx - 1); + ebx += 3; + goto LCopyByte3; + + // Copy Byte 3 +LCopyByte3: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 3 +LBlock3: + tst = eax & 8; + if (!tst) goto LLen3_0; + tst = eax & 16; + if (!tst) goto LLen3_1; + tst = eax & 32; + if (!tst) goto LLen3_2; + tst = eax & 64; + if (!tst) goto LLen3_3; + tst = eax & 128; + if (!tst) goto LLen3_4; + tst = eax & 256; + if (!tst) goto LLen3_5; + tst = eax & 512; + if (!tst) goto LLen3_6; + tst = eax & 1024; + if (!tst) goto LLen3_7; + tst = eax & 2048; + if (!tst) goto LLen3_8; + tst = eax & 4096; + if (!tst) goto LLen3_9; + tst = eax & 8192; + if (!tst) goto LLen3_10; + tst = eax & 16384; + if (!tst) goto LLen3_11; + goto LDone; +LLen3_0: + ecx = 1; + tst = eax & 16; + if (!tst) goto LLitSingle4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; +LLen3_1: + ecx = ((eax >> 5) & 1) | 2; + tst = eax & 64; + if (!tst) goto LLitByte6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; +LLen3_2: + ecx = ((eax >> 6) & 3) | 4; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 1; + if (!tst) goto LLitByte0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; +LLen3_3: + ecx = ((eax >> 7) & 7) | 8; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 4; + if (!tst) goto LLitByte2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; +LLen3_4: + ecx = ((eax >> 8) & 15) | 16; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 16; + if (!tst) goto LLitByte4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; +LLen3_5: + ecx = ((eax >> 9) & 31) | 32; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 64; + if (!tst) goto LLitByte6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; +LLen3_6: + ecx = ((eax >> 10) & 63) | 64; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 1; + if (!tst) goto LLitByte0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; +LLen3_7: + ecx = ((eax >> 11) & 127) | 128; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 4; + if (!tst) goto LLitByte2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; +LLen3_8: + ecx = ((eax >> 12) & 255) | 256; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 16; + if (!tst) goto LLitByte4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; +LLen3_9: + ecx = ((eax >> 13) & 511) | 512; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 64; + if (!tst) goto LLitByte6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; +LLen3_10: + ecx = ((eax >> 14) & 1023) | 1024; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 1; + if (!tst) goto LLitByte0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; +LLen3_11: + ecx = ((eax >> 15) & 2047) | 2048; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 4; + if (!tst) goto LLitByte2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; + +LLitSingle3: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 4; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock4; + +LLitByte3: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + ecx--; + edx = (eax >> 4) & 15; +#ifdef SAFETY + esi = ebx - 3 + ecx; + if (esi > pbLimSrc) goto LFail; + esi -= ecx; +#else //!SAFETY + esi = ebx - 3; +#endif //!SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + ebx = esi + 4; + eax = *(ulong*)esi; + esi_u = eax << 4; + edx |= esi_u; + *edi++ = edx; + goto LBlock4; + +L6BitOffByte4: + esi_u = ((eax >> 6) & 63) + 1; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte4; + +L9BitOffByte0: + esi_u = ((eax >> 3) & 511) + 65; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte4; + +L12BitOffByte4: + esi_u = ((eax >> 8) & 4095) + 577; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte4; + +L20BitOffByte4: + esi_u = ((eax >> 8) & 1048575) + 4673; + ecx += 2; + eax = *(ulong*)(ebx - 1); + ebx += 3; + goto LCopyByte4; + + // Copy Byte 4 +LCopyByte4: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 4 +LBlock4: + tst = eax & 16; + if (!tst) goto LLen4_0; + tst = eax & 32; + if (!tst) goto LLen4_1; + tst = eax & 64; + if (!tst) goto LLen4_2; + tst = eax & 128; + if (!tst) goto LLen4_3; + tst = eax & 256; + if (!tst) goto LLen4_4; + tst = eax & 512; + if (!tst) goto LLen4_5; + tst = eax & 1024; + if (!tst) goto LLen4_6; + tst = eax & 2048; + if (!tst) goto LLen4_7; + tst = eax & 4096; + if (!tst) goto LLen4_8; + tst = eax & 8192; + if (!tst) goto LLen4_9; + tst = eax & 16384; + if (!tst) goto LLen4_10; + tst = eax & 32768; + if (!tst) goto LLen4_11; + goto LDone; +LLen4_0: + ecx = 1; + tst = eax & 32; + if (!tst) goto LLitSingle5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; +LLen4_1: + ecx = ((eax >> 6) & 1) | 2; + tst = eax & 128; + if (!tst) goto LLitByte7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; +LLen4_2: + ecx = ((eax >> 7) & 3) | 4; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 2; + if (!tst) goto LLitByte1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; +LLen4_3: + ecx = ((eax >> 8) & 7) | 8; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 8; + if (!tst) goto LLitByte3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; +LLen4_4: + ecx = ((eax >> 9) & 15) | 16; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 32; + if (!tst) goto LLitByte5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; +LLen4_5: + ecx = ((eax >> 10) & 31) | 32; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 128; + if (!tst) goto LLitByte7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; +LLen4_6: + ecx = ((eax >> 11) & 63) | 64; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 2; + if (!tst) goto LLitByte1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; +LLen4_7: + ecx = ((eax >> 12) & 127) | 128; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 8; + if (!tst) goto LLitByte3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; +LLen4_8: + ecx = ((eax >> 13) & 255) | 256; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 32; + if (!tst) goto LLitByte5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; +LLen4_9: + ecx = ((eax >> 14) & 511) | 512; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 128; + if (!tst) goto LLitByte7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; +LLen4_10: + ecx = ((eax >> 15) & 1023) | 1024; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 2; + if (!tst) goto LLitByte1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; +LLen4_11: + ecx = ((eax >> 16) & 2047) | 2048; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 8; + if (!tst) goto LLitByte3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; + +LLitSingle4: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 5; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock5; + +LLitByte4: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + ecx--; + edx = (eax >> 5) & 7; +#ifdef SAFETY + esi = ebx - 3 + ecx; + if (esi > pbLimSrc) goto LFail; + esi -= ecx; +#else //!SAFETY + esi = ebx - 3; +#endif //!SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + ebx = esi + 4; + eax = *(ulong*)esi; + esi_u = eax << 3; + edx |= esi_u; + *edi++ = edx; + goto LBlock5; + +L6BitOffByte5: + esi_u = ((eax >> 7) & 63) + 1; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte5; + +L9BitOffByte1: + esi_u = ((eax >> 4) & 511) + 65; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte5; + +L12BitOffByte5: + esi_u = ((eax >> 9) & 4095) + 577; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte5; + +L20BitOffByte5: + esi_u = ((eax >> 9) & 1048575) + 4673; + ecx += 2; + eax = *(ulong*)(ebx - 1); + ebx += 3; + goto LCopyByte5; + + // Copy Byte 5 +LCopyByte5: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 5 +LBlock5: + tst = eax & 32; + if (!tst) goto LLen5_0; + tst = eax & 64; + if (!tst) goto LLen5_1; + tst = eax & 128; + if (!tst) goto LLen5_2; + tst = eax & 256; + if (!tst) goto LLen5_3; + tst = eax & 512; + if (!tst) goto LLen5_4; + tst = eax & 1024; + if (!tst) goto LLen5_5; + tst = eax & 2048; + if (!tst) goto LLen5_6; + tst = eax & 4096; + if (!tst) goto LLen5_7; + tst = eax & 8192; + if (!tst) goto LLen5_8; + tst = eax & 16384; + if (!tst) goto LLen5_9; + tst = eax & 32768; + if (!tst) goto LLen5_10; + tst = eax & 65536; + if (!tst) goto LLen5_11; + goto LDone; +LLen5_0: + ecx = 1; + tst = eax & 64; + if (!tst) goto LLitSingle6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; +LLen5_1: + ecx = ((eax >> 7) & 1) | 2; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 1; + if (!tst) goto LLitByte0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; +LLen5_2: + ecx = ((eax >> 8) & 3) | 4; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 4; + if (!tst) goto LLitByte2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; +LLen5_3: + ecx = ((eax >> 9) & 7) | 8; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 16; + if (!tst) goto LLitByte4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; +LLen5_4: + ecx = ((eax >> 10) & 15) | 16; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 64; + if (!tst) goto LLitByte6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; +LLen5_5: + ecx = ((eax >> 11) & 31) | 32; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 1; + if (!tst) goto LLitByte0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; +LLen5_6: + ecx = ((eax >> 12) & 63) | 64; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 4; + if (!tst) goto LLitByte2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; +LLen5_7: + ecx = ((eax >> 13) & 127) | 128; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 16; + if (!tst) goto LLitByte4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; +LLen5_8: + ecx = ((eax >> 14) & 255) | 256; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 64; + if (!tst) goto LLitByte6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; +LLen5_9: + ecx = ((eax >> 15) & 511) | 512; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 1; + if (!tst) goto LLitByte0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; +LLen5_10: + ecx = ((eax >> 16) & 1023) | 1024; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 4; + if (!tst) goto LLitByte2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; +LLen5_11: + ecx = ((eax >> 17) & 2047) | 2048; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 16; + if (!tst) goto LLitByte4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; + +LLitSingle5: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 6; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock6; + +LLitByte5: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + ecx--; + edx = (eax >> 6) & 3; +#ifdef SAFETY + esi = ebx - 3 + ecx; + if (esi > pbLimSrc) goto LFail; + esi -= ecx; +#else //!SAFETY + esi = ebx - 3; +#endif //!SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + ebx = esi + 4; + eax = *(ulong*)esi; + esi_u = eax << 2; + edx |= esi_u; + *edi++ = edx; + goto LBlock6; + +L6BitOffByte6: + esi_u = ((eax >> 8) & 63) + 1; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte6; + +L9BitOffByte2: + esi_u = ((eax >> 5) & 511) + 65; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte6; + +L12BitOffByte6: + esi_u = ((eax >> 10) & 4095) + 577; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte6; + +L20BitOffByte6: + esi_u = ((eax >> 10) & 1048575) + 4673; + ecx += 2; + eax = *(ulong*)(ebx - 1); + ebx += 3; + goto LCopyByte6; + + // Copy Byte 6 +LCopyByte6: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 6 +LBlock6: + tst = eax & 64; + if (!tst) goto LLen6_0; + tst = eax & 128; + if (!tst) goto LLen6_1; + tst = eax & 256; + if (!tst) goto LLen6_2; + tst = eax & 512; + if (!tst) goto LLen6_3; + tst = eax & 1024; + if (!tst) goto LLen6_4; + tst = eax & 2048; + if (!tst) goto LLen6_5; + tst = eax & 4096; + if (!tst) goto LLen6_6; + tst = eax & 8192; + if (!tst) goto LLen6_7; + tst = eax & 16384; + if (!tst) goto LLen6_8; + tst = eax & 32768; + if (!tst) goto LLen6_9; + tst = eax & 65536; + if (!tst) goto LLen6_10; + tst = eax & 131072; + if (!tst) goto LLen6_11; + goto LDone; +LLen6_0: + ecx = 1; + tst = eax & 128; + if (!tst) goto LLitSingle7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; +LLen6_1: + ecx = ((eax >> 8) & 1) | 2; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 2; + if (!tst) goto LLitByte1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; +LLen6_2: + ecx = ((eax >> 9) & 3) | 4; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 8; + if (!tst) goto LLitByte3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; +LLen6_3: + ecx = ((eax >> 10) & 7) | 8; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 32; + if (!tst) goto LLitByte5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; +LLen6_4: + ecx = ((eax >> 11) & 15) | 16; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 128; + if (!tst) goto LLitByte7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; +LLen6_5: + ecx = ((eax >> 12) & 31) | 32; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 2; + if (!tst) goto LLitByte1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; +LLen6_6: + ecx = ((eax >> 13) & 63) | 64; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 8; + if (!tst) goto LLitByte3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; +LLen6_7: + ecx = ((eax >> 14) & 127) | 128; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 32; + if (!tst) goto LLitByte5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; +LLen6_8: + ecx = ((eax >> 15) & 255) | 256; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 128; + if (!tst) goto LLitByte7; + tst = eax & 256; + if (!tst) goto L6BitOffByte7; + tst = eax & 512; + if (!tst) goto L9BitOffByte7; + tst = eax & 1024; + if (!tst) goto L12BitOffByte7; + goto L20BitOffByte7; +LLen6_9: + ecx = ((eax >> 16) & 511) | 512; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 2; + if (!tst) goto LLitByte1; + tst = eax & 4; + if (!tst) goto L6BitOffByte1; + tst = eax & 8; + if (!tst) goto L9BitOffByte1; + tst = eax & 16; + if (!tst) goto L12BitOffByte1; + goto L20BitOffByte1; +LLen6_10: + ecx = ((eax >> 17) & 1023) | 1024; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 8; + if (!tst) goto LLitByte3; + tst = eax & 16; + if (!tst) goto L6BitOffByte3; + tst = eax & 32; + if (!tst) goto L9BitOffByte3; + tst = eax & 64; + if (!tst) goto L12BitOffByte3; + goto L20BitOffByte3; +LLen6_11: + ecx = ((eax >> 18) & 2047) | 2048; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 32; + if (!tst) goto LLitByte5; + tst = eax & 64; + if (!tst) goto L6BitOffByte5; + tst = eax & 128; + if (!tst) goto L9BitOffByte5; + tst = eax & 256; + if (!tst) goto L12BitOffByte5; + goto L20BitOffByte5; + +LLitSingle6: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 7; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock7; + +LLitByte6: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + ecx--; + edx = (eax >> 7) & 1; +#ifdef SAFETY + esi = ebx - 3 + ecx; + if (esi > pbLimSrc) goto LFail; + esi -= ecx; +#else //!SAFETY + esi = ebx - 3; +#endif //!SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + ebx = esi + 4; + eax = *(ulong*)esi; + esi_u = eax << 1; + edx |= esi_u; + *edi++ = edx; + goto LBlock7; + +L6BitOffByte7: + esi_u = ((eax >> 9) & 63) + 1; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte7; + +L9BitOffByte3: + esi_u = ((eax >> 6) & 511) + 65; + ecx += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LCopyByte7; + +L12BitOffByte7: + esi_u = ((eax >> 11) & 4095) + 577; + ecx += 1; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LCopyByte7; + +L20BitOffByte7: + esi_u = ((eax >> 11) & 1048575) + 4673; + ecx += 2; + eax = *(ulong*)(ebx - 1); + ebx += 3; + goto LCopyByte7; + + // Copy Byte 7 +LCopyByte7: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 7 +LBlock7: + tst = eax & 128; + if (!tst) goto LLen7_0; + tst = eax & 256; + if (!tst) goto LLen7_1; + tst = eax & 512; + if (!tst) goto LLen7_2; + tst = eax & 1024; + if (!tst) goto LLen7_3; + tst = eax & 2048; + if (!tst) goto LLen7_4; + tst = eax & 4096; + if (!tst) goto LLen7_5; + tst = eax & 8192; + if (!tst) goto LLen7_6; + tst = eax & 16384; + if (!tst) goto LLen7_7; + tst = eax & 32768; + if (!tst) goto LLen7_8; + tst = eax & 65536; + if (!tst) goto LLen7_9; + tst = eax & 131072; + if (!tst) goto LLen7_10; + tst = eax & 262144; + if (!tst) goto LLen7_11; + goto LDone; +LLen7_0: + ecx = 1; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 1; + if (!tst) goto LLitSingle0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; +LLen7_1: + ecx = ((eax >> 9) & 1) | 2; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 4; + if (!tst) goto LLitByte2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; +LLen7_2: + ecx = ((eax >> 10) & 3) | 4; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 16; + if (!tst) goto LLitByte4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; +LLen7_3: + ecx = ((eax >> 11) & 7) | 8; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 64; + if (!tst) goto LLitByte6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; +LLen7_4: + ecx = ((eax >> 12) & 15) | 16; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 1; + if (!tst) goto LLitByte0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; +LLen7_5: + ecx = ((eax >> 13) & 31) | 32; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 4; + if (!tst) goto LLitByte2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; +LLen7_6: + ecx = ((eax >> 14) & 63) | 64; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 16; + if (!tst) goto LLitByte4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; +LLen7_7: + ecx = ((eax >> 15) & 127) | 128; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 64; + if (!tst) goto LLitByte6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; +LLen7_8: + ecx = ((eax >> 16) & 255) | 256; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 1; + if (!tst) goto LLitByte0; + tst = eax & 2; + if (!tst) goto L6BitOffByte0; + tst = eax & 4; + if (!tst) goto L9BitOffByte0; + tst = eax & 8; + if (!tst) goto L12BitOffByte0; + goto L20BitOffByte0; +LLen7_9: + ecx = ((eax >> 17) & 511) | 512; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 4; + if (!tst) goto LLitByte2; + tst = eax & 8; + if (!tst) goto L6BitOffByte2; + tst = eax & 16; + if (!tst) goto L9BitOffByte2; + tst = eax & 32; + if (!tst) goto L12BitOffByte2; + goto L20BitOffByte2; +LLen7_10: + ecx = ((eax >> 18) & 1023) | 1024; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 16; + if (!tst) goto LLitByte4; + tst = eax & 32; + if (!tst) goto L6BitOffByte4; + tst = eax & 64; + if (!tst) goto L9BitOffByte4; + tst = eax & 128; + if (!tst) goto L12BitOffByte4; + goto L20BitOffByte4; +LLen7_11: + ecx = ((eax >> 19) & 2047) | 2048; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 64; + if (!tst) goto LLitByte6; + tst = eax & 128; + if (!tst) goto L6BitOffByte6; + tst = eax & 256; + if (!tst) goto L9BitOffByte6; + tst = eax & 512; + if (!tst) goto L12BitOffByte6; + goto L20BitOffByte6; + +LDone: + cbTot = edi - pvDst; +// clang-format on + diff --git a/kauai/src/kcdc_c.c b/kauai/src/kcdc_c.c new file mode 100644 index 00000000..83e0d20b --- /dev/null +++ b/kauai/src/kcdc_c.c @@ -0,0 +1,315 @@ +/* Copyright (c) Microsoft Corporation. + Licensed under the MIT License. */ + +/*************************************************************************** +This c file is compiled to a command-line exe which when run produces +the 80386 asm version of the KCDC decompression code. + +Register usage: + eax: source bytes + ebx: source address + edi: destination address + edx: working space + ecx: for rep movsb + esi: for rep movsb +***************************************************************************/ +#include +#include +#include +#include +#include "codkpri.h" + +const int kcbitMinMoveByDword = 3; + +const bool fFalse = 0; +const bool fTrue = 1; +static FILE *output = NULL; + +void Setup(void); +void End(void); +void Advance(long cb); +void Test(long ibit); +void Block(long ibit); +void Literal(long ibit); +void Offset(long ibit, long cbit, long dibBase, long cbBase); +void GetLen(long ibit); +void CallCopy(long ibit, long cbit); +void Copy(long ibit); + +int main(int argc, char *argv[]) +{ + if (argc != 2) + { + fprintf(stderr, "usage: %s ", argv[0]); + return EXIT_FAILURE; + } + output = fopen(argv[1], "w"); + if (output == NULL) + { + fprintf(stderr, "could not open %s", argv[1]); + return EXIT_FAILURE; + } + + long ibit; + + Setup(); + + for (ibit = 0; ibit < 8; ibit++) + { + Copy(ibit); + Block(ibit); + } + + End(); + return 0; +} + +void Setup(void) +{ + // fprintf(output, " // Setup\n" + // " long cbTot;\n" + // " byte *pbLimDst = (byte *)pvDst + cbDst;\n\n" + // "__asm\n" + // " {\n" + // " mov edi,pvDst\n" + // " mov ebx,pvSrc\n" + // " inc ebx\n"); + fprintf(output, "// clang-format off\n" + " // Setup\n" + " long cbTot;\n" + " byte *pbLimDst = (byte *)pvDst + cbDst;\n" + " ulong eax = 0;\n" + " byte *ebx = 0;\n" + " ulong ecx = 0;\n" + " ulong edx = 0;\n" + " byte *edi = 0;\n" + " byte *esi = 0;\n" + " ulong esi_u = 0;\n" + " bool tst = false;\n" + " edi = (byte*)pvDst;\n" + " ebx = (byte*)pvSrc + 1;\n"); + + Advance(4); + + // fprintf(output, " jmp LBlock0\n"); + fprintf(output, " goto LBlock0;\n"); +} + +void Copy(long ibit) +{ + fprintf(output, "\n // Copy Byte %d\nLCopyByte%d:\n", ibit, ibit); + + // fprintf(output, "#ifdef SAFETY\n" + // " push edx\n" + // " lea edx,[edi+ecx]\n" + // " cmp edx,pbLimDst\n" + // " pop edx\n" + // " ja LFail\n" + // "#endif //SAFETY\n"); + fprintf(output, "#ifdef SAFETY\n" + " if ((edi + ecx) > pbLimDst) goto LFail;\n" + "#endif //SAFETY\n"); + + // fprintf(output, " neg esi\n" + // " add esi,edi\n"); + fprintf(output, " esi = edi - esi_u;\n"); + + // fprintf(output, "#ifdef SAFETY\n" + // " cmp esi,pvDst\n" + // " jb LFail\n" + // "#endif //SAFETY\n"); + fprintf(output, "#ifdef SAFETY\n" + " if (esi < pvDst) goto LFail;\n" + "#endif //SAFETY\n"); + + // if (fDword) + // { + // fprintf(output, " mov edx,ecx\n" + // " shr ecx,2\n" + // " and edx,3\n" + // " rep movsd\n" + // " mov ecx,edx\n" + // " rep movsb\n"); + // } + // else + // fprintf(output, " rep movsb\n"); + fprintf(output, " for (; ecx > 0; ecx--) *edi++ = *esi++;\n"); +} + +void End(void) +{ + // fprintf(output, "\nLDone:\n" + // " sub edi,pvDst\n" + // " mov cbTot,edi\n" + // " }\n\n"); + fprintf(output, "\nLDone:\n" + " cbTot = edi - pvDst;\n" + "// clang-format on\n\n"); +} + +void Advance(long cb) +{ + switch (cb) + { + case 0: + break; + case 1: + // fprintf(output, " mov eax,[ebx-3]\n" + // " inc ebx\n"); + fprintf(output, " eax = *(ulong*)(ebx - 3);\n" + " ebx++;\n"); + break; + case 2: + // fprintf(output, " mov eax,[ebx-2]\n" + // " add ebx,2\n"); + fprintf(output, " eax = *(ulong*)(ebx - 2);\n" + " ebx += 2;\n"); + break; + case 3: + // fprintf(output, " mov eax,[ebx-1]\n" + // " add ebx,3\n"); + fprintf(output, " eax = *(ulong*)(ebx - 1);\n" + " ebx += 3;\n"); + break; + case 4: + // fprintf(output, " mov eax,[ebx]\n" + // " add ebx,4\n"); + fprintf(output, " eax = *(ulong*)ebx;\n" + " ebx += 4;\n"); + break; + default: + fprintf(output, "*** BUG\n"); + break; + } +} + +void Test(long ibit) +{ + fprintf(output, " tst = eax & %d;\n", 1 << ibit); +} + +void Block(long ibit) +{ + fprintf(output, "\n // Block %d\n", ibit); + fprintf(output, "LBlock%d:\n", ibit); + + Test(ibit); + // fprintf(output, " jz LLiteral%d\n", ibit + 1); + fprintf(output, " if (!tst) goto LLiteral%d;\n", ibit + 1); + Test(ibit + 1); + // fprintf(output, " jz L%dBit%d\n", kcbitKcdc0, ibit + 2); + fprintf(output, " if (!tst) goto L%dBit%d;\n", kcbitKcdc0, ibit + 2); + Test(ibit + 2); + // fprintf(output, " jz L%dBit%d\n", kcbitKcdc1, ibit + 3); + fprintf(output, " if (!tst) goto L%dBit%d;\n", kcbitKcdc1, ibit + 3); + Test(ibit + 3); + // fprintf(output, " jz L%dBit%d\n", kcbitKcdc2, ibit + 4); + fprintf(output, " if (!tst) goto L%dBit%d;\n", kcbitKcdc2, ibit + 4); + // fprintf(output, " jmp L%dBit%d\n", kcbitKcdc3, ibit + 4); + fprintf(output, " goto L%dBit%d;\n", kcbitKcdc3, ibit + 4); + + Literal(ibit + 1); + Offset(ibit + 2, kcbitKcdc0, kdibMinKcdc0, 2); + Offset(ibit + 3, kcbitKcdc1, kdibMinKcdc1, 2); + Offset(ibit + 4, kcbitKcdc2, kdibMinKcdc2, 2); + Offset(ibit + 4, kcbitKcdc3, kdibMinKcdc3, 3); +} + +void Literal(long ibit) +{ + fprintf(output, "\n // Literal %d\n", ibit); + fprintf(output, "LLiteral%d:\n", ibit); + + // fprintf(output, "#ifdef SAFETY\n" + // " cmp edi,pbLimDst\n" + // " jae LFail\n" + // "#endif //SAFETY\n"); + fprintf(output, "#ifdef SAFETY\n" + " if (edi >= pbLimDst) goto LFail;\n" + "#endif //SAFETY\n"); + + // fprintf(output, + // " mov edx,eax\n" + // " shr edx,%d\n" + // " mov [edi],dl\n" + // " inc edi\n", + // ibit); + fprintf(output, " *edi++ = eax >> %d;\n", ibit); + + ibit += 8; + Advance(ibit / 8); + // fprintf(output, " jmp LBlock%d\n", ibit & 0x07); + fprintf(output, " goto LBlock%d;\n", ibit & 0x07); +} + +void Offset(long ibit, long cbit, long dibBase, long cbBase) +{ + fprintf(output, "\nL%dBit%d:\n", cbit, ibit); + + // fprintf(output, " mov esi,eax\n"); + // fprintf(output, " mov ecx,%d\n", cbBase); + // fprintf(output, " shr esi,%d\n", ibit); + // fprintf(output, " and esi,%d\n", (1 << cbit) - 1); + fprintf(output, " esi_u = (eax >> %d) & %d;\n", ibit, (1 << cbit) - 1); + fprintf(output, " ecx = %d;\n", cbBase); + + if (kcbitKcdc3 == cbit) + { + // Put in the test for being done + // fprintf(output, " cmp esi,%d\n", (1 << cbit) - 1); + // fprintf(output, " je LDone\n"); + fprintf(output, " if (esi_u == %d) goto LDone;\n", (1 << cbit) - 1); + } + + // if (1 == dibBase) + // fprintf(output, " inc esi\n"); + // else + // fprintf(output, " add esi,%d\n", dibBase); + fprintf(output, " esi_u += %d;\n", dibBase); + + ibit += cbit; + Advance(ibit / 8); + ibit &= 0x07; + + GetLen(ibit); +} + +void GetLen(long ibit) +{ + static long _cactCall = 0; + long cbit; + + _cactCall++; + for (cbit = 0; cbit <= kcbitMaxLenKcdc; cbit++) + { + Test(ibit + cbit); + // fprintf(output, " jz LLen%d_%d\n", _cactCall, cbit); + fprintf(output, " if (!tst) goto LLen%d_%d;\n", _cactCall, cbit); + } + // fprintf(output, " jmp LFail\n"); + fprintf(output, " goto LFail;\n"); + + for (cbit = 0; cbit <= kcbitMaxLenKcdc; cbit++) + { + fprintf(output, "LLen%d_%d:\n", _cactCall, cbit); + if (cbit > 0) + { + // fprintf(output, " mov edx,eax\n"); + // fprintf(output, " shr edx,%d\n", ibit + cbit + 1); + // fprintf(output, " add ecx,%d\n", (1 << cbit) - 1); + // fprintf(output, " and edx,%d\n", (1 << cbit) - 1); + // fprintf(output, " add ecx,edx\n"); + fprintf(output, " edx = (eax >> %d) & %d;\n", ibit + cbit + 1, (1 << cbit) - 1); + fprintf(output, " ecx += %d + edx;\n", (1 << cbit) - 1); + } + CallCopy(ibit + cbit + cbit + 1, cbit); + } +} + +void CallCopy(long ibit, long cbit) +{ + Advance(ibit / 8); + ibit &= 0x07; + + fprintf(output, "goto LCopyByte%d\n;", ibit); +} diff --git a/kauai/src/kcdc_c.h b/kauai/src/kcdc_c.h new file mode 100644 index 00000000..4b042b77 --- /dev/null +++ b/kauai/src/kcdc_c.h @@ -0,0 +1,3430 @@ +// clang-format off + // Setup + long cbTot; + byte *pbLimDst = (byte *)pvDst + cbDst; + ulong eax = 0; + byte *ebx = 0; + ulong ecx = 0; + ulong edx = 0; + byte *edi = 0; + byte *esi = 0; + ulong esi_u = 0; + bool tst = false; + edi = (byte*)pvDst; + ebx = (byte*)pvSrc + 1; + eax = *(ulong*)ebx; + ebx += 4; + goto LBlock0; + + // Copy Byte 0 +LCopyByte0: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 0 +LBlock0: + tst = eax & 1; + if (!tst) goto LLiteral1; + tst = eax & 2; + if (!tst) goto L6Bit2; + tst = eax & 4; + if (!tst) goto L9Bit3; + tst = eax & 8; + if (!tst) goto L12Bit4; + goto L20Bit4; + + // Literal 1 +LLiteral1: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 1; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock1; + +L6Bit2: + esi_u = (eax >> 2) & 63; + ecx = 2; + esi_u += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 1; + if (!tst) goto LLen1_0; + tst = eax & 2; + if (!tst) goto LLen1_1; + tst = eax & 4; + if (!tst) goto LLen1_2; + tst = eax & 8; + if (!tst) goto LLen1_3; + tst = eax & 16; + if (!tst) goto LLen1_4; + tst = eax & 32; + if (!tst) goto LLen1_5; + tst = eax & 64; + if (!tst) goto LLen1_6; + tst = eax & 128; + if (!tst) goto LLen1_7; + tst = eax & 256; + if (!tst) goto LLen1_8; + tst = eax & 512; + if (!tst) goto LLen1_9; + tst = eax & 1024; + if (!tst) goto LLen1_10; + tst = eax & 2048; + if (!tst) goto LLen1_11; + goto LFail; +LLen1_0: +goto LCopyByte1 +;LLen1_1: + edx = (eax >> 2) & 1; + ecx += 1 + edx; +goto LCopyByte3 +;LLen1_2: + edx = (eax >> 3) & 3; + ecx += 3 + edx; +goto LCopyByte5 +;LLen1_3: + edx = (eax >> 4) & 7; + ecx += 7 + edx; +goto LCopyByte7 +;LLen1_4: + edx = (eax >> 5) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen1_5: + edx = (eax >> 6) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen1_6: + edx = (eax >> 7) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen1_7: + edx = (eax >> 8) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen1_8: + edx = (eax >> 9) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen1_9: + edx = (eax >> 10) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen1_10: + edx = (eax >> 11) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen1_11: + edx = (eax >> 12) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +; +L9Bit3: + esi_u = (eax >> 3) & 511; + ecx = 2; + esi_u += 65; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 16; + if (!tst) goto LLen2_0; + tst = eax & 32; + if (!tst) goto LLen2_1; + tst = eax & 64; + if (!tst) goto LLen2_2; + tst = eax & 128; + if (!tst) goto LLen2_3; + tst = eax & 256; + if (!tst) goto LLen2_4; + tst = eax & 512; + if (!tst) goto LLen2_5; + tst = eax & 1024; + if (!tst) goto LLen2_6; + tst = eax & 2048; + if (!tst) goto LLen2_7; + tst = eax & 4096; + if (!tst) goto LLen2_8; + tst = eax & 8192; + if (!tst) goto LLen2_9; + tst = eax & 16384; + if (!tst) goto LLen2_10; + tst = eax & 32768; + if (!tst) goto LLen2_11; + goto LFail; +LLen2_0: +goto LCopyByte5 +;LLen2_1: + edx = (eax >> 6) & 1; + ecx += 1 + edx; +goto LCopyByte7 +;LLen2_2: + edx = (eax >> 7) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen2_3: + edx = (eax >> 8) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen2_4: + edx = (eax >> 9) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen2_5: + edx = (eax >> 10) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen2_6: + edx = (eax >> 11) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen2_7: + edx = (eax >> 12) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen2_8: + edx = (eax >> 13) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen2_9: + edx = (eax >> 14) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen2_10: + edx = (eax >> 15) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +;LLen2_11: + edx = (eax >> 16) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte3 +; +L12Bit4: + esi_u = (eax >> 4) & 4095; + ecx = 2; + esi_u += 577; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 1; + if (!tst) goto LLen3_0; + tst = eax & 2; + if (!tst) goto LLen3_1; + tst = eax & 4; + if (!tst) goto LLen3_2; + tst = eax & 8; + if (!tst) goto LLen3_3; + tst = eax & 16; + if (!tst) goto LLen3_4; + tst = eax & 32; + if (!tst) goto LLen3_5; + tst = eax & 64; + if (!tst) goto LLen3_6; + tst = eax & 128; + if (!tst) goto LLen3_7; + tst = eax & 256; + if (!tst) goto LLen3_8; + tst = eax & 512; + if (!tst) goto LLen3_9; + tst = eax & 1024; + if (!tst) goto LLen3_10; + tst = eax & 2048; + if (!tst) goto LLen3_11; + goto LFail; +LLen3_0: +goto LCopyByte1 +;LLen3_1: + edx = (eax >> 2) & 1; + ecx += 1 + edx; +goto LCopyByte3 +;LLen3_2: + edx = (eax >> 3) & 3; + ecx += 3 + edx; +goto LCopyByte5 +;LLen3_3: + edx = (eax >> 4) & 7; + ecx += 7 + edx; +goto LCopyByte7 +;LLen3_4: + edx = (eax >> 5) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen3_5: + edx = (eax >> 6) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen3_6: + edx = (eax >> 7) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen3_7: + edx = (eax >> 8) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen3_8: + edx = (eax >> 9) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen3_9: + edx = (eax >> 10) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen3_10: + edx = (eax >> 11) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen3_11: + edx = (eax >> 12) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +; +L20Bit4: + esi_u = (eax >> 4) & 1048575; + ecx = 3; + if (esi_u == 1048575) goto LDone; + esi_u += 4673; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 1; + if (!tst) goto LLen4_0; + tst = eax & 2; + if (!tst) goto LLen4_1; + tst = eax & 4; + if (!tst) goto LLen4_2; + tst = eax & 8; + if (!tst) goto LLen4_3; + tst = eax & 16; + if (!tst) goto LLen4_4; + tst = eax & 32; + if (!tst) goto LLen4_5; + tst = eax & 64; + if (!tst) goto LLen4_6; + tst = eax & 128; + if (!tst) goto LLen4_7; + tst = eax & 256; + if (!tst) goto LLen4_8; + tst = eax & 512; + if (!tst) goto LLen4_9; + tst = eax & 1024; + if (!tst) goto LLen4_10; + tst = eax & 2048; + if (!tst) goto LLen4_11; + goto LFail; +LLen4_0: +goto LCopyByte1 +;LLen4_1: + edx = (eax >> 2) & 1; + ecx += 1 + edx; +goto LCopyByte3 +;LLen4_2: + edx = (eax >> 3) & 3; + ecx += 3 + edx; +goto LCopyByte5 +;LLen4_3: + edx = (eax >> 4) & 7; + ecx += 7 + edx; +goto LCopyByte7 +;LLen4_4: + edx = (eax >> 5) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen4_5: + edx = (eax >> 6) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen4_6: + edx = (eax >> 7) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen4_7: + edx = (eax >> 8) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen4_8: + edx = (eax >> 9) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen4_9: + edx = (eax >> 10) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen4_10: + edx = (eax >> 11) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen4_11: + edx = (eax >> 12) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +; + // Copy Byte 1 +LCopyByte1: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 1 +LBlock1: + tst = eax & 2; + if (!tst) goto LLiteral2; + tst = eax & 4; + if (!tst) goto L6Bit3; + tst = eax & 8; + if (!tst) goto L9Bit4; + tst = eax & 16; + if (!tst) goto L12Bit5; + goto L20Bit5; + + // Literal 2 +LLiteral2: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 2; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock2; + +L6Bit3: + esi_u = (eax >> 3) & 63; + ecx = 2; + esi_u += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 2; + if (!tst) goto LLen5_0; + tst = eax & 4; + if (!tst) goto LLen5_1; + tst = eax & 8; + if (!tst) goto LLen5_2; + tst = eax & 16; + if (!tst) goto LLen5_3; + tst = eax & 32; + if (!tst) goto LLen5_4; + tst = eax & 64; + if (!tst) goto LLen5_5; + tst = eax & 128; + if (!tst) goto LLen5_6; + tst = eax & 256; + if (!tst) goto LLen5_7; + tst = eax & 512; + if (!tst) goto LLen5_8; + tst = eax & 1024; + if (!tst) goto LLen5_9; + tst = eax & 2048; + if (!tst) goto LLen5_10; + tst = eax & 4096; + if (!tst) goto LLen5_11; + goto LFail; +LLen5_0: +goto LCopyByte2 +;LLen5_1: + edx = (eax >> 3) & 1; + ecx += 1 + edx; +goto LCopyByte4 +;LLen5_2: + edx = (eax >> 4) & 3; + ecx += 3 + edx; +goto LCopyByte6 +;LLen5_3: + edx = (eax >> 5) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen5_4: + edx = (eax >> 6) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen5_5: + edx = (eax >> 7) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen5_6: + edx = (eax >> 8) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen5_7: + edx = (eax >> 9) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen5_8: + edx = (eax >> 10) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen5_9: + edx = (eax >> 11) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen5_10: + edx = (eax >> 12) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen5_11: + edx = (eax >> 13) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +; +L9Bit4: + esi_u = (eax >> 4) & 511; + ecx = 2; + esi_u += 65; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 32; + if (!tst) goto LLen6_0; + tst = eax & 64; + if (!tst) goto LLen6_1; + tst = eax & 128; + if (!tst) goto LLen6_2; + tst = eax & 256; + if (!tst) goto LLen6_3; + tst = eax & 512; + if (!tst) goto LLen6_4; + tst = eax & 1024; + if (!tst) goto LLen6_5; + tst = eax & 2048; + if (!tst) goto LLen6_6; + tst = eax & 4096; + if (!tst) goto LLen6_7; + tst = eax & 8192; + if (!tst) goto LLen6_8; + tst = eax & 16384; + if (!tst) goto LLen6_9; + tst = eax & 32768; + if (!tst) goto LLen6_10; + tst = eax & 65536; + if (!tst) goto LLen6_11; + goto LFail; +LLen6_0: +goto LCopyByte6 +;LLen6_1: + edx = (eax >> 7) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen6_2: + edx = (eax >> 8) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen6_3: + edx = (eax >> 9) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen6_4: + edx = (eax >> 10) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen6_5: + edx = (eax >> 11) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen6_6: + edx = (eax >> 12) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen6_7: + edx = (eax >> 13) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen6_8: + edx = (eax >> 14) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen6_9: + edx = (eax >> 15) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen6_10: + edx = (eax >> 16) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +;LLen6_11: + edx = (eax >> 17) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte4 +; +L12Bit5: + esi_u = (eax >> 5) & 4095; + ecx = 2; + esi_u += 577; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 2; + if (!tst) goto LLen7_0; + tst = eax & 4; + if (!tst) goto LLen7_1; + tst = eax & 8; + if (!tst) goto LLen7_2; + tst = eax & 16; + if (!tst) goto LLen7_3; + tst = eax & 32; + if (!tst) goto LLen7_4; + tst = eax & 64; + if (!tst) goto LLen7_5; + tst = eax & 128; + if (!tst) goto LLen7_6; + tst = eax & 256; + if (!tst) goto LLen7_7; + tst = eax & 512; + if (!tst) goto LLen7_8; + tst = eax & 1024; + if (!tst) goto LLen7_9; + tst = eax & 2048; + if (!tst) goto LLen7_10; + tst = eax & 4096; + if (!tst) goto LLen7_11; + goto LFail; +LLen7_0: +goto LCopyByte2 +;LLen7_1: + edx = (eax >> 3) & 1; + ecx += 1 + edx; +goto LCopyByte4 +;LLen7_2: + edx = (eax >> 4) & 3; + ecx += 3 + edx; +goto LCopyByte6 +;LLen7_3: + edx = (eax >> 5) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen7_4: + edx = (eax >> 6) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen7_5: + edx = (eax >> 7) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen7_6: + edx = (eax >> 8) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen7_7: + edx = (eax >> 9) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen7_8: + edx = (eax >> 10) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen7_9: + edx = (eax >> 11) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen7_10: + edx = (eax >> 12) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen7_11: + edx = (eax >> 13) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +; +L20Bit5: + esi_u = (eax >> 5) & 1048575; + ecx = 3; + if (esi_u == 1048575) goto LDone; + esi_u += 4673; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 2; + if (!tst) goto LLen8_0; + tst = eax & 4; + if (!tst) goto LLen8_1; + tst = eax & 8; + if (!tst) goto LLen8_2; + tst = eax & 16; + if (!tst) goto LLen8_3; + tst = eax & 32; + if (!tst) goto LLen8_4; + tst = eax & 64; + if (!tst) goto LLen8_5; + tst = eax & 128; + if (!tst) goto LLen8_6; + tst = eax & 256; + if (!tst) goto LLen8_7; + tst = eax & 512; + if (!tst) goto LLen8_8; + tst = eax & 1024; + if (!tst) goto LLen8_9; + tst = eax & 2048; + if (!tst) goto LLen8_10; + tst = eax & 4096; + if (!tst) goto LLen8_11; + goto LFail; +LLen8_0: +goto LCopyByte2 +;LLen8_1: + edx = (eax >> 3) & 1; + ecx += 1 + edx; +goto LCopyByte4 +;LLen8_2: + edx = (eax >> 4) & 3; + ecx += 3 + edx; +goto LCopyByte6 +;LLen8_3: + edx = (eax >> 5) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen8_4: + edx = (eax >> 6) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen8_5: + edx = (eax >> 7) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen8_6: + edx = (eax >> 8) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen8_7: + edx = (eax >> 9) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen8_8: + edx = (eax >> 10) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen8_9: + edx = (eax >> 11) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen8_10: + edx = (eax >> 12) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen8_11: + edx = (eax >> 13) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +; + // Copy Byte 2 +LCopyByte2: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 2 +LBlock2: + tst = eax & 4; + if (!tst) goto LLiteral3; + tst = eax & 8; + if (!tst) goto L6Bit4; + tst = eax & 16; + if (!tst) goto L9Bit5; + tst = eax & 32; + if (!tst) goto L12Bit6; + goto L20Bit6; + + // Literal 3 +LLiteral3: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 3; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock3; + +L6Bit4: + esi_u = (eax >> 4) & 63; + ecx = 2; + esi_u += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 4; + if (!tst) goto LLen9_0; + tst = eax & 8; + if (!tst) goto LLen9_1; + tst = eax & 16; + if (!tst) goto LLen9_2; + tst = eax & 32; + if (!tst) goto LLen9_3; + tst = eax & 64; + if (!tst) goto LLen9_4; + tst = eax & 128; + if (!tst) goto LLen9_5; + tst = eax & 256; + if (!tst) goto LLen9_6; + tst = eax & 512; + if (!tst) goto LLen9_7; + tst = eax & 1024; + if (!tst) goto LLen9_8; + tst = eax & 2048; + if (!tst) goto LLen9_9; + tst = eax & 4096; + if (!tst) goto LLen9_10; + tst = eax & 8192; + if (!tst) goto LLen9_11; + goto LFail; +LLen9_0: +goto LCopyByte3 +;LLen9_1: + edx = (eax >> 4) & 1; + ecx += 1 + edx; +goto LCopyByte5 +;LLen9_2: + edx = (eax >> 5) & 3; + ecx += 3 + edx; +goto LCopyByte7 +;LLen9_3: + edx = (eax >> 6) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen9_4: + edx = (eax >> 7) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen9_5: + edx = (eax >> 8) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen9_6: + edx = (eax >> 9) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen9_7: + edx = (eax >> 10) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen9_8: + edx = (eax >> 11) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen9_9: + edx = (eax >> 12) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen9_10: + edx = (eax >> 13) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen9_11: + edx = (eax >> 14) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +; +L9Bit5: + esi_u = (eax >> 5) & 511; + ecx = 2; + esi_u += 65; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 64; + if (!tst) goto LLen10_0; + tst = eax & 128; + if (!tst) goto LLen10_1; + tst = eax & 256; + if (!tst) goto LLen10_2; + tst = eax & 512; + if (!tst) goto LLen10_3; + tst = eax & 1024; + if (!tst) goto LLen10_4; + tst = eax & 2048; + if (!tst) goto LLen10_5; + tst = eax & 4096; + if (!tst) goto LLen10_6; + tst = eax & 8192; + if (!tst) goto LLen10_7; + tst = eax & 16384; + if (!tst) goto LLen10_8; + tst = eax & 32768; + if (!tst) goto LLen10_9; + tst = eax & 65536; + if (!tst) goto LLen10_10; + tst = eax & 131072; + if (!tst) goto LLen10_11; + goto LFail; +LLen10_0: +goto LCopyByte7 +;LLen10_1: + edx = (eax >> 8) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen10_2: + edx = (eax >> 9) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen10_3: + edx = (eax >> 10) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen10_4: + edx = (eax >> 11) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen10_5: + edx = (eax >> 12) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen10_6: + edx = (eax >> 13) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen10_7: + edx = (eax >> 14) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen10_8: + edx = (eax >> 15) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen10_9: + edx = (eax >> 16) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +;LLen10_10: + edx = (eax >> 17) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte3 +;LLen10_11: + edx = (eax >> 18) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte5 +; +L12Bit6: + esi_u = (eax >> 6) & 4095; + ecx = 2; + esi_u += 577; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 4; + if (!tst) goto LLen11_0; + tst = eax & 8; + if (!tst) goto LLen11_1; + tst = eax & 16; + if (!tst) goto LLen11_2; + tst = eax & 32; + if (!tst) goto LLen11_3; + tst = eax & 64; + if (!tst) goto LLen11_4; + tst = eax & 128; + if (!tst) goto LLen11_5; + tst = eax & 256; + if (!tst) goto LLen11_6; + tst = eax & 512; + if (!tst) goto LLen11_7; + tst = eax & 1024; + if (!tst) goto LLen11_8; + tst = eax & 2048; + if (!tst) goto LLen11_9; + tst = eax & 4096; + if (!tst) goto LLen11_10; + tst = eax & 8192; + if (!tst) goto LLen11_11; + goto LFail; +LLen11_0: +goto LCopyByte3 +;LLen11_1: + edx = (eax >> 4) & 1; + ecx += 1 + edx; +goto LCopyByte5 +;LLen11_2: + edx = (eax >> 5) & 3; + ecx += 3 + edx; +goto LCopyByte7 +;LLen11_3: + edx = (eax >> 6) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen11_4: + edx = (eax >> 7) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen11_5: + edx = (eax >> 8) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen11_6: + edx = (eax >> 9) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen11_7: + edx = (eax >> 10) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen11_8: + edx = (eax >> 11) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen11_9: + edx = (eax >> 12) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen11_10: + edx = (eax >> 13) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen11_11: + edx = (eax >> 14) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +; +L20Bit6: + esi_u = (eax >> 6) & 1048575; + ecx = 3; + if (esi_u == 1048575) goto LDone; + esi_u += 4673; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 4; + if (!tst) goto LLen12_0; + tst = eax & 8; + if (!tst) goto LLen12_1; + tst = eax & 16; + if (!tst) goto LLen12_2; + tst = eax & 32; + if (!tst) goto LLen12_3; + tst = eax & 64; + if (!tst) goto LLen12_4; + tst = eax & 128; + if (!tst) goto LLen12_5; + tst = eax & 256; + if (!tst) goto LLen12_6; + tst = eax & 512; + if (!tst) goto LLen12_7; + tst = eax & 1024; + if (!tst) goto LLen12_8; + tst = eax & 2048; + if (!tst) goto LLen12_9; + tst = eax & 4096; + if (!tst) goto LLen12_10; + tst = eax & 8192; + if (!tst) goto LLen12_11; + goto LFail; +LLen12_0: +goto LCopyByte3 +;LLen12_1: + edx = (eax >> 4) & 1; + ecx += 1 + edx; +goto LCopyByte5 +;LLen12_2: + edx = (eax >> 5) & 3; + ecx += 3 + edx; +goto LCopyByte7 +;LLen12_3: + edx = (eax >> 6) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen12_4: + edx = (eax >> 7) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen12_5: + edx = (eax >> 8) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen12_6: + edx = (eax >> 9) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen12_7: + edx = (eax >> 10) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen12_8: + edx = (eax >> 11) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen12_9: + edx = (eax >> 12) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen12_10: + edx = (eax >> 13) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen12_11: + edx = (eax >> 14) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +; + // Copy Byte 3 +LCopyByte3: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 3 +LBlock3: + tst = eax & 8; + if (!tst) goto LLiteral4; + tst = eax & 16; + if (!tst) goto L6Bit5; + tst = eax & 32; + if (!tst) goto L9Bit6; + tst = eax & 64; + if (!tst) goto L12Bit7; + goto L20Bit7; + + // Literal 4 +LLiteral4: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 4; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock4; + +L6Bit5: + esi_u = (eax >> 5) & 63; + ecx = 2; + esi_u += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 8; + if (!tst) goto LLen13_0; + tst = eax & 16; + if (!tst) goto LLen13_1; + tst = eax & 32; + if (!tst) goto LLen13_2; + tst = eax & 64; + if (!tst) goto LLen13_3; + tst = eax & 128; + if (!tst) goto LLen13_4; + tst = eax & 256; + if (!tst) goto LLen13_5; + tst = eax & 512; + if (!tst) goto LLen13_6; + tst = eax & 1024; + if (!tst) goto LLen13_7; + tst = eax & 2048; + if (!tst) goto LLen13_8; + tst = eax & 4096; + if (!tst) goto LLen13_9; + tst = eax & 8192; + if (!tst) goto LLen13_10; + tst = eax & 16384; + if (!tst) goto LLen13_11; + goto LFail; +LLen13_0: +goto LCopyByte4 +;LLen13_1: + edx = (eax >> 5) & 1; + ecx += 1 + edx; +goto LCopyByte6 +;LLen13_2: + edx = (eax >> 6) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen13_3: + edx = (eax >> 7) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen13_4: + edx = (eax >> 8) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen13_5: + edx = (eax >> 9) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen13_6: + edx = (eax >> 10) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen13_7: + edx = (eax >> 11) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen13_8: + edx = (eax >> 12) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen13_9: + edx = (eax >> 13) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen13_10: + edx = (eax >> 14) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen13_11: + edx = (eax >> 15) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +; +L9Bit6: + esi_u = (eax >> 6) & 511; + ecx = 2; + esi_u += 65; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 128; + if (!tst) goto LLen14_0; + tst = eax & 256; + if (!tst) goto LLen14_1; + tst = eax & 512; + if (!tst) goto LLen14_2; + tst = eax & 1024; + if (!tst) goto LLen14_3; + tst = eax & 2048; + if (!tst) goto LLen14_4; + tst = eax & 4096; + if (!tst) goto LLen14_5; + tst = eax & 8192; + if (!tst) goto LLen14_6; + tst = eax & 16384; + if (!tst) goto LLen14_7; + tst = eax & 32768; + if (!tst) goto LLen14_8; + tst = eax & 65536; + if (!tst) goto LLen14_9; + tst = eax & 131072; + if (!tst) goto LLen14_10; + tst = eax & 262144; + if (!tst) goto LLen14_11; + goto LFail; +LLen14_0: + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen14_1: + edx = (eax >> 9) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen14_2: + edx = (eax >> 10) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen14_3: + edx = (eax >> 11) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen14_4: + edx = (eax >> 12) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen14_5: + edx = (eax >> 13) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen14_6: + edx = (eax >> 14) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen14_7: + edx = (eax >> 15) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen14_8: + edx = (eax >> 16) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen14_9: + edx = (eax >> 17) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +;LLen14_10: + edx = (eax >> 18) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte4 +;LLen14_11: + edx = (eax >> 19) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte6 +; +L12Bit7: + esi_u = (eax >> 7) & 4095; + ecx = 2; + esi_u += 577; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 8; + if (!tst) goto LLen15_0; + tst = eax & 16; + if (!tst) goto LLen15_1; + tst = eax & 32; + if (!tst) goto LLen15_2; + tst = eax & 64; + if (!tst) goto LLen15_3; + tst = eax & 128; + if (!tst) goto LLen15_4; + tst = eax & 256; + if (!tst) goto LLen15_5; + tst = eax & 512; + if (!tst) goto LLen15_6; + tst = eax & 1024; + if (!tst) goto LLen15_7; + tst = eax & 2048; + if (!tst) goto LLen15_8; + tst = eax & 4096; + if (!tst) goto LLen15_9; + tst = eax & 8192; + if (!tst) goto LLen15_10; + tst = eax & 16384; + if (!tst) goto LLen15_11; + goto LFail; +LLen15_0: +goto LCopyByte4 +;LLen15_1: + edx = (eax >> 5) & 1; + ecx += 1 + edx; +goto LCopyByte6 +;LLen15_2: + edx = (eax >> 6) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen15_3: + edx = (eax >> 7) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen15_4: + edx = (eax >> 8) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen15_5: + edx = (eax >> 9) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen15_6: + edx = (eax >> 10) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen15_7: + edx = (eax >> 11) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen15_8: + edx = (eax >> 12) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen15_9: + edx = (eax >> 13) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen15_10: + edx = (eax >> 14) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen15_11: + edx = (eax >> 15) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +; +L20Bit7: + esi_u = (eax >> 7) & 1048575; + ecx = 3; + if (esi_u == 1048575) goto LDone; + esi_u += 4673; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 8; + if (!tst) goto LLen16_0; + tst = eax & 16; + if (!tst) goto LLen16_1; + tst = eax & 32; + if (!tst) goto LLen16_2; + tst = eax & 64; + if (!tst) goto LLen16_3; + tst = eax & 128; + if (!tst) goto LLen16_4; + tst = eax & 256; + if (!tst) goto LLen16_5; + tst = eax & 512; + if (!tst) goto LLen16_6; + tst = eax & 1024; + if (!tst) goto LLen16_7; + tst = eax & 2048; + if (!tst) goto LLen16_8; + tst = eax & 4096; + if (!tst) goto LLen16_9; + tst = eax & 8192; + if (!tst) goto LLen16_10; + tst = eax & 16384; + if (!tst) goto LLen16_11; + goto LFail; +LLen16_0: +goto LCopyByte4 +;LLen16_1: + edx = (eax >> 5) & 1; + ecx += 1 + edx; +goto LCopyByte6 +;LLen16_2: + edx = (eax >> 6) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen16_3: + edx = (eax >> 7) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen16_4: + edx = (eax >> 8) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen16_5: + edx = (eax >> 9) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen16_6: + edx = (eax >> 10) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen16_7: + edx = (eax >> 11) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen16_8: + edx = (eax >> 12) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen16_9: + edx = (eax >> 13) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen16_10: + edx = (eax >> 14) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen16_11: + edx = (eax >> 15) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +; + // Copy Byte 4 +LCopyByte4: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 4 +LBlock4: + tst = eax & 16; + if (!tst) goto LLiteral5; + tst = eax & 32; + if (!tst) goto L6Bit6; + tst = eax & 64; + if (!tst) goto L9Bit7; + tst = eax & 128; + if (!tst) goto L12Bit8; + goto L20Bit8; + + // Literal 5 +LLiteral5: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 5; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock5; + +L6Bit6: + esi_u = (eax >> 6) & 63; + ecx = 2; + esi_u += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 16; + if (!tst) goto LLen17_0; + tst = eax & 32; + if (!tst) goto LLen17_1; + tst = eax & 64; + if (!tst) goto LLen17_2; + tst = eax & 128; + if (!tst) goto LLen17_3; + tst = eax & 256; + if (!tst) goto LLen17_4; + tst = eax & 512; + if (!tst) goto LLen17_5; + tst = eax & 1024; + if (!tst) goto LLen17_6; + tst = eax & 2048; + if (!tst) goto LLen17_7; + tst = eax & 4096; + if (!tst) goto LLen17_8; + tst = eax & 8192; + if (!tst) goto LLen17_9; + tst = eax & 16384; + if (!tst) goto LLen17_10; + tst = eax & 32768; + if (!tst) goto LLen17_11; + goto LFail; +LLen17_0: +goto LCopyByte5 +;LLen17_1: + edx = (eax >> 6) & 1; + ecx += 1 + edx; +goto LCopyByte7 +;LLen17_2: + edx = (eax >> 7) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen17_3: + edx = (eax >> 8) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen17_4: + edx = (eax >> 9) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen17_5: + edx = (eax >> 10) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen17_6: + edx = (eax >> 11) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen17_7: + edx = (eax >> 12) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen17_8: + edx = (eax >> 13) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen17_9: + edx = (eax >> 14) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen17_10: + edx = (eax >> 15) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +;LLen17_11: + edx = (eax >> 16) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte3 +; +L9Bit7: + esi_u = (eax >> 7) & 511; + ecx = 2; + esi_u += 65; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 1; + if (!tst) goto LLen18_0; + tst = eax & 2; + if (!tst) goto LLen18_1; + tst = eax & 4; + if (!tst) goto LLen18_2; + tst = eax & 8; + if (!tst) goto LLen18_3; + tst = eax & 16; + if (!tst) goto LLen18_4; + tst = eax & 32; + if (!tst) goto LLen18_5; + tst = eax & 64; + if (!tst) goto LLen18_6; + tst = eax & 128; + if (!tst) goto LLen18_7; + tst = eax & 256; + if (!tst) goto LLen18_8; + tst = eax & 512; + if (!tst) goto LLen18_9; + tst = eax & 1024; + if (!tst) goto LLen18_10; + tst = eax & 2048; + if (!tst) goto LLen18_11; + goto LFail; +LLen18_0: +goto LCopyByte1 +;LLen18_1: + edx = (eax >> 2) & 1; + ecx += 1 + edx; +goto LCopyByte3 +;LLen18_2: + edx = (eax >> 3) & 3; + ecx += 3 + edx; +goto LCopyByte5 +;LLen18_3: + edx = (eax >> 4) & 7; + ecx += 7 + edx; +goto LCopyByte7 +;LLen18_4: + edx = (eax >> 5) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen18_5: + edx = (eax >> 6) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen18_6: + edx = (eax >> 7) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen18_7: + edx = (eax >> 8) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen18_8: + edx = (eax >> 9) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen18_9: + edx = (eax >> 10) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen18_10: + edx = (eax >> 11) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen18_11: + edx = (eax >> 12) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +; +L12Bit8: + esi_u = (eax >> 8) & 4095; + ecx = 2; + esi_u += 577; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 16; + if (!tst) goto LLen19_0; + tst = eax & 32; + if (!tst) goto LLen19_1; + tst = eax & 64; + if (!tst) goto LLen19_2; + tst = eax & 128; + if (!tst) goto LLen19_3; + tst = eax & 256; + if (!tst) goto LLen19_4; + tst = eax & 512; + if (!tst) goto LLen19_5; + tst = eax & 1024; + if (!tst) goto LLen19_6; + tst = eax & 2048; + if (!tst) goto LLen19_7; + tst = eax & 4096; + if (!tst) goto LLen19_8; + tst = eax & 8192; + if (!tst) goto LLen19_9; + tst = eax & 16384; + if (!tst) goto LLen19_10; + tst = eax & 32768; + if (!tst) goto LLen19_11; + goto LFail; +LLen19_0: +goto LCopyByte5 +;LLen19_1: + edx = (eax >> 6) & 1; + ecx += 1 + edx; +goto LCopyByte7 +;LLen19_2: + edx = (eax >> 7) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen19_3: + edx = (eax >> 8) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen19_4: + edx = (eax >> 9) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen19_5: + edx = (eax >> 10) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen19_6: + edx = (eax >> 11) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen19_7: + edx = (eax >> 12) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen19_8: + edx = (eax >> 13) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen19_9: + edx = (eax >> 14) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen19_10: + edx = (eax >> 15) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +;LLen19_11: + edx = (eax >> 16) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte3 +; +L20Bit8: + esi_u = (eax >> 8) & 1048575; + ecx = 3; + if (esi_u == 1048575) goto LDone; + esi_u += 4673; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 16; + if (!tst) goto LLen20_0; + tst = eax & 32; + if (!tst) goto LLen20_1; + tst = eax & 64; + if (!tst) goto LLen20_2; + tst = eax & 128; + if (!tst) goto LLen20_3; + tst = eax & 256; + if (!tst) goto LLen20_4; + tst = eax & 512; + if (!tst) goto LLen20_5; + tst = eax & 1024; + if (!tst) goto LLen20_6; + tst = eax & 2048; + if (!tst) goto LLen20_7; + tst = eax & 4096; + if (!tst) goto LLen20_8; + tst = eax & 8192; + if (!tst) goto LLen20_9; + tst = eax & 16384; + if (!tst) goto LLen20_10; + tst = eax & 32768; + if (!tst) goto LLen20_11; + goto LFail; +LLen20_0: +goto LCopyByte5 +;LLen20_1: + edx = (eax >> 6) & 1; + ecx += 1 + edx; +goto LCopyByte7 +;LLen20_2: + edx = (eax >> 7) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen20_3: + edx = (eax >> 8) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen20_4: + edx = (eax >> 9) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen20_5: + edx = (eax >> 10) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen20_6: + edx = (eax >> 11) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen20_7: + edx = (eax >> 12) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen20_8: + edx = (eax >> 13) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen20_9: + edx = (eax >> 14) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen20_10: + edx = (eax >> 15) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +;LLen20_11: + edx = (eax >> 16) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte3 +; + // Copy Byte 5 +LCopyByte5: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 5 +LBlock5: + tst = eax & 32; + if (!tst) goto LLiteral6; + tst = eax & 64; + if (!tst) goto L6Bit7; + tst = eax & 128; + if (!tst) goto L9Bit8; + tst = eax & 256; + if (!tst) goto L12Bit9; + goto L20Bit9; + + // Literal 6 +LLiteral6: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 6; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock6; + +L6Bit7: + esi_u = (eax >> 7) & 63; + ecx = 2; + esi_u += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 32; + if (!tst) goto LLen21_0; + tst = eax & 64; + if (!tst) goto LLen21_1; + tst = eax & 128; + if (!tst) goto LLen21_2; + tst = eax & 256; + if (!tst) goto LLen21_3; + tst = eax & 512; + if (!tst) goto LLen21_4; + tst = eax & 1024; + if (!tst) goto LLen21_5; + tst = eax & 2048; + if (!tst) goto LLen21_6; + tst = eax & 4096; + if (!tst) goto LLen21_7; + tst = eax & 8192; + if (!tst) goto LLen21_8; + tst = eax & 16384; + if (!tst) goto LLen21_9; + tst = eax & 32768; + if (!tst) goto LLen21_10; + tst = eax & 65536; + if (!tst) goto LLen21_11; + goto LFail; +LLen21_0: +goto LCopyByte6 +;LLen21_1: + edx = (eax >> 7) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen21_2: + edx = (eax >> 8) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen21_3: + edx = (eax >> 9) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen21_4: + edx = (eax >> 10) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen21_5: + edx = (eax >> 11) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen21_6: + edx = (eax >> 12) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen21_7: + edx = (eax >> 13) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen21_8: + edx = (eax >> 14) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen21_9: + edx = (eax >> 15) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen21_10: + edx = (eax >> 16) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +;LLen21_11: + edx = (eax >> 17) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte4 +; +L9Bit8: + esi_u = (eax >> 8) & 511; + ecx = 2; + esi_u += 65; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 2; + if (!tst) goto LLen22_0; + tst = eax & 4; + if (!tst) goto LLen22_1; + tst = eax & 8; + if (!tst) goto LLen22_2; + tst = eax & 16; + if (!tst) goto LLen22_3; + tst = eax & 32; + if (!tst) goto LLen22_4; + tst = eax & 64; + if (!tst) goto LLen22_5; + tst = eax & 128; + if (!tst) goto LLen22_6; + tst = eax & 256; + if (!tst) goto LLen22_7; + tst = eax & 512; + if (!tst) goto LLen22_8; + tst = eax & 1024; + if (!tst) goto LLen22_9; + tst = eax & 2048; + if (!tst) goto LLen22_10; + tst = eax & 4096; + if (!tst) goto LLen22_11; + goto LFail; +LLen22_0: +goto LCopyByte2 +;LLen22_1: + edx = (eax >> 3) & 1; + ecx += 1 + edx; +goto LCopyByte4 +;LLen22_2: + edx = (eax >> 4) & 3; + ecx += 3 + edx; +goto LCopyByte6 +;LLen22_3: + edx = (eax >> 5) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen22_4: + edx = (eax >> 6) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen22_5: + edx = (eax >> 7) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen22_6: + edx = (eax >> 8) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen22_7: + edx = (eax >> 9) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen22_8: + edx = (eax >> 10) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen22_9: + edx = (eax >> 11) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen22_10: + edx = (eax >> 12) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen22_11: + edx = (eax >> 13) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +; +L12Bit9: + esi_u = (eax >> 9) & 4095; + ecx = 2; + esi_u += 577; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 32; + if (!tst) goto LLen23_0; + tst = eax & 64; + if (!tst) goto LLen23_1; + tst = eax & 128; + if (!tst) goto LLen23_2; + tst = eax & 256; + if (!tst) goto LLen23_3; + tst = eax & 512; + if (!tst) goto LLen23_4; + tst = eax & 1024; + if (!tst) goto LLen23_5; + tst = eax & 2048; + if (!tst) goto LLen23_6; + tst = eax & 4096; + if (!tst) goto LLen23_7; + tst = eax & 8192; + if (!tst) goto LLen23_8; + tst = eax & 16384; + if (!tst) goto LLen23_9; + tst = eax & 32768; + if (!tst) goto LLen23_10; + tst = eax & 65536; + if (!tst) goto LLen23_11; + goto LFail; +LLen23_0: +goto LCopyByte6 +;LLen23_1: + edx = (eax >> 7) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen23_2: + edx = (eax >> 8) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen23_3: + edx = (eax >> 9) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen23_4: + edx = (eax >> 10) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen23_5: + edx = (eax >> 11) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen23_6: + edx = (eax >> 12) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen23_7: + edx = (eax >> 13) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen23_8: + edx = (eax >> 14) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen23_9: + edx = (eax >> 15) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen23_10: + edx = (eax >> 16) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +;LLen23_11: + edx = (eax >> 17) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte4 +; +L20Bit9: + esi_u = (eax >> 9) & 1048575; + ecx = 3; + if (esi_u == 1048575) goto LDone; + esi_u += 4673; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 32; + if (!tst) goto LLen24_0; + tst = eax & 64; + if (!tst) goto LLen24_1; + tst = eax & 128; + if (!tst) goto LLen24_2; + tst = eax & 256; + if (!tst) goto LLen24_3; + tst = eax & 512; + if (!tst) goto LLen24_4; + tst = eax & 1024; + if (!tst) goto LLen24_5; + tst = eax & 2048; + if (!tst) goto LLen24_6; + tst = eax & 4096; + if (!tst) goto LLen24_7; + tst = eax & 8192; + if (!tst) goto LLen24_8; + tst = eax & 16384; + if (!tst) goto LLen24_9; + tst = eax & 32768; + if (!tst) goto LLen24_10; + tst = eax & 65536; + if (!tst) goto LLen24_11; + goto LFail; +LLen24_0: +goto LCopyByte6 +;LLen24_1: + edx = (eax >> 7) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen24_2: + edx = (eax >> 8) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen24_3: + edx = (eax >> 9) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen24_4: + edx = (eax >> 10) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen24_5: + edx = (eax >> 11) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen24_6: + edx = (eax >> 12) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen24_7: + edx = (eax >> 13) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen24_8: + edx = (eax >> 14) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen24_9: + edx = (eax >> 15) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen24_10: + edx = (eax >> 16) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +;LLen24_11: + edx = (eax >> 17) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte4 +; + // Copy Byte 6 +LCopyByte6: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 6 +LBlock6: + tst = eax & 64; + if (!tst) goto LLiteral7; + tst = eax & 128; + if (!tst) goto L6Bit8; + tst = eax & 256; + if (!tst) goto L9Bit9; + tst = eax & 512; + if (!tst) goto L12Bit10; + goto L20Bit10; + + // Literal 7 +LLiteral7: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 7; + eax = *(ulong*)(ebx - 3); + ebx++; + goto LBlock7; + +L6Bit8: + esi_u = (eax >> 8) & 63; + ecx = 2; + esi_u += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 64; + if (!tst) goto LLen25_0; + tst = eax & 128; + if (!tst) goto LLen25_1; + tst = eax & 256; + if (!tst) goto LLen25_2; + tst = eax & 512; + if (!tst) goto LLen25_3; + tst = eax & 1024; + if (!tst) goto LLen25_4; + tst = eax & 2048; + if (!tst) goto LLen25_5; + tst = eax & 4096; + if (!tst) goto LLen25_6; + tst = eax & 8192; + if (!tst) goto LLen25_7; + tst = eax & 16384; + if (!tst) goto LLen25_8; + tst = eax & 32768; + if (!tst) goto LLen25_9; + tst = eax & 65536; + if (!tst) goto LLen25_10; + tst = eax & 131072; + if (!tst) goto LLen25_11; + goto LFail; +LLen25_0: +goto LCopyByte7 +;LLen25_1: + edx = (eax >> 8) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen25_2: + edx = (eax >> 9) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen25_3: + edx = (eax >> 10) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen25_4: + edx = (eax >> 11) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen25_5: + edx = (eax >> 12) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen25_6: + edx = (eax >> 13) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen25_7: + edx = (eax >> 14) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen25_8: + edx = (eax >> 15) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen25_9: + edx = (eax >> 16) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +;LLen25_10: + edx = (eax >> 17) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte3 +;LLen25_11: + edx = (eax >> 18) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte5 +; +L9Bit9: + esi_u = (eax >> 9) & 511; + ecx = 2; + esi_u += 65; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 4; + if (!tst) goto LLen26_0; + tst = eax & 8; + if (!tst) goto LLen26_1; + tst = eax & 16; + if (!tst) goto LLen26_2; + tst = eax & 32; + if (!tst) goto LLen26_3; + tst = eax & 64; + if (!tst) goto LLen26_4; + tst = eax & 128; + if (!tst) goto LLen26_5; + tst = eax & 256; + if (!tst) goto LLen26_6; + tst = eax & 512; + if (!tst) goto LLen26_7; + tst = eax & 1024; + if (!tst) goto LLen26_8; + tst = eax & 2048; + if (!tst) goto LLen26_9; + tst = eax & 4096; + if (!tst) goto LLen26_10; + tst = eax & 8192; + if (!tst) goto LLen26_11; + goto LFail; +LLen26_0: +goto LCopyByte3 +;LLen26_1: + edx = (eax >> 4) & 1; + ecx += 1 + edx; +goto LCopyByte5 +;LLen26_2: + edx = (eax >> 5) & 3; + ecx += 3 + edx; +goto LCopyByte7 +;LLen26_3: + edx = (eax >> 6) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen26_4: + edx = (eax >> 7) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen26_5: + edx = (eax >> 8) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen26_6: + edx = (eax >> 9) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen26_7: + edx = (eax >> 10) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen26_8: + edx = (eax >> 11) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen26_9: + edx = (eax >> 12) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen26_10: + edx = (eax >> 13) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen26_11: + edx = (eax >> 14) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +; +L12Bit10: + esi_u = (eax >> 10) & 4095; + ecx = 2; + esi_u += 577; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 64; + if (!tst) goto LLen27_0; + tst = eax & 128; + if (!tst) goto LLen27_1; + tst = eax & 256; + if (!tst) goto LLen27_2; + tst = eax & 512; + if (!tst) goto LLen27_3; + tst = eax & 1024; + if (!tst) goto LLen27_4; + tst = eax & 2048; + if (!tst) goto LLen27_5; + tst = eax & 4096; + if (!tst) goto LLen27_6; + tst = eax & 8192; + if (!tst) goto LLen27_7; + tst = eax & 16384; + if (!tst) goto LLen27_8; + tst = eax & 32768; + if (!tst) goto LLen27_9; + tst = eax & 65536; + if (!tst) goto LLen27_10; + tst = eax & 131072; + if (!tst) goto LLen27_11; + goto LFail; +LLen27_0: +goto LCopyByte7 +;LLen27_1: + edx = (eax >> 8) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen27_2: + edx = (eax >> 9) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen27_3: + edx = (eax >> 10) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen27_4: + edx = (eax >> 11) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen27_5: + edx = (eax >> 12) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen27_6: + edx = (eax >> 13) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen27_7: + edx = (eax >> 14) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen27_8: + edx = (eax >> 15) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen27_9: + edx = (eax >> 16) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +;LLen27_10: + edx = (eax >> 17) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte3 +;LLen27_11: + edx = (eax >> 18) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte5 +; +L20Bit10: + esi_u = (eax >> 10) & 1048575; + ecx = 3; + if (esi_u == 1048575) goto LDone; + esi_u += 4673; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 64; + if (!tst) goto LLen28_0; + tst = eax & 128; + if (!tst) goto LLen28_1; + tst = eax & 256; + if (!tst) goto LLen28_2; + tst = eax & 512; + if (!tst) goto LLen28_3; + tst = eax & 1024; + if (!tst) goto LLen28_4; + tst = eax & 2048; + if (!tst) goto LLen28_5; + tst = eax & 4096; + if (!tst) goto LLen28_6; + tst = eax & 8192; + if (!tst) goto LLen28_7; + tst = eax & 16384; + if (!tst) goto LLen28_8; + tst = eax & 32768; + if (!tst) goto LLen28_9; + tst = eax & 65536; + if (!tst) goto LLen28_10; + tst = eax & 131072; + if (!tst) goto LLen28_11; + goto LFail; +LLen28_0: +goto LCopyByte7 +;LLen28_1: + edx = (eax >> 8) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte1 +;LLen28_2: + edx = (eax >> 9) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte3 +;LLen28_3: + edx = (eax >> 10) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte5 +;LLen28_4: + edx = (eax >> 11) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte7 +;LLen28_5: + edx = (eax >> 12) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte1 +;LLen28_6: + edx = (eax >> 13) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte3 +;LLen28_7: + edx = (eax >> 14) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte5 +;LLen28_8: + edx = (eax >> 15) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte7 +;LLen28_9: + edx = (eax >> 16) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte1 +;LLen28_10: + edx = (eax >> 17) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte3 +;LLen28_11: + edx = (eax >> 18) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte5 +; + // Copy Byte 7 +LCopyByte7: +#ifdef SAFETY + if ((edi + ecx) > pbLimDst) goto LFail; +#endif //SAFETY + esi = edi - esi_u; +#ifdef SAFETY + if (esi < pvDst) goto LFail; +#endif //SAFETY + for (; ecx > 0; ecx--) *edi++ = *esi++; + + // Block 7 +LBlock7: + tst = eax & 128; + if (!tst) goto LLiteral8; + tst = eax & 256; + if (!tst) goto L6Bit9; + tst = eax & 512; + if (!tst) goto L9Bit10; + tst = eax & 1024; + if (!tst) goto L12Bit11; + goto L20Bit11; + + // Literal 8 +LLiteral8: +#ifdef SAFETY + if (edi >= pbLimDst) goto LFail; +#endif //SAFETY + *edi++ = eax >> 8; + eax = *(ulong*)(ebx - 2); + ebx += 2; + goto LBlock0; + +L6Bit9: + esi_u = (eax >> 9) & 63; + ecx = 2; + esi_u += 1; + eax = *(ulong*)(ebx - 3); + ebx++; + tst = eax & 128; + if (!tst) goto LLen29_0; + tst = eax & 256; + if (!tst) goto LLen29_1; + tst = eax & 512; + if (!tst) goto LLen29_2; + tst = eax & 1024; + if (!tst) goto LLen29_3; + tst = eax & 2048; + if (!tst) goto LLen29_4; + tst = eax & 4096; + if (!tst) goto LLen29_5; + tst = eax & 8192; + if (!tst) goto LLen29_6; + tst = eax & 16384; + if (!tst) goto LLen29_7; + tst = eax & 32768; + if (!tst) goto LLen29_8; + tst = eax & 65536; + if (!tst) goto LLen29_9; + tst = eax & 131072; + if (!tst) goto LLen29_10; + tst = eax & 262144; + if (!tst) goto LLen29_11; + goto LFail; +LLen29_0: + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen29_1: + edx = (eax >> 9) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen29_2: + edx = (eax >> 10) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen29_3: + edx = (eax >> 11) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen29_4: + edx = (eax >> 12) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen29_5: + edx = (eax >> 13) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen29_6: + edx = (eax >> 14) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen29_7: + edx = (eax >> 15) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen29_8: + edx = (eax >> 16) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen29_9: + edx = (eax >> 17) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +;LLen29_10: + edx = (eax >> 18) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte4 +;LLen29_11: + edx = (eax >> 19) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte6 +; +L9Bit10: + esi_u = (eax >> 10) & 511; + ecx = 2; + esi_u += 65; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 8; + if (!tst) goto LLen30_0; + tst = eax & 16; + if (!tst) goto LLen30_1; + tst = eax & 32; + if (!tst) goto LLen30_2; + tst = eax & 64; + if (!tst) goto LLen30_3; + tst = eax & 128; + if (!tst) goto LLen30_4; + tst = eax & 256; + if (!tst) goto LLen30_5; + tst = eax & 512; + if (!tst) goto LLen30_6; + tst = eax & 1024; + if (!tst) goto LLen30_7; + tst = eax & 2048; + if (!tst) goto LLen30_8; + tst = eax & 4096; + if (!tst) goto LLen30_9; + tst = eax & 8192; + if (!tst) goto LLen30_10; + tst = eax & 16384; + if (!tst) goto LLen30_11; + goto LFail; +LLen30_0: +goto LCopyByte4 +;LLen30_1: + edx = (eax >> 5) & 1; + ecx += 1 + edx; +goto LCopyByte6 +;LLen30_2: + edx = (eax >> 6) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen30_3: + edx = (eax >> 7) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen30_4: + edx = (eax >> 8) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen30_5: + edx = (eax >> 9) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen30_6: + edx = (eax >> 10) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen30_7: + edx = (eax >> 11) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen30_8: + edx = (eax >> 12) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen30_9: + edx = (eax >> 13) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen30_10: + edx = (eax >> 14) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen30_11: + edx = (eax >> 15) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +; +L12Bit11: + esi_u = (eax >> 11) & 4095; + ecx = 2; + esi_u += 577; + eax = *(ulong*)(ebx - 2); + ebx += 2; + tst = eax & 128; + if (!tst) goto LLen31_0; + tst = eax & 256; + if (!tst) goto LLen31_1; + tst = eax & 512; + if (!tst) goto LLen31_2; + tst = eax & 1024; + if (!tst) goto LLen31_3; + tst = eax & 2048; + if (!tst) goto LLen31_4; + tst = eax & 4096; + if (!tst) goto LLen31_5; + tst = eax & 8192; + if (!tst) goto LLen31_6; + tst = eax & 16384; + if (!tst) goto LLen31_7; + tst = eax & 32768; + if (!tst) goto LLen31_8; + tst = eax & 65536; + if (!tst) goto LLen31_9; + tst = eax & 131072; + if (!tst) goto LLen31_10; + tst = eax & 262144; + if (!tst) goto LLen31_11; + goto LFail; +LLen31_0: + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen31_1: + edx = (eax >> 9) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen31_2: + edx = (eax >> 10) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen31_3: + edx = (eax >> 11) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen31_4: + edx = (eax >> 12) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen31_5: + edx = (eax >> 13) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen31_6: + edx = (eax >> 14) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen31_7: + edx = (eax >> 15) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen31_8: + edx = (eax >> 16) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen31_9: + edx = (eax >> 17) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +;LLen31_10: + edx = (eax >> 18) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte4 +;LLen31_11: + edx = (eax >> 19) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte6 +; +L20Bit11: + esi_u = (eax >> 11) & 1048575; + ecx = 3; + if (esi_u == 1048575) goto LDone; + esi_u += 4673; + eax = *(ulong*)(ebx - 1); + ebx += 3; + tst = eax & 128; + if (!tst) goto LLen32_0; + tst = eax & 256; + if (!tst) goto LLen32_1; + tst = eax & 512; + if (!tst) goto LLen32_2; + tst = eax & 1024; + if (!tst) goto LLen32_3; + tst = eax & 2048; + if (!tst) goto LLen32_4; + tst = eax & 4096; + if (!tst) goto LLen32_5; + tst = eax & 8192; + if (!tst) goto LLen32_6; + tst = eax & 16384; + if (!tst) goto LLen32_7; + tst = eax & 32768; + if (!tst) goto LLen32_8; + tst = eax & 65536; + if (!tst) goto LLen32_9; + tst = eax & 131072; + if (!tst) goto LLen32_10; + tst = eax & 262144; + if (!tst) goto LLen32_11; + goto LFail; +LLen32_0: + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte0 +;LLen32_1: + edx = (eax >> 9) & 1; + ecx += 1 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte2 +;LLen32_2: + edx = (eax >> 10) & 3; + ecx += 3 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte4 +;LLen32_3: + edx = (eax >> 11) & 7; + ecx += 7 + edx; + eax = *(ulong*)(ebx - 3); + ebx++; +goto LCopyByte6 +;LLen32_4: + edx = (eax >> 12) & 15; + ecx += 15 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte0 +;LLen32_5: + edx = (eax >> 13) & 31; + ecx += 31 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte2 +;LLen32_6: + edx = (eax >> 14) & 63; + ecx += 63 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte4 +;LLen32_7: + edx = (eax >> 15) & 127; + ecx += 127 + edx; + eax = *(ulong*)(ebx - 2); + ebx += 2; +goto LCopyByte6 +;LLen32_8: + edx = (eax >> 16) & 255; + ecx += 255 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte0 +;LLen32_9: + edx = (eax >> 17) & 511; + ecx += 511 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte2 +;LLen32_10: + edx = (eax >> 18) & 1023; + ecx += 1023 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte4 +;LLen32_11: + edx = (eax >> 19) & 2047; + ecx += 2047 + edx; + eax = *(ulong*)(ebx - 1); + ebx += 3; +goto LCopyByte6 +; +LDone: + cbTot = edi - pvDst; +// clang-format on + diff --git a/kauai/src/mdev2pri.h b/kauai/src/mdev2pri.h index 55658080..096489ea 100644 --- a/kauai/src/mdev2pri.h +++ b/kauai/src/mdev2pri.h @@ -33,12 +33,12 @@ struct MH byte *lpData; DWORD dwBufferLength; DWORD dwBytesRecorded; - DWORD dwUser; + DWORD_PTR dwUser; DWORD dwFlags; MH *lpNext; - DWORD reserved; + DWORD_PTR reserved; DWORD dwOffset; - DWORD dwReserved[8]; + DWORD_PTR dwReserved[4]; }; typedef MH *PMH; @@ -171,7 +171,7 @@ class MSMIX : public MSMIX_PAR void _WaitForBuffers(void); void _SubmitBuffers(ulong tsCur); - static void _MidiProc(ulong luUser, void *pvData, ulong luData); + static void _MidiProc(ULONG_PTR luUser, void *pvData, ULONG_PTR luData); void _Notify(void *pvData, PMDWS pmdws); static ulong __stdcall _ThreadProc(void *pv); @@ -202,7 +202,7 @@ class MSMIX : public MSMIX_PAR /*************************************************************************** The midi stream interface. ***************************************************************************/ -typedef void (*PFNMIDI)(ulong luUser, void *pvData, ulong luData); +typedef void (*PFNMIDI)(ULONG_PTR luUser, void *pvData, ULONG_PTR luData); typedef class MISI *PMISI; #define MISI_PAR BASE @@ -214,7 +214,7 @@ class MISI : public MISI_PAR protected: HMS _hms; // the midi stream handle PFNMIDI _pfnCall; // call back function - ulong _luUser; // user data to send back + ULONG_PTR _luUser; // user data to send back // system volume level - to be saved and restored. The volume we set // is always relative to this @@ -222,7 +222,7 @@ class MISI : public MISI_PAR ulong _luVolSys; long _vlmBase; // our current volume relative to _luVolSys. - MISI(PFNMIDI pfn, ulong luUser); + MISI(PFNMIDI pfn, ULONG_PTR luUser); virtual bool _FOpen(void) = 0; virtual bool _FClose(void) = 0; @@ -239,7 +239,7 @@ class MISI : public MISI_PAR virtual bool FActive(void); virtual bool FActivate(bool fActivate); - virtual bool FQueueBuffer(void *pvData, long cb, long ibStart, long cactPlay, ulong luData) = 0; + virtual bool FQueueBuffer(void *pvData, long cb, long ibStart, long cactPlay, ULONG_PTR luData) = 0; virtual void StopPlaying(void) = 0; }; @@ -296,7 +296,7 @@ class WMS : public WMS_PAR bool _fDone : 1; // tells the aux thread to terminate MMRESULT(WINAPI *_pfnOpen) - (HMS *phms, LPUINT puDeviceID, DWORD cMidi, DWORD dwCallback, DWORD dwInstance, DWORD fdwOpen); + (HMS *phms, LPUINT puDeviceID, DWORD cMidi, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen); MMRESULT(WINAPI *_pfnClose)(HMS hms); MMRESULT(WINAPI *_pfnProperty)(HMS hms, LPBYTE lpb, DWORD dwProperty); MMRESULT(WINAPI *_pfnPosition)(HMS hms, LPMMTIME lpmmt, UINT cbmmt); @@ -305,7 +305,7 @@ class WMS : public WMS_PAR MMRESULT(WINAPI *_pfnRestart)(HMS hms); MMRESULT(WINAPI *_pfnStop)(HMS hms); - WMS(PFNMIDI pfn, ulong luUser); + WMS(PFNMIDI pfn, ULONG_PTR luUser); bool _FInit(void); virtual bool _FOpen(void); @@ -316,14 +316,14 @@ class WMS : public WMS_PAR long _CmhSubmitBuffers(void); void _ResetStream(void); - static void __stdcall _MidiProc(HMS hms, ulong msg, ulong luUser, ulong lu1, ulong lu2); + static void CALLBACK _MidiProc(HMS hms, UINT msg, DWORD_PTR luUser, DWORD_PTR lu1, DWORD_PTR lu2); void _Notify(HMS hms, PMH pmh); static ulong __stdcall _ThreadProc(void *pv); ulong _LuThread(void); public: - static PWMS PwmsNew(PFNMIDI pfn, ulong luUser); + static PWMS PwmsNew(PFNMIDI pfn, ULONG_PTR luUser); ~WMS(void); #ifdef STREAM_BUG @@ -331,7 +331,7 @@ class WMS : public WMS_PAR virtual bool FActivate(bool fActivate); #endif // STREAM_BUG - virtual bool FQueueBuffer(void *pvData, long cb, long ibStart, long cactPlay, ulong luData); + virtual bool FQueueBuffer(void *pvData, long cb, long ibStart, long cactPlay, ULONG_PTR luData); virtual void StopPlaying(void); }; @@ -355,7 +355,7 @@ class OMS : public OMS_PAR long ibStart; long cactPlay; - ulong luData; + ULONG_PTR luData; }; MUTX _mutx; @@ -372,7 +372,7 @@ class OMS : public OMS_PAR PMEV _pmevLim; ulong _tsCur; - OMS(PFNMIDI pfn, ulong luUser); + OMS(PFNMIDI pfn, ULONG_PTR luUser); bool _FInit(void); virtual bool _FOpen(void); @@ -383,10 +383,10 @@ class OMS : public OMS_PAR void _ReleaseBuffers(void); public: - static POMS PomsNew(PFNMIDI pfn, ulong luUser); + static POMS PomsNew(PFNMIDI pfn, ULONG_PTR luUser); ~OMS(void); - virtual bool FQueueBuffer(void *pvData, long cb, long ibStart, long cactPlay, ulong luData); + virtual bool FQueueBuffer(void *pvData, long cb, long ibStart, long cactPlay, ULONG_PTR luData); virtual void StopPlaying(void); }; diff --git a/kauai/src/menu.h b/kauai/src/menu.h index ba9853b6..499c9205 100644 --- a/kauai/src/menu.h +++ b/kauai/src/menu.h @@ -116,9 +116,9 @@ class MUB : public MUB_PAR virtual void EnqueueWcid(long wcid); #endif // WIN - virtual bool FAddListCid(long cid, long lw0, PSTN pstn); - virtual bool FRemoveListCid(long cid, long lw0, PSTN pstn = pvNil); - virtual bool FChangeListCid(long cid, long lwOld, PSTN pstnOld, long lwNew, PSTN pstnNew); + virtual bool FAddListCid(long cid, LONG_PTR lw0, PSTN pstn); + virtual bool FRemoveListCid(long cid, LONG_PTR lw0, PSTN pstn = pvNil); + virtual bool FChangeListCid(long cid, LONG_PTR lwOld, PSTN pstnOld, LONG_PTR lwNew, PSTN pstnNew); virtual bool FRemoveAllListCid(long cid); }; diff --git a/kauai/src/menuwin.cpp b/kauai/src/menuwin.cpp index c27f02a5..70373a3a 100644 --- a/kauai/src/menuwin.cpp +++ b/kauai/src/menuwin.cpp @@ -145,7 +145,7 @@ void MUB::EnqueueWcid(long wcid) Adds an item identified by the given list cid, long parameter and string. ***************************************************************************/ -bool MUB::FAddListCid(long cid, long lw0, PSTN pstn) +bool MUB::FAddListCid(long cid, LONG_PTR lw0, PSTN pstn) { AssertThis(0); AssertPo(pstn, 0); @@ -242,7 +242,7 @@ bool MUB::FAddListCid(long cid, long lw0, PSTN pstn) or string. If pstn is non-nil, it is used to find the item. If pstn is nil, lw0 is used to identify the item. ***************************************************************************/ -bool MUB::FRemoveListCid(long cid, long lw0, PSTN pstn) +bool MUB::FRemoveListCid(long cid, LONG_PTR lw0, PSTN pstn) { AssertThis(0); AssertNilOrPo(pstn, 0); @@ -435,7 +435,7 @@ bool MUB::FRemoveAllListCid(long cid) lwNew is set as the new long parameter and if pstnNew is non-nil, it is used as the new menu item text. ***************************************************************************/ -bool MUB::FChangeListCid(long cid, long lwOld, PSTN pstnOld, long lwNew, PSTN pstnNew) +bool MUB::FChangeListCid(long cid, LONG_PTR lwOld, PSTN pstnOld, LONG_PTR lwNew, PSTN pstnNew) { AssertThis(0); AssertNilOrPo(pstnOld, 0); diff --git a/kauai/src/mididev2.cpp b/kauai/src/mididev2.cpp index 750c0d55..bb0ae956 100644 --- a/kauai/src/mididev2.cpp +++ b/kauai/src/mididev2.cpp @@ -580,8 +580,8 @@ bool MSMIX::_FInit(void) return fFalse; _pglmsos->SetMinGrow(1); - if (pvNil == (_pmisi = WMS::PwmsNew(_MidiProc, (ulong)this)) && - pvNil == (_pmisi = OMS::PomsNew(_MidiProc, (ulong)this))) + if (pvNil == (_pmisi = WMS::PwmsNew(_MidiProc, (ULONG_PTR)this)) && + pvNil == (_pmisi = OMS::PomsNew(_MidiProc, (ULONG_PTR)this))) { return fFalse; } @@ -867,7 +867,7 @@ void MSMIX::_SubmitBuffers(ulong tsCur) _cpvOut++; pvData = msos.pmdws->PvLockData(&cb); - if (_pmisi->FQueueBuffer(pvData, cb, cbSkip, msos.cactPlay, (ulong)msos.pmdws)) + if (_pmisi->FQueueBuffer(pvData, cb, cbSkip, msos.cactPlay, (ULONG_PTR)msos.pmdws)) { // it worked! _fPlaying = fTrue; @@ -1066,7 +1066,7 @@ bool MSMIX::_FGetKeyEvents(PMDWS pmdws, ulong dtsSeek, long *pcbSkip) /*************************************************************************** Call back from the midi stream stuff. ***************************************************************************/ -void MSMIX::_MidiProc(ulong luUser, void *pvData, ulong luData) +void MSMIX::_MidiProc(ULONG_PTR luUser, void *pvData, ULONG_PTR luData) { PMSMIX pmsmix; PMDWS pmdws; @@ -1222,7 +1222,7 @@ ulong MSMIX::_LuThread(void) /*************************************************************************** Constructor for the MIDI stream interface. ***************************************************************************/ -MISI::MISI(PFNMIDI pfn, ulong luUser) +MISI::MISI(PFNMIDI pfn, ULONG_PTR luUser) { AssertBaseThis(0); Assert(pvNil != pfn, 0); @@ -1375,7 +1375,7 @@ bool MISI::FActivate(bool fActivate) /*************************************************************************** Constructor for the Win95 Midi stream class. ***************************************************************************/ -WMS::WMS(PFNMIDI pfn, ulong luUser) : MISI(pfn, luUser) +WMS::WMS(PFNMIDI pfn, ULONG_PTR luUser) : MISI(pfn, luUser) { } @@ -1410,7 +1410,7 @@ WMS::~WMS(void) /*************************************************************************** Create a new WMS. ***************************************************************************/ -PWMS WMS::PwmsNew(PFNMIDI pfn, ulong luUser) +PWMS WMS::PwmsNew(PFNMIDI pfn, ULONG_PTR luUser) { PWMS pwms; @@ -1553,7 +1553,7 @@ bool WMS::_FOpen(void) if (hNil != _hms) goto LDone; - if (MMSYSERR_NOERROR != (*_pfnOpen)(&_hms, &uT, 1, (ulong)_MidiProc, (ulong)this, CALLBACK_FUNCTION)) + if (MMSYSERR_NOERROR != (*_pfnOpen)(&_hms, &uT, 1, (DWORD_PTR)_MidiProc, (DWORD_PTR)this, CALLBACK_FUNCTION)) { goto LFail; } @@ -1677,7 +1677,7 @@ void WMS::_ResetStream(void) This submits a buffer and restarts the midi stream. If the data is bigger than 64K, this (in conjunction with _Notify) deals with it. ***************************************************************************/ -bool WMS::FQueueBuffer(void *pvData, long cb, long ibStart, long cactPlay, ulong luData) +bool WMS::FQueueBuffer(void *pvData, long cb, long ibStart, long cactPlay, ULONG_PTR luData) { AssertThis(0); AssertPvCb(pvData, cb); @@ -1766,7 +1766,7 @@ long WMS::_CmhSubmitBuffers(void) cbMh = LwMin(pmsir->cb - pmsir->ibNext, kcbMaxWmsBuffer); pmh->dwBufferLength = cbMh; pmh->dwBytesRecorded = cbMh; - pmh->dwUser = (ulong)pmsir; + pmh->dwUser = (DWORD_PTR)pmsir; pmsir->ibNext += cbMh; pmsir->rgibLim[imh] = pmsir->ibNext; @@ -1835,7 +1835,7 @@ void WMS::StopPlaying(void) to 0, this stops the midi stream. If the indicated sound is done, we notify the client. ***************************************************************************/ -void __stdcall WMS::_MidiProc(HMS hms, ulong msg, ulong luUser, ulong lu1, ulong lu2) +void CALLBACK WMS::_MidiProc(HMS hms, UINT msg, DWORD_PTR luUser, DWORD_PTR lu1, DWORD_PTR lu2) { PWMS pwms; PMH pmh; @@ -1991,7 +1991,7 @@ void WMS::_DoCallBacks() /*************************************************************************** Constructor for our own midi stream api implementation. ***************************************************************************/ -OMS::OMS(PFNMIDI pfn, ulong luUser) : MISI(pfn, luUser) +OMS::OMS(PFNMIDI pfn, ULONG_PTR luUser) : MISI(pfn, luUser) { } @@ -2023,7 +2023,7 @@ OMS::~OMS(void) /*************************************************************************** Create a new OMS. ***************************************************************************/ -POMS OMS::PomsNew(PFNMIDI pfn, ulong luUser) +POMS OMS::PomsNew(PFNMIDI pfn, ULONG_PTR luUser) { POMS poms; @@ -2165,7 +2165,7 @@ bool OMS::_FClose(void) /*************************************************************************** Queue a buffer to the midi stream. ***************************************************************************/ -bool OMS::FQueueBuffer(void *pvData, long cb, long ibStart, long cactPlay, ulong luData) +bool OMS::FQueueBuffer(void *pvData, long cb, long ibStart, long cactPlay, ULONG_PTR luData) { AssertThis(0); AssertPvCb(pvData, cb); diff --git a/kauai/src/screxe.cpp b/kauai/src/screxe.cpp index a0e14c62..66ddc860 100644 --- a/kauai/src/screxe.cpp +++ b/kauai/src/screxe.cpp @@ -749,7 +749,7 @@ void SCEB::_WarnSz(PSZ psz, ...) STN stn1, stn2; SZS szs; - stn1.FFormatRgch(psz, CchSz(psz), (ulong *)(&psz + 1)); + stn1.FFormatRgch(psz, CchSz(psz), (ULONG_PTR *)(&psz + 1)); stn2.FFormatSz(PszLit("Script ('%f', 0x%x, %d): %s"), _pscpt->Ctg(), _pscpt->Cno(), _ilwCur, &stn1); stn2.GetSzs(szs); Warn(szs); diff --git a/kauai/src/util.h b/kauai/src/util.h index 733f9a51..b2e4a27f 100644 --- a/kauai/src/util.h +++ b/kauai/src/util.h @@ -60,8 +60,8 @@ typedef HCURSOR HCRS; #endif // WIN -#define size(foo) ((long)sizeof(foo)) -#define offset(FOO, field) ((int)&((FOO *)0)->field) +#define size(foo) ((size_t)sizeof(foo)) +#define offset(FOO, field) ((size_t)&((FOO *)0)->field) #define CvFromRgv(rgv) (size(rgv) / size(rgv[0])) #define BLOCK diff --git a/kauai/src/utilmem.cpp b/kauai/src/utilmem.cpp index f4d50174..b9866394 100644 --- a/kauai/src/utilmem.cpp +++ b/kauai/src/utilmem.cpp @@ -206,6 +206,7 @@ bool FAllocPv(void **ppv, long cb, ulong grfmem, long mpr) long *plw; long ilw; +#ifdef IN_80386 __asm { mov plw,ebp } for (ilw = 0; ilw < kclwStackMbh; ilw++) { @@ -220,6 +221,12 @@ bool FAllocPv(void **ppv, long cb, ulong grfmem, long mpr) plw = (long *)*plw; } } +#else + for (ilw = 0; ilw < kclwStackMbh; ilw++) + { + pmbh->rglwStack[ilw] = 0; + } +#endif // !IN_80386 #endif // WIN // write the footer diff --git a/kauai/src/utilstr.cpp b/kauai/src/utilstr.cpp index 1e4545e5..ffc3870d 100644 --- a/kauai/src/utilstr.cpp +++ b/kauai/src/utilstr.cpp @@ -548,14 +548,15 @@ void STN::GetSzs(PSZS pszs) following needs a number also. So the above example would be "%<1>d %<0>d %<2>d %d", producing { 1, 0, 2, 3 }. - WARNING: all arguments should be 4 bytes long. + WARNING: all arguments should be sizeof(void*) bytes long. ***************************************************************************/ bool STN::FFormat(PSTN pstnFormat, ...) { AssertThis(0); AssertPo(pstnFormat, 0); - return FFormatRgch(pstnFormat->Prgch(), pstnFormat->Cch(), (ulong *)(&pstnFormat + 1)); + // FIXME: Use standards-conformant method to pass params + return FFormatRgch(pstnFormat->Prgch(), pstnFormat->Cch(), (ULONG_PTR *)(&pstnFormat + 1)); } /*************************************************************************** @@ -566,13 +567,14 @@ bool STN::FFormatSz(PSZ pszFormat, ...) AssertThis(0); AssertSz(pszFormat); - return FFormatRgch(pszFormat, CchSz(pszFormat), (ulong *)(&pszFormat + 1)); + // FIXME: Use standards-conformant method to pass params + return FFormatRgch(pszFormat, CchSz(pszFormat), (ULONG_PTR *)(&pszFormat + 1)); } /*************************************************************************** Core routine for sprintf functionality. ***************************************************************************/ -bool STN::FFormatRgch(achar *prgchFormat, long cchFormat, ulong *prgluData) +bool STN::FFormatRgch(achar *prgchFormat, long cchFormat, ULONG_PTR *prgluData) { AssertThis(0); AssertIn(cchFormat, 0, kcchMaxStn + 1); @@ -591,7 +593,8 @@ bool STN::FFormatRgch(achar *prgchFormat, long cchFormat, ulong *prgluData) long cch; long cchMin; long ivArg; - ulong lu, luRad; + ULONG_PTR lu; + ulong luRad; achar ch; achar rgchT[kcchMaxStn]; achar *prgchTerm; @@ -684,7 +687,7 @@ bool STN::FFormatRgch(achar *prgchFormat, long cchFormat, ulong *prgluData) // code after the switch assumes that prgchTerm points to the // characters to add to the stream and cch is the number of characters - AssertPvCb(prgluData, LwMul(ivArg + 1, size(ulong))); + AssertPvCb(prgluData, LwMul(ivArg + 1, size(ULONG_PTR))); lu = prgluData[ivArg++]; prgchTerm = rgchT; switch (ch) diff --git a/kauai/src/utilstr.h b/kauai/src/utilstr.h index 2c5712e5..e9b37c08 100644 --- a/kauai/src/utilstr.h +++ b/kauai/src/utilstr.h @@ -479,7 +479,7 @@ class STN bool FFormat(PSTN pstnFormat, ...); bool FFormatSz(PSZ pszFormat, ...); - bool FFormatRgch(achar *prgchFormat, long cchFormat, ulong *prgluData); + bool FFormatRgch(achar *prgchFormat, long cchFormat, ULONG_PTR *prgluData); bool FGetLw(long *plw, long lwBase = 0); bool FExpandControls(void); }; diff --git a/kauai/src/video.cpp b/kauai/src/video.cpp index 7e18689d..16dcf737 100644 --- a/kauai/src/video.cpp +++ b/kauai/src/video.cpp @@ -372,7 +372,7 @@ GVDW::~GVDW(void) MCI_GENERIC_PARMS mci; PSNDV psndv; - mciSendCommand(_lwDevice, MCI_CLOSE, MCI_WAIT, (long)&mci); + mciSendCommand(_lwDevice, MCI_CLOSE, MCI_WAIT, (LONG_PTR)&mci); if (pvNil != vpsndm && pvNil != (psndv = vpsndm->PsndvFromCtg(kctgWave))) { psndv->Suspend(fFalse); @@ -406,7 +406,7 @@ bool GVDW::_FInit(PFNI pfni, PGOB pgobBase) mciOpen.dwStyle = WS_CHILD | WS_CLIPSIBLINGS | WS_DISABLED; mciOpen.hWndParent = _pgobBase->HwndContainer(); if (0 != mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT | MCI_ANIM_OPEN_PARENT | MCI_ANIM_OPEN_WS, - (long)&mciOpen)) + (LONG_PTR)&mciOpen)) { goto LFail; } @@ -422,7 +422,7 @@ bool GVDW::_FInit(PFNI pfni, PGOB pgobBase) // REVIEW shonk: mmsystem.h defines MCI_ANIM_STATUS_HWND as 0x00004003, // which doesn't give us the hwnd. 4001 does! mciStatus.dwItem = 0x00004001; - if (0 != mciSendCommand(_lwDevice, MCI_STATUS, MCI_STATUS_ITEM, (long)&mciStatus)) + if (0 != mciSendCommand(_lwDevice, MCI_STATUS, MCI_STATUS_ITEM, (LONG_PTR)&mciStatus)) { goto LFail; } @@ -432,14 +432,14 @@ bool GVDW::_FInit(PFNI pfni, PGOB pgobBase) ClearPb(&mciStatus, size(mciStatus)); mciStatus.dwItem = MCI_STATUS_LENGTH; mciStatus.dwTrack = 1; - if (0 != mciSendCommand(_lwDevice, MCI_STATUS, MCI_STATUS_ITEM, (long)&mciStatus)) + if (0 != mciSendCommand(_lwDevice, MCI_STATUS, MCI_STATUS_ITEM, (LONG_PTR)&mciStatus)) { goto LFail; } _nfrMac = mciStatus.dwReturn; // get the rectangle - if (0 != mciSendCommand(_lwDevice, MCI_WHERE, MCI_ANIM_WHERE_SOURCE, (long)&mciRect)) + if (0 != mciSendCommand(_lwDevice, MCI_WHERE, MCI_ANIM_WHERE_SOURCE, (LONG_PTR)&mciRect)) { goto LFail; } @@ -487,7 +487,7 @@ long GVDW::NfrCur(void) ClearPb(&mciStatus, size(mciStatus)); mciStatus.dwItem = MCI_STATUS_POSITION; mciStatus.dwTrack = 1; - if (0 != mciSendCommand(_lwDevice, MCI_STATUS, MCI_STATUS_ITEM, (long)&mciStatus)) + if (0 != mciSendCommand(_lwDevice, MCI_STATUS, MCI_STATUS_ITEM, (LONG_PTR)&mciStatus)) { Warn("getting position failed"); return 0; @@ -515,7 +515,7 @@ void GVDW::GotoNfr(long nfr) ClearPb(&mciSeek, size(mciSeek)); mciSeek.dwTo = nfr; - if (0 != mciSendCommand(_lwDevice, MCI_SEEK, MCI_TO, (long)&mciSeek)) + if (0 != mciSendCommand(_lwDevice, MCI_SEEK, MCI_TO, (LONG_PTR)&mciSeek)) { Warn("seeking failed"); } @@ -543,7 +543,7 @@ bool GVDW::FPlaying(void) ClearPb(&mciStatus, size(mciStatus)); mciStatus.dwItem = MCI_STATUS_MODE; mciStatus.dwTrack = 1; - if (0 == mciSendCommand(_lwDevice, MCI_STATUS, MCI_STATUS_ITEM, (long)&mciStatus) && + if (0 == mciSendCommand(_lwDevice, MCI_STATUS, MCI_STATUS_ITEM, (LONG_PTR)&mciStatus) && (MCI_MODE_STOP == mciStatus.dwReturn || MCI_MODE_PAUSE == mciStatus.dwReturn)) { _fPlaying = fFalse; @@ -580,7 +580,7 @@ bool GVDW::FPlay(RC *prc) // start the movie playing ClearPb(&mciPlay, size(mciPlay)); - if (0 != mciSendCommand(_lwDevice, MCI_PLAY, MCI_MCIAVI_PLAY_WINDOW, (long)&mciPlay)) + if (0 != mciSendCommand(_lwDevice, MCI_PLAY, MCI_MCIAVI_PLAY_WINDOW, (LONG_PTR)&mciPlay)) { return fFalse; } @@ -623,7 +623,7 @@ void GVDW::Stop(void) MCI_GENERIC_PARMS mciPause; ClearPb(&mciPause, size(mciPause)); - mciSendCommand(_lwDevice, MCI_PAUSE, 0, (long)&mciPause); + mciSendCommand(_lwDevice, MCI_PAUSE, 0, (LONG_PTR)&mciPause); #endif // WIN #ifdef MAC @@ -666,7 +666,7 @@ void GVDW::_SetRc(void) // show the playback window ClearPb(&mciWindow, size(mciWindow)); mciWindow.nCmdShow = SW_SHOW; - mciSendCommand(_lwDevice, MCI_WINDOW, MCI_ANIM_WINDOW_STATE, (long)&mciWindow); + mciSendCommand(_lwDevice, MCI_WINDOW, MCI_ANIM_WINDOW_STATE, (LONG_PTR)&mciWindow); _fVisible = fTrue; } #endif // WIN diff --git a/src/engine/actredit.cpp b/src/engine/actredit.cpp index 7dfd3b7f..0034b81e 100644 --- a/src/engine/actredit.cpp +++ b/src/engine/actredit.cpp @@ -758,7 +758,7 @@ bool ACTR::FPaste(long nfrm, SCEN *pscen) { return fFalse; } - if (pcrf != _tagTmpl.pcrf) + if (pcrf != RefToPcrf(_tagTmpl.pcrfRef)) { // Need to save this actor's tagTmpl in this movie because it came from another movie @@ -839,7 +839,7 @@ bool ACTR::FPaste(long nfrm, SCEN *pscen) if (aevsnd.tag.sid != ksidUseCrf) continue; // Save tag (this may be a new movie) - if (!aevsnd.tag.pcrf->Pcfl()->FFind(aevsnd.tag.ctg, aevsnd.tag.cno)) + if (!RefToPcrf(aevsnd.tag.pcrfRef)->Pcfl()->FFind(aevsnd.tag.ctg, aevsnd.tag.cno)) { PushErc(ercSocNoSndOnPaste); _RemoveAev(iaev); diff --git a/src/engine/modl.cpp b/src/engine/modl.cpp index da792cc2..13f6408c 100644 --- a/src/engine/modl.cpp +++ b/src/engine/modl.cpp @@ -9,6 +9,7 @@ Review Status: REVIEWED - any changes to this file must be reviewed! ***************************************************************************/ +#include #include "soc.h" ASSERTNAME @@ -80,6 +81,40 @@ bool MODL::FReadModl(PCRF pcrf, CTG ctg, CNO cno, PBLCK pblck, PBACO *ppbaco, lo return fTrue; } +// Portable version of br_face for reading from files. +// Original comes from BRender model.h. +// br_material* material has been replaced with a ulong. +#pragma pack(4) +typedef struct BRF_IO +{ + br_uint_16 vertices[3]; /* Vertices around face */ + br_uint_16 edges[3]; /* Edges around face */ + ulong material; /* Face material (or NULL) */ + br_uint_16 smoothing; /* Controls if shared edges are smooth */ + br_uint_8 flags; /* Bits 0,1 and 2 denote internal edges */ + br_uint_8 _pad0; + br_fvector3 n; /* Plane equation of face */ + br_scalar d; +} BRF_IO; +#pragma pack() + +void BRF_IoToNative(BRF* dst, const BRF_IO* src, size_t count) +{ + for (size_t f = 0; f < count; f++) + { + for (int i = 0; i < 3; i++) + dst[f].vertices[i] = src[f].vertices[i]; + for (int i = 0; i < 3; i++) + dst[f].edges[i] = src[f].edges[i]; + dst[f].material = pvNil; + dst[f].smoothing = src[f].smoothing; + dst[f].flags = src[f].flags; + dst[f]._pad0 = src[f]._pad0; + dst[f].n = src[f].n; + dst[f].d = src[f].d; + } +} + /*************************************************************************** Reads a MODL from a BLCK ***************************************************************************/ @@ -109,9 +144,13 @@ bool MODL::_FInit(PBLCK pblck) SwapBytesBom(&modlf, kbomModlf); Assert(kboCur == modlf.bo, "bad MODL!"); + printf("size of MODLF == %d\n", (int)size(MODLF)); + printf("size of BRV == %d\n", (int)size(BRV)); + printf("size of BRF == %d\n", (int)size(BRF_IO)); + // Allocate space for the BMDL, array of vertices, and array of faces cbrgbrv = LwMul(modlf.cver, size(BRV)); - cbrgbrf = LwMul(modlf.cfac, size(BRF)); + cbrgbrf = LwMul(modlf.cfac, size(BRF_IO)); if (modlf.rRadius == rZero) { @@ -123,8 +162,16 @@ bool MODL::_FInit(PBLCK pblck) CopyPb(&pmodlThis, _pbmdl->identifier, size(PMODL)); if (!pblck->FReadRgb(_pbmdl->vertices, cbrgbrv, size(MODLF))) return fFalse; - if (!pblck->FReadRgb(_pbmdl->faces, cbrgbrf, size(MODLF) + cbrgbrv)) + BRF_IO* faces_io = new BRF_IO[modlf.cfac]; + if (!pblck->FReadRgb(faces_io, cbrgbrf, size(MODLF) + cbrgbrv)) + { + delete[] faces_io; return fFalse; + } + + BRF_IoToNative(_pbmdl->faces, faces_io, modlf.cfac); + + delete[] faces_io; BrModelAdd(_pbmdl); @@ -160,18 +207,25 @@ bool MODL::_FInit(PBLCK pblck) SwapBytesBom(pbrv, kbomBrv); } } - if (!pblck->FReadRgb(_pbmdl->prepared_faces, cbrgbrf, size(MODLF) + cbrgbrv)) + BRF_IO* prepared_faces_io = new BRF_IO[modlf.cfac]; + if (!pblck->FReadRgb(prepared_faces_io, cbrgbrf, size(MODLF) + cbrgbrv)) { + delete[] prepared_faces_io; return fFalse; } if (kboOther == modlf.bo) { - for (ibrf = 0, pbrf = _pbmdl->prepared_faces; ibrf < modlf.cfac; ibrf++, pbrf++) + BRF_IO* pbrf; + for (ibrf = 0, pbrf = prepared_faces_io; ibrf < modlf.cfac; ibrf++, pbrf++) { SwapBytesBom(pbrf, kbomBrf); } } + BRF_IoToNative(_pbmdl->prepared_faces, prepared_faces_io, modlf.cfac); + + delete[] prepared_faces_io; + _pbmdl->flags = BR_MODF_PREPREPARED; _pbmdl->nprepared_vertices = (ushort)modlf.cver; _pbmdl->nprepared_faces = (ushort)modlf.cfac; @@ -235,7 +289,7 @@ PMODL MODL::PmodlReadFromDat(FNI *pfni) PMODL MODL::PmodlFromBmdl(PBMDL pbmdl) { AssertVarMem(pbmdl); - PMODL pmodl = (PMODL) * (long *)pbmdl->identifier; + PMODL pmodl = (PMODL) * (PMODL *)pbmdl->identifier; AssertPo(pmodl, 0); return pmodl; } @@ -422,7 +476,7 @@ void MODL::AssertValid(ulong grf) { MODL_PAR::AssertValid(fobjAllocated); AssertVarMem(_pbmdl); - Assert((PMODL) * (long *)_pbmdl->identifier == this, "Bad MODL identifier"); + Assert((PMODL) * (PMODL *)_pbmdl->identifier == this, "Bad MODL identifier"); } /*************************************************************************** diff --git a/src/engine/movie.cpp b/src/engine/movie.cpp index c3a4fd56..38c94f96 100644 --- a/src/engine/movie.cpp +++ b/src/engine/movie.cpp @@ -6135,7 +6135,7 @@ void MVU::SetTagTool(PTAG ptag) // Make sure the new tag has been opened, if it's a "ksidUseCrf" tag if (ptag->sid == ksidUseCrf) { - AssertPo(ptag->pcrf, 0); + AssertPo(RefToPcrf(ptag->pcrfRef), 0); } #endif diff --git a/src/engine/mtrl.cpp b/src/engine/mtrl.cpp index c1b3bdf2..0b990c38 100644 --- a/src/engine/mtrl.cpp +++ b/src/engine/mtrl.cpp @@ -305,7 +305,7 @@ PMTRL MTRL::PmtrlFromBmtl(PBMTL pbmtl) { AssertVarMem(pbmtl); - PMTRL pmtrl = (PMTRL) * (long *)pbmtl->identifier; + PMTRL pmtrl = (PMTRL) * (PMTRL *)pbmtl->identifier; AssertPo(pmtrl, 0); return pmtrl; } diff --git a/src/engine/scene.cpp b/src/engine/scene.cpp index 95dc1407..707c8526 100644 --- a/src/engine/scene.cpp +++ b/src/engine/scene.cpp @@ -7201,7 +7201,7 @@ void ReleasePpsse(PSSE *ppsse) for (itagc = 0; itagc < psse->ctagc; itagc++) { - if (psse->Ptag(itagc)->pcrf != pvNil) + if (psse->Ptag(itagc)->pcrfRef != pvNil) TAGM::CloseTag(psse->Ptag(itagc)); } @@ -7234,14 +7234,14 @@ PSSE SSE::PsseDupFromGg(PGG pgg, long iv, bool fDupTags) { if (psse->Ptag(itagc)->sid == ksidUseCrf) { - AssertPo(psse->Ptag(itagc)->pcrf, 0); + AssertPo(RefToPcrf(psse->Ptag(itagc)->pcrfRef), 0); TAGM::DupTag(psse->Ptag(itagc)); } } else { // Clear the crf on read, since the caller isn't having us dupe the tag - psse->Ptag(itagc)->pcrf = pvNil; + psse->Ptag(itagc)->pcrfRef = pvNil; } } diff --git a/src/engine/srec.cpp b/src/engine/srec.cpp index 5d0f7974..d4875dcd 100644 --- a/src/engine/srec.cpp +++ b/src/engine/srec.cpp @@ -124,14 +124,14 @@ bool SREC::_FOpenRecord(void) if (pvNil == _hwavein) { // open a wavein device - if (waveInOpen(&_hwavein, WAVE_MAPPER, _priff->PwfxGet(), (DWORD)_WaveInProc, (DWORD)this, CALLBACK_FUNCTION)) + if (waveInOpen(&_hwavein, WAVE_MAPPER, _priff->PwfxGet(), (DWORD_PTR)_WaveInProc, (DWORD_PTR)this, CALLBACK_FUNCTION)) { // it doesn't support this format return fFalse; } // prepare header on block of data - _wavehdr.dwUser = (DWORD)this; + _wavehdr.dwUser = (DWORD_PTR)this; if (waveInPrepareHeader(_hwavein, &_wavehdr, sizeof(WAVEHDR))) { waveInClose(_hwavein); @@ -257,7 +257,7 @@ void SREC::_UpdateStatus(void) /*************************************************************************** Figure out if we're recording or not ***************************************************************************/ -void SREC::_WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) +void CALLBACK SREC::_WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { // the psrec pointer is a pointer to the class which generated the event and owns the device SREC *psrec = (SREC *)dwInstance; diff --git a/src/engine/tagman.cpp b/src/engine/tagman.cpp index d1fd5df1..210a729e 100644 --- a/src/engine/tagman.cpp +++ b/src/engine/tagman.cpp @@ -38,9 +38,51 @@ short names. ***************************************************************************/ +#include #include "soc.h" ASSERTNAME +ulong g_nextPcrfRef = 1; // FIXME: handle/prevent overflow and generally make this more robust +// These two maps form a bidirectional map of refs and their corresponding PCRF's. +static std::map g_refToPcrfMap; +static std::map g_pcrfToRefMap; + +PCRF RefToPcrf(ulong ref) +{ + if (ref == 0) + return pvNil; + return g_refToPcrfMap[ref]; +} + +ulong PcrfToRef(PCRF pcrf) +{ + if (pcrf == pvNil) + return 0; + if (g_pcrfToRefMap.find(pcrf) == g_pcrfToRefMap.end()) + { + g_pcrfToRefMap[pcrf] = g_nextPcrfRef; + ++g_nextPcrfRef; + } + + return g_pcrfToRefMap[pcrf]; +} + +void ReleasePpoPcrfRef(ulong* ref) +{ + if (*ref != 0) + { + PCRF pcrf = g_refToPcrfMap[*ref]; + if (pcrf->CactRef() <= 1) + { + // PCRF will be deleted, remove it from the bimap. + g_pcrfToRefMap.erase(pcrf); + g_refToPcrfMap.erase(*ref); + } + ReleasePpo(&pcrf); + *ref = 0; + } +} + RTCLASS(TAGM) const BOM kbomSid = 0xc0000000; @@ -779,14 +821,14 @@ bool TAGM::FBuildChildTag(PTAG ptagPar, CHID chid, CTG ctgChild, PTAG ptagChild) if (ksidUseCrf == ptagPar->sid) { - AssertPo(ptagPar->pcrf, 0); - if (!ptagPar->pcrf->Pcfl()->FGetKidChidCtg(ptagPar->ctg, ptagPar->cno, chid, ctgChild, &kid)) + AssertPo(RefToPcrf(ptagPar->pcrfRef), 0); + if (!RefToPcrf(ptagPar->pcrfRef)->Pcfl()->FGetKidChidCtg(ptagPar->ctg, ptagPar->cno, chid, ctgChild, &kid)) { return fFalse; // child chunk not found } ptagChild->sid = ksidUseCrf; - ptagChild->pcrf = ptagPar->pcrf; - ptagPar->pcrf->AddRef(); + ptagChild->pcrfRef = ptagPar->pcrfRef; + RefToPcrf(ptagPar->pcrfRef)->AddRef(); ptagChild->ctg = kid.cki.ctg; ptagChild->cno = kid.cki.cno; return fTrue; @@ -890,8 +932,8 @@ PBACO TAGM::PbacoFetch(PTAG ptag, PFNRPO pfnrpo, bool fUseCD) { // Tag knows pcrf, so just read from there. Nothing we can do if // it's not there. - AssertPo(ptag->pcrf, 0); - return ptag->pcrf->PbacoFetch(ptag->ctg, ptag->cno, pfnrpo); + AssertPo(RefToPcrf(ptag->pcrfRef), 0); + return RefToPcrf(ptag->pcrfRef)->PbacoFetch(ptag->ctg, ptag->cno, pfnrpo); } // fTrue parameter ensures that _PcrmSourceGet won't hit the CD @@ -990,12 +1032,12 @@ bool TAGM::FOpenTag(PTAG ptag, PCRF pcrfDest, PCFL pcflSrc) { if (!pcflSrc->FCopy(ptag->ctg, ptag->cno, pcrfDest->Pcfl(), &cnoDest)) { - ptag->pcrf = pvNil; + ptag->pcrfRef = pvNil; return fFalse; // copy failed } ptag->cno = cnoDest; } - ptag->pcrf = pcrfDest; + ptag->pcrfRef = PcrfToRef(pcrfDest); pcrfDest->AddRef(); return fTrue; } @@ -1015,9 +1057,9 @@ bool TAGM::FSaveTag(PTAG ptag, PCRF pcrf, bool fRedirect) if (ptag->sid != ksidUseCrf) return fTrue; - AssertPo(ptag->pcrf, 0); + AssertPo(RefToPcrf(ptag->pcrfRef), 0); - if (!ptag->pcrf->Pcfl()->FCopy(ptag->ctg, ptag->cno, pcrf->Pcfl(), &cnoDest)) + if (!RefToPcrf(ptag->pcrfRef)->Pcfl()->FCopy(ptag->ctg, ptag->cno, pcrf->Pcfl(), &cnoDest)) { return fFalse; // copy failed } @@ -1025,8 +1067,8 @@ bool TAGM::FSaveTag(PTAG ptag, PCRF pcrf, bool fRedirect) if (fRedirect) { pcrf->AddRef(); - ReleasePpo(&ptag->pcrf); - ptag->pcrf = pcrf; + ReleasePpoPcrfRef(&ptag->pcrfRef); + ptag->pcrfRef = PcrfToRef(pcrf); ptag->cno = cnoDest; } @@ -1044,8 +1086,8 @@ void TAGM::DupTag(PTAG ptag) if (ptag->sid == ksidUseCrf) { - AssertPo(ptag->pcrf, 0); - ptag->pcrf->AddRef(); + AssertPo(RefToPcrf(ptag->pcrfRef), 0); + RefToPcrf(ptag->pcrfRef)->AddRef(); } } @@ -1061,8 +1103,8 @@ void TAGM::CloseTag(PTAG ptag) if (ptag->sid == ksidUseCrf) { - AssertPo(ptag->pcrf, 0); - ReleasePpo(&ptag->pcrf); + AssertPo(RefToPcrf(ptag->pcrfRef), 0); + ReleasePpoPcrfRef(&ptag->pcrfRef); } } @@ -1091,9 +1133,9 @@ ulong TAGM::FcmpCompareTags(PTAG ptag1, PTAG ptag2) // If both sids are ksidUseCrf, compare CRFs if (ptag1->sid == ksidUseCrf) // implies ptag2->sid == ksidUseCrf { - if (ptag1->pcrf < ptag2->pcrf) + if (ptag1->pcrfRef < ptag2->pcrfRef) return fcmpLt; - if (ptag1->pcrf > ptag2->pcrf) + if (ptag1->pcrfRef > ptag2->pcrfRef) return fcmpGt; } return fcmpEq; @@ -1151,8 +1193,8 @@ void TAG::MarkMem(void) { if (sid == ksidUseCrf) { - AssertPo(pcrf, 0); - MarkMemObj(pcrf); + AssertPo(RefToPcrf(pcrfRef), 0); + MarkMemObj(RefToPcrf(pcrfRef)); } } #endif // DEBUG diff --git a/src/studio/browser.cpp b/src/studio/browser.cpp index 3c9e6ee3..3b6f0de4 100644 --- a/src/studio/browser.cpp +++ b/src/studio/browser.cpp @@ -1964,7 +1964,7 @@ bool BRWN::FCmdOk(PCMD pcmd) PMVU pmvu; pmvu = (PMVU)(_pstdio->Pmvie()->PddgGet(0)); tag.sid = ksidInvalid; - tag.pcrf = pvNil; + tag.pcrfRef = pvNil; pmvu->SetTagTool(&tag); // No need to close tag with ksidInvalid } @@ -2057,7 +2057,7 @@ bool BRWM::_FUpdateLists(void) if (!pcfl->FGetCkiCtg(kctgMsnd, icki, &cki)) goto LNext; tag.sid = ksidUseCrf; // Non-CD-loaded content - tag.pcrf = _pcrf; + tag.pcrfRef = PcrfToRef(_pcrf); tag.ctg = kctgMsnd; tag.cno = cki.cno; @@ -2141,7 +2141,7 @@ bool BRWM::_FAddThd(STN *pstn, CKI *pcki) ; thd.tag.sid = ksidUseCrf; - thd.tag.pcrf = _pcrf; + thd.tag.pcrfRef = PcrfToRef(_pcrf); thd.tag.ctg = pcki->ctg; thd.tag.cno = pcki->cno; thd.cno = cnoNil; // unused @@ -2175,7 +2175,7 @@ void BRWM::_ProcessSelection(void) _GetThumFromIthum(_ithumSelect, &thumSelect, &sid); tag.sid = sid; - tag.pcrf = (ksidUseCrf == sid) ? _pcrf : pvNil; + tag.pcrfRef = (ksidUseCrf == sid) ? PcrfToRef(_pcrf) : pvNil; tag.ctg = kctgMsnd; tag.cno = (CNO)thumSelect; @@ -2367,7 +2367,7 @@ bool BRWM::FCmdDel(PCMD pcmd) // Delete the midi or wave child chunk from the msnd // Invalidate the sound tag.sid = ksidUseCrf; // Non-CD-loaded content - tag.pcrf = _pcrf; + tag.pcrfRef = PcrfToRef(_pcrf); tag.ctg = kctgMsnd; _GetThumFromIthum(_ithumSelect, &tag.cno, &sid); diff --git a/src/studio/esl.cpp b/src/studio/esl.cpp index 27fd89d8..506ef07b 100644 --- a/src/studio/esl.cpp +++ b/src/studio/esl.cpp @@ -485,7 +485,7 @@ bool ESLT::FCmdSetFont(PCMD pcmd) TAG tagTdfNew; tagTdfNew.sid = pcmd->rglw[1]; - tagTdfNew.pcrf = pvNil; + tagTdfNew.pcrfRef = pvNil; tagTdfNew.ctg = kctgTdf; tagTdfNew.cno = pcmd->rglw[0]; @@ -530,7 +530,7 @@ bool ESLT::FCmdSetColor(PCMD pcmd) TAG tagTdfNew; tagTdfNew.sid = pcmd->rglw[1]; - tagTdfNew.pcrf = pvNil; + tagTdfNew.pcrfRef = pvNil; tagTdfNew.ctg = kctgMtrl; tagTdfNew.cno = pcmd->rglw[0]; diff --git a/src/studio/mminstal.cpp b/src/studio/mminstal.cpp index ffbb1400..ebf0c733 100644 --- a/src/studio/mminstal.cpp +++ b/src/studio/mminstal.cpp @@ -323,11 +323,11 @@ WORD wHaveMCI(LPSTR dwDeviceType) mciOpen.lpstrAlias = NULL; // mciErr = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID, (DWORD)(LPMCI_OPEN_PARMS)&mciOpen); - mciErr = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE, (DWORD)(LPMCI_OPEN_PARMS)&mciOpen); + mciErr = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE, (DWORD_PTR)(LPMCI_OPEN_PARMS)&mciOpen); if (MMSYSERR_NOERROR == mciErr) { - mciSendCommand(mciOpen.wDeviceID, MCI_CLOSE, 0, (DWORD)(LPMCI_OPEN_PARMS)&mciOpen); + mciSendCommand(mciOpen.wDeviceID, MCI_CLOSE, 0, (DWORD_PTR)(LPMCI_OPEN_PARMS)&mciOpen); } #ifdef _DEBUG diff --git a/src/studio/portf.cpp b/src/studio/portf.cpp index 3d5b95b5..d36ef431 100644 --- a/src/studio/portf.cpp +++ b/src/studio/portf.cpp @@ -154,7 +154,7 @@ bool FPortGetFniOpen(FNI *pfni, LPTSTR lpstrFilter, LPTSTR lpstrTitle, FNI *pfni diPortfolio.fDrawnBkgnd = fFalse; diPortfolio.grfPrevType = grfPrevType; diPortfolio.cnoWave = cnoWave; - ofn.lCustData = (DWORD)&diPortfolio; + ofn.lCustData = (LPARAM)&diPortfolio; ofn.lpstrFilter = lpstrFilter; ofn.lpstrTitle = lpstrTitle; @@ -288,7 +288,7 @@ bool FPortGetFniSave(FNI *pfni, LPTSTR lpstrFilter, LPTSTR lpstrTitle, LPTSTR lp diPortfolio.fDrawnBkgnd = fFalse; diPortfolio.grfPrevType = grfPrevType; diPortfolio.cnoWave = cnoWave; - ofn.lCustData = (DWORD)&diPortfolio; + ofn.lCustData = (LPARAM)&diPortfolio; ofn.lpstrFilter = lpstrFilter; ofn.lpstrTitle = lpstrTitle; @@ -474,7 +474,7 @@ bool FPortGetFniSave(FNI *pfni, LPTSTR lpstrFilter, LPTSTR lpstrTitle, LPTSTR lp child of the common dlg. ***************************************************************************/ -UINT CALLBACK OpenHookProc(HWND hwndCustom, UINT msg, UINT wParam, LONG lParam) +UINT_PTR CALLBACK OpenHookProc(HWND hwndCustom, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { @@ -489,13 +489,13 @@ UINT CALLBACK OpenHookProc(HWND hwndCustom, UINT msg, UINT wParam, LONG lParam) lpOfn = (OPENFILENAME *)lParam; pdiPortfolio = (PDLGINFO)(lpOfn->lCustData); - SetWindowLong(hwndCustom, GWL_USERDATA, (LONG)pdiPortfolio); + SetWindowLongPtr(hwndCustom, GWLP_USERDATA, (LONG_PTR)pdiPortfolio); hwndDlg = GetParent(hwndCustom); // Give ourselves a way to access the custom dlg hwnd // from the common dlg subclass wndproc. - SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)hwndCustom); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)hwndCustom); // Hide common dlg controls that we're not interested in here. Use the Common Dialog // Message for hiding the control. The documentation on CDM_HIDECONTROL doesn't really @@ -563,24 +563,24 @@ UINT CALLBACK OpenHookProc(HWND hwndCustom, UINT msg, UINT wParam, LONG lParam) // the window anyway.. // Subclass the push btns to prevent the background flashing in the default color. - lpBtnProc = (WNDPROC)SetWindowLong(GetDlgItem(hwndCustom, IDC_BUTTON1), GWL_WNDPROC, (LONG)SubClassBtnProc); + lpBtnProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndCustom, IDC_BUTTON1), GWLP_WNDPROC, (LONG_PTR)SubClassBtnProc); lpOtherBtnProc = - (WNDPROC)SetWindowLong(GetDlgItem(hwndCustom, IDC_BUTTON2), GWL_WNDPROC, (LONG)SubClassBtnProc); + (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndCustom, IDC_BUTTON2), GWLP_WNDPROC, (LONG_PTR)SubClassBtnProc); Assert(lpBtnProc == lpOtherBtnProc, "Custom portfolio buttons (ok/cancel) have different window procs"); lpOtherBtnProc = - (WNDPROC)SetWindowLong(GetDlgItem(hwndCustom, IDC_BUTTON3), GWL_WNDPROC, (LONG)SubClassBtnProc); + (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndCustom, IDC_BUTTON3), GWLP_WNDPROC, (LONG_PTR)SubClassBtnProc); Assert(lpBtnProc == lpOtherBtnProc, "Custom portfolio buttons (ok/home) have different window procs"); // Subclass the preview window to allow custom draw. lpPreviewProc = - (WNDPROC)SetWindowLong(GetDlgItem(hwndCustom, IDC_PREVIEW), GWL_WNDPROC, (LONG)SubClassPreviewProc); + (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndCustom, IDC_PREVIEW), GWLP_WNDPROC, (LONG_PTR)SubClassPreviewProc); // Subclass the main common dlg window to stop static control backgrounds being // fill with the current system color. Instead use a color that matches our // custom background bitmap. - lpDlgProc = (WNDPROC)SetWindowLong(hwndDlg, GWL_WNDPROC, (LONG)SubClassDlgProc); + lpDlgProc = (WNDPROC)SetWindowLongPtr(hwndDlg, GWLP_WNDPROC, (LONG_PTR)SubClassDlgProc); // For the save portfolio we want the file name control to have focus when displayed. if (!pdiPortfolio->fIsOpen) @@ -796,7 +796,7 @@ UINT CALLBACK OpenHookProc(HWND hwndCustom, UINT msg, UINT wParam, LONG lParam) // Win95 has finished doing any resizing of the custom dlg and the controls. // So take any special action now to ensure the portfolio still looks good. - PDLGINFO pdiPortfolio = (PDLGINFO)GetWindowLong(hwndCustom, GWL_USERDATA); + PDLGINFO pdiPortfolio = (PDLGINFO)GetWindowLongPtr(hwndCustom, GWLP_USERDATA); RCS rcsApp; POINT ptBtn; int ypBtn; @@ -982,7 +982,7 @@ UINT CALLBACK OpenHookProc(HWND hwndCustom, UINT msg, UINT wParam, LONG lParam) case WM_PAINT: { PDLGINFO pdiPortfolio; - pdiPortfolio = (PDLGINFO)GetWindowLong(hwndCustom, GWL_USERDATA); + pdiPortfolio = (PDLGINFO)GetWindowLongPtr(hwndCustom, GWLP_USERDATA); // Repaint the entire portfolio. RepaintPortfolio(hwndCustom); @@ -1015,7 +1015,7 @@ void RepaintPortfolio(HWND hwndCustom) PAINTSTRUCT ps; TEXTMETRIC tmCaption; SZ szCaption; - PDLGINFO pdiPortfolio = (PDLGINFO)GetWindowLong(hwndCustom, GWL_USERDATA); + PDLGINFO pdiPortfolio = (PDLGINFO)GetWindowLongPtr(hwndCustom, GWLP_USERDATA); PMBMP pmbmp, pmbmpBtn; int iBtn; CNO cnoBack; @@ -1217,7 +1217,7 @@ void OpenPreview(HWND hwndCustom, PGNV pgnvOff, RCS *prcsPreview) SZ szFile; ERS ersT; ERS *pers; - PDLGINFO pdiPortfolio = (PDLGINFO)GetWindowLong(hwndCustom, GWL_USERDATA); + PDLGINFO pdiPortfolio = (PDLGINFO)GetWindowLongPtr(hwndCustom, GWLP_USERDATA); bool fPreviewed = fFalse; RC rcPreview(*prcsPreview); @@ -1468,7 +1468,7 @@ LRESULT CALLBACK SubClassDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM l // Draw the control background in the light gray that matched the custom // background bitmap. Otherwise the background is drawn in the current // system color, which may not match the background at all. - return ((LONG)GetStockObject(LTGRAY_BRUSH)); + return ((LRESULT)GetStockObject(LTGRAY_BRUSH)); } case WM_SYSCOMMAND: { // Is a screen saver trying to start? @@ -1487,7 +1487,7 @@ LRESULT CALLBACK SubClassDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM l // custom dlg now, to prevent the common dlg controls appearing before // the portfolio background. Note that GetDlgItem(hwndDlg, ) // returns zero here, as the Menu part of the custom dlg is zero. - HWND hwndCustom = (HWND)GetWindowLong(hwndDlg, GWL_USERDATA); + HWND hwndCustom = (HWND)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); if (hwndCustom != 0) UpdateWindow(hwndCustom); diff --git a/src/studio/stdiobrw.cpp b/src/studio/stdiobrw.cpp index ba06357d..37d326c7 100644 --- a/src/studio/stdiobrw.cpp +++ b/src/studio/stdiobrw.cpp @@ -425,7 +425,7 @@ void BRWB::_ApplySelection(long thumSelect, long sid) PMVU pmvu; tag.sid = sid; - tag.pcrf = pvNil; + tag.pcrfRef = pvNil; tag.ctg = kctgBkgd; tag.cno = (CNO)thumSelect; @@ -472,7 +472,7 @@ void BRWP::_ApplySelection(long thumSelect, long sid) AssertPo(pmvu, 0); tag.sid = sid; - tag.pcrf = pvNil; + tag.pcrfRef = pvNil; tag.ctg = kctgTmpl; tag.cno = (CNO)thumSelect; @@ -550,7 +550,7 @@ void BRWM::_ApplySelection(long thumSelect, long sid) tag.cno = (CNO)thumSelect; tag.sid = sid; if (ksidUseCrf != sid) - tag.pcrf = pvNil; + tag.pcrfRef = pvNil; else { if (!_pstdio->Pmvie()->FEnsureAutosave(&_pcrf)) diff --git a/src/studio/utest.cpp b/src/studio/utest.cpp index b532bfa3..690d76b5 100644 --- a/src/studio/utest.cpp +++ b/src/studio/utest.cpp @@ -1568,7 +1568,7 @@ bool APP::_FReadTitlesFromReg(PGST *ppgst) { Warn("Missing InstallDirectory registry entry or registry error"); _FGenericError("Missing InstallDirectory registry entry or registry error"); - goto LFail; + goto LFallback; } for (iValue = 0; RegEnumValue(hkey, iValue, szSid, &cchSid, NULL, NULL, (unsigned char *)szTitle, &cchTitle) != @@ -1588,6 +1588,7 @@ bool APP::_FReadTitlesFromReg(PGST *ppgst) cchSid = kcchMaxSz; } +LFallback: if (pgst->IvMac() == 0) { stnTitle.SetSz(PszLit("3D Movie Maker/3DMovie"));