mirror of
https://github.com/holub/mame
synced 2025-10-06 09:00:04 +03:00
catnmous: better approximation of colours, should be pretty close now
This commit is contained in:
parent
f489eeaaef
commit
695febb4ac
@ -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 )
|
||||
|
@ -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;
|
||||
|
@ -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]));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user