mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
ef9340: add support for double width/height characters
This commit is contained in:
parent
548cf5c585
commit
deec658426
@ -368,7 +368,7 @@ The C7420 Home Computer Module contains a Z80, 16K RAM and 16K ROM.
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<software name="helicopt">
|
||||
<software name="helicopt" supported="partial">
|
||||
<description>Helicopter Rescue (Euro)</description>
|
||||
<year>1983</year>
|
||||
<publisher>Philips</publisher>
|
||||
|
@ -2,11 +2,21 @@
|
||||
// copyright-holders:Wilbert Pol, hap
|
||||
/***************************************************************************
|
||||
|
||||
Thomson EF9340 + EF9341 teletext graphics chips with 1KB external character ram.
|
||||
Thomson EF9340 + EF9341 teletext graphics, this device is a combination of chips.
|
||||
|
||||
Minimal components:
|
||||
- Thomson EF9340 "VIN"
|
||||
- Thomson EF9341 "GEN"
|
||||
- 2*1KB RAM, A for attributes, B for character codes
|
||||
|
||||
There's also an optional extended character memory, it can be RAM or ROM.
|
||||
This is implemented with a callback. The datasheet explains how to hook up
|
||||
1KB RAM, but it's possible to have more.
|
||||
|
||||
TODO:
|
||||
- busy state (right now it is immediate)
|
||||
- character width/height doubling
|
||||
- internal display timing (on g7400, most of it is done externally)
|
||||
- read slice from internal ROM
|
||||
- window boxing
|
||||
- Y zoom
|
||||
|
||||
@ -29,6 +39,8 @@ ef9340_1_device::ef9340_1_device(const machine_config &mconfig, const char *tag,
|
||||
: device_t(mconfig, EF9340_1, tag, owner, clock)
|
||||
, device_video_interface(mconfig, *this)
|
||||
, m_charset(*this, "ef9340_1")
|
||||
, m_write_exram(*this)
|
||||
, m_read_exram(*this)
|
||||
{
|
||||
}
|
||||
|
||||
@ -47,6 +59,9 @@ const tiny_rom_entry *ef9340_1_device::device_rom_region() const
|
||||
|
||||
void ef9340_1_device::device_start()
|
||||
{
|
||||
m_write_exram.resolve_safe();
|
||||
m_read_exram.resolve_safe(0xff);
|
||||
|
||||
// Let the screen create our temporary bitmap with the screen's dimensions
|
||||
screen().register_screen_bitmap(m_tmp_bitmap);
|
||||
|
||||
@ -68,10 +83,10 @@ void ef9340_1_device::device_start()
|
||||
m_ef9340.M = 0;
|
||||
m_ef9340.blink = false;
|
||||
m_ef9340.blink_prescaler = 0;
|
||||
m_ef9340.h_parity = false;
|
||||
|
||||
memset(m_ram_a, 0, sizeof(m_ram_a));
|
||||
memset(m_ram_b, 0, sizeof(m_ram_b));
|
||||
memset(m_ram_b, 0, sizeof(m_ef934x_ext_char_ram));
|
||||
|
||||
// register our state
|
||||
save_item(NAME(m_ef9341.TA));
|
||||
@ -85,10 +100,10 @@ void ef9340_1_device::device_start()
|
||||
save_item(NAME(m_ef9340.M));
|
||||
save_item(NAME(m_ef9340.blink));
|
||||
save_item(NAME(m_ef9340.blink_prescaler));
|
||||
save_item(NAME(m_ef9340.h_parity));
|
||||
|
||||
save_item(NAME(m_ram_a));
|
||||
save_item(NAME(m_ram_b));
|
||||
save_item(NAME(m_ef934x_ext_char_ram));
|
||||
}
|
||||
|
||||
|
||||
@ -143,20 +158,6 @@ void ef9340_1_device::ef9340_inc_c()
|
||||
}
|
||||
|
||||
|
||||
uint16_t ef9340_1_device::external_chargen_address(uint8_t b, uint8_t slice)
|
||||
{
|
||||
uint8_t cc = b & 0x7f;
|
||||
|
||||
if ( slice & 8 )
|
||||
{
|
||||
// 0 0 CCE4 CCE3 CCE2 CCE1 CCE0 CCE6 CCE5 ADR0
|
||||
return ( ( cc << 3 ) & 0xf8 ) | ( ( cc >> 4 ) & 0x06) | ( slice & 0x01 );
|
||||
}
|
||||
// CCE6 CCE5 CCE4 CCE3 CCE2 CCE1 CCE0 ADR2 ADR1 ADR0
|
||||
return ( cc << 3 ) | ( slice & 0x07 );
|
||||
}
|
||||
|
||||
|
||||
void ef9340_1_device::ef9341_write( uint8_t command, uint8_t b, uint8_t data )
|
||||
{
|
||||
LOG("ef9341 %s write, t%s, data %02X\n", command ? "command" : "data", b ? "B" : "A", data );
|
||||
@ -226,12 +227,10 @@ void ef9340_1_device::ef9341_write( uint8_t command, uint8_t b, uint8_t data )
|
||||
{
|
||||
uint8_t a = m_ram_a[addr];
|
||||
uint8_t b = m_ram_b[addr];
|
||||
uint8_t slice = ( m_ef9340.M & 0x0f ) % 10;
|
||||
uint8_t slice = m_ef9340.M & 0x0f;
|
||||
|
||||
if ( b >= 0xa0 )
|
||||
{
|
||||
m_ef934x_ext_char_ram[ ( ( a & 0x80 ) << 3 ) | external_chargen_address( b, slice ) ] = m_ef9341.TA;
|
||||
}
|
||||
if (b >= 0xa0)
|
||||
m_write_exram(a << 12 | b << 4 | slice, m_ef9341.TA);
|
||||
|
||||
// Increment slice number
|
||||
m_ef9340.M = ( m_ef9340.M & 0xf0) | ( ( slice + 1 ) % 10 );
|
||||
@ -293,13 +292,15 @@ uint8_t ef9340_1_device::ef9341_read( uint8_t command, uint8_t b )
|
||||
{
|
||||
uint8_t a = m_ram_a[addr];
|
||||
uint8_t b = m_ram_b[addr];
|
||||
uint8_t slice = ( m_ef9340.M & 0x0f ) % 10;
|
||||
uint8_t slice = m_ef9340.M & 0x0f;
|
||||
|
||||
if ( b >= 0xa0 )
|
||||
{
|
||||
m_ef9341.TA = m_ef934x_ext_char_ram[ ( ( a & 0x80 ) << 3 ) | external_chargen_address( b, slice ) ];
|
||||
m_ef9341.TB = 0;
|
||||
}
|
||||
m_ef9341.TA = 0xff;
|
||||
m_ef9341.TB = 0xff;
|
||||
|
||||
if (b >= 0xa0)
|
||||
m_ef9341.TA = m_read_exram(a << 12 | b << 4 | slice);
|
||||
else
|
||||
logerror("ef9341 read slice from internal\n");
|
||||
|
||||
// Increment slice number
|
||||
m_ef9340.M = ( m_ef9340.M & 0xf0) | ( ( slice + 1 ) % 10 );
|
||||
@ -329,26 +330,32 @@ void ef9340_1_device::ef9340_scanline(int vpos)
|
||||
if (vpos < 0)
|
||||
return;
|
||||
|
||||
// display automaton active at 40-290, or 32-242
|
||||
int max_vpos = ( m_ef9340.R & 0x40 ) ? 250 : 210;
|
||||
int slice = vpos % 10;
|
||||
bool dh = false;
|
||||
if (vpos == 0)
|
||||
m_ef9340.h_parity = false;
|
||||
|
||||
if ( m_ef9340.R & 0x01 && vpos < max_vpos )
|
||||
// display automaton active at 40-290, or 32-242
|
||||
int max_vpos = (m_ef9340.R & 0x40) ? 250 : 210;
|
||||
|
||||
if (m_ef9340.R & 0x01 && vpos < max_vpos)
|
||||
{
|
||||
int y = vpos;
|
||||
int y_row, slice;
|
||||
int y_row = 0;
|
||||
uint16_t char_data = 0x00;
|
||||
uint8_t fg = 0;
|
||||
uint8_t bg = 0;
|
||||
bool del = false;
|
||||
bool underline = false;
|
||||
bool blank = false;
|
||||
bool w_parity = false;
|
||||
|
||||
if ( y < 10 )
|
||||
if ( vpos < 10 )
|
||||
{
|
||||
// Service row
|
||||
if ( m_ef9340.R & 0x08 )
|
||||
if (m_ef9340.R & 0x08)
|
||||
{
|
||||
// Service row is enabled
|
||||
y_row = 31;
|
||||
slice = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -361,101 +368,129 @@ void ef9340_1_device::ef9340_scanline(int vpos)
|
||||
else
|
||||
{
|
||||
// Displaying regular row
|
||||
y_row = ((m_ef9340.Y0 & 0x1f) + (y - 10) / 10) % 24;
|
||||
slice = (y - 10) % 10;
|
||||
y_row = ((m_ef9340.Y0 & 0x1f) + (vpos - 10) / 10) % 24;
|
||||
}
|
||||
|
||||
for ( int x = 0; x < 40; x++ )
|
||||
for (int x = 0; x < 40; x++)
|
||||
{
|
||||
uint16_t addr = ef9340_get_c_addr( x, y_row );
|
||||
int s = slice;
|
||||
uint16_t addr = ef9340_get_c_addr(x, y_row);
|
||||
uint8_t a = m_ram_a[addr];
|
||||
uint8_t b = m_ram_b[addr];
|
||||
uint8_t char_data = 0x00;
|
||||
bool blink = m_ef9340.R & 0x80 && m_ef9340.blink;
|
||||
bool cursor = m_ef9340.R & 0x10 && x == m_ef9340.X && y_row == m_ef9340.Y;
|
||||
bool invert = cursor && !blink;
|
||||
bool alpha = !bool(a & 0x80);
|
||||
bool dw = false;
|
||||
|
||||
if (alpha)
|
||||
if (a & 0x80)
|
||||
{
|
||||
// Alphanumeric
|
||||
if ( b & 0x80 )
|
||||
// graphics
|
||||
if ((b & 0xe0) != 0x80)
|
||||
{
|
||||
if ( b & 0x60 )
|
||||
{
|
||||
// Extension
|
||||
char_data = m_ef934x_ext_char_ram[ external_chargen_address( b & 0x7f, slice ) ];
|
||||
fg = a & 0x07;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Deliminator
|
||||
alpha = false;
|
||||
blank = m_ef9340.R & 0x04 && b & 0x01;
|
||||
underline = bool(b & 0x04);
|
||||
char_data = 0xff;
|
||||
fg = a & 0x07;
|
||||
bg = a >> 4 & 0x07;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal
|
||||
if (slice == 9 && underline)
|
||||
char_data = 0xff;
|
||||
else
|
||||
char_data = m_charset[((b & 0x7f) * 10) + slice];
|
||||
fg = a & 0x07;
|
||||
bg = a >> 4 & 0x07;
|
||||
|
||||
if (b & 0x80)
|
||||
char_data = m_read_exram(a << 12 | b << 4 | s);
|
||||
else
|
||||
char_data = m_charset[((b | 0x80) * 10) + s];
|
||||
}
|
||||
|
||||
// Inverted
|
||||
if (alpha && a & 0x40)
|
||||
{
|
||||
invert = !invert;
|
||||
blink = m_ef9340.R & 0x80 && !m_ef9340.blink;
|
||||
}
|
||||
// illegal
|
||||
else
|
||||
char_data = 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Graphics
|
||||
if ( b & 0x80 )
|
||||
// alphanumeric
|
||||
if ((b & 0xe0) != 0x80)
|
||||
{
|
||||
if ( b & 0x60 )
|
||||
// double height
|
||||
if (a & 0x10)
|
||||
{
|
||||
// Extension
|
||||
char_data = m_ef934x_ext_char_ram[ 0x400 | external_chargen_address( b & 0x7f, slice ) ];
|
||||
fg = a & 0x07;
|
||||
bg = a >> 4 & 0x07;
|
||||
dh = true;
|
||||
if (m_ef9340.h_parity)
|
||||
s += 10;
|
||||
if (s > 0)
|
||||
s = (s - 1) / 2;
|
||||
}
|
||||
|
||||
fg = a & 0x07;
|
||||
u16 c = 0;
|
||||
|
||||
if (b & 0x80)
|
||||
c = m_read_exram(a << 12 | b << 4 | s);
|
||||
else if (s == 9 && underline)
|
||||
c = 0xff;
|
||||
else
|
||||
c = m_charset[((b & 0x7f) * 10) + s];
|
||||
|
||||
// double width
|
||||
dw = bool(a & 0x20);
|
||||
if (dw)
|
||||
{
|
||||
if (!w_parity)
|
||||
char_data = bitswap<16>(c,7,7,6,6,5,5,4,4,3,3,2,2,1,1,0,0);
|
||||
}
|
||||
else
|
||||
char_data = c;
|
||||
|
||||
// inverted
|
||||
if (a & 0x40)
|
||||
{
|
||||
// Illegal
|
||||
invert = !invert;
|
||||
blink = m_ef9340.R & 0x80 && !m_ef9340.blink;
|
||||
}
|
||||
}
|
||||
|
||||
// deliminator
|
||||
else
|
||||
{
|
||||
// Normal
|
||||
char_data = m_charset[((b | 0x80) * 10) + slice];
|
||||
fg = a & 0x07;
|
||||
bg = a >> 4 & 0x07;
|
||||
char_data = 0xff;
|
||||
|
||||
del = true;
|
||||
}
|
||||
}
|
||||
|
||||
// blink character
|
||||
if (blink && !cursor && (b & 0xe0) != 0x80 && ~a & 0x08)
|
||||
char_data = 0;
|
||||
char_data &= ~0xff;
|
||||
|
||||
if (invert)
|
||||
char_data ^= 0xff;
|
||||
|
||||
for ( int i = 0; i < 8; i++ )
|
||||
if (dw)
|
||||
w_parity = !w_parity;
|
||||
else
|
||||
w_parity = false;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint16_t d = blank ? 0 : (char_data & 1) ? fg : bg;
|
||||
m_tmp_bitmap.pix16(m_offset_y + vpos, m_offset_x + x*8 + i ) = d | 8;
|
||||
m_tmp_bitmap.pix16(m_offset_y + vpos, m_offset_x + x*8 + i) = d | 8;
|
||||
char_data >>= 1;
|
||||
}
|
||||
|
||||
if (del)
|
||||
{
|
||||
blank = m_ef9340.R & 0x04 && b & 0x01;
|
||||
underline = bool(b & 0x04);
|
||||
|
||||
del = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// determine next h parity
|
||||
if (vpos >= 10 && slice == 9)
|
||||
{
|
||||
if (dh)
|
||||
m_ef9340.h_parity = !m_ef9340.h_parity;
|
||||
else
|
||||
m_ef9340.h_parity = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,6 +26,8 @@ public:
|
||||
|
||||
// configuration helpers
|
||||
ef9340_1_device &set_offsets(int x, int y) { m_offset_x = x; m_offset_y = y; return *this; } // when used with overlay chip
|
||||
auto write_exram() { return m_write_exram.bind(); } // ADR0-ADR3 in a0-a3, B in a4-a11, A in a12-a19
|
||||
auto read_exram() { return m_read_exram.bind(); } // "
|
||||
|
||||
ef9340_1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
@ -44,9 +46,6 @@ protected:
|
||||
inline uint16_t ef9340_get_c_addr(uint8_t x, uint8_t y);
|
||||
inline void ef9340_inc_c();
|
||||
|
||||
// Calculate the external chargen address for a character and slice
|
||||
inline uint16_t external_chargen_address(uint8_t b, uint8_t slice);
|
||||
|
||||
void ef9340_scanline(int vpos);
|
||||
|
||||
/* timers */
|
||||
@ -79,11 +78,14 @@ protected:
|
||||
uint8_t M;
|
||||
bool blink;
|
||||
int blink_prescaler;
|
||||
bool h_parity;
|
||||
} m_ef9340;
|
||||
|
||||
uint8_t m_ram_a[0x400];
|
||||
uint8_t m_ram_b[0x400];
|
||||
uint8_t m_ef934x_ext_char_ram[0x800]; // The G7400 has 2KB of external ram hooked up. The datasheet only describes how to hookup 1KB.
|
||||
|
||||
devcb_write8 m_write_exram;
|
||||
devcb_read8 m_read_exram;
|
||||
};
|
||||
|
||||
|
||||
|
@ -33,9 +33,6 @@ XTAL notes (differs per model):
|
||||
- G7400: 5.911MHz + 8.867MHz
|
||||
|
||||
TODO:
|
||||
- verify odyssey3 cpu/video clocks
|
||||
- odyssey sets 210 line mode in plus graphics, which cuts off the bottom part
|
||||
of the screen
|
||||
- backgamm doesn't draw all the sprites, what causes it? It doesn't seem like
|
||||
it's a 824x bug since it does properly write data in the partial screen updates
|
||||
- 824x screen resolution is not strictly defined, height(243) is correct, but
|
||||
@ -48,8 +45,20 @@ TODO:
|
||||
be correct
|
||||
- ppp(the tetris game) does not work properly on PAL, is this homebrew NTSC-only,
|
||||
or is it due to PAL video timing? The game does mid-scanline updates
|
||||
- g7400 helicopt sometimes locks up at the sea level, timing related?
|
||||
- g7400 probably has different video timing too (not same as g7000)
|
||||
- g7400 graphics problems, mostly due to missing features in ef934x
|
||||
- 4in1 and musician are not supposed to work on g7400, but work fine on MAME,
|
||||
reason they shouldn't work is probably because they write to P2
|
||||
- verify odyssey3 cpu/video clocks
|
||||
- odyssey3 keyboard layout is not the same as g7400, but there is no software
|
||||
to test the scancodes
|
||||
|
||||
BTANB:
|
||||
- a lot of PAL games have problems on NTSC (the other way around, not so much)
|
||||
- g7400 games don't look correct on odyssey3: ef934x graphics are placed lower
|
||||
- Blackjack (Videopac 5) does not work on G7400
|
||||
|
||||
Plenty games have minor bugs not worth mentioning here.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
@ -68,6 +77,8 @@ TODO:
|
||||
#include "speaker.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class odyssey2_state : public driver_device
|
||||
{
|
||||
public:
|
||||
@ -88,6 +99,8 @@ public:
|
||||
void videopac(machine_config &config);
|
||||
void videopacf(machine_config &config);
|
||||
|
||||
void odyssey2_palette(palette_device &palette) const;
|
||||
|
||||
protected:
|
||||
required_device<i8048_device> m_maincpu;
|
||||
required_device<i8244_device> m_i8244;
|
||||
@ -99,7 +112,6 @@ protected:
|
||||
uint8_t m_p2 = 0xff;
|
||||
|
||||
DECLARE_READ_LINE_MEMBER(t1_read);
|
||||
void odyssey2_palette(palette_device &palette) const;
|
||||
|
||||
void odyssey2_io(address_map &map);
|
||||
void odyssey2_mem(address_map &map);
|
||||
@ -109,8 +121,8 @@ protected:
|
||||
required_ioport_array<8> m_keyboard;
|
||||
required_ioport_array<2> m_joysticks;
|
||||
|
||||
uint8_t io_read(offs_t offset);
|
||||
void io_write(offs_t offset, uint8_t data);
|
||||
virtual uint8_t io_read(offs_t offset);
|
||||
virtual void io_write(offs_t offset, uint8_t data);
|
||||
uint8_t bus_read();
|
||||
void bus_write(uint8_t data);
|
||||
uint8_t p1_read();
|
||||
@ -128,7 +140,7 @@ public:
|
||||
g7400_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: odyssey2_state(mconfig, type, tag)
|
||||
, m_i8243(*this, "i8243")
|
||||
, m_ef9340_1(*this, "ef9340_1")
|
||||
, m_ef934x(*this, "ef934x")
|
||||
{ }
|
||||
|
||||
void g7400(machine_config &config);
|
||||
@ -137,24 +149,311 @@ public:
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
|
||||
virtual uint8_t io_read(offs_t offset) override;
|
||||
virtual void io_write(offs_t offset, uint8_t data) override;
|
||||
|
||||
private:
|
||||
required_device<i8243_device> m_i8243;
|
||||
required_device<ef9340_1_device> m_ef9340_1;
|
||||
required_device<ef9340_1_device> m_ef934x;
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
void p2_write(uint8_t data);
|
||||
uint8_t io_vpp(offs_t offset, uint8_t data);
|
||||
uint8_t io_read(offs_t offset);
|
||||
void io_write(offs_t offset, uint8_t data);
|
||||
template<int P> void i8243_port_w(uint8_t data);
|
||||
|
||||
void g7400_io(address_map &map);
|
||||
inline offs_t ef934x_extram_address(offs_t offset);
|
||||
uint8_t ef934x_extram_r(offs_t offset);
|
||||
void ef934x_extram_w(offs_t offset, uint8_t data);
|
||||
|
||||
uint8_t m_mix_in = 0xff;
|
||||
uint8_t m_mix_out = 0xff;
|
||||
uint8_t m_mix_i8244 = 0xff;
|
||||
uint8_t m_mix_ef934x = 0xff;
|
||||
uint8_t m_ef934x_extram[0x800];
|
||||
};
|
||||
|
||||
void odyssey2_state::machine_start()
|
||||
{
|
||||
memset(m_ram, 0, sizeof(m_ram));
|
||||
|
||||
save_item(NAME(m_ram));
|
||||
save_item(NAME(m_p1));
|
||||
save_item(NAME(m_p2));
|
||||
}
|
||||
|
||||
void g7400_state::machine_start()
|
||||
{
|
||||
odyssey2_state::machine_start();
|
||||
memset(m_ef934x_extram, 0, sizeof(m_ef934x_extram));
|
||||
|
||||
save_item(NAME(m_mix_i8244));
|
||||
save_item(NAME(m_mix_ef934x));
|
||||
save_item(NAME(m_ef934x_extram));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Video
|
||||
******************************************************************************/
|
||||
|
||||
constexpr rgb_t odyssey2_colors[] =
|
||||
{
|
||||
// Background,Grid Dim
|
||||
{ 0x00, 0x00, 0x00 }, /* Black */ // i r g b
|
||||
{ 0x79, 0x00, 0x00 }, /* Red - Calibrated To Real VideoPac */ // i R g b
|
||||
{ 0x00, 0x6d, 0x07 }, /* Green - Calibrated To Real VideoPac */ // i r G b
|
||||
{ 0x77, 0x67, 0x0b }, /* Khaki - Calibrated To Real VideoPac */ // i R g B
|
||||
{ 0x1a, 0x37, 0xbe }, /* Blue - Calibrated To Real VideoPac */ // i r g B
|
||||
{ 0x94, 0x30, 0x9f }, /* Violet - Calibrated To Real VideoPac */ // i R g B
|
||||
{ 0x2a, 0xaa, 0xbe }, /* Blue-Green - Calibrated To Real VideoPac */ // i r G B
|
||||
{ 0xce, 0xce, 0xce }, /* Lt Grey */ // i R G B
|
||||
|
||||
// Background,Grid Bright
|
||||
{ 0x67, 0x67, 0x67 }, /* Grey - Calibrated To Real VideoPac */ // I R g B
|
||||
{ 0xc7, 0x51, 0x51 }, /* Lt Red - Calibrated To Real VideoPac */ // I R g b
|
||||
{ 0x56, 0xc4, 0x69 }, /* Lt Green - Calibrated To Real VideoPac */ // I R g B
|
||||
{ 0xc6, 0xb8, 0x6a }, /* Lt Yellow - Calibrated To Real VideoPac */ // I R G b
|
||||
{ 0x5c, 0x80, 0xf6 }, /* Lt Blue - Calibrated To Real VideoPac */ // I R g B
|
||||
{ 0xdc, 0x84, 0xe8 }, /* Lt Violet - Calibrated To Real VideoPac */ // I R g B
|
||||
{ 0x77, 0xe6, 0xeb }, /* Lt Blue-Green - Calibrated To Real VideoPac */ // I R g b
|
||||
{ 0xff, 0xff, 0xff } /* White */ // I R G B
|
||||
};
|
||||
|
||||
void odyssey2_state::odyssey2_palette(palette_device &palette) const
|
||||
{
|
||||
palette.set_pen_colors(0, odyssey2_colors);
|
||||
}
|
||||
|
||||
|
||||
uint32_t odyssey2_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
m_i8244->screen_update(screen, bitmap, cliprect);
|
||||
|
||||
u8 lum = ~m_p1 >> 4 & 0x08;
|
||||
|
||||
// apply external LUM setting
|
||||
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
bitmap.pix16(y, x) |= lum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t g7400_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
u8 lum = ~m_p1 >> 4 & 0x08;
|
||||
bitmap_ind16 *ef934x_bitmap = m_ef934x->get_bitmap();
|
||||
|
||||
// apply external LUM setting
|
||||
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
{
|
||||
rectangle clip = cliprect;
|
||||
clip.min_y = clip.max_y = y;
|
||||
|
||||
m_i8244->screen_update(screen, bitmap, clip);
|
||||
|
||||
for (int x = clip.min_x; x <= clip.max_x; x++)
|
||||
{
|
||||
uint16_t d = bitmap.pix16(y, x);
|
||||
uint16_t e = ef934x_bitmap->pix16(y, x);
|
||||
|
||||
// I outputs to CX
|
||||
bool i2 = !BIT(m_mix_ef934x, e & 0x07);
|
||||
m_i8244->write_cx(x, i2);
|
||||
|
||||
if (m_mix_i8244 == 0xff || ((e & 0x08) && BIT(m_mix_i8244, d & 0x07)))
|
||||
{
|
||||
// Use i8245 input
|
||||
bitmap.pix16(y, x) |= lum;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use EF934x input
|
||||
bitmap.pix16(y, x) = i2 ? e | 0x08 : e & 0x07;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
I/O
|
||||
******************************************************************************/
|
||||
|
||||
uint8_t odyssey2_state::io_read(offs_t offset)
|
||||
{
|
||||
u8 data = m_cart->io_read(offset);
|
||||
if (!(m_p1 & 0x10) && ~offset & 0x80)
|
||||
data &= m_ram[offset];
|
||||
|
||||
if ((m_p1 & 0x48) == 0)
|
||||
data &= m_i8244->read(offset);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void odyssey2_state::io_write(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (!(m_p1 & 0x40))
|
||||
{
|
||||
m_cart->io_write(offset, data);
|
||||
if (!(m_p1 & 0x10) && ~offset & 0x80)
|
||||
m_ram[offset] = data;
|
||||
}
|
||||
|
||||
if (!(m_p1 & 0x08))
|
||||
m_i8244->write(offset, data);
|
||||
}
|
||||
|
||||
uint8_t odyssey2_state::p1_read()
|
||||
{
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
// 8048 ports
|
||||
|
||||
void odyssey2_state::p1_write(uint8_t data)
|
||||
{
|
||||
// LUM changed
|
||||
if ((m_p1 ^ data) & 0x80)
|
||||
m_screen->update_now();
|
||||
|
||||
m_p1 = data;
|
||||
m_cart->write_p1(m_p1 & 0x13);
|
||||
}
|
||||
|
||||
uint8_t odyssey2_state::p2_read()
|
||||
{
|
||||
u8 data = 0xff;
|
||||
|
||||
if (!(m_p1 & 0x04))
|
||||
{
|
||||
// 74148 priority encoder, GS to P24, outputs to P25-P27
|
||||
u8 inp = count_leading_zeros(m_keyboard[m_p2 & 0x07]->read()) - 24;
|
||||
if (inp < 8)
|
||||
data &= inp << 5 | 0xf;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void odyssey2_state::p2_write(uint8_t data)
|
||||
{
|
||||
m_p2 = data;
|
||||
m_cart->write_p2(m_p2 & 0x0f);
|
||||
}
|
||||
|
||||
uint8_t odyssey2_state::bus_read()
|
||||
{
|
||||
u8 data = 0xff;
|
||||
|
||||
if (!(m_p1 & 0x04))
|
||||
{
|
||||
u8 sel = m_p2 & 0x07;
|
||||
if (sel < 2)
|
||||
data &= ~m_joysticks[sel]->read();
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void odyssey2_state::bus_write(uint8_t data)
|
||||
{
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(odyssey2_state::t1_read)
|
||||
{
|
||||
return m_i8244->vblank() | m_i8244->hblank();
|
||||
}
|
||||
|
||||
|
||||
// G7400-specific
|
||||
|
||||
uint8_t g7400_state::io_read(offs_t offset)
|
||||
{
|
||||
u8 data = odyssey2_state::io_read(offset);
|
||||
return io_vpp(offset, data);
|
||||
}
|
||||
|
||||
void g7400_state::io_write(offs_t offset, uint8_t data)
|
||||
{
|
||||
odyssey2_state::io_write(offset, data);
|
||||
io_vpp(offset, data);
|
||||
}
|
||||
|
||||
uint8_t g7400_state::io_vpp(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (!(m_p1 & 0x20))
|
||||
{
|
||||
// A2 to R/W pin
|
||||
if (offset & 4)
|
||||
data &= m_ef934x->ef9341_read( offset & 0x02, offset & 0x01 );
|
||||
else
|
||||
m_ef934x->ef9341_write( offset & 0x02, offset & 0x01, data );
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void g7400_state::p2_write(uint8_t data)
|
||||
{
|
||||
odyssey2_state::p2_write(data);
|
||||
m_i8243->p2_w(m_p2 & 0x0f);
|
||||
}
|
||||
|
||||
template<int P>
|
||||
void g7400_state::i8243_port_w(uint8_t data)
|
||||
{
|
||||
// P4,P5: color mix I8244 side (IC674)
|
||||
// P6,P7: color mix EF9340 side (IC678)
|
||||
u8 mask = 0xf;
|
||||
if (~P & 1)
|
||||
{
|
||||
data <<= 4;
|
||||
mask <<= 4;
|
||||
}
|
||||
|
||||
m_screen->update_now();
|
||||
|
||||
if (P & 2)
|
||||
m_mix_i8244 = (m_mix_i8244 & ~mask) | (data & mask);
|
||||
else
|
||||
m_mix_ef934x = (m_mix_ef934x & ~mask) | (data & mask);
|
||||
}
|
||||
|
||||
|
||||
// EF9341 extended RAM
|
||||
|
||||
offs_t g7400_state::ef934x_extram_address(offs_t offset)
|
||||
{
|
||||
u8 latch = (offset >> 12 & 0x80) | (offset >> 4 & 0x7f);
|
||||
u16 address = (latch & 0x1f) | (offset << 9 & 0x200) | (latch << 3 & 0x400);
|
||||
|
||||
if (offset & 8)
|
||||
return address | (latch & 0x60);
|
||||
else
|
||||
return address | (offset << 4 & 0x60) | (latch << 2 & 0x180);
|
||||
}
|
||||
|
||||
uint8_t g7400_state::ef934x_extram_r(offs_t offset)
|
||||
{
|
||||
return m_ef934x_extram[ef934x_extram_address(offset)];
|
||||
}
|
||||
|
||||
void g7400_state::ef934x_extram_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
m_ef934x_extram[ef934x_extram_address(offset)] = data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Address Maps
|
||||
******************************************************************************/
|
||||
|
||||
void odyssey2_state::odyssey2_mem(address_map &map)
|
||||
{
|
||||
@ -163,18 +462,16 @@ void odyssey2_state::odyssey2_mem(address_map &map)
|
||||
map(0x0c00, 0x0fff).r(m_cart, FUNC(o2_cart_slot_device::read_rom0c));
|
||||
}
|
||||
|
||||
|
||||
void odyssey2_state::odyssey2_io(address_map &map)
|
||||
{
|
||||
map(0x00, 0xff).rw(FUNC(odyssey2_state::io_read), FUNC(odyssey2_state::io_write));
|
||||
}
|
||||
|
||||
|
||||
void g7400_state::g7400_io(address_map &map)
|
||||
{
|
||||
map(0x00, 0xff).rw(FUNC(g7400_state::io_read), FUNC(g7400_state::io_write));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
Input Ports
|
||||
******************************************************************************/
|
||||
|
||||
static INPUT_PORTS_START( odyssey2 )
|
||||
PORT_START("KEY.0")
|
||||
@ -335,269 +632,14 @@ static INPUT_PORTS_START( g7400 )
|
||||
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
|
||||
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Break") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(PAUSE))
|
||||
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Cntl") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
|
||||
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_UNUSED)
|
||||
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED)
|
||||
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_UNUSED)
|
||||
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_UNUSED)
|
||||
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
constexpr rgb_t odyssey2_colors[] =
|
||||
{
|
||||
// Background,Grid Dim
|
||||
{ 0x00, 0x00, 0x00 }, /* Black */ // i r g b
|
||||
{ 0x79, 0x00, 0x00 }, /* Red - Calibrated To Real VideoPac */ // i R g b
|
||||
{ 0x00, 0x6d, 0x07 }, /* Green - Calibrated To Real VideoPac */ // i r G b
|
||||
{ 0x77, 0x67, 0x0b }, /* Khaki - Calibrated To Real VideoPac */ // i R g B
|
||||
{ 0x1a, 0x37, 0xbe }, /* Blue - Calibrated To Real VideoPac */ // i r g B
|
||||
{ 0x94, 0x30, 0x9f }, /* Violet - Calibrated To Real VideoPac */ // i R g B
|
||||
{ 0x2a, 0xaa, 0xbe }, /* Blue-Green - Calibrated To Real VideoPac */ // i r G B
|
||||
{ 0xce, 0xce, 0xce }, /* Lt Grey */ // i R G B
|
||||
|
||||
// Background,Grid Bright
|
||||
{ 0x67, 0x67, 0x67 }, /* Grey - Calibrated To Real VideoPac */ // I R g B
|
||||
{ 0xc7, 0x51, 0x51 }, /* Lt Red - Calibrated To Real VideoPac */ // I R g b
|
||||
{ 0x56, 0xc4, 0x69 }, /* Lt Green - Calibrated To Real VideoPac */ // I R g B
|
||||
{ 0xc6, 0xb8, 0x6a }, /* Lt Yellow - Calibrated To Real VideoPac */ // I R G b
|
||||
{ 0x5c, 0x80, 0xf6 }, /* Lt Blue - Calibrated To Real VideoPac */ // I R g B
|
||||
{ 0xdc, 0x84, 0xe8 }, /* Lt Violet - Calibrated To Real VideoPac */ // I R g B
|
||||
{ 0x77, 0xe6, 0xeb }, /* Lt Blue-Green - Calibrated To Real VideoPac */ // I R g b
|
||||
{ 0xff, 0xff, 0xff } /* White */ // I R G B
|
||||
};
|
||||
|
||||
|
||||
void odyssey2_state::odyssey2_palette(palette_device &palette) const
|
||||
{
|
||||
palette.set_pen_colors(0, odyssey2_colors);
|
||||
}
|
||||
|
||||
|
||||
void odyssey2_state::machine_start()
|
||||
{
|
||||
memset(m_ram, 0, sizeof(m_ram));
|
||||
|
||||
save_item(NAME(m_ram));
|
||||
save_item(NAME(m_p1));
|
||||
save_item(NAME(m_p2));
|
||||
}
|
||||
|
||||
|
||||
void g7400_state::machine_start()
|
||||
{
|
||||
odyssey2_state::machine_start();
|
||||
|
||||
save_item(NAME(m_mix_in));
|
||||
save_item(NAME(m_mix_out));
|
||||
}
|
||||
|
||||
|
||||
/****** External RAM ******************************/
|
||||
|
||||
uint8_t odyssey2_state::io_read(offs_t offset)
|
||||
{
|
||||
u8 data = m_cart->io_read(offset);
|
||||
if (!(m_p1 & 0x10) && ~offset & 0x80)
|
||||
data &= m_ram[offset];
|
||||
|
||||
if ((m_p1 & 0x48) == 0)
|
||||
data &= m_i8244->read(offset);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void odyssey2_state::io_write(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (!(m_p1 & 0x40))
|
||||
{
|
||||
m_cart->io_write(offset, data);
|
||||
if (!(m_p1 & 0x10) && ~offset & 0x80)
|
||||
m_ram[offset] = data;
|
||||
}
|
||||
|
||||
if (!(m_p1 & 0x08))
|
||||
m_i8244->write(offset, data);
|
||||
}
|
||||
|
||||
|
||||
uint8_t g7400_state::io_vpp(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (!(m_p1 & 0x20))
|
||||
{
|
||||
// A2 to R/W pin
|
||||
if (offset & 4)
|
||||
data &= m_ef9340_1->ef9341_read( offset & 0x02, offset & 0x01 );
|
||||
else
|
||||
m_ef9340_1->ef9341_write( offset & 0x02, offset & 0x01, data );
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
uint8_t g7400_state::io_read(offs_t offset)
|
||||
{
|
||||
u8 data = odyssey2_state::io_read(offset);
|
||||
return io_vpp(offset, data);
|
||||
}
|
||||
|
||||
|
||||
void g7400_state::io_write(offs_t offset, uint8_t data)
|
||||
{
|
||||
odyssey2_state::io_write(offset, data);
|
||||
io_vpp(offset, data);
|
||||
}
|
||||
|
||||
|
||||
uint32_t odyssey2_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
m_i8244->screen_update(screen, bitmap, cliprect);
|
||||
|
||||
u8 lum = ~m_p1 >> 4 & 0x08;
|
||||
|
||||
// apply external LUM setting
|
||||
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
bitmap.pix16(y, x) |= lum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint32_t g7400_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
u8 lum = ~m_p1 >> 4 & 0x08;
|
||||
bitmap_ind16 *ef934x_bitmap = m_ef9340_1->get_bitmap();
|
||||
|
||||
// apply external LUM setting
|
||||
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
{
|
||||
rectangle clip = cliprect;
|
||||
clip.min_y = clip.max_y = y;
|
||||
|
||||
m_i8244->screen_update(screen, bitmap, clip);
|
||||
|
||||
for (int x = clip.min_x; x <= clip.max_x; x++)
|
||||
{
|
||||
uint16_t d = bitmap.pix16(y, x);
|
||||
uint16_t e = ef934x_bitmap->pix16(y, x);
|
||||
|
||||
// I outputs to CX
|
||||
bool i2 = !BIT(m_mix_out, e & 0x07);
|
||||
m_i8244->write_cx(x, i2);
|
||||
|
||||
if (m_mix_in == 0xff || ((e & 0x08) && BIT(m_mix_in, d & 0x07)))
|
||||
{
|
||||
// Use i8245 input
|
||||
bitmap.pix16(y, x) |= lum;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use EF934x input
|
||||
bitmap.pix16(y, x) = i2 ? e | 0x08 : e & 0x07;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
READ_LINE_MEMBER(odyssey2_state::t1_read)
|
||||
{
|
||||
return m_i8244->vblank() | m_i8244->hblank();
|
||||
}
|
||||
|
||||
|
||||
uint8_t odyssey2_state::p1_read()
|
||||
{
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
void odyssey2_state::p1_write(uint8_t data)
|
||||
{
|
||||
// LUM changed
|
||||
if ((m_p1 ^ data) & 0x80)
|
||||
m_screen->update_now();
|
||||
|
||||
m_p1 = data;
|
||||
m_cart->write_p1(m_p1 & 0x13);
|
||||
}
|
||||
|
||||
|
||||
uint8_t odyssey2_state::p2_read()
|
||||
{
|
||||
u8 data = 0xff;
|
||||
|
||||
if (!(m_p1 & 0x04))
|
||||
{
|
||||
// 74148 priority encoder, GS to P24, outputs to P25-P27
|
||||
u8 inp = count_leading_zeros(m_keyboard[m_p2 & 0x07]->read()) - 24;
|
||||
if (inp < 8)
|
||||
data &= inp << 5 | 0xf;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void odyssey2_state::p2_write(uint8_t data)
|
||||
{
|
||||
m_p2 = data;
|
||||
m_cart->write_p2(m_p2 & 0x0f);
|
||||
}
|
||||
|
||||
|
||||
void g7400_state::p2_write(uint8_t data)
|
||||
{
|
||||
odyssey2_state::p2_write(data);
|
||||
m_i8243->p2_w(m_p2 & 0x0f);
|
||||
}
|
||||
|
||||
|
||||
uint8_t odyssey2_state::bus_read()
|
||||
{
|
||||
u8 data = 0xff;
|
||||
|
||||
if (!(m_p1 & 0x04))
|
||||
{
|
||||
u8 sel = m_p2 & 0x07;
|
||||
if (sel < 2)
|
||||
data &= ~m_joysticks[sel]->read();
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void odyssey2_state::bus_write(uint8_t data)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<int P>
|
||||
void g7400_state::i8243_port_w(uint8_t data)
|
||||
{
|
||||
// P4,P5: color mix out (IC674)
|
||||
// P6,P7: color mix in (IC678)
|
||||
u8 mask = 0xf;
|
||||
if (~P & 1)
|
||||
{
|
||||
data <<= 4;
|
||||
mask <<= 4;
|
||||
}
|
||||
|
||||
m_screen->update_now();
|
||||
|
||||
if (P & 2)
|
||||
m_mix_in = (m_mix_in & ~mask) | (data & mask);
|
||||
else
|
||||
m_mix_out = (m_mix_out & ~mask) | (data & mask);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Machine Configs
|
||||
******************************************************************************/
|
||||
|
||||
void odyssey2_state::odyssey2(machine_config &config)
|
||||
{
|
||||
@ -622,13 +664,14 @@ void odyssey2_state::odyssey2(machine_config &config)
|
||||
|
||||
PALETTE(config, "palette", FUNC(odyssey2_state::odyssey2_palette), 16);
|
||||
|
||||
SPEAKER(config, "mono").front_center();
|
||||
I8244(config, m_i8244, XTAL(7'159'090) / 2);
|
||||
m_i8244->set_screen("screen");
|
||||
m_i8244->set_screen_size(356, 243);
|
||||
m_i8244->irq_cb().set_inputline(m_maincpu, MCS48_INPUT_IRQ);
|
||||
m_i8244->add_route(ALL_OUTPUTS, "mono", 0.40);
|
||||
|
||||
SPEAKER(config, "mono").front_center();
|
||||
|
||||
/* cartridge */
|
||||
O2_CART_SLOT(config, m_cart, o2_cart, nullptr);
|
||||
SOFTWARE_LIST(config, "cart_list").set_original("odyssey2");
|
||||
@ -664,7 +707,7 @@ void g7400_state::g7400(machine_config &config)
|
||||
/* basic machine hardware */
|
||||
I8048(config, m_maincpu, XTAL(5'911'000));
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &g7400_state::odyssey2_mem);
|
||||
m_maincpu->set_addrmap(AS_IO, &g7400_state::g7400_io);
|
||||
m_maincpu->set_addrmap(AS_IO, &g7400_state::odyssey2_io);
|
||||
m_maincpu->p1_in_cb().set(FUNC(g7400_state::p1_read));
|
||||
m_maincpu->p1_out_cb().set(FUNC(g7400_state::p1_write));
|
||||
m_maincpu->p2_in_cb().set(FUNC(g7400_state::p2_read));
|
||||
@ -689,16 +732,19 @@ void g7400_state::g7400(machine_config &config)
|
||||
m_i8243->p6_out_cb().set(FUNC(g7400_state::i8243_port_w<2>));
|
||||
m_i8243->p7_out_cb().set(FUNC(g7400_state::i8243_port_w<3>));
|
||||
|
||||
EF9340_1(config, m_ef9340_1, XTAL(8'867'000)/5 * 2, "screen");
|
||||
m_ef9340_1->set_offsets(15, 5);
|
||||
EF9340_1(config, m_ef934x, XTAL(8'867'000)/5 * 2, "screen");
|
||||
m_ef934x->set_offsets(15, 5);
|
||||
m_ef934x->read_exram().set(FUNC(g7400_state::ef934x_extram_r));
|
||||
m_ef934x->write_exram().set(FUNC(g7400_state::ef934x_extram_w));
|
||||
|
||||
SPEAKER(config, "mono").front_center();
|
||||
I8245(config, m_i8244, XTAL(8'867'000)/5 * 2);
|
||||
m_i8244->set_screen("screen");
|
||||
m_i8244->set_screen_size(356, 243);
|
||||
m_i8244->irq_cb().set_inputline(m_maincpu, MCS48_INPUT_IRQ);
|
||||
m_i8244->add_route(ALL_OUTPUTS, "mono", 0.40);
|
||||
|
||||
SPEAKER(config, "mono").front_center();
|
||||
|
||||
/* cartridge */
|
||||
O2_CART_SLOT(config, m_cart, o2_cart, nullptr);
|
||||
SOFTWARE_LIST(config, "cart_list").set_original("g7400");
|
||||
@ -716,11 +762,21 @@ void g7400_state::odyssey3(machine_config &config)
|
||||
m_i8244->irq_cb().set_inputline(m_maincpu, MCS48_INPUT_IRQ);
|
||||
m_i8244->add_route(ALL_OUTPUTS, "mono", 0.40);
|
||||
|
||||
m_ef9340_1->set_clock(XTAL(7'159'090) / 2);
|
||||
m_ef934x->set_clock(XTAL(7'159'090) / 2);
|
||||
m_ef934x->set_offsets(15, 15);
|
||||
|
||||
m_maincpu->set_clock((XTAL(7'159'090) * 3) / 4);
|
||||
|
||||
// same color encoder as O2 (no RGB port)
|
||||
PALETTE(config.replace(), "palette", FUNC(odyssey2_state::odyssey2_palette), 16);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
ROM Definitions
|
||||
******************************************************************************/
|
||||
|
||||
ROM_START (odyssey2)
|
||||
ROM_REGION(0x0400,"maincpu",0)
|
||||
ROM_LOAD ("o2bios.rom", 0x0000, 0x0400, CRC(8016a315) SHA1(b2e1955d957a475de2411770452eff4ea19f4cee))
|
||||
@ -752,12 +808,19 @@ ROM_START (odyssey3)
|
||||
ROM_LOAD ("odyssey3.bin", 0x0000, 0x0400, CRC(e2b23324) SHA1(0a38c5f2cea929d2fe0a23e5e1a60de9155815dc))
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS */
|
||||
COMP( 1979, odyssey2, 0, 0, odyssey2, odyssey2, odyssey2_state, empty_init, "Magnavox", "Odyssey 2 (US)", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1978, videopac, odyssey2, 0, videopac, odyssey2, odyssey2_state, empty_init, "Philips", "Videopac G7000 (Europe)", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1979, videopacf, odyssey2, 0, videopacf, odyssey2, odyssey2_state, empty_init, "Philips", "Videopac C52 (France)", MACHINE_SUPPORTS_SAVE )
|
||||
|
||||
COMP( 1983, g7400, 0, 0, g7400, g7400, g7400_state, empty_init, "Philips", "Videopac+ G7400 (Europe)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_GRAPHICS )
|
||||
COMP( 1983, jopac, g7400, 0, g7400, g7400, g7400_state, empty_init, "Philips (Brandt license)", "Jopac JO7400 (France)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_GRAPHICS )
|
||||
COMP( 1983, odyssey3, g7400, 0, odyssey3, g7400, g7400_state, empty_init, "Magnavox", "Odyssey 3 Command Center (US, prototype)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_GRAPHICS )
|
||||
|
||||
/******************************************************************************
|
||||
Drivers
|
||||
******************************************************************************/
|
||||
|
||||
// YEAR NAME PARENT CMP MACHINE INPUT STATE INIT COMPANY, FULLNAME, FLAGS
|
||||
COMP( 1979, odyssey2, 0, 0, odyssey2, odyssey2, odyssey2_state, empty_init, "Magnavox", "Odyssey 2 (US)", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1978, videopac, odyssey2, 0, videopac, odyssey2, odyssey2_state, empty_init, "Philips", "Videopac G7000 (Europe)", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1979, videopacf, odyssey2, 0, videopacf, odyssey2, odyssey2_state, empty_init, "Philips", "Videopac C52 (France)", MACHINE_SUPPORTS_SAVE )
|
||||
|
||||
COMP( 1983, g7400, 0, 0, g7400, g7400, g7400_state, empty_init, "Philips", "Videopac+ G7400 (Europe)", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1983, jopac, g7400, 0, g7400, g7400, g7400_state, empty_init, "Philips (Brandt license)", "Jopac JO7400 (France)", MACHINE_SUPPORTS_SAVE )
|
||||
COMP( 1983, odyssey3, g7400, 0, odyssey3, g7400, g7400_state, empty_init, "Magnavox", "Odyssey 3 Command Center (US, prototype)", MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -164,6 +164,7 @@ void intchess_state::vram_w(offs_t offset, u8 data)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
I/O
|
||||
******************************************************************************/
|
||||
|
Loading…
Reference in New Issue
Block a user