mirror of
https://github.com/holub/mame
synced 2025-10-07 17:27:06 +03:00
277 lines
6.8 KiB
C
277 lines
6.8 KiB
C
/*\
|
|
* * Linus Akesson's "Craft"
|
|
* *
|
|
* * Driver by MooglyGuy
|
|
\*/
|
|
|
|
#include "emu.h"
|
|
#include "cpu/avr8/avr8.h"
|
|
#include "sound/dac.h"
|
|
|
|
#define VERBOSE_LEVEL (0)
|
|
|
|
#define ENABLE_VERBOSE_LOG (0)
|
|
|
|
#if ENABLE_VERBOSE_LOG
|
|
inline void craft_state::verboselog(int n_level, const char *s_fmt, ...)
|
|
{
|
|
if( VERBOSE_LEVEL >= n_level )
|
|
{
|
|
va_list v;
|
|
char buf[ 32768 ];
|
|
va_start( v, s_fmt );
|
|
vsprintf( buf, s_fmt, v );
|
|
va_end( v );
|
|
logerror( "%08x: %s", m_maincpu->safe_pc(), buf );
|
|
}
|
|
}
|
|
#else
|
|
#define verboselog(x,y,z,...)
|
|
#endif
|
|
|
|
#define MASTER_CLOCK 20000000
|
|
|
|
#define VISIBLE_CYCLES 480
|
|
#define HSYNC_CYCLES 155
|
|
#define LINE_CYCLES (VISIBLE_CYCLES + HSYNC_CYCLES)
|
|
#define VISIBLE_LINES 480
|
|
#define VSYNC_LINES 45
|
|
#define LINES_PER_FRAME (VISIBLE_LINES + VSYNC_LINES)
|
|
#define CYCLES_PER_FRAME (LINES_PER_FRAME * LINE_CYCLES)
|
|
#define PIXELS_PER_FRAME (CYCLES_PER_FRAME)
|
|
|
|
/****************************************************\
|
|
* I/O devices *
|
|
\****************************************************/
|
|
|
|
class craft_state : public driver_device
|
|
{
|
|
public:
|
|
craft_state(const machine_config &mconfig, device_type type, const char *tag)
|
|
: driver_device(mconfig, type, tag),
|
|
m_maincpu(*this, "maincpu"),
|
|
m_dac(*this, "dac")
|
|
{
|
|
}
|
|
|
|
void video_update();
|
|
|
|
virtual void machine_start();
|
|
|
|
UINT32 m_last_cycles;
|
|
UINT64 m_frame_start_cycle;
|
|
|
|
UINT8 m_port_b;
|
|
UINT8 m_port_c;
|
|
UINT8 m_port_d;
|
|
|
|
UINT8 m_latched_color;
|
|
UINT8 m_pixels[PIXELS_PER_FRAME];
|
|
|
|
required_device<avr8_device> m_maincpu;
|
|
|
|
DECLARE_READ8_MEMBER(port_r);
|
|
DECLARE_WRITE8_MEMBER(port_w);
|
|
DECLARE_DRIVER_INIT(craft);
|
|
virtual void machine_reset();
|
|
UINT32 screen_update_craft(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
|
#if ENABLE_VERBOSE_LOG
|
|
inline void verboselog(int n_level, const char *s_fmt, ...);
|
|
#endif
|
|
required_device<dac_device> m_dac;
|
|
};
|
|
|
|
void craft_state::machine_start()
|
|
{
|
|
}
|
|
|
|
READ8_MEMBER(craft_state::port_r)
|
|
{
|
|
switch( offset )
|
|
{
|
|
case 0x00: // Port A
|
|
case 0x01: // Port B
|
|
case 0x02: // Port C
|
|
case 0x03: // Port D
|
|
// Unhandled
|
|
return 0x00;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
WRITE8_MEMBER(craft_state::port_w)
|
|
{
|
|
switch( offset )
|
|
{
|
|
case 0x00: // Port A
|
|
// Unhandled
|
|
break;
|
|
|
|
case 0x01: // Port B
|
|
{
|
|
UINT8 old_port_b = m_port_b;
|
|
UINT8 pins = data;
|
|
UINT8 changed = pins ^ old_port_b;
|
|
if(pins & changed & 0x02)
|
|
{
|
|
m_frame_start_cycle = m_maincpu->get_elapsed_cycles();
|
|
video_update();
|
|
}
|
|
if(changed & 0x08)
|
|
{
|
|
video_update();
|
|
m_latched_color = (pins & 0x08) ? (m_port_c & 0x3f) : 0x3f;
|
|
}
|
|
m_port_b = data;
|
|
break;
|
|
}
|
|
|
|
case 0x02: // Port C
|
|
video_update();
|
|
m_port_c = data;
|
|
m_latched_color = m_port_c;
|
|
break;
|
|
|
|
case 0x03: // Port D
|
|
{
|
|
m_port_d = data;
|
|
UINT8 audio_sample = (data & 0x02) | ((data & 0xf4) >> 2);
|
|
m_dac->write_unsigned8(audio_sample << 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void craft_state::video_update()
|
|
{
|
|
UINT64 cycles = m_maincpu->get_elapsed_cycles();
|
|
UINT32 frame_cycles = (UINT32)(cycles - m_frame_start_cycle);
|
|
|
|
if (m_last_cycles < frame_cycles)
|
|
{
|
|
for (UINT32 pixidx = m_last_cycles; pixidx < frame_cycles && pixidx < PIXELS_PER_FRAME; pixidx++)
|
|
{
|
|
m_pixels[pixidx] = m_latched_color;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UINT32 end_clear = sizeof(m_pixels) - m_last_cycles;
|
|
UINT32 start_clear = frame_cycles;
|
|
end_clear = (end_clear > PIXELS_PER_FRAME) ? (PIXELS_PER_FRAME - m_last_cycles) : end_clear;
|
|
start_clear = (start_clear > PIXELS_PER_FRAME) ? PIXELS_PER_FRAME : start_clear;
|
|
if (m_last_cycles < PIXELS_PER_FRAME)
|
|
{
|
|
memset(m_pixels + m_last_cycles, 0, end_clear);
|
|
}
|
|
if (start_clear < PIXELS_PER_FRAME)
|
|
{
|
|
memset(m_pixels, 0, start_clear);
|
|
}
|
|
}
|
|
|
|
m_last_cycles = frame_cycles;
|
|
}
|
|
|
|
/****************************************************\
|
|
* Address maps *
|
|
\****************************************************/
|
|
|
|
static ADDRESS_MAP_START( craft_prg_map, AS_PROGRAM, 8, craft_state )
|
|
AM_RANGE(0x0000, 0x1fff) AM_ROM
|
|
ADDRESS_MAP_END
|
|
|
|
static ADDRESS_MAP_START( craft_data_map, AS_DATA, 8, craft_state )
|
|
AM_RANGE(0x0100, 0x04ff) AM_RAM
|
|
ADDRESS_MAP_END
|
|
|
|
static ADDRESS_MAP_START( craft_io_map, AS_IO, 8, craft_state )
|
|
AM_RANGE(0x00, 0x03) AM_READWRITE( port_r, port_w )
|
|
ADDRESS_MAP_END
|
|
|
|
/****************************************************\
|
|
* Input ports *
|
|
\****************************************************/
|
|
|
|
static INPUT_PORTS_START( craft )
|
|
PORT_START("MAIN")
|
|
PORT_BIT(0xff, IP_ACTIVE_HIGH, IPT_UNUSED)
|
|
INPUT_PORTS_END
|
|
|
|
/****************************************************\
|
|
* Video hardware *
|
|
\****************************************************/
|
|
|
|
UINT32 craft_state::screen_update_craft(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
|
{
|
|
for(int y = 0; y < LINES_PER_FRAME; y++)
|
|
{
|
|
UINT32 *line = &bitmap.pix32(y);
|
|
for(int x = 0; x < LINE_CYCLES; x++)
|
|
{
|
|
UINT8 pixel = m_pixels[y * LINE_CYCLES + x];
|
|
UINT8 r = 0x55 * ((pixel & 0x30) >> 4);
|
|
UINT8 g = 0x55 * ((pixel & 0x0c) >> 2);
|
|
UINT8 b = 0x55 * (pixel & 0x03);
|
|
line[x] = 0xff000000 | (r << 16) | (g << 8) | b;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************\
|
|
* Machine definition *
|
|
\****************************************************/
|
|
|
|
DRIVER_INIT_MEMBER(craft_state,craft)
|
|
{
|
|
}
|
|
|
|
void craft_state::machine_reset()
|
|
{
|
|
m_dac->write_unsigned8(0x00);
|
|
|
|
m_frame_start_cycle = 0;
|
|
m_last_cycles = 0;
|
|
}
|
|
|
|
const avr8_config atmega88_config =
|
|
{
|
|
"eeprom"
|
|
};
|
|
|
|
static MACHINE_CONFIG_START( craft, craft_state )
|
|
|
|
/* basic machine hardware */
|
|
MCFG_CPU_ADD("maincpu", ATMEGA88, MASTER_CLOCK)
|
|
MCFG_CPU_AVR8_CONFIG(atmega88_config)
|
|
MCFG_CPU_PROGRAM_MAP(craft_prg_map)
|
|
MCFG_CPU_DATA_MAP(craft_data_map)
|
|
MCFG_CPU_IO_MAP(craft_io_map)
|
|
|
|
/* video hardware */
|
|
MCFG_SCREEN_ADD("screen", RASTER)
|
|
MCFG_SCREEN_REFRESH_RATE(59.99)
|
|
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(1429)) /* accurate */
|
|
MCFG_SCREEN_SIZE(635, 525)
|
|
MCFG_SCREEN_VISIBLE_AREA(47, 526, 36, 515)
|
|
MCFG_SCREEN_UPDATE_DRIVER(craft_state, screen_update_craft)
|
|
MCFG_PALETTE_LENGTH(0x1000)
|
|
|
|
/* sound hardware */
|
|
MCFG_SPEAKER_STANDARD_MONO("avr8")
|
|
MCFG_SOUND_ADD("dac", DAC, 0)
|
|
MCFG_SOUND_ROUTE(0, "avr8", 1.00)
|
|
MACHINE_CONFIG_END
|
|
|
|
ROM_START( craft )
|
|
ROM_REGION( 0x2000, "maincpu", 0 ) /* Main program store */
|
|
ROM_LOAD( "craft.bin", 0x0000, 0x2000, CRC(2e6f9ad2) SHA1(75e495bf18395d74289ca7ee2649622fc4010457) )
|
|
ROM_REGION( 0x200, "eeprom", 0 ) /* on-die eeprom */
|
|
ROM_LOAD( "eeprom.raw", 0x0000, 0x0200, CRC(e18a2af9) SHA1(81fc6f2d391edfd3244870214fac37929af0ac0c) )
|
|
ROM_END
|
|
|
|
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
|
|
CONS(2008, craft, 0, 0, craft, craft, craft_state, craft, "Linus Akesson", "Craft", GAME_NOT_WORKING)
|