1 // license:BSD-3-Clause
2 // copyright-holders:R. Belmont
3 /*
4     Cristaltec "Game Cristal" (MAME bootleg)
5 
6     Skeleton driver by R. Belmont, based on taitowlf.c by Ville Linde
7 
8     Note:
9     - bp 000F16B5 do bx=0x16bb (can't skip this check?)
10 
11     Specs: P3-866, SiS 630 graphics card, SiS 7018 sound, Windows 98, DirectX 8.1.
12 
13     Input is via a custom COM1 port JAMMA adaptor.
14 
15     The custom emulator is a heavily modified version of MAME32.  If you extract the
16     disk image, it's in C:\GH4\GH4.EXE.  It's UPX compressed, so unpack it before doing
17     any forensics.  The emulator does run on Windows as new as XP Pro SP2 but you can't
18     control it due to the lack of the custom input.
19 
20     Updates 27/11/2007 (Diego Nappino):
21     The COM1 port is opened at 19200 bps, No parity, 8 bit data,1 stop bit.
22     The protocol is based on a 6 bytes frame with a leading byte valued 0x05 and a trailing one at 0x02
23     The four middle bytes are used, in negative logic (0xFF = No button pressed), to implement the inputs.
24     Each bit meaning as follows :
25 
26                Byte 1         Byte 2          Byte 3        Byte 4
27        Bit 0    P1-Credit      P1-Button C     P2-Left        UNUSED
28     Bit 1    P1-Start       P1-Button D     P2-Right       UNUSED
29     Bit 2    P1-Down        P1-Button E     P2-Button A    SERVICE
30     Bit 3    P1-Up          TEST            P2-Button B    UNUSED
31     Bit 4    P1-Left        P2-Credit       P2-Button C    UNUSED
32     Bit 5    P1-Right       P2-Start        P2-Button D    UNUSED
33     Bit 6    P1-Button A    P2-Down         P2-Button E    UNUSED
34     Bit 7    P1-Button B    P2-Up           VIDEO-MODE     UNUSED
35 
36     The JAMMA adaptor sends a byte frame each time an input changes. So, in example, if the P1-Button A and P1-Button B are both pressed, it will send :
37 
38     0x05 0xFC 0xFF 0xFF 0xFF 0x02
39 
40     And when the buttons are both released
41 
42     0x05 0xFF 0xFF 0xFF 0xFF 0x02
43 
44     CPUID info:
45     Original set:
46 
47     CPUID Level:       EAX:           EBX:           ECX:           EDX:
48     00000000       00000003       756E6547       6C65746E       49656E69
49     00000001       0000068A       00000002       00000000       0387F9FF
50     00000002       03020101       00000000       00000000       0C040882
51     00000003       00000000       00000000       CA976D2E       000082F6
52     80000000       00000000       00000000       CA976D2E       000082F6
53     C0000000       00000000       00000000       CA976D2E       000082F6
54 
55 
56     Version 2:
57     CPUID Level:       EAX:           EBX:           ECX:           EDX:
58     00000000       00000003       756E6547       6C65746E       49656E69
59     00000001       0000068A       00000002       00000000       0387F9FF
60     00000002       03020101       00000000       00000000       0C040882
61     00000003       00000000       00000000       B8BA1941       00038881
62     80000000       00000000       00000000       B8BA1941       00038881
63     C0000000       00000000       00000000       B8BA1941       00038881
64 
65 */
66 
67 #include "emu.h"
68 #include "cpu/i386/i386.h"
69 #include "machine/idectrl.h"
70 #include "machine/lpci.h"
71 #include "machine/pckeybrd.h"
72 #include "machine/pcshare.h"
73 #include "emupal.h"
74 #include "screen.h"
75 
76 
77 class gamecstl_state : public pcat_base_state
78 {
79 public:
gamecstl_state(const machine_config & mconfig,device_type type,const char * tag)80 	gamecstl_state(const machine_config &mconfig, device_type type, const char *tag)
81 		: pcat_base_state(mconfig, type, tag),
82 		m_cga_ram(*this, "cga_ram"),
83 		m_gfxdecode(*this, "gfxdecode"),
84 		m_palette(*this, "palette")  { }
85 
86 	void gamecstl(machine_config &config);
87 
88 	void init_gamecstl();
89 
90 private:
91 	required_shared_ptr<uint32_t> m_cga_ram;
92 	required_device<gfxdecode_device> m_gfxdecode;
93 	required_device<palette_device> m_palette;
94 	std::unique_ptr<uint32_t[]> m_bios_ram;
95 	uint8_t m_mtxc_config_reg[256];
96 	uint8_t m_piix4_config_reg[4][256];
97 
98 	void pnp_config_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
99 	void pnp_data_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
100 	void bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
101 	virtual void machine_start() override;
102 	virtual void machine_reset() override;
103 	virtual void video_start() override;
104 	uint32_t screen_update_gamecstl(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
105 	void draw_char(bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, int ch, int att, int x, int y);
106 	void intel82439tx_init();
107 	void gamecstl_io(address_map &map);
108 	void gamecstl_map(address_map &map);
109 
110 	uint8_t mtxc_config_r(int function, int reg);
111 	void mtxc_config_w(int function, int reg, uint8_t data);
112 	uint32_t intel82439tx_pci_r(int function, int reg, uint32_t mem_mask);
113 	void intel82439tx_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask);
114 	uint8_t piix4_config_r(int function, int reg);
115 	void piix4_config_w(int function, int reg, uint8_t data);
116 	uint32_t intel82371ab_pci_r(int function, int reg, uint32_t mem_mask);
117 	void intel82371ab_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask);
118 	uint32_t pci_3dfx_r(int function, int reg, uint32_t mem_mask);
119 	void pci_3dfx_w(int function, int reg, uint32_t data, uint32_t mem_mask);
120 };
121 
122 
123 static const rgb_t cga_palette[16] =
124 {
125 	rgb_t( 0x00, 0x00, 0x00 ), rgb_t( 0x00, 0x00, 0xaa ), rgb_t( 0x00, 0xaa, 0x00 ), rgb_t( 0x00, 0xaa, 0xaa ),
126 	rgb_t( 0xaa, 0x00, 0x00 ), rgb_t( 0xaa, 0x00, 0xaa ), rgb_t( 0xaa, 0x55, 0x00 ), rgb_t( 0xaa, 0xaa, 0xaa ),
127 	rgb_t( 0x55, 0x55, 0x55 ), rgb_t( 0x55, 0x55, 0xff ), rgb_t( 0x55, 0xff, 0x55 ), rgb_t( 0x55, 0xff, 0xff ),
128 	rgb_t( 0xff, 0x55, 0x55 ), rgb_t( 0xff, 0x55, 0xff ), rgb_t( 0xff, 0xff, 0x55 ), rgb_t( 0xff, 0xff, 0xff ),
129 };
130 
video_start()131 void gamecstl_state::video_start()
132 {
133 	int i;
134 	for (i=0; i < 16; i++)
135 		m_palette->set_pen_color(i, cga_palette[i]);
136 }
137 
draw_char(bitmap_ind16 & bitmap,const rectangle & cliprect,gfx_element * gfx,int ch,int att,int x,int y)138 void gamecstl_state::draw_char(bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, int ch, int att, int x, int y)
139 {
140 	int index = 0;
141 	uint8_t const *const dp = gfx->get_data(ch);
142 
143 	for (int j=y; j < y+8; j++)
144 	{
145 		uint16_t *const p = &bitmap.pix(j);
146 
147 		for (int i=x; i < x+8; i++)
148 		{
149 			uint8_t pen = dp[index++];
150 			if (pen)
151 				p[i] = gfx->colorbase() + (att & 0xf);
152 			else
153 				p[i] = gfx->colorbase()  + ((att >> 4) & 0x7);
154 		}
155 	}
156 }
157 
screen_update_gamecstl(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)158 uint32_t gamecstl_state::screen_update_gamecstl(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
159 {
160 	gfx_element *gfx = m_gfxdecode->gfx(0);
161 	uint32_t const *const cga = m_cga_ram;
162 	int index = 0;
163 
164 	bitmap.fill(0, cliprect);
165 
166 	for (int j=0; j < 25; j++)
167 	{
168 		for (int i=0; i < 80; i+=2)
169 		{
170 			int att0 = (cga[index] >> 8) & 0xff;
171 			int ch0 = (cga[index] >> 0) & 0xff;
172 			int att1 = (cga[index] >> 24) & 0xff;
173 			int ch1 = (cga[index] >> 16) & 0xff;
174 
175 			draw_char(bitmap, cliprect, gfx, ch0, att0, i*8, j*8);
176 			draw_char(bitmap, cliprect, gfx, ch1, att1, (i*8)+8, j*8);
177 			index++;
178 		}
179 	}
180 	return 0;
181 }
182 
183 // Intel 82439TX System Controller (MTXC)
184 
mtxc_config_r(int function,int reg)185 uint8_t gamecstl_state::mtxc_config_r(int function, int reg)
186 {
187 	logerror("MTXC: read %d, %02X\n", function, reg);
188 	return m_mtxc_config_reg[reg];
189 }
190 
mtxc_config_w(int function,int reg,uint8_t data)191 void gamecstl_state::mtxc_config_w(int function, int reg, uint8_t data)
192 {
193 	logerror("%s:MTXC: write %d, %02X, %02X\n", machine().describe_context(), function, reg, data);
194 
195 	switch(reg)
196 	{
197 		case 0x59:      // PAM0
198 		{
199 			if (data & 0x10)        // enable RAM access to region 0xf0000 - 0xfffff
200 			{
201 				membank("bank1")->set_base(m_bios_ram.get());
202 			}
203 			else                    // disable RAM access (reads go to BIOS ROM)
204 			{
205 				membank("bank1")->set_base(memregion("bios")->base() + 0x30000);
206 			}
207 			break;
208 		}
209 	}
210 
211 	m_mtxc_config_reg[reg] = data;
212 }
213 
intel82439tx_init()214 void gamecstl_state::intel82439tx_init()
215 {
216 	m_mtxc_config_reg[0x60] = 0x02;
217 	m_mtxc_config_reg[0x61] = 0x02;
218 	m_mtxc_config_reg[0x62] = 0x02;
219 	m_mtxc_config_reg[0x63] = 0x02;
220 	m_mtxc_config_reg[0x64] = 0x02;
221 	m_mtxc_config_reg[0x65] = 0x02;
222 }
223 
intel82439tx_pci_r(int function,int reg,uint32_t mem_mask)224 uint32_t gamecstl_state::intel82439tx_pci_r(int function, int reg, uint32_t mem_mask)
225 {
226 	uint32_t r = 0;
227 	if (ACCESSING_BITS_24_31)
228 	{
229 		r |= mtxc_config_r(function, reg + 3) << 24;
230 	}
231 	if (ACCESSING_BITS_16_23)
232 	{
233 		r |= mtxc_config_r(function, reg + 2) << 16;
234 	}
235 	if (ACCESSING_BITS_8_15)
236 	{
237 		r |= mtxc_config_r(function, reg + 1) << 8;
238 	}
239 	if (ACCESSING_BITS_0_7)
240 	{
241 		r |= mtxc_config_r(function, reg + 0) << 0;
242 	}
243 	return r;
244 }
245 
intel82439tx_pci_w(int function,int reg,uint32_t data,uint32_t mem_mask)246 void gamecstl_state::intel82439tx_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask)
247 {
248 	if (ACCESSING_BITS_24_31)
249 	{
250 		mtxc_config_w(function, reg + 3, (data >> 24) & 0xff);
251 	}
252 	if (ACCESSING_BITS_16_23)
253 	{
254 		mtxc_config_w(function, reg + 2, (data >> 16) & 0xff);
255 	}
256 	if (ACCESSING_BITS_8_15)
257 	{
258 		mtxc_config_w(function, reg + 1, (data >> 8) & 0xff);
259 	}
260 	if (ACCESSING_BITS_0_7)
261 	{
262 		mtxc_config_w(function, reg + 0, (data >> 0) & 0xff);
263 	}
264 }
265 
266 // Intel 82371AB PCI-to-ISA / IDE bridge (PIIX4)
267 
piix4_config_r(int function,int reg)268 uint8_t gamecstl_state::piix4_config_r(int function, int reg)
269 {
270 	logerror("PIIX4: read %d, %02X\n", function, reg);
271 	return m_piix4_config_reg[function][reg];
272 }
273 
piix4_config_w(int function,int reg,uint8_t data)274 void gamecstl_state::piix4_config_w(int function, int reg, uint8_t data)
275 {
276 	logerror("%s:PIIX4: write %d, %02X, %02X\n", machine().describe_context(), function, reg, data);
277 	m_piix4_config_reg[function][reg] = data;
278 }
279 
intel82371ab_pci_r(int function,int reg,uint32_t mem_mask)280 uint32_t gamecstl_state::intel82371ab_pci_r(int function, int reg, uint32_t mem_mask)
281 {
282 	uint32_t r = 0;
283 	if (ACCESSING_BITS_24_31)
284 	{
285 		r |= piix4_config_r(function, reg + 3) << 24;
286 	}
287 	if (ACCESSING_BITS_16_23)
288 	{
289 		r |= piix4_config_r(function, reg + 2) << 16;
290 	}
291 	if (ACCESSING_BITS_8_15)
292 	{
293 		r |= piix4_config_r(function, reg + 1) << 8;
294 	}
295 	if (ACCESSING_BITS_0_7)
296 	{
297 		r |= piix4_config_r(function, reg + 0) << 0;
298 	}
299 	return r;
300 }
301 
intel82371ab_pci_w(int function,int reg,uint32_t data,uint32_t mem_mask)302 void gamecstl_state::intel82371ab_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask)
303 {
304 	if (ACCESSING_BITS_24_31)
305 	{
306 		piix4_config_w(function, reg + 3, (data >> 24) & 0xff);
307 	}
308 	if (ACCESSING_BITS_16_23)
309 	{
310 		piix4_config_w(function, reg + 2, (data >> 16) & 0xff);
311 	}
312 	if (ACCESSING_BITS_8_15)
313 	{
314 		piix4_config_w(function, reg + 1, (data >> 8) & 0xff);
315 	}
316 	if (ACCESSING_BITS_0_7)
317 	{
318 		piix4_config_w(function, reg + 0, (data >> 0) & 0xff);
319 	}
320 }
321 
322 // ISA Plug-n-Play
pnp_config_w(offs_t offset,uint32_t data,uint32_t mem_mask)323 void gamecstl_state::pnp_config_w(offs_t offset, uint32_t data, uint32_t mem_mask)
324 {
325 	if (ACCESSING_BITS_8_15)
326 	{
327 //      osd_printf_debug("PNP Config: %02X\n", (data >> 8) & 0xff);
328 	}
329 }
330 
pnp_data_w(offs_t offset,uint32_t data,uint32_t mem_mask)331 void gamecstl_state::pnp_data_w(offs_t offset, uint32_t data, uint32_t mem_mask)
332 {
333 	if (ACCESSING_BITS_8_15)
334 	{
335 //      osd_printf_debug("PNP Data: %02X\n", (data >> 8) & 0xff);
336 	}
337 }
338 
339 
340 
bios_ram_w(offs_t offset,uint32_t data,uint32_t mem_mask)341 void gamecstl_state::bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask)
342 {
343 	if (m_mtxc_config_reg[0x59] & 0x20)     // write to RAM if this region is write-enabled
344 	{
345 		COMBINE_DATA(m_bios_ram.get() + offset);
346 	}
347 }
348 
349 /*****************************************************************************/
350 
gamecstl_map(address_map & map)351 void gamecstl_state::gamecstl_map(address_map &map)
352 {
353 	map(0x00000000, 0x0009ffff).ram();
354 	map(0x000a0000, 0x000affff).ram();
355 	map(0x000b0000, 0x000b7fff).ram().share("cga_ram");
356 	map(0x000e0000, 0x000effff).ram();
357 	map(0x000f0000, 0x000fffff).bankr("bank1");
358 	map(0x000f0000, 0x000fffff).w(FUNC(gamecstl_state::bios_ram_w));
359 	map(0x00100000, 0x01ffffff).ram();
360 	map(0xfffc0000, 0xffffffff).rom().region("bios", 0);    /* System BIOS */
361 }
362 
gamecstl_io(address_map & map)363 void gamecstl_state::gamecstl_io(address_map &map)
364 {
365 	pcat32_io_common(map);
366 	map(0x00e8, 0x00eb).noprw();
367 	map(0x00ec, 0x00ef).noprw();
368 	map(0x01f0, 0x01f7).rw("ide", FUNC(ide_controller_device::cs0_r), FUNC(ide_controller_device::cs0_w));
369 	map(0x0300, 0x03af).noprw();
370 	map(0x03b0, 0x03df).noprw();
371 	map(0x0278, 0x027b).w(FUNC(gamecstl_state::pnp_config_w));
372 	map(0x03f0, 0x03f7).rw("ide", FUNC(ide_controller_device::cs1_r), FUNC(ide_controller_device::cs1_w));
373 	map(0x0a78, 0x0a7b).w(FUNC(gamecstl_state::pnp_data_w));
374 	map(0x0cf8, 0x0cff).rw("pcibus", FUNC(pci_bus_legacy_device::read), FUNC(pci_bus_legacy_device::write));
375 }
376 
377 /*****************************************************************************/
378 
379 static const gfx_layout CGA_charlayout =
380 {
381 	8,8,                    /* 8 x 16 characters */
382 	256,                    /* 256 characters */
383 	1,                      /* 1 bits per pixel */
384 	{ 0 },                  /* no bitplanes; 1 bit per pixel */
385 	/* x offsets */
386 	{ 0,1,2,3,4,5,6,7 },
387 	/* y offsets */
388 	{ 0*8,1*8,2*8,3*8,
389 		4*8,5*8,6*8,7*8 },
390 	8*8                     /* every char takes 8 bytes */
391 };
392 
393 static GFXDECODE_START( gfx_cga )
394 /* Support up to four CGA fonts */
395 	GFXDECODE_ENTRY( "gfx1", 0x0000, CGA_charlayout,              0, 256 )   /* Font 0 */
396 	GFXDECODE_ENTRY( "gfx1", 0x0800, CGA_charlayout,              0, 256 )   /* Font 1 */
397 	GFXDECODE_ENTRY( "gfx1", 0x1000, CGA_charlayout,              0, 256 )   /* Font 2 */
398 	GFXDECODE_ENTRY( "gfx1", 0x1800, CGA_charlayout,              0, 256 )   /* Font 3*/
399 GFXDECODE_END
400 
INPUT_PORTS_START(gamecstl)401 static INPUT_PORTS_START(gamecstl)
402 INPUT_PORTS_END
403 
404 void gamecstl_state::machine_start()
405 {
406 }
407 
machine_reset()408 void gamecstl_state::machine_reset()
409 {
410 	membank("bank1")->set_base(memregion("bios")->base() + 0x30000);
411 }
412 
gamecstl(machine_config & config)413 void gamecstl_state::gamecstl(machine_config &config)
414 {
415 	/* basic machine hardware */
416 	PENTIUM3(config, m_maincpu, 200000000);
417 	m_maincpu->set_addrmap(AS_PROGRAM, &gamecstl_state::gamecstl_map);
418 	m_maincpu->set_addrmap(AS_IO, &gamecstl_state::gamecstl_io);
419 	m_maincpu->set_irq_acknowledge_callback("pic8259_1", FUNC(pic8259_device::inta_cb));
420 
421 	pcat_common(config);
422 
423 	pci_bus_legacy_device &pcibus(PCI_BUS_LEGACY(config, "pcibus", 0, 0));
424 	pcibus.set_device(0, FUNC(gamecstl_state::intel82439tx_pci_r), FUNC(gamecstl_state::intel82439tx_pci_w));
425 	pcibus.set_device(7, FUNC(gamecstl_state::intel82371ab_pci_r), FUNC(gamecstl_state::intel82371ab_pci_w));
426 
427 	ide_controller_device &ide(IDE_CONTROLLER(config, "ide").options(ata_devices, "hdd", nullptr, true));
428 	ide.irq_handler().set("pic8259_2", FUNC(pic8259_device::ir6_w));
429 
430 	/* video hardware */
431 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
432 	screen.set_refresh_hz(60);
433 	screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
434 	screen.set_size(640, 480);
435 	screen.set_visarea(0, 639, 0, 199);
436 	screen.set_screen_update(FUNC(gamecstl_state::screen_update_gamecstl));
437 	screen.set_palette(m_palette);
438 
439 	GFXDECODE(config, m_gfxdecode, m_palette, gfx_cga);
440 	PALETTE(config, m_palette).set_entries(16);
441 }
442 
init_gamecstl()443 void gamecstl_state::init_gamecstl()
444 {
445 	m_bios_ram = std::make_unique<uint32_t[]>(0x10000/4);
446 
447 	intel82439tx_init();
448 }
449 
450 /*****************************************************************************/
451 
452 // not the correct BIOS, f205v owes me a dump of it...
453 ROM_START(gamecstl)
454 	ROM_REGION32_LE(0x40000, "bios", 0)
455 	ROM_LOAD( "bios.bin",     0x000000, 0x040000, BAD_DUMP CRC(27834ce9) SHA1(134c546dd75138c6f4bc5729b40e20e118454df9) )
456 
457 	ROM_REGION(0x08100, "gfx1", 0)
458 	ROM_LOAD("cga.chr",     0x00000, 0x01000, BAD_DUMP CRC(42009069) SHA1(ed08559ce2d7f97f68b9f540bddad5b6295294dd))
459 
460 	DISK_REGION( "ide:0:hdd:image" )
461 	DISK_IMAGE( "gamecstl", 0, SHA1(b431af3c42c48ba07972d77a3d24e60ee1e4359e) )
462 ROM_END
463 
464 ROM_START(gamecst2)
465 	ROM_REGION32_LE(0x40000, "bios", 0)
466 	ROM_LOAD( "bios.bin",     0x000000, 0x040000, BAD_DUMP CRC(27834ce9) SHA1(134c546dd75138c6f4bc5729b40e20e118454df9) )
467 
468 	ROM_REGION(0x08100, "gfx1", 0)
469 	ROM_LOAD("cga.chr",     0x00000, 0x01000, BAD_DUMP CRC(42009069) SHA1(ed08559ce2d7f97f68b9f540bddad5b6295294dd))
470 
471 	DISK_REGION( "ide:0:hdd:image" )
472 	DISK_IMAGE( "gamecst2", 0, SHA1(14e1b311cb474801c7bdda3164a0c220fb102159) )
473 ROM_END
474 
475 /*****************************************************************************/
476 
477 GAME(2002, gamecstl, 0,        gamecstl, gamecstl, gamecstl_state, init_gamecstl, ROT0, "Cristaltec", "GameCristal",                 MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
478 GAME(2002, gamecst2, gamecstl, gamecstl, gamecstl, gamecstl_state, init_gamecstl, ROT0, "Cristaltec", "GameCristal (version 2.613)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
479