1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * $Source: r:/prj/lib/src/2d/RCS/fl8rsd8.c $
21  * $Revision: 1.6 $
22  * $Author: kevin $
23  * $Date: 1994/10/27 18:26:56 $
24  *
25  * Routines for drawing rsd bitmaps into a flat 8 canvas.
26  *
27  * This file is part of the 2d library.
28  *
29  * $Log: fl8rsd8.c $
30  * Revision 1.6  1994/10/27  18:26:56  kevin
31  * fixed gr_rsd8_blit prototype.
32  *
33  * Revision 1.5  1994/10/25  15:13:14  kevin
34  * Renamed funcs, use fast rsd blitter when possible.
35  *
36  * Revision 1.4  1993/10/19  09:50:54  kaboom
37  * Replaced #include <grd.h" with new headers split from grd.h.
38  *
39  * Revision 1.3  1993/10/01  16:00:47  kaboom
40  * Converted to include clpcon.h instead of clip.h
41  *
42  * Revision 1.2  1993/07/13  17:47:13  kaboom
43  * Fixed bugs in clipping case off right edge.  Updated for padded clipping
44  * rectangle.
45  *
46  * Revision 1.1  1993/02/16  14:17:21  kaboom
47  * Initial revision
48  *
49  ********************************************************************
50  * Log from old flat8.c:
51  * Revision 1.7  1992/12/14  18:08:40  kaboom
52  * Fixed bug in flat8_rsd8_[u]bitmap() -- were omitting bottom lines.
53  */
54 
55 #include "clpcon.h"
56 #include "cnvdat.h"
57 #include "fl8tf.h"
58 #include "general.h"
59 #include "grdbm.h"
60 #include "lg.h"
61 #include "rsd.h"
62 #include <string.h>
63 
64 // prototypes
65 void gr_rsd8_blit(uchar *rsd_src, uchar *dst, int grd_bm_row, int bm_w);
66 
67 //### MLA- not supposed to be used (PC code is in RSDBLT.ASM)
gr_rsd8_blit(uchar * rsd_src,uchar * dst,int grd_bm_row,int bm_w)68 void gr_rsd8_blit(uchar *rsd_src, uchar *dst, int grd_bm_row, int bm_w) {
69     DEBUG("%s: ask mark", __FUNCTION__);
70 }
71 
gri_flat8_rsd8_ubitmap(grs_bitmap * bm,short x,short y)72 void gri_flat8_rsd8_ubitmap(grs_bitmap *bm, short x, short y) {
73     /*   uchar *p_dst;
74        uchar *rsd_src;                     // rsd source buffer
75 
76        rsd_src = bm->bits;
77        p_dst = grd_bm.bits + grd_bm.row*y + x;
78        gr_rsd8_blit(rsd_src,p_dst,grd_bm.row,bm->w);*/
79     unpack_rsd8_ubitmap(bm, x, y);
80 }
81 
gri_flat8_rsd8_bitmap(grs_bitmap * bm,short x_left,short y_top)82 int gri_flat8_rsd8_bitmap(grs_bitmap *bm, short x_left, short y_top) {
83     short x, y;           /* current destination position */
84     short x_right, y_bot; /* opposite edges of bitmap */
85     short x_off, y_off;   /* x,y offset for clip */
86     ulong start_byte;     /* byte to start drawing */
87     ulong cur_byte;       /* current position within rsd */
88     uchar *p_dst;
89     uchar *rsd_src;  /* rsd source buffer */
90     short rsd_code;  /* last rsd opcode */
91     short rsd_count; /* count for last opcode */
92     short op_count;  /* operational count */
93     int code;        /* clip code to return */
94 
95     rsd_src = bm->bits;
96     x = x_left;
97     y = y_top;
98     x_off = y_off = cur_byte = rsd_count = 0;
99     x_right = x_left + bm->w;
100     y_bot = y_top + bm->h;
101 
102     /* clip bitmap to rectangular clipping window. */
103     if (x_left > grd_clip.right || x_right <= grd_clip.left || y_top > grd_clip.bot || y_bot <= grd_clip.top)
104         /* completely clipped, forget it. */
105         return CLIP_ALL;
106 
107     code = CLIP_NONE;
108     if (x_left < grd_clip.left) {
109         /* clipped off left edge. */
110         x_off = grd_clip.left - x_left;
111         x = grd_clip.left;
112         code |= CLIP_LEFT;
113     }
114     if (y < grd_clip.top) {
115         /* clipped off top edge. */
116         y_off = grd_clip.top - y_top;
117         y = grd_clip.top;
118         code |= CLIP_TOP;
119     }
120     if (x_right >= grd_clip.right) {
121         /* clipped off right edge. */
122         x_right = grd_clip.right;
123         code |= CLIP_RIGHT;
124     }
125     if (y_bot > grd_clip.bot) {
126         /* clipped off bottom edge. */
127         y_bot = grd_clip.bot;
128         code |= CLIP_BOT;
129     }
130 
131     if (code == CLIP_NONE) {
132         gr_ubitmap(bm, x_left, y_top);
133         return CLIP_NONE;
134     }
135 
136     if (y_off > 0 || x_off > 0) {
137         /* been clipped of left and/or top, so we need to skip from beginning
138            of rsd buffer to be at x_off,y_off within rsd bitmap. */
139         start_byte = y_off * bm->row + x_off;
140         while (cur_byte < start_byte) {
141             if (rsd_count == 0)
142                 /* no pending opcodes, get a new one. */
143                 RSD_GET_TOKEN();
144             if (cur_byte + rsd_count <= start_byte) {
145                 /* current code doesn't hit start_byte yet, so skip all of it. */
146                 switch (rsd_code) {
147                 case RSD_RUN:
148                     /* advance past 1 byte of run color. */
149                     rsd_src++;
150                     break;
151                 case RSD_SKIP:
152                     break;
153                 default: /* RSD_DUMP */
154                     /* advance past rsd_count bytes of dump pixel data. */
155                     rsd_src += rsd_count;
156                     break;
157                 }
158                 cur_byte += rsd_count;
159                 rsd_count = 0;
160             } else {
161                 /* current code goes past start_byte, so skip only enough to get
162                    to start_byte. */
163                 op_count = start_byte - cur_byte;
164                 switch (rsd_code) {
165                 case RSD_RUN:
166                     break;
167                 case RSD_SKIP:
168                     break;
169                 default: /* RSD_DUMP */
170                     rsd_src += op_count;
171                     break;
172                 }
173                 cur_byte += op_count;
174                 rsd_count -= op_count;
175             }
176         }
177     }
178 
179     p_dst = grd_bm.bits + y * grd_bm.row + x;
180 
181     /* process each scanline in two chunks. the first is the clipped section
182        from the right edge, wrapping around to to the left. the second is the
183        unclipped area in the middle. */
184     while (y < y_bot) {
185         /* clipped section. */
186         while (x < x_left + x_off) {
187             if (rsd_count == 0)
188                 RSD_GET_TOKEN();
189             if (x + rsd_count <= x_left + x_off) {
190                 switch (rsd_code) {
191                 case RSD_RUN:
192                     rsd_src++;
193                     break;
194                 case RSD_SKIP:
195                     break;
196                 default: /* RSD_DUMP */
197                     rsd_src += rsd_count;
198                     break;
199                 }
200                 x += rsd_count;
201                 rsd_count = 0;
202             } else {
203                 op_count = x_left + x_off - x;
204                 switch (rsd_code) {
205                 case RSD_RUN:
206                     break;
207                 case RSD_SKIP:
208                     break;
209                 default: /* RSD_DUMP */
210                     rsd_src += op_count;
211                     break;
212                 }
213                 rsd_count -= op_count;
214                 x += op_count;
215             }
216         }
217 
218         /* section to draw. */
219         while (x < x_right) {
220             if (rsd_count == 0)
221                 RSD_GET_TOKEN();
222             if (x + rsd_count <= x_right) {
223                 switch (rsd_code) {
224                 case RSD_RUN:
225                     LG_memset(p_dst, *rsd_src, rsd_count);
226                     rsd_src++;
227                     break;
228                 case RSD_SKIP:
229                     break;
230                 default: /* RSD_DUMP */
231                     LG_memcpy(p_dst, rsd_src, rsd_count);
232                     rsd_src += rsd_count;
233                     break;
234                 }
235                 x += rsd_count;
236                 p_dst += rsd_count;
237                 rsd_count = 0;
238             } else {
239                 op_count = x_right - x;
240                 switch (rsd_code) {
241                 case RSD_RUN:
242                     LG_memset(p_dst, *rsd_src, op_count);
243                     break;
244                 case RSD_SKIP:
245                     break;
246                 default: /* RSD_DUMP */
247                     LG_memcpy(p_dst, rsd_src, op_count);
248                     rsd_src += op_count;
249                     break;
250                 }
251                 x += op_count;
252                 p_dst += op_count;
253                 rsd_count -= op_count;
254             }
255         }
256 
257         /* reset x to be beginning of line and set y to next scanline. */
258         x -= bm->w;
259         p_dst += grd_bm.row - (x_right - x_left) + x_off;
260         y++;
261     }
262 rsd_done:
263     return code;
264 }
265