1 // Based on MAME sources by Phil Stroffolino, Aaron Giles, and Alex W. Jackson
2
3 #include "tiles_generic.h"
4 #include "m68000_intf.h"
5
6 UINT8 *c45RoadRAM = NULL; // external
7
8 static UINT8 *c45RoadTiles = NULL;
9 static UINT16 *c45RoadBitmap = NULL;
10 static UINT8 *c45RoadClut = NULL;
11 static UINT8 c45_temp_clut[0x100];
12 static INT32 c45_transparent_color = 0x7fffffff;
13
c45RoadReset()14 void c45RoadReset()
15 {
16 if (c45RoadRAM != NULL) memset (c45RoadRAM, 0, 0x20000);
17 if (c45RoadTiles != NULL) memset (c45RoadTiles, 0, 0x40000);
18 }
19
c45RoadInit(UINT32 transparent_color,UINT8 * clut)20 void c45RoadInit(UINT32 transparent_color, UINT8 *clut)
21 {
22 c45RoadRAM = (UINT8*)BurnMalloc(0x20000);
23 c45RoadTiles = (UINT8*)BurnMalloc(0x40000);
24
25 c45RoadClut = clut;
26 c45RoadBitmap = (UINT16*)BurnMalloc(0x400 * sizeof(UINT16));
27
28 c45_transparent_color = transparent_color;
29
30 if (c45RoadClut == NULL) {
31 c45RoadClut = c45_temp_clut;
32 for (INT32 i = 0; i < 0x100; i++) c45RoadClut[i] = i;
33 }
34 }
35
c45RoadExit()36 void c45RoadExit()
37 {
38 if (c45RoadRAM != NULL) BurnFree(c45RoadRAM);
39 if (c45RoadTiles != NULL) BurnFree(c45RoadTiles);
40 if (c45RoadBitmap != NULL) BurnFree(c45RoadBitmap);
41
42 c45RoadRAM = NULL;
43 c45RoadTiles = NULL;
44 c45RoadBitmap = NULL;
45
46 c45RoadClut = NULL;
47
48 c45_transparent_color = 0x7fffffff;
49 }
50
update_tile_pixel(INT32 offset)51 static inline void update_tile_pixel(INT32 offset)
52 {
53 UINT16 s = BURN_ENDIAN_SWAP_INT16(*((UINT16*)(c45RoadRAM + (offset * 2))));
54
55 UINT8 *pxl = c45RoadTiles + ((offset * 8) & 0x3fff8);
56
57 for (INT32 x = 7; x >= 0; x--) {
58 pxl[7-x] = (((s >> (x + 8)) & 1) << 1) | ((s >> x) & 1);
59 }
60 }
61
c45_road_write_word(UINT32 address,UINT16 data)62 static void __fastcall c45_road_write_word(UINT32 address, UINT16 data)
63 {
64 UINT16 *ram = (UINT16*)c45RoadRAM;
65
66 INT32 offset = (address & 0x1ffff) / 2;
67
68 if (offset < (0x1fa00 / 2)) // tiles
69 {
70 if (data != BURN_ENDIAN_SWAP_INT16(ram[offset])) {
71 ram[offset] = BURN_ENDIAN_SWAP_INT16(data);
72 update_tile_pixel(offset);
73 }
74 }
75 else // scroll regs
76 {
77 ram[offset] = BURN_ENDIAN_SWAP_INT16(data);
78 }
79 }
80
c45_road_write_byte(UINT32 address,UINT8 data)81 static void __fastcall c45_road_write_byte(UINT32 address, UINT8 data)
82 {
83 UINT16 *ram = (UINT16*)c45RoadRAM;
84
85 INT32 offset = (address & 0x1ffff) ^ 1;
86
87 if (offset < 0x1fa00) // tiles
88 {
89 if (data != ram[offset]) {
90 c45RoadRAM[offset] = data;
91 update_tile_pixel(offset/2);
92 }
93 }
94 else // scroll regs
95 {
96 c45RoadRAM[offset] = data;
97 }
98 }
99
c45RoadMap68k(UINT32 address)100 void c45RoadMap68k(UINT32 address)
101 {
102 SekMapHandler(7, address, address | 0x1ffff, MAP_WRITE);
103 SekSetWriteWordHandler(7, c45_road_write_word);
104 SekSetWriteByteHandler(7, c45_road_write_byte);
105
106 SekMapMemory(c45RoadRAM, address, address | 0x0ffff, MAP_WRITE);
107 }
108
predraw_c45_road_tiles_line(UINT32 line,UINT32 startx,UINT32 pixels_wide,UINT32 incx)109 static void predraw_c45_road_tiles_line(UINT32 line, UINT32 startx, UINT32 pixels_wide, UINT32 incx)
110 {
111 UINT16 *ram = (UINT16*)c45RoadRAM;
112
113 INT32 startx_shift = startx >> 20;
114 INT32 endx_shift = (((pixels_wide * incx) >> 20) + 1) + startx_shift;
115
116 INT32 offs = ((line / 16) * 64) + startx_shift;
117
118 INT32 code_offset = (line & 0xf) * 16;
119
120 for (INT32 sx = startx_shift; sx < endx_shift; sx++, offs++)
121 {
122 INT32 color = ((BURN_ENDIAN_SWAP_INT16(ram[offs]) >> 10) << 2);
123 UINT8 *gfx = c45RoadTiles + ((BURN_ENDIAN_SWAP_INT16(ram[offs]) & 0x3ff) * 256 + code_offset);
124 UINT8 *clut = c45RoadClut + color;
125
126 for (INT32 x = 0; x < 16; x++)
127 {
128 c45RoadBitmap[((sx * 16) + x) & 0x3ff] = BURN_ENDIAN_SWAP_INT16(clut[gfx[x]] + 0xf00);
129 }
130 }
131 }
132
c45RoadDraw()133 void c45RoadDraw()
134 {
135 INT32 min_x, min_y, max_x, max_y;
136
137 GenericTilesGetClip(&min_x, &max_x, &min_y, &max_y);
138
139 UINT16 *m_lineram = (UINT16*)(c45RoadRAM + 0x1fa00);
140
141 UINT32 yscroll = BURN_ENDIAN_SWAP_INT16(m_lineram[0x3fe/2]);
142
143 static INT32 ROAD_COLS = 64;
144 static INT32 ROAD_ROWS = 512;
145 static INT32 ROAD_TILE_SIZE = 16;
146 static INT32 ROAD_TILEMAP_WIDTH = ROAD_TILE_SIZE * ROAD_COLS;
147 static INT32 ROAD_TILEMAP_HEIGHT = ROAD_TILE_SIZE * ROAD_ROWS;
148
149 // loop over scanlines
150 for (INT32 y = min_y; y < max_y; y++)
151 {
152 // skip if we are not the right priority
153 INT32 screenx = BURN_ENDIAN_SWAP_INT16(m_lineram[y + 15]);
154
155 INT32 pri = (screenx & 0xf000) >> 12;
156
157 // skip if we don't have a valid zoom factor
158 UINT32 zoomx = BURN_ENDIAN_SWAP_INT16(m_lineram[0x400/2 + y + 15]) & 0x3ff;
159 if (zoomx == 0)
160 continue;
161
162 // skip if we don't have a valid source increment
163 UINT32 sourcey = BURN_ENDIAN_SWAP_INT16(m_lineram[0x200/2 + y + 15]) + yscroll;
164 const UINT16 *source_gfx = c45RoadBitmap;
165 UINT32 dsourcex = (ROAD_TILEMAP_WIDTH << 16) / zoomx;
166 if (dsourcex == 0)
167 continue;
168
169 // mask off priority bits and sign-extend
170 screenx &= 0x0fff;
171 if (screenx & 0x0800)
172 screenx |= ~0x7ff;
173
174 // adjust the horizontal placement
175 screenx -= (64+16); // needs adjustment to left
176
177 INT32 numpixels = (44 * ROAD_TILE_SIZE << 16) / dsourcex;
178 UINT32 sourcex = 0;
179
180 // crop left
181 INT32 clip_pixels = min_x - screenx;
182 if (clip_pixels > 0)
183 {
184 numpixels -= clip_pixels;
185 sourcex += dsourcex*clip_pixels;
186 screenx = min_x;
187 }
188
189 // crop right
190 clip_pixels = (screenx + numpixels) - (max_x + 1);
191 if (clip_pixels > 0)
192 numpixels -= clip_pixels;
193
194 UINT16 *dest = pTransDraw + y * nScreenWidth;
195 UINT8 *pdest = pPrioDraw + y * nScreenWidth;
196
197 predraw_c45_road_tiles_line(sourcey & (ROAD_TILEMAP_HEIGHT - 1), sourcex, numpixels, dsourcex);
198
199 while (numpixels-- > 0)
200 {
201 INT32 destpri = pdest[screenx];
202 INT32 pixel = source_gfx[sourcex >> 16];
203
204 if (destpri <= pri ) {
205 if (pixel != c45_transparent_color) {
206 dest[screenx] = BURN_ENDIAN_SWAP_INT16(pixel);
207 }
208 pdest[screenx] = pri;
209 }
210 screenx++;
211 sourcex += dsourcex;
212 }
213 }
214 }
215
216 // call from save state
c45RoadState(INT32 nAction)217 void c45RoadState(INT32 nAction)
218 {
219 if (c45RoadRAM == NULL) return;
220
221 struct BurnArea ba;
222 memset(&ba, 0, sizeof(ba));
223 ba.Data = c45RoadRAM;
224 ba.nLen = 0x20000;
225 ba.szName = "C45 Road RAM";
226 BurnAcb(&ba);
227
228 if (nAction & ACB_WRITE)
229 {
230 for (INT32 i = 0x10000; i < 0x1fa00; i++) {
231 update_tile_pixel(i / 2);
232 }
233 #if 0
234 INT32 Planes[2] = { 0, 8 };
235 INT32 XOffs[16] = { STEP8(0, 1), STEP8(16, 1) };
236 INT32 YOffs[16] = { STEP16(0, 32) };
237
238 GfxDecode(0x0400, 2, 16, 16, Planes, XOffs, YOffs, 0x200, c45RoadRAM + 0x10000, c45RoadTiles);
239 #endif
240 }
241 }
242