123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600 |
- /*
- THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
- SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
- END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
- ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
- IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
- SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
- FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
- CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
- AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
- COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
- */
- /*
- * $Source: f:/miner/source/2d/rcs/roller.c $
- * $Revision: 1.15 $
- * $Author: john $
- * $Date: 1994/10/26 23:55:54 $
- *
- * bitmap scaler, roller
- *
- * $Log: roller.c $
- * Revision 1.15 1994/10/26 23:55:54 john
- * Took out roller; Took out inverse table.
- *
- * Revision 1.14 1994/05/06 12:49:48 john
- * Added supertransparency; neatend things up; took out warnings.
- *
- * Revision 1.13 1994/02/04 13:21:38 matt
- * Took out test code
- *
- * Revision 1.12 1994/02/01 17:25:31 john
- * Made transparency color be 255 all the time.
- *
- * Revision 1.11 1993/12/08 16:40:47 mike
- * Prevent blowup bug when xright < xleft.
- *
- * Revision 1.10 1993/12/07 12:32:19 john
- * moved bmd_palette to gr_palette
- *
- * Revision 1.9 1993/12/03 18:41:10 unknown
- * Put in check for trying to render_scanline wider than compiled code.
- *
- * Revision 1.8 1993/12/03 15:13:49 mike
- * Fix transparency problem by moving setting of Transparency_color.
- *
- * Revision 1.7 1993/12/03 12:05:13 mike
- * Make compiled code bitmaps clip.
- *
- * Revision 1.6 1993/12/02 18:40:38 mike
- * Suppress "Too many compiled code pointers" Error.
- *
- * Revision 1.5 1993/11/28 12:07:35 mike
- * Fix bugs in compiled code roller
- *
- * Revision 1.4 1993/11/23 13:03:17 mike
- * Add compiled code roller.
- *
- * Revision 1.3 1993/11/18 14:22:44 mike
- * fix bugs
- *
- * Revision 1.2 1993/11/17 19:01:10 mike
- * Add roller.
- *
- * Revision 1.1 1993/11/16 09:36:51 mike
- * Initial revision
- *
- *
- */
- #pragma off (unreferenced)
- static char rcsid[] = "$Id: roller.c 1.15 1994/10/26 23:55:54 john Exp $";
- #pragma on (unreferenced)
- #define COMPILED_CODE 1
- #define TRANSPARENCY_COLOR 255
- #include <math.h>
- #include <limits.h>
- #include <stdio.h>
- #include <conio.h>
- #include <stdlib.h>
- #include "mono.h"
- #include "fix.h"
- #include "3d.h"
- #include "gr.h"
- #include "error.h"
- //#define USE_ROLLER 1
- #ifdef USE_ROLLER
- typedef struct xyuv {
- fix x,y,u,v;
- } xyuv;
- extern grs_bitmap ** Texture; // Array of textmaps
- int Compiled_code_width;
- //int Transparency_color = TRANSPARENCY_COLOR;
- // --------------------------------------------------------------------------------------
- // Create 4 xyuv points at array vb4, extracting data from 3 g3s_point points in vb.
- // Create 4th point using formula (p3 = p0 + p2 - p1)
- void create_4_points(grs_point *vb, xyuv *vb4, int width, int height)
- {
- int i;
- for (i=0; i<3; i++) {
- vb4[i].x = vb[i].x;
- vb4[i].y = vb[i].y;
- }
- vb4[3].x = vb[0].x + vb[2].x - vb[1].x;
- vb4[3].y = vb[0].y + vb[2].y - vb[1].y;
-
- // Set u,v coordinates.
- vb4[0].u = 0;
- vb4[0].v = 0;
- vb4[1].u = width*F1_0 - 1;
- vb4[1].v = 0;
- vb4[2].u = width*F1_0 - 1;
- vb4[2].v = height*F1_0 - 1;
- vb4[3].u = 0;
- vb4[3].v = height*F1_0 - 1;
- }
- // --------------------------------------------------------------------------------------
- // Compute deltas given 4 points. Actually, only the first three are needed.
- // For du_dx, dv_dx, determine whether p1 - p0 or p2 - p1 has larger absolute value, and
- // compute deltas from those two points.
- // Do similarly for du_dy, dv_dy.
- // If, in either x or y, the maximum has absolute value of 0, then the bitmap is
- // degenerate. Delta values of 0 are returned in those cases.
- void compute_deltas(xyuv *vb, int *min_y, int *max_y, int *lbind, int *rbind,
- fix *du_dx, fix *dv_dx, fix *xleft, fix *uleft, fix *vleft, fix *xright,
- fix *dx_dy_left, fix *du_dy_left, fix *dv_dy_left, fix *dx_dy_right, fix *du_dy_right, fix *dv_dy_right, int *min_x, int *max_x)
- {
- int i;
- //-- fix denom;
- int min_y_ind,min_x_ind;
- int left_break_ind,right_break_ind;
- float fldenom;
- fldenom = f2fl(vb[1].x - vb[0].x) * f2fl(vb[1].y - vb[2].y) - f2fl(vb[1].y - vb[0].y) * f2fl(vb[1].x - vb[2].x);
- *du_dx = fl2f(( f2fl(vb[1].u - vb[0].u) * f2fl(vb[1].y - vb[2].y) - f2fl(vb[1].y - vb[0].y) * f2fl(vb[1].u - vb[2].u)) / fldenom);
- *dv_dx = fl2f(( f2fl(vb[1].v - vb[0].v) * f2fl(vb[1].y - vb[2].y) - f2fl(vb[1].y - vb[0].y) * f2fl(vb[1].v - vb[2].v)) / fldenom);
- //-- denom = fixmul(vb[1].x - vb[0].x , vb[1].y - vb[2].y) - fixmul(vb[1].y - vb[0].y , vb[1].x - vb[2].x);
- //--
- //-- // If denom is very small, we risk overflow
- //-- if (abs(denom) < F1_0/2) {
- //-- mprintf(0,"Warning -- denom is nearly 0, bashing to 1.0.\n");
- //-- Int3();
- //-- denom = F1_0;
- //-- }
- //--
- //-- *du_dx = fixdiv( fixmul(vb[1].u - vb[0].u , vb[1].y - vb[2].y) - fixmul(vb[1].y - vb[0].y , vb[1].u - vb[2].u), denom );
- //-- *dv_dx = fixdiv( fixmul(vb[1].v - vb[0].v , vb[1].y - vb[2].y) - fixmul(vb[1].y - vb[0].y , vb[1].v - vb[2].v), denom );
- // Compute vertex containing minimum x, y, set min_x, max_x, min_y, max_y
- *min_y = 10000;
- *min_x = 10000;
- for (i=0; i<4; i++) {
- if (f2i(vb[i].y) < *min_y) {
- *min_y = f2i(vb[i].y);
- min_y_ind = i;
- }
- if (f2i(vb[i].x) < *min_x) {
- *min_x = f2i(vb[i].x);
- min_x_ind = i;
- }
- }
- *max_y = f2i(vb[(min_y_ind + 2) % 4].y);
- *max_x = f2i(vb[(min_x_ind + 2) % 4].x);
- *xleft = vb[min_y_ind].x;
- *uleft = vb[min_y_ind].u;
- *vleft = vb[min_y_ind].v;
- // Check for horizontal bitmap (min_y and following vertex have same y coord integer)
- left_break_ind = (min_y_ind + 3) % 4;
- if (f2i(vb[(min_y_ind+1) % 4].y) == *min_y) {
- right_break_ind = (min_y_ind + 2) % 4;
- *xright = vb[(min_y_ind+1)%4].x;
- } else {
- right_break_ind = (min_y_ind + 1) % 4;
- *xright = *xleft; // bitmap not horizontal, left and right start out the same
- }
- *lbind = left_break_ind;
- *rbind = right_break_ind;
- // Compute delta x for left and right.
- if (*max_y - *min_y) {
- int dy;
- dy = f2i(vb[left_break_ind].y) - *min_y;
- if (dy) {
- *dx_dy_left = (vb[*lbind].x - *xleft)/(f2i(vb[left_break_ind].y) - *min_y);
- *du_dy_left = (vb[left_break_ind].u - vb[min_y_ind].u)/(f2i(vb[left_break_ind].y) - *min_y);
- *dv_dy_left = (vb[left_break_ind].v - vb[min_y_ind].v)/(f2i(vb[left_break_ind].y) - *min_y);
- } else {
- *dx_dy_left = 0;
- *du_dy_left = 0;
- *dv_dy_left = 0;
- }
- dy = f2i(vb[right_break_ind].y) - *min_y;
- if (dy) {
- *dx_dy_right = (vb[*rbind].x - *xright)/(f2i(vb[right_break_ind].y) - *min_y);
- *du_dy_right = (vb[right_break_ind].u - vb[min_y_ind].u)/(f2i(vb[right_break_ind].y) - *min_y);
- *dv_dy_right = (vb[right_break_ind].v - vb[min_y_ind].v)/(f2i(vb[right_break_ind].y) - *min_y);
- } else {
- *dx_dy_right = 0;
- *du_dy_right = 0;
- *dv_dy_right = 0;
- }
- } else { // bitmap is one row tall, don't care about delta x
- *dx_dy_left = 0;
- *du_dy_left = 0;
- *dv_dy_left = 0;
- *dx_dy_right = 0;
- *du_dy_right = 0;
- *dv_dy_right = 0;
- }
- }
- // 8A 06 mov al,[esi]
- // 3C 81 cmp al,129
- // 74 02 je skip
- // 88 07 mov [edi],al
- // 47 skip: inc edi
- // 81 C6 00001234 add esi,1234h
-
- // 6 00000000 8A 1E mov bl,[esi]
- // 7 00000002 8A 03 mov al,[ebx]
- // 8 00000004 8A 04 03 mov al,[ebx+eax]
- // 6 00000000 8A 0E mov cl,[esi]
- // 7 00000002 8A 03 mov al,[ebx]
- // 8 00000004 8A 04 0A mov al,[edx+ecx]
- // 9 00000007 80 F9 81 cmp cl,129
- #define mov_cl_si_1 0x8a
- #define mov_cl_si_2 0x0e
- #define mov_bl_si_1 0x8a
- #define mov_bl_si_2 0x1e
- #define mov_al_si_1 0x8a
- #define mov_al_si_2 0x06
- #define cmp_al_k 0x3c
- #define cmp_cl_k_1 0x80
- #define cmp_cl_k_2 0xf9
- #define je_addr 0x74
- #define mov_al_edx_ecx_1 0x8a
- #define mov_al_edx_ecx_2 0x04
- #define mov_al_edx_ecx_3 0x0a
- #define mov_di_al_1 0x88
- #define mov_di_al_2 0x07
- #define add_si_k_1 0x81
- #define add_si_k_2 0xc6
- #define inc_di 0x47
- #define ret 0xc3
- #define MAX_COMPILED_CODE_POINTERS 1000
- #define MAX_COMPILED_CODE (MAX_COMPILED_CODE_POINTERS * 15)
- char Compiled_code[MAX_COMPILED_CODE];
- int Compiled_code_pointers[MAX_COMPILED_CODE_POINTERS];
- // --------------------------------------------------------------------------------------
- // 8a 04 mov al,[si]
- // 88 05 mov [di],al
- // 81 c6 34 12 add si,1234
- // 47 inc di
- // c3 ret
- // Return true if too much compiled code, else return false.
- int create_compiled_code(fix du_dx, fix dv_dx, int width, int min_x, int max_x)
- {
- #if COMPILED_CODE
- int x;
- char *ccp;
- int *ccpp;
- int *ccp_int;
- int delta_si;
- fix cur_u, cur_v, new_u, new_v;
- int delta_x;
- cur_u = 0;
- cur_v = 0;
- new_u = du_dx;
- new_v = dv_dx;
- ccp = Compiled_code;
- ccpp = Compiled_code_pointers;
- // Initialize all code pointers to something which will cause an exception.
- for (x=0; x<MAX_COMPILED_CODE_POINTERS; x++)
- Compiled_code_pointers[x] = 0xffffffff;
- if (max_x - min_x +2 >= MAX_COMPILED_CODE_POINTERS)
- delta_x = MAX_COMPILED_CODE_POINTERS-1;
- else
- delta_x = max_x - min_x + 2;
- Compiled_code_width = delta_x;
- for (x=0; x<=delta_x; x++) {
- *ccpp++ = (int) ccp;
- *ccp++ = mov_cl_si_1;
- *ccp++ = mov_cl_si_2;
- *ccp++ = cmp_cl_k_1;
- *ccp++ = cmp_cl_k_2;
- *ccp++ = TRANSPARENCY_COLOR; //Transparency_color; // transparency color
- *ccp++ = je_addr;
- *ccp++ = 5; // je $+5
- *ccp++ = mov_al_edx_ecx_1;
- *ccp++ = mov_al_edx_ecx_2;
- *ccp++ = mov_al_edx_ecx_3;
- *ccp++ = mov_di_al_1;
- *ccp++ = mov_di_al_2;
- *ccp++ = add_si_k_1;
- *ccp++ = add_si_k_2;
- delta_si = f2i(new_u) - f2i(cur_u) + ( f2i(new_v) - f2i(cur_v)) * width;
- ccp_int = (int *)ccp;
- *ccp_int = delta_si;
- ccp += sizeof(int)/sizeof(char);
- *ccp++ = inc_di;
- if (ccp - Compiled_code >= MAX_COMPILED_CODE - 15)
- return 1; //Error("Too much compiled code.\n");
- if (ccpp - Compiled_code_pointers >= MAX_COMPILED_CODE_POINTERS)
- return 1; //Error("Too many compiled code pointers.\n");
- cur_u = new_u;
- cur_v = new_v;
- new_u += du_dx;
- new_v += dv_dx;
- }
- *ccpp++ = (int) ccp;
- *ccp = ret;
- return 0;
- #else
- if (min_x + max_x + width + du_dx == dv_dx - 9000)
- mprintf(0,"Holy smokes!");
- return 0;
- #endif
- }
- int call_compiled_code(char *start_si, char *start_di, int xleft, int xright, int light_value);
- #pragma aux call_compiled_code parm [esi] [edi] [eax] [ebx] [edx] value [eax] modify [ecx edx] = \
- "pusha" \
- "sub ebx,eax" \
- "mov eax,Compiled_code_pointers" \
- "inc ebx" \
- "mov ebx,Compiled_code_pointers[ebx*4]" \
- "mov cl,[ebx]" \
- "push ebx" \
- "push ecx" \
- "mov byte ptr [ebx],0c3h" \
- "sub ecx,ecx" \
- "shl edx,8" \
- "add edx,offset gr_fade_table" \
- "call eax" \
- "pop ecx" \
- "pop ebx" \
- "mov [ebx],cl" \
- "popa"
- // --------------------------------------------------------------------------------------
- void render_scanline(unsigned char *pixptr, int width, int y, fix xleft, fix xright, fix u, fix v, fix du_dx, fix dv_dx, int light_value)
- {
- #if COMPILED_CODE
- unsigned char *start_si, *start_di;
- if (xright - xleft < 0)
- return;
- start_si = pixptr + f2i(u) + f2i(v) * width;
- start_di = grd_curcanv->cv_bitmap.bm_data + grd_curcanv->cv_bitmap.bm_rowsize*y + f2i(xleft);
- if (f2i(xright) - f2i(xleft) < Compiled_code_width)
- call_compiled_code(start_si, start_di, f2i(xleft), f2i(xright), light_value);
- else
- mprintf(0,"Not calling compiled code for xleft = %i, xright = %i, width = %i\n",f2i(xleft), f2i(xright), f2i(width));
- if (du_dx + dv_dx == 3)
- mprintf(0,"That's peculiar...\n");
- #else
- int x;
- for (x=f2i(xleft); x<f2i(xright); x++) {
- int color;
- color = *(pixptr + f2i(v)*width + f2i(u));
- if (color != TRANSPARENCY_COLOR ) { //Transparency_color) {
- gr_setcolor(color);
- gr_pixel(x,y);
- }
- u += du_dx;
- v += dv_dx;
- }
- #endif
- }
- // --------------------------------------------------------------------------------------
- void render_bitmap(grs_bitmap *bp, xyuv *vb, int min_y, int max_y, int lbind, int rbind,
- fix du_dx, fix dv_dx, fix xleft, fix uleft, fix vleft, fix xright,
- fix dx_dy_left, fix du_dy_left, fix dv_dy_left, fix dx_dy_right, fix du_dy_right, fix dv_dy_right, int light_value)
- {
- int y;
- int lby, rby;
- fix dx_dyl,du_dyl,dv_dyl;
- fix dx_dyr,du_dyr,dv_dyr;
- fix fix_width;
- unsigned char *pixptr = bp->bm_data;
- int width = bp->bm_w;
- lby = f2i(vb[lbind].y);
- rby = f2i(vb[rbind].y);
- dx_dyl = dx_dy_left;
- du_dyl = du_dy_left;
- dv_dyl = dv_dy_left;
- dx_dyr = dx_dy_right;
- du_dyr = du_dy_right;
- dv_dyr = dv_dy_right;
- // Now, render the bitmap.
- if (max_y >= grd_curcanv->cv_bitmap.bm_h)
- max_y = grd_curcanv->cv_bitmap.bm_h-1;
- for (y=min_y; y<=max_y; y++) {
- fix u,v;
- u = uleft;
- v = vleft;
- if (y == lby) {
- dx_dy_left = dx_dyr;
- du_dy_left = du_dyr;
- dv_dy_left = dv_dyr;
- xleft = vb[lbind].x;
- uleft = vb[lbind].u;
- vleft = vb[lbind].v;
- }
- if (y == rby) {
- dx_dy_right = dx_dyl;
- xright = vb[rbind].x;
- }
- fix_width = i2f(grd_curcanv->cv_bitmap.bm_w);
- if (y >= 0) {
- fix txright = xright;
- fix txleft = xleft;
- if (txleft < 0) {
- u -= fixmul(txleft,du_dx);
- v -= fixmul(txleft,dv_dx);
- txleft = 0;
- }
- if (txright > fix_width)
- txright = fix_width-F1_0;
- if ((xright > 0) && (xleft < fix_width))
- render_scanline(pixptr, width, y, txleft, txright, u, v, du_dx, dv_dx, light_value);
- }
- xleft += dx_dy_left;
- xright += dx_dy_right;
- uleft += du_dy_left;
- vleft += dv_dy_left;
- }
- }
- // --------------------------------------------------------------------------------------
- // A scaled/rotated bitmap is defined by 3 vertices, upper left, upper right, lower right
- void rotate_bitmap(grs_bitmap *bp, grs_point *vertbuf, int light_value)
- {
- fix du_dx,dv_dx;
- int min_y,max_y;
- int lbind,rbind;
- fix xleft,xright;
- fix uleft,vleft;
- fix dx_dy_left, du_dy_left, dv_dy_left, dx_dy_right, du_dy_right, dv_dy_right;
- int min_x, max_x;
- //char *pixptr = bp->bm_data;
- //int width = bp->bm_w;
-
- xyuv vb[4];
- create_4_points(vertbuf, vb, bp->bm_w, bp->bm_h);
- compute_deltas(vb, &min_y, &max_y, &lbind, &rbind, &du_dx, &dv_dx, &xleft, &uleft, &vleft, &xright,
- &dx_dy_left, &du_dy_left, &dv_dy_left, &dx_dy_right, &du_dy_right, &dv_dy_right, &min_x, &max_x);
- // // Nasty, ugly, illegal hack -- set transparency color based on top 3 left pixels.
- // if ((*pixptr == *(pixptr+width)) && (*pixptr == *(pixptr+1))) // try upper left corner
- // Transparency_color = *pixptr;
- // else if ((*(pixptr+width-1) == *(pixptr+width-2)) && (*(pixptr+width-1) == *(pixptr+2*width-1))) // try upper right corner
- // Transparency_color = *(pixptr + width - 1);
- // else
- // Transparency_color = TRANSPARENCY_COLOR;
- if (max_x - min_x < MAX_COMPILED_CODE_POINTERS) {
- if (!create_compiled_code(du_dx, dv_dx, bp->bm_w, min_x, max_x))
- render_bitmap(bp, vb, min_y, max_y, lbind, rbind, du_dx, dv_dx, xleft, uleft, vleft, xright,
- dx_dy_left, du_dy_left, dv_dy_left, dx_dy_right, du_dy_right, dv_dy_right, light_value);
- }
- }
- // --------------------------------------------------------------------------------------
- #define DEFAULT_X_SIZE 32
- #define DEFAULT_Y_SIZE 32
- #define CENTER_X 160
- #define CENTER_Y 100
- void set_coords(grs_point *verts, float bank, float scale)
- {
- int i;
- float x[3],y[3];
- float sinbank,cosbank;
- cosbank = cos(bank*3.14159/180.0);
- sinbank = sin(bank*3.14159/180.0);
- x[0] = -DEFAULT_X_SIZE * scale;
- y[0] = -DEFAULT_Y_SIZE * scale;
- x[1] = +DEFAULT_X_SIZE * scale;
- y[1] = -DEFAULT_Y_SIZE * scale;
- x[2] = +DEFAULT_X_SIZE * scale;
- y[2] = +DEFAULT_Y_SIZE * scale;
- for (i=0; i<3; i++) {
- verts[i].x = fl2f(x[i] * cosbank - y[i] * sinbank + CENTER_X);
- verts[i].y = fl2f(x[i] * sinbank + y[i] * cosbank + CENTER_Y);
- }
- }
- //##// --------------------------------------------------------------------------------------
- //##void test_rotate_bitmap(void)
- //##{
- //## static float bank = 0.0;
- //##
- //## grs_point verts[3];
- //##
- //## bank += 4.0;
- //##
- //## set_coords(verts, bank, 2*pow(sin(bank/40),2)+.8);
- //##
- //##// verts[0].x = 50 * F1_0;
- //##// verts[0].y = 50 * F1_0;
- //##//
- //##// verts[1].x = 150 * F1_0;
- //##// verts[1].y = 80 * F1_0;
- //##//
- //##// verts[2].x = 180 * F1_0;
- //##// verts[2].y = 120 * F1_0;
- //##
- //## rotate_bitmap(Texture[36],verts, 15);
- //##}
- #else
- void rotate_bitmap(grs_bitmap *bp, grs_point *vertbuf, int light_value)
- {
- bp = bp;
- vertbuf = vertbuf;
- light_value = light_value;
-
- Int3(); // ROLLER IS IFDEF'D OUT !!!!!!!
- }
- #endif // USE_ROLLER
|