/* Copyright (C) 2015-2018 Night Dive Studios, LLC. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* * $Source: r:/prj/lib/src/2d/RCS/fl8lw.c $ * $Revision: 1.4 $ * $Author: kevin $ * $Date: 1994/08/16 12:50:16 $ * * Routines to wall floor map a flat8 bitmap to a generic canvas. * * This file is part of the 2d library. * */ #include "cnvdat.h" #include "fl8tf.h" #include "fl8tmapdv.h" #include "gente.h" #include "poly.h" #include "scrmac.h" #include "tmapint.h" #include "vtab.h" int gri_lit_wall_umap_loop(grs_tmap_loop_info *tli); int gri_lit_wall_umap_loop_1D(grs_tmap_loop_info *tli); int gri_lit_wall_umap_loop(grs_tmap_loop_info *tli) { fix u, v, i, du, dv, di, dy, d; // locals used to store copies of tli-> stuff, so its in registers on the PPC int k, y; uint32_t t_mask; uint32_t t_wlog; uchar *t_bits; uchar *p_dest; int32_t gr_row; uchar *g_ltab; fix inv_dy; int32_t *t_vtab; #if InvDiv inv_dy = fix_div(fix_make(1, 0), tli->w); u = fix_mul_asm_safe(tli->left.u, inv_dy); du = fix_mul_asm_safe(tli->right.u, inv_dy) - u; v = fix_mul_asm_safe(tli->left.v, inv_dy); dv = fix_mul_asm_safe(tli->right.v, inv_dy) - v; i = fix_mul_asm_safe(tli->left.i, inv_dy); di = fix_mul_asm_safe(tli->right.i, inv_dy) - i; if (di >= -256 && di <= 256) i += 1024; #else u = fix_div(tli->left.u, tli->w); du = fix_div(tli->right.u, tli->w) - u; v = fix_div(tli->left.v, tli->w); dv = fix_div(tli->right.v, tli->w) - v; i = fix_div(tli->left.i, tli->w); di = fix_div(tli->right.i, tli->w) - i; if (di >= -256 && di <= 256) i += 1024; #endif dy = tli->right.y - tli->left.y; t_mask = tli->mask; t_wlog = tli->bm.wlog; g_ltab = grd_screen->ltab; t_vtab = tli->vtab; t_bits = tli->bm.bits; gr_row = grd_bm.row; do { if ((d = fix_ceil(tli->right.y) - fix_ceil(tli->left.y)) > 0) { d = fix_ceil(tli->left.y) - tli->left.y; #if InvDiv inv_dy = fix_div(fix_make(1, 0) << 8, dy); di = fix_mul_asm_safe_light(di, inv_dy); inv_dy >>= 8; du = fix_mul_asm_safe(du, inv_dy); dv = fix_mul_asm_safe(dv, inv_dy); #else du = fix_div(du, dy); dv = fix_div(dv, dy); di = fix_div(di, dy); #endif u += fix_mul(du, d); v += fix_mul(dv, d); i += fix_mul(di, d); y = fix_cint(tli->right.y) - fix_cint(tli->left.y); p_dest = grd_bm.bits + (gr_row * fix_cint(tli->left.y)) + tli->x; switch (tli->bm.hlog) { case GRL_OPAQUE: for (; y > 0; y--) { k = t_vtab[fix_fint(v)] + fix_fint(u); *p_dest = g_ltab[t_bits[k] + fix_light(i)]; // gr_fill_upixel(g_ltab[t_bits[k]+fix_light(i)],t_x,y); p_dest += gr_row; u += du; v += dv; i += di; } break; case GRL_TRANS: for (; y > 0; y--) { k = t_vtab[fix_fint(v)] + fix_fint(u); k = t_bits[k]; if (k != 0) *p_dest = g_ltab[k + fix_light(i)]; // gr_fill_upixel(g_ltab[k+fix_light(i)],t_x,y); p_dest += gr_row; u += du; v += dv; i += di; } break; case GRL_OPAQUE | GRL_LOG2: for (; y > 0; y--) { k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask; *p_dest = g_ltab[t_bits[k] + fix_light(i)]; p_dest += gr_row; u += du; v += dv; i += di; } break; case GRL_TRANS | GRL_LOG2: for (; y > 0; y--) { k = ((fix_fint(v) << t_wlog) + fix_fint(u)) & t_mask; k = t_bits[k]; if (k != 0) *p_dest = g_ltab[k + fix_light(i)]; // gr_fill_upixel(g_ltab[k+fix_light(i)],t_x,y); p_dest += gr_row; u += du; v += dv; i += di; } break; } } else if (d < 0) return TRUE; /* punt this tmap */ tli->w += tli->dw; // figure out new left u & v & i inv_dy = 0; k = tli->left.u + tli->left.du; y = tli->left.v + tli->left.dv; tli->left.i += tli->left.di; #if InvDiv inv_dy = fix_div(fix_make(1, 0), tli->w); u = fix_mul_asm_safe(k, inv_dy); v = fix_mul_asm_safe(y, inv_dy); i = fix_mul_asm_safe(tli->left.i, inv_dy); if (di >= -256 && di <= 256) i += 1024; #else u = fix_div(k, tli->w); v = fix_div(y, tli->w); i = fix_div(tli->left.i, tli->w); if (di >= -256 && di <= 256) i += 1024; #endif tli->left.u = k; tli->left.v = y; // figure out new right u & v & i k = tli->right.u + tli->right.du; y = tli->right.v + tli->right.dv; tli->right.i += tli->right.di; #if InvDiv du = fix_mul_asm_safe(k, inv_dy) - u; dv = fix_mul_asm_safe(y, inv_dy) - v; di = fix_mul_asm_safe(tli->right.i, inv_dy) - i; #else du = fix_div(k, tli->w) - u; dv = fix_div(y, tli->w) - v; di = fix_div(tli->right.i, tli->w) - i; #endif tli->right.u = k; tli->right.v = y; tli->left.y += tli->left.dy; tli->right.y += tli->right.dy; dy = tli->right.y - tli->left.y; tli->x++; } while (--(tli->n) > 0); return FALSE; /* tmap OK */ } void gri_trans_lit_wall_umap_init(grs_tmap_loop_info *tli) { if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) { tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1; tli->bm.hlog = GRL_TRANS | GRL_LOG2; } else { tli->vtab = gr_make_vtab(&(tli->bm)); tli->bm.hlog = GRL_TRANS; } tli->loop_func = (void (*)())gri_lit_wall_umap_loop; tli->left_edge_func = (void (*)())gri_uviwy_edge; tli->right_edge_func = (void (*)())gri_uviwy_edge; } void gri_opaque_lit_wall_umap_init(grs_tmap_loop_info *tli) { if ((tli->bm.row == (1 << tli->bm.wlog)) && (tli->bm.h == (1 << tli->bm.hlog))) { tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1; tli->bm.hlog = GRL_OPAQUE | GRL_LOG2; } else { tli->vtab = gr_make_vtab(&(tli->bm)); tli->bm.hlog = GRL_OPAQUE; } tli->loop_func = (void (*)())gri_lit_wall_umap_loop; tli->left_edge_func = (void (*)())gri_uviwy_edge; tli->right_edge_func = (void (*)())gri_uviwy_edge; } /*extern "C" { extern int HandleWallLitLoop1D_PPC(grs_tmap_loop_info *tli, fix u, fix v, fix i, fix dv, fix di, fix dy, uchar *g_ltab, int32_t *t_vtab, uchar *o_bits, int32_t gr_row, uint32_t t_mask, uint32_t t_wlog); }*/ int HandleWallLitLoop1D_C(grs_tmap_loop_info *tli, fix u, fix v, fix i, fix dv, fix di, fix dy, uchar *g_ltab, uchar *o_bits, int32_t gr_row, uint32_t t_mask, uint32_t t_wlog) { fix d, inv_dy; register fix lefty, righty; int32_t k, y; uchar *t_bits; uchar *p_dest; lefty = tli->left.y; righty = tli->right.y; do { if ((d = fix_ceil(righty) - fix_ceil(lefty)) > 0) { d = fix_ceil(lefty) - lefty; inv_dy = fix_div(fix_make(1, 0) << 8, dy); dv = fix_mul_asm_safe(dv, inv_dy >> 8); di = fix_mul_asm_safe_light(di, inv_dy); v += fix_mul(dv, d); i += fix_mul(di, d); if (di >= -256 && di <= 256) i += 256; y = fix_cint(righty) - fix_cint(lefty); p_dest = grd_bm.bits + (gr_row * fix_cint(lefty)) + tli->x; t_bits = o_bits + fix_fint(u); // inner loop for (; y > 0; y--) { k = (fix_fint(v) << t_wlog) & t_mask; *p_dest = g_ltab[t_bits[k] + fix_light(i)]; p_dest += gr_row; v += dv; i += di; } } else if (d < 0) return TRUE; // punt this tmap tli->w += tli->dw; // figure out new left u & v & i k = tli->left.u + tli->left.du; y = tli->left.v + tli->left.dv; tli->left.i += tli->left.di; inv_dy = fix_div(fix_make(1, 0), tli->w); u = fix_mul_asm_safe(k, inv_dy); v = fix_mul_asm_safe(y, inv_dy); i = fix_mul_asm_safe(tli->left.i, inv_dy); tli->left.u = k; tli->left.v = y; // figure out new right u & v & i k = tli->right.u + tli->right.du; y = tli->right.v + tli->right.dv; tli->right.i += tli->right.di; dv = fix_mul_asm_safe(y, inv_dy) - v; di = fix_mul_asm_safe(tli->right.i, inv_dy) - i; if (di >= -256 && di <= 256) i += 1024; tli->right.u = k; tli->right.v = y; lefty += tli->left.dy; righty += tli->right.dy; dy = righty - lefty; tli->x++; } while (--(tli->n) > 0); tli->left.y = lefty; tli->right.y = righty; return FALSE; // tmap OK } // ================================================================================== // Wall_1D versions of routines int gri_lit_wall_umap_loop_1D(grs_tmap_loop_info *tli) { fix u, v, i, dv, di, dy; // locals used to store copies of tli-> stuff, so its in registers on the PPC int k, y; uint32_t t_mask; uint32_t t_wlog; int32_t gr_row; uchar *g_ltab; uchar *o_bits; fix inv_dy; #if InvDiv inv_dy = fix_div(fix_make(1, 0), tli->w); u = fix_mul_asm_safe(tli->left.u, inv_dy); v = fix_mul_asm_safe(tli->left.v, inv_dy); dv = fix_mul_asm_safe(tli->right.v, inv_dy) - v; i = fix_mul_asm_safe(tli->left.i, inv_dy); di = fix_mul_asm_safe(tli->right.i, inv_dy) - i; if (di >= -256 && di <= 256) i += 512; #else u = fix_div(tli->left.u, tli->w); v = fix_div(tli->left.v, tli->w); dv = fix_div(tli->right.v, tli->w) - v; i = fix_div(tli->left.i, tli->w); di = fix_div(tli->right.i, tli->w) - i; if (di >= -256 && di <= 256) i += 512; #endif dy = tli->right.y - tli->left.y; t_mask = tli->mask; t_wlog = tli->bm.wlog; g_ltab = grd_screen->ltab; o_bits = tli->bm.bits; gr_row = grd_bm.row; return HandleWallLitLoop1D_C(tli, u, v, i, dv, di, dy, g_ltab, o_bits, gr_row, t_mask, t_wlog); } void gri_opaque_lit_wall1d_umap_init(grs_tmap_loop_info *tli) { // Wall1D is always log2 /* if ((tli->bm.row==(1<bm.wlog)) && (tli->bm.h==(1<bm.hlog))) {*/ tli->mask = (1 << (tli->bm.hlog + tli->bm.wlog)) - 1; tli->bm.hlog = GRL_OPAQUE | GRL_LOG2; /* } else { tli->vtab=gr_make_vtab(&(tli->bm)); tli->bm.hlog=GRL_OPAQUE; }*/ tli->loop_func = (void (*)())gri_lit_wall_umap_loop_1D; tli->left_edge_func = (void (*)())gri_uviwy_edge; tli->right_edge_func = (void (*)())gri_uviwy_edge; }