From 695febb4ac53f49a6e0f66113a86230c549bf265 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Mon, 8 Feb 2016 15:38:02 +1100 Subject: [PATCH] catnmous: better approximation of colours, should be pretty close now --- src/mame/drivers/laserbat.cpp | 18 ++-- src/mame/includes/laserbat.h | 9 +- src/mame/video/laserbat.cpp | 155 ++++++++++++++++++++++------------ 3 files changed, 119 insertions(+), 63 deletions(-) diff --git a/src/mame/drivers/laserbat.cpp b/src/mame/drivers/laserbat.cpp index 38f7d3cbb39..0c590a19cec 100644 --- a/src/mame/drivers/laserbat.cpp +++ b/src/mame/drivers/laserbat.cpp @@ -74,9 +74,6 @@ TODO: - work out where all the magic layer offsets come from - - need to confirm colour weight resistors on catnmous (detailed photo required): - R58, R59, R60, R61, R62, R65, R66, R67, R68, R69, R72, R73, R74, R75 - (network connected between 11M, 12M, Q5, Q7, Q8) - sound in laserbat (with schematics) and in catnmous */ @@ -497,9 +494,6 @@ static MACHINE_CONFIG_START( laserbat_base, laserbat_state_base ) MCFG_SCREEN_UPDATE_DRIVER(laserbat_state_base, screen_update_laserbat) MCFG_SCREEN_PALETTE("palette") - MCFG_PALETTE_ADD("palette", 256) - MCFG_PALETTE_INIT_OWNER(laserbat_state_base, laserbat) - MCFG_PLS100_ADD("gfxmix") MCFG_DEVICE_ADD("pvi1", S2636, XTAL_14_31818MHz/3) @@ -520,6 +514,10 @@ MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED_CLASS( laserbat, laserbat_base, laserbat_state ) + // video hardware + MCFG_PALETTE_ADD("palette", 256) + MCFG_PALETTE_INIT_OWNER(laserbat_state, laserbat) + // sound board devices MCFG_SPEAKER_STANDARD_MONO("mono") @@ -548,6 +546,10 @@ MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED_CLASS( catnmous, laserbat_base, catnmous_state ) + // video hardware + MCFG_PALETTE_ADD("palette", 256) + MCFG_PALETTE_INIT_OWNER(catnmous_state, catnmous) + // sound board devices MCFG_CPU_ADD("audiocpu", M6802, 3580000) // ? MCFG_CPU_PROGRAM_MAP(catnmous_sound_map) @@ -758,5 +760,5 @@ ROM_END GAME( 1981, laserbat, 0, laserbat, laserbat, laserbat_state_base, laserbat, ROT0, "Zaccaria", "Laser Battle", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1981, lazarian, laserbat, laserbat, lazarian, laserbat_state_base, laserbat, ROT0, "Zaccaria (Bally Midway license)", "Lazarian", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1982, catnmous, 0, catnmous, catnmous, laserbat_state_base, laserbat, ROT90, "Zaccaria", "Cat and Mouse (set 1)", MACHINE_IMPERFECT_COLORS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1982, catnmousa, catnmous, catnmous, catnmous, laserbat_state_base, laserbat, ROT90, "Zaccaria", "Cat and Mouse (set 2)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_COLORS | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1982, catnmous, 0, catnmous, catnmous, laserbat_state_base, laserbat, ROT90, "Zaccaria", "Cat and Mouse (set 1)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1982, catnmousa, catnmous, catnmous, catnmous, laserbat_state_base, laserbat, ROT90, "Zaccaria", "Cat and Mouse (set 2)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/includes/laserbat.h b/src/mame/includes/laserbat.h index f50cd4e1bd9..f6d35ca93d6 100644 --- a/src/mame/includes/laserbat.h +++ b/src/mame/includes/laserbat.h @@ -65,9 +65,6 @@ public: DECLARE_DRIVER_INIT(laserbat); INTERRUPT_GEN_MEMBER(laserbat_interrupt); - // video initialisation - DECLARE_PALETTE_INIT(laserbat); - // video memory and control ports DECLARE_WRITE8_MEMBER(videoram_w); DECLARE_WRITE8_MEMBER(wcoh_w); @@ -162,6 +159,9 @@ public: { } + // video initialisation + DECLARE_PALETTE_INIT(laserbat); + // sound control ports virtual DECLARE_WRITE8_MEMBER(csound2_w) override; @@ -193,6 +193,9 @@ public: { } + // video initialisation + DECLARE_PALETTE_INIT(catnmous); + // sound control ports virtual DECLARE_WRITE8_MEMBER(csound1_w) override; virtual DECLARE_WRITE8_MEMBER(csound2_w) override; diff --git a/src/mame/video/laserbat.cpp b/src/mame/video/laserbat.cpp index fca20043f37..2431304816f 100644 --- a/src/mame/video/laserbat.cpp +++ b/src/mame/video/laserbat.cpp @@ -82,58 +82,6 @@ #include "includes/laserbat.h" -PALETTE_INIT_MEMBER(laserbat_state_base, laserbat) -{ - /* - Uses GRBGRBGR pixel format. The two topmost bist are the LSBs - for red and green. LSB for blue is always effectively 1. The - middle group is the MSB. Yet another crazy thing they did. - - Each colour channel has an emitter follower buffer amlpifier - biased with a 1k resistor to +5V and a 3k3 resistor to ground. - Output is adjusted by connecting additional resistors across the - leg to ground using an open collector buffer - 270R, 820R and - 1k0 for unset MSB to LSB, respectively (blue has no LSB so it - has no 1k0 resistor). - - Assuming 0.7V drop across the emitter follower and no drop - across the open collector buffer, these are the approximate - output voltages: - - 0.0000, 0.1031, 0.1324, 0.2987 , 0.7194, 1.2821, 1.4711, 3.1372 - - The game never sets the colour to any value above 4, effectively - treating it as 5-level red and green, and 3-level blue, for a - total of 75 usable colours. - - From the fact that there's no DC offset on red and green, and - the highest value used is just over 0.7V, I'm guessing the game - expects to drive a standard 0.7V RGB monitor, and higher colour - values would simply saturate the input. To make it not look - like the inside of a coal mine, I've applied gamma decoding at - 2.2 - - However there's that nasty DC offset on the blue caused by the - fact that it has no LSB, but it's eliminated at the AC-coupling - of the input and output of the buffer amplifier on the monitor - interface board. I'm treating it as though it has the same gain - as the other channels. After gamma adjustment, medium red and - medium blue as used by the game have almost the same intensity. - */ - - int const weights[] = { 0, 107, 120, 173, 255, 255, 255, 255 }; - int const blue_weights[] = { 0, 0, 60, 121, 241, 255, 255, 255, 255 }; - for (int entry = 0; palette.entries() > entry; entry++) - { - UINT8 const bits(entry & 0xff); - UINT8 const r(((bits & 0x01) << 1) | ((bits & 0x08) >> 1) | ((bits & 0x40) >> 6)); - UINT8 const g(((bits & 0x02) >> 0) | ((bits & 0x10) >> 2) | ((bits & 0x80) >> 7)); - UINT8 const b(((bits & 0x04) >> 1) | ((bits & 0x20) >> 3) | 0x01); - palette.set_pen_color(entry, rgb_t(weights[r], weights[g], blue_weights[b])); - } -} - - WRITE8_MEMBER(laserbat_state_base::videoram_w) { if (!m_mpx_bkeff) @@ -375,3 +323,106 @@ TIMER_CALLBACK_MEMBER(laserbat_state_base::video_line) } } } + + +PALETTE_INIT_MEMBER(laserbat_state, laserbat) +{ + /* + Uses GRBGRBGR pixel format. The two topmost bist are the LSBs + for red and green. LSB for blue is always effectively 1. The + middle group is the MSB. Yet another crazy thing they did. + + Each colour channel has an emitter follower buffer amlpifier + biased with a 1k resistor to +5V and a 3k3 resistor to ground. + Output is adjusted by connecting additional resistors across the + leg to ground using an open collector buffer - 270R, 820R and + 1k0 for unset MSB to LSB, respectively (blue has no LSB so it + has no 1k0 resistor). + + Assuming 0.7V drop across the emitter follower and no drop + across the open collector buffer, these are the approximate + output voltages: + + 0.0000, 0.1031, 0.1324, 0.2987, 0.7194, 1.2821, 1.4711, 3.1372 + + The game never sets the colour to any value above 4, effectively + treating it as 5-level red and green, and 3-level blue, for a + total of 75 usable colours. + + From the fact that there's no DC offset on red and green, and + the highest value used is just over 0.7V, I'm guessing the game + expects to drive a standard 0.7V RGB monitor, and higher colour + values would simply saturate the input. To make it not look + like the inside of a coal mine, I've applied gamma decoding at + 2.2 + + However there's that nasty DC offset on the blue caused by the + fact that it has no LSB, but it's eliminated at the AC-coupling + of the input and output of the buffer amplifier on the monitor + interface board. I'm treating it as though it has the same gain + as the other channels. After gamma adjustment, medium red and + medium blue as used by the game have almost the same intensity. + */ + + int const weights[] = { 0, 107, 120, 173, 255, 255, 255, 255 }; + int const blue_weights[] = { 0, 0, 60, 121, 241, 255, 255, 255 }; + for (int entry = 0; palette.entries() > entry; entry++) + { + UINT8 const bits(entry & 0xff); + UINT8 const r(((bits & 0x01) << 1) | ((bits & 0x08) >> 1) | ((bits & 0x40) >> 6)); + UINT8 const g(((bits & 0x02) >> 0) | ((bits & 0x10) >> 2) | ((bits & 0x80) >> 7)); + UINT8 const b(((bits & 0x04) >> 1) | ((bits & 0x20) >> 3) | 0x01); + palette.set_pen_color(entry, rgb_t(weights[r], weights[g], blue_weights[b])); + } +} + + +PALETTE_INIT_MEMBER(catnmous_state, catnmous) +{ + /* + Uses GRBGRBGR pixel format. The two topmost bist are the LSBs + for red and green. The middle group is the MSB. Yet another + crazy thing they did. + + Each colour channel has an emitter follower buffer amlpifier + biased with a 1k resistor to +5V and a 3k3 resistor to ground. + Output is adjusted by connecting additional resistors across the + leg to ground using an open collector buffer. Red and green use + 560R, 820R and 1k0 for unset MSB to LSB, respectively. Blue + uses 47R and 820R on the PCB we have a photo of, although the + 47R resistor looks like it could be a bad repair (opposite + orientation and burn marks on PCB). + + Assuming 0.7V drop across the emitter follower and no drop + across the open collector buffer, these are the approximate + output voltages for red and green: + + 0.2419, 0.4606, 0.5229, 0.7194, 0.9188, 1.2821, 1.4711, 3.1372 + + The game uses all colour values except 4. The DC offset will be + eliminated by the AC coupling on the monitor interface board. + The differences steps aren't very linear, they vary from 0.06V + to 0.36V with no particular order. The input would be expected + to saturate somewhere inside the big jump to the highest level. + + Let's assume the 47R resistor is a bad repair and it's supposed + to be 470R. That gives us these output voltages for blue: + + 0.3752, 0.7574, 1.2821, 3.1372 + + To make life easier, I'll assume the monitor is expected to have + half the gain of a standard monitor and no gamma decoding is + necessary. + */ + + int const weights[] = { 0, 40, 51, 87, 123, 189, 224, 255 }; + int const blue_weights[] = { 0, 70, 165, 255 }; + for (int entry = 0; palette.entries() > entry; entry++) + { + UINT8 const bits(entry & 0xff); + UINT8 const r(((bits & 0x01) << 1) | ((bits & 0x08) >> 1) | ((bits & 0x40) >> 6)); + UINT8 const g(((bits & 0x02) >> 0) | ((bits & 0x10) >> 2) | ((bits & 0x80) >> 7)); + UINT8 const b(((bits & 0x04) >> 2) | ((bits & 0x20) >> 4)); + palette.set_pen_color(entry, rgb_t(weights[r], weights[g], blue_weights[b])); + } +}