1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria
3 /***************************************************************************
4 
5   video.c
6 
7   Functions to emulate the video hardware of the machine.
8 
9 ***************************************************************************/
10 
11 #include "emu.h"
12 #include "video/resnet.h"
13 #include "includes/zaccaria.h"
14 
15 
16 /***************************************************************************
17 
18   Convert the color PROMs into a more useable format.
19 
20 
21 Here's the hookup from the proms (82s131) to the r-g-b-outputs
22 
23      Prom 9F        74LS374
24     -----------   ____________
25        12         |  3   2   |---680 ohm----| blue out
26        11         |  4   5   |---1k ohm-----| (+ 470 ohm pulldown)
27        10         |  7   6   |---820 ohm-------|
28         9         |  8   9   |---1k ohm--------| green out
29      Prom 9G      |          |                 | (+ 390 ohm pulldown)
30        12         |  13  12  |---1.2k ohm------|
31        11         |  14  15  |---820 ohm----------|
32        10         |  17  16  |---1k ohm-----------| red out
33         9         |  18  19  |---1.2k ohm---------| (+ 390 ohm pulldown)
34                   |__________|
35 
36 
37 ***************************************************************************/
zaccaria_palette(palette_device & palette) const38 void zaccaria_state::zaccaria_palette(palette_device &palette) const
39 {
40 	uint8_t const *const color_prom = memregion("proms")->base();
41 	static constexpr int resistances_rg[] = { 1200, 1000, 820 };
42 	static constexpr int resistances_b[]  = { 1000, 820 };
43 
44 	double weights_rg[3], weights_b[2];
45 	compute_resistor_weights(0, 0xff, -1.0,
46 			3, resistances_rg, weights_rg, 390, 0,
47 			2, resistances_b,  weights_b,  470, 0,
48 			0, nullptr, nullptr, 0, 0);
49 
50 	for (int i = 0; i < 0x200; i++)
51 	{
52 		/*
53 		  TODO: I'm not sure, but I think that pen 0 must always be black, otherwise
54 		  there's some junk brown background in Jack Rabbit.
55 		  From the schematics it seems that the background color can be changed, but
56 		  I'm not sure where it would be taken from; I think the high bits of
57 		  attributesram, but they are always 0 in these games so they would turn out
58 		  black anyway.
59 		 */
60 		if (!(i & 0x038))
61 			palette.set_indirect_color(i, rgb_t::black());
62 		else
63 		{
64 			int bit0, bit1, bit2;
65 
66 			// red component
67 			bit0 = BIT(color_prom[i + 0x000], 3);
68 			bit1 = BIT(color_prom[i + 0x000], 2);
69 			bit2 = BIT(color_prom[i + 0x000], 1);
70 			int const r = combine_weights(weights_rg, bit0, bit1, bit2);
71 
72 			// green component
73 			bit0 = BIT(color_prom[i + 0x000], 0);
74 			bit1 = BIT(color_prom[i + 0x200], 3);
75 			bit2 = BIT(color_prom[i + 0x200], 2);
76 			int const g = combine_weights(weights_rg, bit0, bit1, bit2);
77 
78 			// blue component
79 			bit0 = BIT(color_prom[i + 0x200], 1);
80 			bit1 = BIT(color_prom[i + 0x200], 0);
81 			int const b = combine_weights(weights_b, bit0, bit1);
82 
83 			palette.set_indirect_color(i, rgb_t(r, g, b));
84 		}
85 	}
86 
87 	/* There are 512 unique colors, which seem to be organized in 8 blocks */
88 	/* of 64. In each block, colors are not in the usual sequential order */
89 	/* but in interleaved order, like Phoenix. Additionally, colors for */
90 	/* background and sprites are interleaved. */
91 	for (int i = 0; i < 8; i++)
92 		for (int j = 0; j < 4; j++)
93 			for (int k = 0; k < 8; k++)
94 				// swap j and k to make the colors sequential
95 				palette.set_pen_indirect(0 + 32 * i + 8 * j + k, 64 * i + 8 * k + 2 * j);
96 
97 	for (int i = 0; i < 8; i++)
98 		for (int j = 0; j < 4; j++)
99 			for (int k = 0; k < 8; k++)
100 				// swap j and k to make the colors sequential
101 				palette.set_pen_indirect(256 + 32 * i + 8 * j + k, 64 * i + 8 * k + 2 * j + 1);
102 }
103 
104 
105 
106 /***************************************************************************
107 
108   Callbacks for the TileMap code
109 
110 ***************************************************************************/
111 
TILE_GET_INFO_MEMBER(zaccaria_state::get_tile_info)112 TILE_GET_INFO_MEMBER(zaccaria_state::get_tile_info)
113 {
114 	uint8_t attr = m_videoram[tile_index + 0x400];
115 	tileinfo.set(0,
116 			m_videoram[tile_index] + ((attr & 0x03) << 8),
117 			((attr & 0x0c) >> 2) + ((m_attributesram[2 * (tile_index % 32) + 1] & 0x07) << 2),
118 			0);
119 }
120 
121 
122 
123 /***************************************************************************
124 
125   Start the video hardware emulation.
126 
127 ***************************************************************************/
128 
video_start()129 void zaccaria_state::video_start()
130 {
131 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(zaccaria_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
132 
133 	m_bg_tilemap->set_scroll_cols(32);
134 }
135 
136 
137 
138 /***************************************************************************
139 
140   Memory handlers
141 
142 ***************************************************************************/
143 
videoram_w(offs_t offset,uint8_t data)144 void zaccaria_state::videoram_w(offs_t offset, uint8_t data)
145 {
146 	m_videoram[offset] = data;
147 	m_bg_tilemap->mark_tile_dirty(offset & 0x3ff);
148 }
149 
attributes_w(offs_t offset,uint8_t data)150 void zaccaria_state::attributes_w(offs_t offset, uint8_t data)
151 {
152 	if (offset & 1)
153 	{
154 		if (m_attributesram[offset] != data)
155 		{
156 			int i;
157 
158 			for (i = offset / 2;i < 0x400;i += 32)
159 				m_bg_tilemap->mark_tile_dirty(i);
160 		}
161 	}
162 	else
163 		m_bg_tilemap->set_scrolly(offset / 2,data);
164 
165 	m_attributesram[offset] = data;
166 }
167 
WRITE_LINE_MEMBER(zaccaria_state::flip_screen_x_w)168 WRITE_LINE_MEMBER(zaccaria_state::flip_screen_x_w)
169 {
170 	flip_screen_x_set(state);
171 }
172 
WRITE_LINE_MEMBER(zaccaria_state::flip_screen_y_w)173 WRITE_LINE_MEMBER(zaccaria_state::flip_screen_y_w)
174 {
175 	flip_screen_y_set(state);
176 }
177 
178 
179 
180 /***************************************************************************
181 
182   Display refresh
183 
184 ***************************************************************************/
185 
186 /* sprite format:
187 
188   76543210
189 0 xxxxxxxx x
190 1 x....... flipy
191   .x...... flipx
192   ..xxxxxx code low
193 2 xx...... code high
194   ..xxx... ?
195   .....xxx color
196 3 xxxxxxxx y
197 
198 offsets 1 and 2 are swapped if accessed from spriteram2
199 
200 */
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,uint8_t * spriteram,int color,int section)201 void zaccaria_state::draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect,uint8_t *spriteram,int color,int section)
202 {
203 	int offs,o1 = 1,o2 = 2;
204 
205 	if (section)
206 	{
207 		o1 = 2;
208 		o2 = 1;
209 	}
210 
211 	for (offs = 0;offs < 0x20;offs += 4)
212 	{
213 		int sx = spriteram[offs + 3] + 1;
214 		int sy = 242 - spriteram[offs];
215 		int flipx = spriteram[offs + o1] & 0x40;
216 		int flipy = spriteram[offs + o1] & 0x80;
217 
218 		if (sx == 1) continue;
219 
220 		if (flip_screen_x())
221 		{
222 			sx = 240 - sx;
223 			flipx = !flipx;
224 		}
225 		if (flip_screen_y())
226 		{
227 			sy = 240 - sy;
228 			flipy = !flipy;
229 		}
230 
231 		m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
232 				(spriteram[offs + o1] & 0x3f) + (spriteram[offs + o2] & 0xc0),
233 				((spriteram[offs + o2] & 0x07) << 2) | color,
234 				flipx,flipy,sx,sy,0);
235 	}
236 }
237 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)238 uint32_t zaccaria_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
239 {
240 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0,0);
241 
242 	// 3 layers of sprites, each with their own palette and priorities
243 	// Not perfect yet, does spriteram(1) layer have a priority bit somewhere?
244 	draw_sprites(bitmap,cliprect,m_spriteram2,2,1);
245 	draw_sprites(bitmap,cliprect,m_spriteram,1,0);
246 	draw_sprites(bitmap,cliprect,m_spriteram2+0x20,0,1);
247 
248 	return 0;
249 }
250