-avr8.c: Fixed register indexing for MULSU opcode. [MooglyGuy]

-avr8.c: Fixed register writeback for LD -Z and LD -Y opcodes. [MooglyGuy]

-craft.c: Preliminary video support, bad vsync and colors still. [MooglyGuy]
This commit is contained in:
Ryan Holtz 2012-10-26 02:47:23 +00:00
parent 029ef2cd18
commit 002feccb1b
3 changed files with 111 additions and 23 deletions

View File

@ -367,6 +367,11 @@ INLINE UINT8 POP(avr8_state *cpustate)
return READ_IO_8(cpustate, sp);
}
UINT64 avr8_get_elapsed_cycles(device_t *device)
{
return get_safe_token(device)->elapsed_cycles;
}
/*****************************************************************************/
// Interrupts
@ -429,14 +434,6 @@ static void avr8_update_interrupt_internal(avr8_state *cpustate, int source)
}
}
/*static void avr8_poll_interrupt(avr8_state *cpustate)
{
for (int idx = 0; idx < AVR8_INTIDX_COUNT; idx++)
{
avr8_update_interrupt_internal(cpustate, idx);
}
}*/
void avr8_update_interrupt(device_t *device, int source)
{
avr8_state *cpustate = get_safe_token(device);
@ -1036,6 +1033,7 @@ static bool avr8_io_reg_read(avr8_state *cpustate, UINT16 offset, UINT8 *data)
case AVR8_REGIDX_TCNT1L:
case AVR8_REGIDX_TCNT1H:
case AVR8_REGIDX_GPIOR0:
case AVR8_REGIDX_TCNT2:
*data = cpustate->r[offset];
return true;
@ -1100,6 +1098,8 @@ static CPU_INIT( avr8 )
cpustate->interrupt_pending = false;
cpustate->elapsed_cycles = 0;
device->save_item(NAME(cpustate->pc));
}
@ -1113,6 +1113,7 @@ static CPU_RESET( avr8 )
cpustate->status = 0;
cpustate->pc = 0;
cpustate->elapsed_cycles = 0;
cpustate->interrupt_pending = false;
}
@ -1160,7 +1161,7 @@ static CPU_EXECUTE( avr8 )
opcycles = 2;
break;
case 0x0300: // MULSU Rd,Rr
sd = (INT8)cpustate->r[16 + RD4(op)] * (UINT8)cpustate->r[16 + RR4(op)];
sd = (INT8)cpustate->r[16 + RD3(op)] * (UINT8)cpustate->r[16 + RR3(op)];
cpustate->r[1] = (sd >> 8) & 0x00ff;
cpustate->r[0] = sd & 0x00ff;
SREG_W(AVR8_SREG_C, (sd & 0x8000) ? 1 : 0);
@ -1393,8 +1394,8 @@ static CPU_EXECUTE( avr8 )
pd = ZREG;
pd--;
cpustate->r[RD5(op)] = READ_IO_8(cpustate, pd);
cpustate->r[27] = (pd >> 8) & 0x00ff;
cpustate->r[26] = pd & 0x00ff;
cpustate->r[31] = (pd >> 8) & 0x00ff;
cpustate->r[30] = pd & 0x00ff;
opcycles = 2;
break;
case 0x0004: // LPM Rd,Z
@ -1429,8 +1430,8 @@ static CPU_EXECUTE( avr8 )
pd = YREG;
pd--;
cpustate->r[RD5(op)] = READ_IO_8(cpustate, pd);
cpustate->r[27] = (pd >> 8) & 0x00ff;
cpustate->r[26] = pd & 0x00ff;
cpustate->r[29] = (pd >> 8) & 0x00ff;
cpustate->r[28] = pd & 0x00ff;
opcycles = 2;
break;
case 0x000c: // LD Rd,X
@ -1970,7 +1971,7 @@ static CPU_EXECUTE( avr8 )
}
else // SBRC Rd, b
{
if(!BIT(cpustate->r[RD5(op)], RR3(op)))
if(NOT(BIT(cpustate->r[RD5(op)], RR3(op))))
{
op = (UINT32)READ_PRG_16(cpustate, cpustate->pc++);
cpustate->pc += avr8_is_long_opcode(op) ? 1 : 0;
@ -1986,6 +1987,8 @@ static CPU_EXECUTE( avr8 )
cpustate->icount -= opcycles;
cpustate->elapsed_cycles += opcycles;
avr8_timer_tick(cpustate, opcycles);
}
}

View File

@ -41,6 +41,8 @@ struct avr8_state
UINT16 timer2_prescale;
UINT16 timer2_prescale_count;
UINT64 elapsed_cycles;
bool interrupt_pending;
};
@ -301,6 +303,7 @@ DECLARE_LEGACY_CPU_DEVICE(ATMEGA88, atmega88);
DECLARE_LEGACY_CPU_DEVICE(ATMEGA644, atmega644);
void avr8_update_interrupt(device_t *device, int source);
UINT64 avr8_get_elapsed_cycles(device_t *device);
CPU_DISASSEMBLE( avr8 );

View File

@ -29,13 +29,23 @@ INLINE void verboselog(running_machine &machine, int n_level, const char *s_fmt,
#define verboselog(x,y,z,...)
#endif
#define MASTER_CLOCK 20000000
#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 defines *
\****************************************************/
#define AVR8_DDRD (state->m_regs[AVR8_REGIDX_DDRD])
#define AVR8_PORTC (state->m_regs[AVR8_REGIDX_PORTC])
#define AVR8_DDRC (state->m_regs[AVR8_REGIDX_DDRC])
#define AVR8_PORTB (state->m_regs[AVR8_REGIDX_PORTB])
#define AVR8_DDRB (state->m_regs[AVR8_REGIDX_DDRB])
@ -72,6 +82,12 @@ public:
UINT8 m_regs[0x100];
UINT8* m_eeprom;
UINT32 last_cycles;
bool spi_pending;
UINT32 spi_start_cycle;
UINT8 m_pixels[PIXELS_PER_FRAME + LINE_CYCLES]; // Allocate one extra line for wrapping in the video update
required_device<cpu_device> m_maincpu;
@ -141,6 +157,38 @@ static void avr8_change_ddr(running_machine &machine, int reg, UINT8 data)
}
}
static void avr8_video_update(running_machine &machine)
{
craft_state *state = machine.driver_data<craft_state>();
UINT64 cycles = avr8_get_elapsed_cycles(state->m_maincpu);
UINT32 frame_cycles = (UINT32)(cycles % CYCLES_PER_FRAME);
if (state->last_cycles < frame_cycles)
{
for (UINT32 pixidx = state->last_cycles; pixidx < frame_cycles; pixidx++)
{
UINT8 value = AVR8_PORTC & 0x3f;
if (state->spi_pending)
{
if (pixidx >= state->spi_start_cycle && pixidx < (state->spi_start_cycle + 16))
{
UINT8 bitidx = 7 - ((pixidx - state->spi_start_cycle) >> 1);
value = ((state->m_regs[AVR8_REGIDX_SPDR] & (1 << bitidx)) ? value : 0x3f);
if (pixidx == (state->spi_start_cycle + 15))
{
state->spi_pending = false;
state->m_regs[AVR8_REGIDX_SPDR] = 0;
}
}
}
state->m_pixels[pixidx] = value;
}
}
state->last_cycles = frame_cycles;
}
static void avr8_change_port(running_machine &machine, int reg, UINT8 data)
{
craft_state *state = machine.driver_data<craft_state>();
@ -156,7 +204,25 @@ static void avr8_change_port(running_machine &machine, int reg, UINT8 data)
//verboselog(machine, 0, "avr8_change_port: PORT%c lines %02x changed\n", avr8_reg_name[reg], changed);
}
if (reg == AVR8_REG_D) {
if (reg == AVR8_REG_C)
{
avr8_video_update(machine);
/*if (frame_cycles >= state->spi_start_cycle && frame_cycles < (state->spi_start_cycle + 16))
{
UINT8 bitidx = 7 - ((frame_cycles - state->spi_start_cycle) >> 1);
state->m_pixels[frame_cycles] = ((state->m_regs[AVR8_REGIDX_SPDR] & (1 << bitidx)) ? 0x3f : (data & 0x3f));
}
else
{
state->m_pixels[frame_cycles] = data & 0x3f;
}*/
AVR8_PORTC = data;
}
if (reg == AVR8_REG_D)
{
UINT8 audio_sample = (data & 0x02) | ((data & 0xf4) >> 2);
state->dac->write_unsigned8(audio_sample << 2);
@ -289,7 +355,10 @@ WRITE8_MEMBER(craft_state::avr8_write)
break;
case AVR8_REGIDX_SPDR:
// TODO
avr8_video_update(machine());
m_regs[offset] = data;
spi_pending = true;
spi_start_cycle = (UINT32)(avr8_get_elapsed_cycles(m_maincpu) % CYCLES_PER_FRAME);
break;
case AVR8_REGIDX_EECR:
@ -363,6 +432,21 @@ INPUT_PORTS_END
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 + HSYNC_CYCLES)];
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;
// Clear behind us
m_pixels[y * LINE_CYCLES + (x + HSYNC_CYCLES)] = 0;
}
}
return 0;
}
@ -395,13 +479,11 @@ static MACHINE_CONFIG_START( craft, craft_state )
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
//MCFG_SCREEN_RAW_PARAMS( MASTER_CLOCK, 634, 0, 633, 525, 0, 481 )
MCFG_SCREEN_REFRESH_RATE(60.08)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(1395)) /* accurate */
MCFG_SCREEN_SIZE(634, 480)
MCFG_SCREEN_VISIBLE_AREA(0, 633, 0, 479)
MCFG_SCREEN_REFRESH_RATE(59.99)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(1429)) /* accurate */
MCFG_SCREEN_SIZE(635, 525)
MCFG_SCREEN_VISIBLE_AREA(0, 634, 0, 524)
MCFG_SCREEN_UPDATE_DRIVER(craft_state, screen_update_craft)
MCFG_PALETTE_LENGTH(0x1000)
/* sound hardware */