1 // license:BSD-3-Clause
2 // copyright-holders:Brad Oliver
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 "includes/espial.h"
13 
14 /***************************************************************************
15 
16   Convert the color PROMs into a more useable format.
17 
18   Espial has two 256x4 palette PROMs.
19 
20   I don't know for sure how the palette PROMs are connected to the RGB
21   output, but it's probably the usual:
22 
23   bit 3 -- 220 ohm resistor  -- BLUE
24         -- 470 ohm resistor  -- BLUE
25         -- 220 ohm resistor  -- GREEN
26   bit 0 -- 470 ohm resistor  -- GREEN
27   bit 3 -- 1  kohm resistor  -- GREEN
28         -- 220 ohm resistor  -- RED
29         -- 470 ohm resistor  -- RED
30   bit 0 -- 1  kohm resistor  -- RED
31 
32 ***************************************************************************/
33 
espial_palette(palette_device & palette) const34 void espial_state::espial_palette(palette_device &palette) const
35 {
36 	uint8_t const *const color_prom = memregion("proms")->base();
37 
38 	for (int i = 0; i < palette.entries(); i++)
39 	{
40 		int bit0, bit1, bit2;
41 
42 		// red component
43 		bit0 = BIT(color_prom[i], 0);
44 		bit1 = BIT(color_prom[i], 1);
45 		bit2 = BIT(color_prom[i], 2);
46 		int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
47 		// green component
48 		bit0 = BIT(color_prom[i], 3);
49 		bit1 = BIT(color_prom[i + palette.entries()], 0);
50 		bit2 = BIT(color_prom[i + palette.entries()], 1);
51 		int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
52 		// blue component
53 		bit0 = 0;
54 		bit1 = BIT(color_prom[i + palette.entries()], 2);
55 		bit2 = BIT(color_prom[i + palette.entries()], 3);
56 		int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
57 
58 		palette.set_pen_color(i, rgb_t(r, g, b));
59 	}
60 }
61 
62 
63 
64 /***************************************************************************
65 
66   Callbacks for the TileMap code
67 
68 ***************************************************************************/
69 
TILE_GET_INFO_MEMBER(espial_state::get_tile_info)70 TILE_GET_INFO_MEMBER(espial_state::get_tile_info)
71 {
72 	uint8_t code = m_videoram[tile_index];
73 	uint8_t col = m_colorram[tile_index];
74 	uint8_t attr = m_attributeram[tile_index];
75 	tileinfo.set(0,
76 					code | ((attr & 0x03) << 8),
77 					col & 0x3f,
78 					TILE_FLIPYX(attr >> 2));
79 }
80 
81 
82 
83 /*************************************
84  *
85  *  Video system start
86  *
87  *************************************/
88 
video_start()89 void espial_state::video_start()
90 {
91 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(espial_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
92 	m_bg_tilemap->set_scroll_cols(32);
93 
94 	save_item(NAME(m_flipscreen));
95 }
96 
VIDEO_START_MEMBER(espial_state,netwars)97 VIDEO_START_MEMBER(espial_state,netwars)
98 {
99 	/* Net Wars has a tile map that's twice as big as Espial's */
100 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(espial_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 64);
101 
102 	m_bg_tilemap->set_scroll_cols(32);
103 	m_bg_tilemap->set_scrolldy(0, 0x100);
104 
105 	save_item(NAME(m_flipscreen));
106 }
107 
108 
109 /*************************************
110  *
111  *  Memory handlers
112  *
113  *************************************/
114 
espial_videoram_w(offs_t offset,uint8_t data)115 void espial_state::espial_videoram_w(offs_t offset, uint8_t data)
116 {
117 	m_videoram[offset] = data;
118 	m_bg_tilemap->mark_tile_dirty(offset);
119 }
120 
121 
espial_colorram_w(offs_t offset,uint8_t data)122 void espial_state::espial_colorram_w(offs_t offset, uint8_t data)
123 {
124 	m_colorram[offset] = data;
125 	m_bg_tilemap->mark_tile_dirty(offset);
126 }
127 
128 
espial_attributeram_w(offs_t offset,uint8_t data)129 void espial_state::espial_attributeram_w(offs_t offset, uint8_t data)
130 {
131 	m_attributeram[offset] = data;
132 	m_bg_tilemap->mark_tile_dirty(offset);
133 }
134 
135 
espial_scrollram_w(offs_t offset,uint8_t data)136 void espial_state::espial_scrollram_w(offs_t offset, uint8_t data)
137 {
138 	m_scrollram[offset] = data;
139 	m_bg_tilemap->set_scrolly(offset, data);
140 }
141 
142 
espial_flipscreen_w(uint8_t data)143 void espial_state::espial_flipscreen_w(uint8_t data)
144 {
145 	m_flipscreen = data;
146 	m_bg_tilemap->set_flip(m_flipscreen ? TILEMAP_FLIPX | TILEMAP_FLIPY : 0);
147 }
148 
149 
150 /*************************************
151  *
152  *  Video update
153  *
154  *************************************/
155 
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)156 void espial_state::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect )
157 {
158 	int offs;
159 
160 	/* Note that it is important to draw them exactly in this */
161 	/* order, to have the correct priorities. */
162 	for (offs = 0; offs < 16; offs++)
163 	{
164 		int sx, sy, code, color, flipx, flipy;
165 
166 
167 		sx = m_spriteram_1[offs + 16];
168 		sy = m_spriteram_2[offs];
169 		code = m_spriteram_1[offs] >> 1;
170 		color = m_spriteram_2[offs + 16];
171 		flipx = m_spriteram_3[offs] & 0x04;
172 		flipy = m_spriteram_3[offs] & 0x08;
173 
174 		if (m_flipscreen)
175 		{
176 			flipx = !flipx;
177 			flipy = !flipy;
178 		}
179 		else
180 		{
181 			sy = 240 - sy;
182 		}
183 
184 		if (m_spriteram_1[offs] & 1) /* double height */
185 		{
186 			if (m_flipscreen)
187 			{
188 				m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
189 						code,color,
190 						flipx,flipy,
191 						sx,sy + 16,0);
192 				m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
193 						code + 1,
194 						color,
195 						flipx,flipy,
196 						sx,sy,0);
197 			}
198 			else
199 			{
200 				m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
201 						code,color,
202 						flipx,flipy,
203 						sx,sy - 16,0);
204 				m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
205 						code + 1,color,
206 						flipx,flipy,
207 						sx,sy,0);
208 			}
209 		}
210 		else
211 		{
212 			m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
213 					code,color,
214 					flipx,flipy,
215 					sx,sy,0);
216 		}
217 	}
218 }
219 
220 
screen_update_espial(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)221 uint32_t espial_state::screen_update_espial(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
222 {
223 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
224 	draw_sprites(bitmap, cliprect);
225 	return 0;
226 }
227