1 // license:BSD-3-Clause
2 // copyright-holders:R. Belmont
3 /***************************************************************************
4
5 Lapis ProColor Server 8*16 video card
6
7 FsFF6001: DAC color # (seems to have the data bits perfectly reversed)
8 FsFF6003: DAC color write (not bitswapped)
9 FsFF6017: Mode (13 = 1bpp, 17 = 2bpp, 1b = 4bpp, 1e = 8bpp, 0a = 15bpp)
10 FsFF7000: Bit 2 is VBL IRQ enable/ack
11 FsFF7001: Bit 0 is VBL status
12
13 ***************************************************************************/
14
15 #include "emu.h"
16 #include "pds30_procolor816.h"
17 #include "screen.h"
18
19 #define PROCOLOR816_SCREEN_NAME "cb264_screen"
20 #define PROCOLOR816_ROM_REGION "cb264_rom"
21
22 #define VRAM_SIZE (0x200000) // 2 megs?
23
24
25 ROM_START( procolor816 )
26 ROM_REGION(0x8000, PROCOLOR816_ROM_REGION, 0)
CRC(ebef6168)27 ROM_LOAD( "procolor_ver60590.bin", 0x000000, 0x008000, CRC(ebef6168) SHA1(e41ecc7d12fc13bc74f9223ca02920e8a7eb072b) )
28 ROM_END
29
30 //**************************************************************************
31 // GLOBAL VARIABLES
32 //**************************************************************************
33
34 DEFINE_DEVICE_TYPE(PDS030_PROCOLOR816, nubus_procolor816_device, "pd3_pc16", "Lapis ProColor Server 8*16")
35
36
37 //-------------------------------------------------
38 // device_add_mconfig - add device configuration
39 //-------------------------------------------------
40
41 void nubus_procolor816_device::device_add_mconfig(machine_config &config)
42 {
43 screen_device &screen(SCREEN(config, PROCOLOR816_SCREEN_NAME, SCREEN_TYPE_RASTER));
44 screen.set_screen_update(FUNC(nubus_procolor816_device::screen_update));
45 screen.set_raw(25175000, 800, 0, 640, 525, 0, 480);
46 screen.set_size(1024, 768);
47 screen.set_visarea(0, 640-1, 0, 480-1);
48 }
49
50 //-------------------------------------------------
51 // rom_region - device-specific ROM region
52 //-------------------------------------------------
53
device_rom_region() const54 const tiny_rom_entry *nubus_procolor816_device::device_rom_region() const
55 {
56 return ROM_NAME( procolor816 );
57 }
58
59 //**************************************************************************
60 // LIVE DEVICE
61 //**************************************************************************
62
63 //-------------------------------------------------
64 // nubus_procolor816_device - constructor
65 //-------------------------------------------------
66
nubus_procolor816_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)67 nubus_procolor816_device::nubus_procolor816_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
68 nubus_procolor816_device(mconfig, PDS030_PROCOLOR816, tag, owner, clock)
69 {
70 }
71
nubus_procolor816_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)72 nubus_procolor816_device::nubus_procolor816_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
73 device_t(mconfig, type, tag, owner, clock),
74 device_video_interface(mconfig, *this),
75 device_nubus_card_interface(mconfig, *this),
76 m_vram32(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_count(0), m_clutoffs(0), m_timer(nullptr)
77 {
78 set_screen(*this, PROCOLOR816_SCREEN_NAME);
79 }
80
81 //-------------------------------------------------
82 // device_start - device-specific startup
83 //-------------------------------------------------
84
device_start()85 void nubus_procolor816_device::device_start()
86 {
87 uint32_t slotspace;
88
89 install_declaration_rom(this, PROCOLOR816_ROM_REGION);
90
91 slotspace = get_slotspace();
92
93 // printf("[procolor816 %p] slotspace = %x\n", this, slotspace);
94
95 m_vram.resize(VRAM_SIZE);
96 m_vram32 = (uint32_t *)&m_vram[0];
97
98 nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32s_delegate(*this, FUNC(nubus_procolor816_device::vram_r)), write32s_delegate(*this, FUNC(nubus_procolor816_device::vram_w)));
99 nubus().install_device(slotspace+0x900000, slotspace+VRAM_SIZE-1+0x900000, read32s_delegate(*this, FUNC(nubus_procolor816_device::vram_r)), write32s_delegate(*this, FUNC(nubus_procolor816_device::vram_w)));
100 nubus().install_device(slotspace+0xf00000, slotspace+0xff7fff, read32s_delegate(*this, FUNC(nubus_procolor816_device::procolor816_r)), write32s_delegate(*this, FUNC(nubus_procolor816_device::procolor816_w)));
101
102 m_timer = timer_alloc(0, nullptr);
103 m_timer->adjust(screen().time_until_pos(479, 0), 0);
104 }
105
106 //-------------------------------------------------
107 // device_reset - device-specific reset
108 //-------------------------------------------------
109
device_reset()110 void nubus_procolor816_device::device_reset()
111 {
112 m_count = 0;
113 m_clutoffs = 0;
114 m_vbl_disable = 1;
115 m_mode = 3;
116 memset(&m_vram[0], 0, VRAM_SIZE);
117 memset(m_palette, 0, sizeof(m_palette));
118
119 m_palette[0] = rgb_t(255, 255, 255);
120 m_palette[0x80] = rgb_t(0, 0, 0);
121 }
122
123
device_timer(emu_timer & timer,device_timer_id tid,int param,void * ptr)124 void nubus_procolor816_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
125 {
126 if (!m_vbl_disable)
127 {
128 raise_slot_irq();
129 }
130
131 m_timer->adjust(screen().time_until_pos(479, 0), 0);
132 }
133
134 /***************************************************************************
135
136 CB264 section
137
138 ***************************************************************************/
139
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)140 uint32_t nubus_procolor816_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
141 {
142 uint8_t const *const vram = &m_vram[4];
143
144 switch (m_mode)
145 {
146 case 0: // 1 bpp?
147 for (int y = 0; y < 480; y++)
148 {
149 uint32_t *scanline = &bitmap.pix(y);
150 for (int x = 0; x < 640/8; x++)
151 {
152 uint8_t const pixels = vram[(y * 640/8) + (BYTE4_XOR_BE(x))];
153
154 *scanline++ = m_palette[(pixels&0x80)];
155 *scanline++ = m_palette[((pixels<<1)&0x80)];
156 *scanline++ = m_palette[((pixels<<2)&0x80)];
157 *scanline++ = m_palette[((pixels<<3)&0x80)];
158 *scanline++ = m_palette[((pixels<<4)&0x80)];
159 *scanline++ = m_palette[((pixels<<5)&0x80)];
160 *scanline++ = m_palette[((pixels<<6)&0x80)];
161 *scanline++ = m_palette[((pixels<<7)&0x80)];
162 }
163 }
164 break;
165
166 case 1: // 2 bpp
167 for (int y = 0; y < 480; y++)
168 {
169 uint32_t *scanline = &bitmap.pix(y);
170 for (int x = 0; x < 640/4; x++)
171 {
172 uint8_t const pixels = vram[(y * 640/4) + (BYTE4_XOR_BE(x))];
173
174 *scanline++ = m_palette[(pixels&0xc0)];
175 *scanline++ = m_palette[((pixels<<2)&0xc0)];
176 *scanline++ = m_palette[((pixels<<4)&0xc0)];
177 *scanline++ = m_palette[((pixels<<6)&0xc0)];
178 }
179 }
180 break;
181
182 case 2: // 4 bpp
183 for (int y = 0; y < 480; y++)
184 {
185 uint32_t *scanline = &bitmap.pix(y);
186 for (int x = 0; x < 640/2; x++)
187 {
188 uint8_t const pixels = vram[(y * 640/2) + (BYTE4_XOR_BE(x))];
189
190 *scanline++ = m_palette[(pixels&0xf0)];
191 *scanline++ = m_palette[((pixels&0x0f)<<4)];
192 }
193 }
194 break;
195
196 case 3: // 8 bpp
197 for (int y = 0; y < 480; y++)
198 {
199 uint32_t *scanline = &bitmap.pix(y);
200 for (int x = 0; x < 640; x++)
201 {
202 uint8_t const pixels = vram[(y * 640) + (BYTE4_XOR_BE(x))];
203 *scanline++ = m_palette[pixels];
204 }
205 }
206 break;
207
208 case 4: // 15 bpp
209 {
210 uint16_t const *const vram16 = (uint16_t *)&m_vram[0];
211
212 for (int y = 0; y < 480; y++)
213 {
214 uint32_t *scanline = &bitmap.pix(y);
215 for (int x = 0; x < 640; x++)
216 {
217 uint16_t const pixels = vram16[(y * 640) + BYTE_XOR_BE(x)];
218 *scanline++ = rgb_t(pal5bit((pixels>>10) & 0x1f), pal5bit((pixels>>5) & 0x1f), pal5bit(pixels & 0x1f));
219 }
220 }
221 }
222 break;
223
224 default:
225 fatalerror("procolor816: unknown video mode %d\n", m_mode);
226 }
227 return 0;
228 }
229
procolor816_w(offs_t offset,uint32_t data,uint32_t mem_mask)230 void nubus_procolor816_device::procolor816_w(offs_t offset, uint32_t data, uint32_t mem_mask)
231 {
232 switch (offset)
233 {
234 case 0x3d805: // mode
235 if (mem_mask == 0xff)
236 {
237 switch (data & 0xff)
238 {
239 case 0x13:
240 m_mode = 0;
241 break;
242
243 case 0x17:
244 m_mode = 1;
245 break;
246
247 case 0x1b:
248 m_mode = 2;
249 break;
250
251 case 0x1e:
252 m_mode = 3;
253 break;
254
255 case 0x0a:
256 m_mode = 4;
257 break;
258 }
259 }
260 break;
261
262 case 0x3d800:
263 if (mem_mask == 0x00ff0000)
264 {
265 // printf("%s %08x to DAC control\n", machine().describe_context().c_str(), data);
266 m_clutoffs = bitswap<8>((data>>16)&0xff, 0, 1, 2, 3, 4, 5, 6, 7);
267 }
268 else if (mem_mask == 0x000000ff)
269 {
270 m_colors[m_count++] = (data & 0xff);
271
272 if (m_count == 3)
273 {
274 // printf("%s RAMDAC: color %02x = %02x %02x %02x\n", machine().describe_context().c_str(), m_clutoffs, m_colors[0], m_colors[1], m_colors[2]);
275 m_palette[m_clutoffs] = rgb_t(m_colors[0], m_colors[1], m_colors[2]);
276 m_clutoffs++;
277 if (m_clutoffs > 255)
278 {
279 m_clutoffs = 0;
280 }
281 m_count = 0;
282 }
283 }
284 break;
285
286 case 0x3dc00: // VBL control
287 if (mem_mask == 0xff000000)
288 {
289 if (data & 0x04000000)
290 {
291 m_vbl_disable = 0;
292 lower_slot_irq();
293 }
294 else
295 {
296 m_vbl_disable = 1;
297 }
298 }
299 break;
300
301 default:
302 // printf("%s procolor816_w: %08x @ %x, mask %08x\n", machine().describe_context().c_str(), data, offset, mem_mask);
303 break;
304 }
305 }
306
procolor816_r(offs_t offset,uint32_t mem_mask)307 uint32_t nubus_procolor816_device::procolor816_r(offs_t offset, uint32_t mem_mask)
308 {
309 if (offset == 0x3dc00)
310 {
311 m_toggle ^= 0xffffffff;
312 return m_toggle;
313 }
314 else if (offset == 0x3d807)
315 {
316 return 0;
317 }
318 else
319 {
320 // printf("procolor816_r: @ %x, mask %08x [PC=%x]\n", offset, mem_mask, machine().device<cpu_device>("maincpu")->pc());
321 }
322
323 return 0;
324 }
325
vram_w(offs_t offset,uint32_t data,uint32_t mem_mask)326 void nubus_procolor816_device::vram_w(offs_t offset, uint32_t data, uint32_t mem_mask)
327 {
328 COMBINE_DATA(&m_vram32[offset]);
329 }
330
vram_r(offs_t offset,uint32_t mem_mask)331 uint32_t nubus_procolor816_device::vram_r(offs_t offset, uint32_t mem_mask)
332 {
333 return m_vram32[offset];
334 }
335