1 /***************************************************************************
2
3 Custom blitter GA9201 KA01-0249 (120pin IC)
4
5
6 This is a tile-based blitter that writes to a frame buffer. The buffer is
7 never cleared, so stuff drawn is left over from frame to frame until it is
8 overwritten.
9
10 Tiles are stored in ROM and have a fixed 16x16 size. The blitter can draw them
11 as single sprites (composed of one or more tiles in the horizontal direction),
12 or as larger sprites whose tile codes are picked from a tilemap in RAM.
13
14 Sprites can be zoomed, distorted and rotated.
15
16 Shadows are supported on pen 14 (shangha3 makes heavy use of them) but it's not
17 clear how they are turned on and off. heberpop definitely doesn't use them,
18 pen 14 is supposed to be solid black (outlines).
19
20 The chip addresses 0x100000 bytes of memory, containing both the command list,
21 tilemap, and spare RAM to be used by the CPU.
22
23 The command list starts at a variable point in memory, set by
24 shangha3_gfxlist_addr_w(), and always ends at 0x0fffff.
25
26 Large sprites refer to a single tilemap starting at 0x000000, the command list
27 contains the coordinates of the place in the tilemap to pick data from.
28
29 The commands list is processed when shangha3_blitter_go_w() is written to, so
30 it is not processed automatically every frame.
31
32 The commands have a fixed length of 16 words. The format is as follows:
33
34 Word | Bit(s) | Use
35 -----+-fedcba9876543210-+----------------
36 0 | ---------------- | unused?
37 1 | xxxx------------ | high bits of tile #; for tilemaps, this is applied to all tiles
38 1 | ----xxxxxxxxxxxx | low bits of tile #; probably unused for tilemaps
39 2 | ---xxxxxxxxx---- | x coordinate of destination top left corner
40 3 | ---xxxxxxxxx---- | y coordinate of destination top left corner
41 4 | ------------x--- | 0 = use code as-is 1 = fetch codes from tilemap RAM
42 4 | -------------x-- | 1 = draw "compressed" tilemap, as if tiles were 8x8 instead of 16x16
43 4 | --------------x- | flip y
44 4 | ---------------x | flip x
45 5 | --------x------- | unknown (used by blocken)
46 5 | ---------xxx---- | high bits of color #; for tilemaps, this is applied to all tiles
47 5 | ------------xxxx | low bits of color #; probably unused for tilemaps
48 6 | xxxxxxxxxxxxxxxx | width-1 of destination rectangle \ if *both* of these are 0,
49 7 | xxxxxxxxxxxxxxxx | height-1 of destination rectangle / disable sprite
50 8 | xxxxxxxxxxxxxxxx | x coordinate*0x10 of source top left corner (tilemaps only?)
51 9 | xxxxxxxxxxxxxxxx | y coordinate*0x10 of source top left corner (tilemaps only?)
52 a | xxxxxxxxxxxxxxxx | x zoom
53 b | xxxxxxxxxxxxxxxx | rotation
54 c | xxxxxxxxxxxxxxxx | rotation
55 d | xxxxxxxxxxxxxxxx | x zoom
56 e | ---------------- | unknown
57 f | ---------------- | unknown
58
59 ***************************************************************************/
60
61 #include "driver.h"
62 #include "vidhrdw/generic.h"
63
64
65 data16_t *shangha3_ram;
66 size_t shangha3_ram_size;
67
68 int shangha3_do_shadows;
69
70 static data16_t gfxlist_addr;
71 static struct mame_bitmap *rawbitmap;
72
73
74
VIDEO_START(shangha3)75 VIDEO_START( shangha3 )
76 {
77 if ((rawbitmap = auto_bitmap_alloc(Machine->drv->screen_width,Machine->drv->screen_height)) == 0)
78 return 1;
79
80 if (shangha3_do_shadows)
81 {
82 int i;
83
84 /* Prepare the shadow table */
85 /* We draw in a raw bitmap so we don't have to remap pens through Machine->pens */
86 for (i = 0;i < 14;i++)
87 gfx_drawmode_table[i] = DRAWMODE_SOURCE;
88 gfx_drawmode_table[14] = DRAWMODE_SHADOW;
89 for (i = 0;i < 128;i++)
90 palette_shadow_table[Machine->pens[i]] = Machine->pens[i+128];
91 }
92
93 return 0;
94 }
95
96
97
WRITE16_HANDLER(shangha3_flipscreen_w)98 WRITE16_HANDLER( shangha3_flipscreen_w )
99 {
100 if (ACCESSING_LSB)
101 {
102 /* bit 7 flips screen, the rest seems to always be set to 0x7e */
103 flip_screen_set(data & 0x80);
104
105 if ((data & 0x7f) != 0x7e) usrintf_showmessage("flipscreen_w %02x",data);
106 }
107 }
108
WRITE16_HANDLER(shangha3_gfxlist_addr_w)109 WRITE16_HANDLER( shangha3_gfxlist_addr_w )
110 {
111 COMBINE_DATA(&gfxlist_addr);
112 }
113
114
WRITE16_HANDLER(shangha3_blitter_go_w)115 WRITE16_HANDLER( shangha3_blitter_go_w )
116 {
117 int offs;
118
119
120 profiler_mark(PROFILER_VIDEO);
121
122 for (offs = gfxlist_addr << 3;offs < shangha3_ram_size/2;offs += 16)
123 {
124 int sx,sy,x,y,code,color,flipx,flipy,sizex,sizey,zoomx,zoomy;
125
126
127 code = shangha3_ram[offs+1];
128 color = shangha3_ram[offs+5] & 0x7f;
129 flipx = shangha3_ram[offs+4] & 0x01;
130 flipy = shangha3_ram[offs+4] & 0x02;
131 sx = (shangha3_ram[offs+2] & 0x1ff0) >> 4;
132 if (sx >= 0x180) sx -= 0x200;
133 sy = (shangha3_ram[offs+3] & 0x1ff0) >> 4;
134 if (sy >= 0x100) sy -= 0x200;
135 sizex = shangha3_ram[offs+6];
136 sizey = shangha3_ram[offs+7];
137 zoomx = shangha3_ram[offs+10];
138 zoomy = shangha3_ram[offs+13];
139
140 if (flip_screen)
141 {
142 sx = 383 - sx - sizex;
143 sy = 255 - sy - sizey;
144 flipx = !flipx;
145 flipy = !flipy;
146 }
147
148 if ((sizex || sizey)
149 /* avoid garbage on startup */
150 && sizex < 512 && sizey < 256 && zoomx < 0x1f0 && zoomy < 0x1f0)
151 {
152 struct rectangle myclip;
153
154 /*if (shangha3_ram[offs+11] || shangha3_ram[offs+12])*/
155 /*logerror("offs %04x: sx %04x sy %04x zoom %04x %04x %04x %04x fx %d fy %d\n",offs,sx,sy,zoomx,shangha3_ram[offs+11]),shangha3_ram[offs+12],zoomy,flipx,flipy);*/
156
157 myclip.min_x = sx;
158 myclip.max_x = sx + sizex;
159 myclip.min_y = sy;
160 myclip.max_y = sy + sizey;
161
162 if (shangha3_ram[offs+4] & 0x08) /* tilemap */
163 {
164 int srcx,srcy,dispx,dispy,w,h,condensed;
165
166 condensed = shangha3_ram[offs+4] & 0x04;
167
168 srcx = shangha3_ram[offs+8]/16;
169 srcy = shangha3_ram[offs+9]/16;
170 dispx = srcx & 0x0f;
171 dispy = srcy & 0x0f;
172
173 h = (sizey+15)/16+1;
174 w = (sizex+15)/16+1;
175
176 if (condensed)
177 {
178 h *= 2;
179 w *= 2;
180 srcx /= 8;
181 srcy /= 8;
182 }
183 else
184 {
185 srcx /= 16;
186 srcy /= 16;
187 }
188
189 for (y = 0;y < h;y++)
190 {
191 for (x = 0;x < w;x++)
192 {
193 int dx,dy,tile;
194
195 if (condensed)
196 {
197 int addr = ((y+srcy) & 0x1f) +
198 0x20 * ((x+srcx) & 0xff);
199 tile = shangha3_ram[addr];
200 dx = 8*x*(0x200-zoomx)/0x100 - dispx;
201 dy = 8*y*(0x200-zoomy)/0x100 - dispy;
202 }
203 else
204 {
205 int addr = ((y+srcy) & 0x0f) +
206 0x10 * ((x+srcx) & 0xff) +
207 0x100 * ((y+srcy) & 0x10);
208 tile = shangha3_ram[addr];
209 dx = 16*x*(0x200-zoomx)/0x100 - dispx;
210 dy = 16*y*(0x200-zoomy)/0x100 - dispy;
211 }
212
213 if (flipx) dx = sx + sizex-15 - dx;
214 else dx = sx + dx;
215 if (flipy) dy = sy + sizey-15 - dy;
216 else dy = sy + dy;
217
218 drawgfx(rawbitmap,Machine->gfx[0],
219 (tile & 0x0fff) | (code & 0xf000),
220 (tile >> 12) | (color & 0x70),
221 flipx,flipy,
222 dx,dy,
223 &myclip,TRANSPARENCY_PEN,15);
224 }
225 }
226 }
227 else /* sprite */
228 {
229 int w;
230
231 if (zoomx <= 1 && zoomy <= 1)
232 drawgfxzoom(rawbitmap,Machine->gfx[0],
233 code,
234 color,
235 flipx,flipy,
236 sx,sy,
237 &myclip,shangha3_do_shadows ? TRANSPARENCY_PEN_TABLE : TRANSPARENCY_PEN,15,
238 0x1000000,0x1000000);
239 else
240 {
241 w = (sizex+15)/16;
242
243 for (x = 0;x < w;x++)
244 {
245 drawgfxzoom(rawbitmap,Machine->gfx[0],
246 code,
247 color,
248 flipx,flipy,
249 sx + 16*x,sy,
250 &myclip,shangha3_do_shadows ? TRANSPARENCY_PEN_TABLE : TRANSPARENCY_PEN,15,
251 (0x200-zoomx)*0x100,(0x200-zoomy)*0x100);
252
253 if ((code & 0x000f) == 0x0f)
254 code = (code + 0x100) & 0xfff0;
255 else
256 code++;
257 }
258 }
259 }
260 }
261 }
262
263 profiler_mark(PROFILER_END);
264 }
265
266
VIDEO_UPDATE(shangha3)267 VIDEO_UPDATE( shangha3 )
268 {
269 copybitmap(bitmap,rawbitmap,0,0,0,0,&Machine->visible_area,TRANSPARENCY_NONE,0);
270 }
271