1 // license:BSD-3-Clause
2 // copyright-holders:Allard van der Bas
3 /***************************************************************************
4 
5     Pooyan
6 
7 ***************************************************************************/
8 
9 #include "emu.h"
10 #include "video/resnet.h"
11 #include "includes/pooyan.h"
12 
13 /***************************************************************************
14 
15   Convert the color PROMs into a more useable format.
16 
17   Pooyan has one 32x8 palette PROM and two 256x4 lookup table PROMs
18   (one for characters, one for sprites).
19   The palette PROM is connected to the RGB output this way:
20 
21   bit 7 -- 220 ohm resistor  -- BLUE
22         -- 470 ohm resistor  -- BLUE
23         -- 220 ohm resistor  -- GREEN
24         -- 470 ohm resistor  -- GREEN
25         -- 1  kohm resistor  -- GREEN
26         -- 220 ohm resistor  -- RED
27         -- 470 ohm resistor  -- RED
28   bit 0 -- 1  kohm resistor  -- RED
29 
30 ***************************************************************************/
31 
pooyan_palette(palette_device & palette) const32 void pooyan_state::pooyan_palette(palette_device &palette) const
33 {
34 	const uint8_t *color_prom = memregion("proms")->base();
35 	static constexpr int resistances_rg[3] = { 1000, 470, 220 };
36 	static constexpr int resistances_b [2] = { 470, 220 };
37 
38 	// compute the color output resistor weights
39 	double rweights[3], gweights[3], bweights[2];
40 	compute_resistor_weights(0, 255, -1.0,
41 			3, resistances_rg, rweights, 1000, 0,
42 			3, resistances_rg, gweights, 1000, 0,
43 			2, resistances_b,  bweights, 1000, 0);
44 
45 	// create a lookup table for the palette
46 	for (int i = 0; i < 0x20; i++)
47 	{
48 		int bit0, bit1, bit2;
49 
50 		// red component
51 		bit0 = BIT(color_prom[i], 0);
52 		bit1 = BIT(color_prom[i], 1);
53 		bit2 = BIT(color_prom[i], 2);
54 		int const r = combine_weights(rweights, bit0, bit1, bit2);
55 
56 		// green component
57 		bit0 = BIT(color_prom[i], 3);
58 		bit1 = BIT(color_prom[i], 4);
59 		bit2 = BIT(color_prom[i], 5);
60 		int const g = combine_weights(gweights, bit0, bit1, bit2);
61 
62 		// blue component
63 		bit0 = BIT(color_prom[i], 6);
64 		bit1 = BIT(color_prom[i], 7);
65 		int const b = combine_weights(bweights, bit0, bit1);
66 
67 		palette.set_indirect_color(i, rgb_t(r, g, b));
68 	}
69 
70 	// color_prom now points to the beginning of the lookup table
71 	color_prom += 0x20;
72 
73 	// characters
74 	for (int i = 0; i < 0x100; i++)
75 	{
76 		uint8_t const ctabentry = (color_prom[i] & 0x0f) | 0x10;
77 		palette.set_pen_indirect(i, ctabentry);
78 	}
79 
80 	// sprites
81 	for (int i = 0x100; i < 0x200; i++)
82 	{
83 		uint8_t const ctabentry = color_prom[i] & 0x0f;
84 		palette.set_pen_indirect(i, ctabentry);
85 	}
86 }
87 
88 
89 
90 /*************************************
91  *
92  *  Tilemap info callback
93  *
94  *************************************/
95 
TILE_GET_INFO_MEMBER(pooyan_state::get_bg_tile_info)96 TILE_GET_INFO_MEMBER(pooyan_state::get_bg_tile_info)
97 {
98 	int attr = m_colorram[tile_index];
99 	int code = m_videoram[tile_index];
100 	int color = attr & 0x0f;
101 	int flags = TILE_FLIPYX(attr >> 6);
102 
103 	tileinfo.set(0, code, color, flags);
104 }
105 
106 
107 
108 /*************************************
109  *
110  *  Video startup
111  *
112  *************************************/
113 
video_start()114 void pooyan_state::video_start()
115 {
116 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(pooyan_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
117 }
118 
119 
120 
121 /*************************************
122  *
123  *  Memory write handlers
124  *
125  *************************************/
126 
videoram_w(offs_t offset,uint8_t data)127 void pooyan_state::videoram_w(offs_t offset, uint8_t data)
128 {
129 	m_videoram[offset] = data;
130 	m_bg_tilemap->mark_tile_dirty(offset);
131 }
132 
133 
colorram_w(offs_t offset,uint8_t data)134 void pooyan_state::colorram_w(offs_t offset, uint8_t data)
135 {
136 	m_colorram[offset] = data;
137 	m_bg_tilemap->mark_tile_dirty(offset);
138 }
139 
140 
WRITE_LINE_MEMBER(pooyan_state::flipscreen_w)141 WRITE_LINE_MEMBER(pooyan_state::flipscreen_w)
142 {
143 	flip_screen_set(!state);
144 }
145 
146 
147 
148 /*************************************
149  *
150  *  Sprite rendering
151  *
152  *************************************/
153 
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)154 void pooyan_state::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect )
155 {
156 	for (int offs = 0x10; offs < 0x40; offs += 2)
157 	{
158 		int sx = m_spriteram[offs];
159 		int sy = 240 - m_spriteram2[offs + 1];
160 
161 		int code = m_spriteram[offs + 1];
162 		int color = m_spriteram2[offs] & 0x0f;
163 		int flipx = ~m_spriteram2[offs] & 0x40;
164 		int flipy = m_spriteram2[offs] & 0x80;
165 
166 
167 			m_gfxdecode->gfx(1)->transmask(bitmap,cliprect,
168 			code,
169 			color,
170 			flipx, flipy,
171 			sx, sy,
172 			m_palette->transpen_mask(*m_gfxdecode->gfx(1), color, 0));
173 	}
174 }
175 
176 
177 
178 /*************************************
179  *
180  *  Video update
181  *
182  *************************************/
183 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)184 uint32_t pooyan_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
185 {
186 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
187 	draw_sprites(bitmap, cliprect);
188 	return 0;
189 }
190