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