1 // license:BSD-3-Clause
2 // copyright-holders:Phil Stroffolino, Aaron Giles, Alex W. Jackson
3 /**************************************************************************************************************/
4 /*
5 Land Line Buffer
6 Land Generator
7 0xf,0x7,0xe,0x6,0xd,0x5,0xc,0x4,
8 0xb,0x3,0xa,0x2,0x9,0x1,0x8,0x0
9
10 */
11
12 /* Preliminary! The road circuitry is identical for all the driving games.
13 *
14 * There are several chunks of RAM
15 *
16 * Road Tilemap:
17 * 0x00000..0x0ffff 64x512 tilemap
18 *
19 * Road Tiles:
20 * 0x10000..0x1f9ff 16x16x2bpp tiles
21 *
22 *
23 * Line Attributes:
24 *
25 * 0x1fa00..0x1fbdf xxx- ---- ---- ---- priority
26 * ---- xxxx xxxx xxxx xscroll
27 *
28 * 0x1fbfe horizontal adjust?
29 * 0x0017
30 * 0x0018 (Final Lap3)
31 *
32 * 0x1fc00..0x1fddf selects line in source bitmap
33 * 0x1fdfe yscroll
34 *
35 * 0x1fe00..0x1ffdf ---- --xx xxxx xxxx zoomx
36 * 0x1fffd always 0xffff 0xffff?
37 */
38
39 #include "emu.h"
40 #include "video/c45.h"
41
42
43 //****************************************************************************
44 // CONSTANTS
45 //****************************************************************************
46
47 // device type definition
48 DEFINE_DEVICE_TYPE(NAMCO_C45_ROAD, namco_c45_road_device, "namco_c45_road", "Namco C45 Road")
49
50
51 const gfx_layout namco_c45_road_device::tilelayout =
52 {
53 ROAD_TILE_SIZE, ROAD_TILE_SIZE,
54 RGN_FRAC(1,1),
55 2,
56 { 0, 8 },
57 { STEP8(0, 1), STEP8(16, 1) },
58 { STEP16(0, 32) },
59 0x200 // offset to next tile
60 };
61
62
63 GFXDECODE_MEMBER( namco_c45_road_device::gfxinfo )
64 GFXDECODE_DEVICE_RAM( "tileram", 0, tilelayout, 0xf00, 64 )
65 GFXDECODE_END
66
67
map(address_map & map)68 void namco_c45_road_device::map(address_map &map)
69 {
70 map(0x00000, 0x0ffff).ram().w(FUNC(namco_c45_road_device::tilemap_w)).share("tmapram");
71 map(0x10000, 0x1f9ff).ram().w(FUNC(namco_c45_road_device::tileram_w)).share("tileram");
72 map(0x1fa00, 0x1ffff).ram().share("lineram");
73 }
74
75
76 //-------------------------------------------------
77 // namco_c45_road_device -- constructor
78 //-------------------------------------------------
79
namco_c45_road_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)80 namco_c45_road_device::namco_c45_road_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
81 device_t(mconfig, NAMCO_C45_ROAD, tag, owner, clock),
82 device_gfx_interface(mconfig, *this, gfxinfo),
83 device_memory_interface(mconfig, *this),
84 m_space_config("c45", ENDIANNESS_BIG, 16, 17, 0, address_map_constructor(FUNC(namco_c45_road_device::map), this)),
85 m_tmapram(*this, "tmapram"),
86 m_tileram(*this, "tileram"),
87 m_lineram(*this, "lineram"),
88 m_clut(*this, "clut"),
89 m_transparent_color(~0)
90 {
91 }
92
93
94
95 // We need these trampolines for now because uplift_submaps()
96 // can't deal with address maps that contain RAM.
97 // We need to explicitly use device_memory_interface::space()
98 // because read/write handlers have a parameter called 'space'
99
100 //-------------------------------------------------
101 // read -- CPU read from our address space
102 //-------------------------------------------------
103
read(offs_t offset)104 uint16_t namco_c45_road_device::read(offs_t offset)
105 {
106 return device_memory_interface::space().read_word(offset*2);
107 }
108
109
110 //-------------------------------------------------
111 // write -- CPU write to our address space
112 //-------------------------------------------------
113
write(offs_t offset,uint16_t data,uint16_t mem_mask)114 void namco_c45_road_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
115 {
116 device_memory_interface::space().write_word(offset*2, data, mem_mask);
117 }
118
119
120 //-------------------------------------------------
121 // tilemap_w -- write to tilemap RAM
122 //-------------------------------------------------
123
tilemap_w(offs_t offset,uint16_t data,uint16_t mem_mask)124 void namco_c45_road_device::tilemap_w(offs_t offset, uint16_t data, uint16_t mem_mask)
125 {
126 COMBINE_DATA(&m_tmapram[offset]);
127 m_tilemap->mark_tile_dirty(offset);
128 }
129
130
131 //-------------------------------------------------
132 // tileram_w -- write to tile RAM
133 //-------------------------------------------------
134
tileram_w(offs_t offset,uint16_t data,uint16_t mem_mask)135 void namco_c45_road_device::tileram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
136 {
137 COMBINE_DATA(&m_tileram[offset]);
138 gfx(0)->mark_dirty(offset / WORDS_PER_ROAD_TILE);
139 }
140
141
142 //-------------------------------------------------
143 // draw -- render to the target bitmap
144 //-------------------------------------------------
145
draw(bitmap_ind16 & bitmap,const rectangle & cliprect,int pri)146 void namco_c45_road_device::draw(bitmap_ind16 &bitmap, const rectangle &cliprect, int pri)
147 {
148 bitmap_ind16 &source_bitmap = m_tilemap->pixmap();
149 unsigned yscroll = m_lineram[0x3fe/2];
150
151 // loop over scanlines
152 for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
153 {
154 // skip if we are not the right priority
155 int screenx = m_lineram[y + 15];
156 if (pri != ((screenx & 0xf000) >> 12))
157 continue;
158
159 // skip if we don't have a valid zoom factor
160 unsigned zoomx = m_lineram[0x400/2 + y + 15] & 0x3ff;
161 if (zoomx == 0)
162 continue;
163
164 // skip if we don't have a valid source increment
165 unsigned sourcey = m_lineram[0x200/2 + y + 15] + yscroll;
166 const uint16_t *source_gfx = &source_bitmap.pix(sourcey & (ROAD_TILEMAP_HEIGHT - 1));
167 unsigned dsourcex = (ROAD_TILEMAP_WIDTH << 16) / zoomx;
168 if (dsourcex == 0)
169 continue;
170
171 // mask off priority bits and sign-extend
172 screenx &= 0x0fff;
173 if (screenx & 0x0800)
174 screenx |= ~0x7ff;
175
176 // adjust the horizontal placement
177 screenx -= 64; // needs adjustment to left
178
179 int numpixels = (44 * ROAD_TILE_SIZE << 16) / dsourcex;
180 unsigned sourcex = 0;
181
182 // crop left
183 int clip_pixels = cliprect.min_x - screenx;
184 if (clip_pixels > 0)
185 {
186 numpixels -= clip_pixels;
187 sourcex += dsourcex*clip_pixels;
188 screenx = cliprect.min_x;
189 }
190
191 // crop right
192 clip_pixels = (screenx + numpixels) - (cliprect.max_x + 1);
193 if (clip_pixels > 0)
194 numpixels -= clip_pixels;
195
196 // TBA: work out palette mapping for Final Lap, Suzuka
197
198 // BUT: support transparent color for Thunder Ceptor
199 uint16_t *dest = &bitmap.pix(y);
200 if (m_transparent_color != ~0)
201 {
202 while (numpixels-- > 0)
203 {
204 int pen = source_gfx[sourcex >> 16];
205 if (palette().pen_indirect(pen) != m_transparent_color)
206 {
207 if (m_clut != nullptr)
208 pen = (pen & ~0xff) | m_clut[pen & 0xff];
209 dest[screenx] = pen;
210 }
211 screenx++;
212 sourcex += dsourcex;
213 }
214 }
215 else
216 {
217 while (numpixels-- > 0)
218 {
219 int pen = source_gfx[sourcex >> 16];
220 if (m_clut != nullptr)
221 pen = (pen & ~0xff) | m_clut[pen & 0xff];
222 dest[screenx++] = pen;
223 sourcex += dsourcex;
224 }
225 }
226 }
227 }
228
229
230 //-------------------------------------------------
231 // device_start -- device startup
232 //-------------------------------------------------
233
device_start()234 void namco_c45_road_device::device_start()
235 {
236 // create a tilemap for the road
237 m_tilemap = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(namco_c45_road_device::get_road_info)),
238 TILEMAP_SCAN_ROWS, ROAD_TILE_SIZE, ROAD_TILE_SIZE, ROAD_COLS, ROAD_ROWS);
239 }
240
241
242 //-------------------------------------------------
243 // memory_space_config - return a description of
244 // any address spaces owned by this device
245 //-------------------------------------------------
246
memory_space_config() const247 device_memory_interface::space_config_vector namco_c45_road_device::memory_space_config() const
248 {
249 return space_config_vector {
250 std::make_pair(0, &m_space_config)
251 };
252 }
253
254
255 //-------------------------------------------------
256 // get_road_info -- tilemap callback
257 //-------------------------------------------------
258
TILE_GET_INFO_MEMBER(namco_c45_road_device::get_road_info)259 TILE_GET_INFO_MEMBER( namco_c45_road_device::get_road_info )
260 {
261 // ------xx xxxxxxxx tile number
262 // xxxxxx-- -------- palette select
263 uint16_t data = m_tmapram[tile_index];
264 int tile = data & 0x3ff;
265 int color = data >> 10;
266 tileinfo.set(0, tile, color, 0);
267 }
268