mirror of
https://github.com/holub/mame
synced 2025-04-26 18:23:08 +03:00
(MESS) AVR8 core updates: [Sandro Ronco]
- added CPSE, LD Z+, ST -Z/-Y/-X and ICALL opcodes. - added ATMEGA644 interrupt vectors. - fixed Z flag in CPC, SBC and SBCI opcodes. - fixed V and C flags in SBIW opcode. - fixed pop/push order in CALL, RCALL, RET and RETI opcodes. - fixed Timer 1 CTC mode. (MESS) uzebox: added video emulation and joystick input. [Sandro Ronco]
This commit is contained in:
parent
b0b86fc563
commit
b021bed2bf
@ -9,10 +9,14 @@
|
||||
the existing opcodes has been shown to wildly corrupt the video output in Craft, so one can assume that the
|
||||
existing timing is 100% correct.
|
||||
|
||||
Unimplemented opcodes: CPSR, LD Z+, ST -Z/-Y/-X, ELPM, SPM, SPM Z+, EIJMP, SLEEP, BREAK, WDR, ICALL, EICALL,
|
||||
JMP, CALL
|
||||
Unimplemented opcodes: ELPM, SPM, SPM Z+, EIJMP, SLEEP, BREAK, WDR, EICALL, JMP, CALL
|
||||
|
||||
- Changelist -
|
||||
23 Dec. 2012 [Sandro Ronco]
|
||||
- Added CPSE, LD Z+, ST -Z/-Y/-X and ICALL opcodes
|
||||
- Fixed Z flag in CPC, SBC and SBCI opcodes
|
||||
- Fixed V and C flags in SBIW opcode
|
||||
|
||||
30 Oct. 2012
|
||||
- Added FMUL, FMULS, FMULSU opcodes [MooglyGuy]
|
||||
- Fixed incorrect flag calculation in ROR opcode [MooglyGuy]
|
||||
@ -664,8 +668,8 @@ void avr8_device::set_irq_line(UINT16 vector, int state)
|
||||
if(SREG_R(AVR8_SREG_I))
|
||||
{
|
||||
SREG_W(AVR8_SREG_I, 0);
|
||||
push((m_pc >> 8) & 0x00ff);
|
||||
push(m_pc & 0x00ff);
|
||||
push((m_pc >> 8) & 0x00ff);
|
||||
m_pc = vector;
|
||||
m_shifted_pc = vector << 1;
|
||||
}
|
||||
@ -717,6 +721,37 @@ void avr8_device::update_interrupt(int source)
|
||||
}
|
||||
|
||||
|
||||
static const CInterruptCondition s_mega644_int_conditions[AVR8_INTIDX_COUNT] =
|
||||
{
|
||||
{ ATMEGA644_INT_SPI_STC, AVR8_REGIDX_SPCR, AVR8_SPCR_SPIE_MASK, AVR8_REGIDX_SPSR, AVR8_SPSR_SPIF_MASK },
|
||||
{ ATMEGA644_INT_T0COMPB, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_OCIE0B_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_OCF0B_MASK },
|
||||
{ ATMEGA644_INT_T0COMPA, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_OCIE0A_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_OCF0A_MASK },
|
||||
{ ATMEGA644_INT_T0OVF, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_TOIE0_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_TOV0_MASK },
|
||||
{ ATMEGA644_INT_T1CAPT, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_ICIE1_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_ICF1_MASK },
|
||||
{ ATMEGA644_INT_T1COMPB, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_OCIE1B_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_OCF1B_MASK },
|
||||
{ ATMEGA644_INT_T1COMPA, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_OCIE1A_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_OCF1A_MASK },
|
||||
{ ATMEGA644_INT_T1OVF, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_TOIE1_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_TOV1_MASK },
|
||||
{ ATMEGA644_INT_T2COMPB, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_OCIE2B_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_OCF2B_MASK },
|
||||
{ ATMEGA644_INT_T2COMPA, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_OCIE2A_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_OCF2A_MASK },
|
||||
{ ATMEGA644_INT_T2OVF, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_TOIE2_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_TOV2_MASK }
|
||||
};
|
||||
|
||||
void atmega644_device::update_interrupt(int source)
|
||||
{
|
||||
CInterruptCondition condition = s_mega644_int_conditions[source];
|
||||
|
||||
int intstate = (m_r[condition.m_regindex] & condition.m_regmask) ? 1 : 0;
|
||||
intstate = (m_r[condition.m_intreg] & condition.m_intmask) ? intstate : 0;
|
||||
|
||||
set_irq_line(condition.m_intindex << 1, intstate);
|
||||
|
||||
if (intstate)
|
||||
{
|
||||
m_r[condition.m_regindex] &= ~condition.m_regmask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// REGISTER HANDLING
|
||||
//**************************************************************************
|
||||
@ -1010,6 +1045,11 @@ void avr8_device::timer1_tick()
|
||||
|
||||
if (count == ocr1[reg])
|
||||
{
|
||||
if (reg == 0)
|
||||
{
|
||||
count = 0;
|
||||
increment = 0;
|
||||
}
|
||||
m_r[AVR8_REGIDX_TIFR1] |= ocf1[reg];
|
||||
update_interrupt(int1[reg]);
|
||||
}
|
||||
@ -1540,6 +1580,41 @@ WRITE8_MEMBER( avr8_device::regs_w )
|
||||
{
|
||||
switch( offset )
|
||||
{
|
||||
case AVR8_REGIDX_R0:
|
||||
case AVR8_REGIDX_R1:
|
||||
case AVR8_REGIDX_R2:
|
||||
case AVR8_REGIDX_R3:
|
||||
case AVR8_REGIDX_R4:
|
||||
case AVR8_REGIDX_R5:
|
||||
case AVR8_REGIDX_R6:
|
||||
case AVR8_REGIDX_R7:
|
||||
case AVR8_REGIDX_R8:
|
||||
case AVR8_REGIDX_R9:
|
||||
case AVR8_REGIDX_R10:
|
||||
case AVR8_REGIDX_R11:
|
||||
case AVR8_REGIDX_R12:
|
||||
case AVR8_REGIDX_R13:
|
||||
case AVR8_REGIDX_R14:
|
||||
case AVR8_REGIDX_R15:
|
||||
case AVR8_REGIDX_R16:
|
||||
case AVR8_REGIDX_R17:
|
||||
case AVR8_REGIDX_R18:
|
||||
case AVR8_REGIDX_R19:
|
||||
case AVR8_REGIDX_R20:
|
||||
case AVR8_REGIDX_R21:
|
||||
case AVR8_REGIDX_R22:
|
||||
case AVR8_REGIDX_R23:
|
||||
case AVR8_REGIDX_R24:
|
||||
case AVR8_REGIDX_R25:
|
||||
case AVR8_REGIDX_R26:
|
||||
case AVR8_REGIDX_R27:
|
||||
case AVR8_REGIDX_R28:
|
||||
case AVR8_REGIDX_R29:
|
||||
case AVR8_REGIDX_R30:
|
||||
case AVR8_REGIDX_R31:
|
||||
m_r[offset] = data;
|
||||
break;
|
||||
|
||||
case AVR8_REGIDX_TCCR0B:
|
||||
verboselog(m_pc, 0, "AVR8: TCCR0B = %02x\n", data );
|
||||
changed_tccr0b(data);
|
||||
@ -1707,6 +1782,11 @@ WRITE8_MEMBER( avr8_device::regs_w )
|
||||
m_r[offset] = data;
|
||||
break;
|
||||
|
||||
case AVR8_REGIDX_GPIOR1:
|
||||
case AVR8_REGIDX_GPIOR2:
|
||||
m_r[offset] = data;
|
||||
break;
|
||||
|
||||
case AVR8_REGIDX_PORTA:
|
||||
m_io->write_byte(0x00, data);
|
||||
m_r[AVR8_REGIDX_PORTA] = data;
|
||||
@ -1755,6 +1835,40 @@ READ8_MEMBER( avr8_device::regs_r )
|
||||
//printf("offset %04x\n", offset);
|
||||
switch( offset )
|
||||
{
|
||||
case AVR8_REGIDX_R0:
|
||||
case AVR8_REGIDX_R1:
|
||||
case AVR8_REGIDX_R2:
|
||||
case AVR8_REGIDX_R3:
|
||||
case AVR8_REGIDX_R4:
|
||||
case AVR8_REGIDX_R5:
|
||||
case AVR8_REGIDX_R6:
|
||||
case AVR8_REGIDX_R7:
|
||||
case AVR8_REGIDX_R8:
|
||||
case AVR8_REGIDX_R9:
|
||||
case AVR8_REGIDX_R10:
|
||||
case AVR8_REGIDX_R11:
|
||||
case AVR8_REGIDX_R12:
|
||||
case AVR8_REGIDX_R13:
|
||||
case AVR8_REGIDX_R14:
|
||||
case AVR8_REGIDX_R15:
|
||||
case AVR8_REGIDX_R16:
|
||||
case AVR8_REGIDX_R17:
|
||||
case AVR8_REGIDX_R18:
|
||||
case AVR8_REGIDX_R19:
|
||||
case AVR8_REGIDX_R20:
|
||||
case AVR8_REGIDX_R21:
|
||||
case AVR8_REGIDX_R22:
|
||||
case AVR8_REGIDX_R23:
|
||||
case AVR8_REGIDX_R24:
|
||||
case AVR8_REGIDX_R25:
|
||||
case AVR8_REGIDX_R26:
|
||||
case AVR8_REGIDX_R27:
|
||||
case AVR8_REGIDX_R28:
|
||||
case AVR8_REGIDX_R29:
|
||||
case AVR8_REGIDX_R30:
|
||||
case AVR8_REGIDX_R31:
|
||||
return m_r[offset];
|
||||
|
||||
case AVR8_REGIDX_SPL:
|
||||
case AVR8_REGIDX_SPH:
|
||||
case AVR8_REGIDX_TCNT1L:
|
||||
@ -1769,10 +1883,22 @@ READ8_MEMBER( avr8_device::regs_r )
|
||||
case AVR8_REGIDX_DDRC:
|
||||
case AVR8_REGIDX_DDRD:
|
||||
case AVR8_REGIDX_GPIOR0:
|
||||
case AVR8_REGIDX_GPIOR1:
|
||||
case AVR8_REGIDX_GPIOR2:
|
||||
case AVR8_REGIDX_EEDR:
|
||||
case AVR8_REGIDX_SREG:
|
||||
return m_r[offset];
|
||||
|
||||
// TODO: consider the DDRx
|
||||
case AVR8_REGIDX_PINA:
|
||||
return m_io->read_byte(AVR8_REG_A);
|
||||
case AVR8_REGIDX_PINB:
|
||||
return m_io->read_byte(AVR8_REG_B);
|
||||
case AVR8_REGIDX_PINC:
|
||||
return m_io->read_byte(AVR8_REG_C);
|
||||
case AVR8_REGIDX_PIND:
|
||||
return m_io->read_byte(AVR8_REG_D);
|
||||
|
||||
default:
|
||||
verboselog(m_pc, 0, "AVR8: Unknown Register Read: %02x\n", (UINT8)offset);
|
||||
return 0;
|
||||
@ -1919,7 +2045,7 @@ void avr8_device::execute_run()
|
||||
SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7)));
|
||||
SREG_W(AVR8_SREG_N, BIT(res,7));
|
||||
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
|
||||
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
|
||||
SREG_W(AVR8_SREG_Z, (res == 0) ? SREG_R(AVR8_SREG_Z) : 0);
|
||||
SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
|
||||
break;
|
||||
case 0x0800:
|
||||
@ -1934,7 +2060,7 @@ void avr8_device::execute_run()
|
||||
SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7)));
|
||||
SREG_W(AVR8_SREG_N, BIT(res,7));
|
||||
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
|
||||
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
|
||||
SREG_W(AVR8_SREG_Z, (res == 0) ? SREG_R(AVR8_SREG_Z) : 0);
|
||||
SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
|
||||
break;
|
||||
case 0x0c00:
|
||||
@ -1957,9 +2083,15 @@ void avr8_device::execute_run()
|
||||
case 0x1000:
|
||||
switch(op & 0x0c00)
|
||||
{
|
||||
case 0x0000: // CPSR Rd,Rr
|
||||
//output += sprintf( output, "CPSE R%d, R%d", RD5(op), RR5(op) );
|
||||
unimplemented_opcode(op);
|
||||
case 0x0000: // CPSE Rd,Rr
|
||||
rd = m_r[RD5(op)];
|
||||
rr = m_r[RR5(op)];
|
||||
if (rd == rr)
|
||||
{
|
||||
op = (UINT32)m_program->read_word(m_shifted_pc + 2);
|
||||
opcycles += is_long_opcode(op) ? 2 : 1;
|
||||
m_pc += is_long_opcode(op) ? 2 : 1;
|
||||
}
|
||||
break;
|
||||
case 0x0400: // CP Rd,Rr
|
||||
rd = m_r[RD5(op)];
|
||||
@ -2056,7 +2188,7 @@ void avr8_device::execute_run()
|
||||
SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7)));
|
||||
SREG_W(AVR8_SREG_N, BIT(res,7));
|
||||
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
|
||||
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
|
||||
SREG_W(AVR8_SREG_Z, (res == 0) ? SREG_R(AVR8_SREG_Z) : 0);
|
||||
SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
|
||||
break;
|
||||
case 0x5000: // SUBI Rd,K
|
||||
@ -2129,7 +2261,12 @@ void avr8_device::execute_run()
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x0001: // LD Rd,Z+
|
||||
unimplemented_opcode(op);
|
||||
pd = ZREG;
|
||||
m_r[RD5(op)] = m_data->read_byte(pd);
|
||||
pd++;
|
||||
m_r[31] = (pd >> 8) & 0x00ff;
|
||||
m_r[30] = pd & 0x00ff;
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x0002: // LD Rd,-Z
|
||||
pd = ZREG;
|
||||
@ -2226,8 +2363,12 @@ void avr8_device::execute_run()
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x0002: // ST -Z,Rd
|
||||
//output += sprintf( output, "ST -Z , R%d", RD5(op) );
|
||||
unimplemented_opcode(op);
|
||||
pd = ZREG;
|
||||
pd--;
|
||||
m_data->write_byte(pd, m_r[RD5(op)]);
|
||||
m_r[31] = (pd >> 8) & 0x00ff;
|
||||
m_r[30] = pd & 0x00ff;
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x0009: // ST Y+,Rd
|
||||
pd = YREG;
|
||||
@ -2238,8 +2379,12 @@ void avr8_device::execute_run()
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x000a: // ST -Y,Rd
|
||||
//output += sprintf( output, "ST -Y , R%d", RD5(op) );
|
||||
unimplemented_opcode(op);
|
||||
pd = YREG;
|
||||
pd--;
|
||||
m_data->write_byte(pd, m_r[RD5(op)]);
|
||||
m_r[29] = (pd >> 8) & 0x00ff;
|
||||
m_r[28] = pd & 0x00ff;
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x000c: // ST X,Rd
|
||||
m_data->write_byte(XREG, m_r[RD5(op)]);
|
||||
@ -2253,8 +2398,12 @@ void avr8_device::execute_run()
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x000e: // ST -X,Rd
|
||||
//output += sprintf( output, "ST -X , R%d", RD5(op) );
|
||||
unimplemented_opcode(op);
|
||||
pd = XREG;
|
||||
pd--;
|
||||
m_data->write_byte(pd, m_r[RD5(op)]);
|
||||
m_r[27] = (pd >> 8) & 0x00ff;
|
||||
m_r[26] = pd & 0x00ff;
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x000f: // PUSH Rd
|
||||
push(m_r[RD5(op)]);
|
||||
@ -2397,8 +2546,8 @@ void avr8_device::execute_run()
|
||||
break;
|
||||
case 0x000e: // CALL k
|
||||
case 0x000f:
|
||||
push(((m_pc + 1) >> 8) & 0x00ff);
|
||||
push((m_pc + 1) & 0x00ff);
|
||||
push((m_pc + 2) & 0x00ff);
|
||||
push(((m_pc + 2) >> 8) & 0x00ff);
|
||||
offs = KCONST22(op) << 16;
|
||||
m_pc++;
|
||||
m_shifted_pc += 2;
|
||||
@ -2485,14 +2634,14 @@ void avr8_device::execute_run()
|
||||
switch(op & 0x00f0)
|
||||
{
|
||||
case 0x0000: // RET
|
||||
m_pc = pop();
|
||||
m_pc |= pop() << 8;
|
||||
m_pc = pop() << 8;
|
||||
m_pc |= pop();
|
||||
m_pc--;
|
||||
opcycles = 4;
|
||||
break;
|
||||
case 0x0010: // RETI
|
||||
m_pc = pop();
|
||||
m_pc |= pop() << 8;
|
||||
m_pc = pop() << 8;
|
||||
m_pc |= pop();
|
||||
m_pc--;
|
||||
SREG_W(AVR8_SREG_I, 1);
|
||||
opcycles = 4;
|
||||
@ -2535,8 +2684,11 @@ void avr8_device::execute_run()
|
||||
switch(op & 0x00f0)
|
||||
{
|
||||
case 0x0000: // ICALL
|
||||
//output += sprintf( output, "ICALL" );
|
||||
unimplemented_opcode(op);
|
||||
push((m_pc + 1) & 0x00ff);
|
||||
push(((m_pc + 1) >> 8) & 0x00ff);
|
||||
m_pc = ZREG;
|
||||
m_pc--;
|
||||
opcycles = 3;
|
||||
break;
|
||||
case 0x0010: // EICALL
|
||||
//output += sprintf( output, "EICALL" );
|
||||
@ -2598,11 +2750,11 @@ void avr8_device::execute_run()
|
||||
pd = rd;
|
||||
pd |= rr << 8;
|
||||
pd -= KCONST6(op);
|
||||
SREG_W(AVR8_SREG_V, BIT(pd,15) & NOT(BIT(rr,7)));
|
||||
SREG_W(AVR8_SREG_V, NOT(BIT(pd,15)) & BIT(rr,7));
|
||||
SREG_W(AVR8_SREG_N, BIT(pd,15));
|
||||
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
|
||||
SREG_W(AVR8_SREG_Z, (pd == 0) ? 1 : 0);
|
||||
SREG_W(AVR8_SREG_C, NOT(BIT(pd,15)) & BIT(rr,7));
|
||||
SREG_W(AVR8_SREG_C, BIT(pd,15) & NOT(BIT(rr,7)));
|
||||
m_r[24 + (DCONST(op) << 1)] = pd & 0x00ff;
|
||||
m_r[25 + (DCONST(op) << 1)] = (pd >> 8) & 0x00ff;
|
||||
opcycles = 2;
|
||||
@ -2662,8 +2814,8 @@ void avr8_device::execute_run()
|
||||
break;
|
||||
case 0xd000: // RCALL k
|
||||
offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff));
|
||||
push(((m_pc + 1) >> 8) & 0x00ff);
|
||||
push((m_pc + 1) & 0x00ff);
|
||||
push(((m_pc + 1) >> 8) & 0x00ff);
|
||||
m_pc += offs;
|
||||
opcycles = 3;
|
||||
break;
|
||||
|
@ -9,10 +9,14 @@
|
||||
the existing opcodes has been shown to wildly corrupt the video output in Craft, so one can assume that the
|
||||
existing timing is 100% correct.
|
||||
|
||||
Unimplemented opcodes: CPSR, LD Z+, ST Z+, ST -Z/-Y/-X, ELPM, SPM, SPM Z+, EIJMP, SLEEP, BREAK, WDR, ICALL,
|
||||
EICALL, JMP, CALL, SBIW
|
||||
Unimplemented opcodes: ELPM, SPM, SPM Z+, EIJMP, SLEEP, BREAK, WDR, EICALL, JMP, CALL
|
||||
|
||||
- Changelist -
|
||||
23 Dec. 2012 [Sandro Ronco]
|
||||
- Added CPSE, LD Z+, ST -Z/-Y/-X and ICALL opcodes
|
||||
- Fixed Z flag in CPC, SBC and SBCI opcodes
|
||||
- Fixed V and C flags in SBIW opcode
|
||||
|
||||
30 Oct. 2012
|
||||
- Added FMUL, FMULS, FMULSU opcodes [MooglyGuy]
|
||||
- Fixed incorrect flag calculation in ROR opcode [MooglyGuy]
|
||||
@ -71,7 +75,7 @@ public:
|
||||
static void static_set_config(device_t &device, const avr8_config &config);
|
||||
|
||||
// public interfaces
|
||||
void update_interrupt(int source);
|
||||
virtual void update_interrupt(int source);
|
||||
UINT64 get_elapsed_cycles()
|
||||
{
|
||||
return m_elapsed_cycles;
|
||||
@ -232,6 +236,8 @@ class atmega644_device : public avr8_device
|
||||
public:
|
||||
// construction/destruction
|
||||
atmega644_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
virtual void update_interrupt(int source);
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
@ -308,6 +314,36 @@ enum
|
||||
AVR8_INT_ANALOG_COMP,
|
||||
AVR8_INT_TWI,
|
||||
AVR8_INT_SPM_RDY,
|
||||
|
||||
// ATMEGA644
|
||||
ATMEGA644_INT_RESET = 0,
|
||||
ATMEGA644_INT_INT0,
|
||||
ATMEGA644_INT_INT1,
|
||||
ATMEGA644_INT_INT2,
|
||||
ATMEGA644_INT_PCINT0,
|
||||
ATMEGA644_INT_PCINT1,
|
||||
ATMEGA644_INT_PCINT2,
|
||||
ATMEGA644_INT_PCINT3,
|
||||
ATMEGA644_INT_WDT,
|
||||
ATMEGA644_INT_T2COMPA,
|
||||
ATMEGA644_INT_T2COMPB,
|
||||
ATMEGA644_INT_T2OVF,
|
||||
ATMEGA644_INT_T1CAPT,
|
||||
ATMEGA644_INT_T1COMPA,
|
||||
ATMEGA644_INT_T1COMPB,
|
||||
ATMEGA644_INT_T1OVF,
|
||||
ATMEGA644_INT_T0COMPA,
|
||||
ATMEGA644_INT_T0COMPB,
|
||||
ATMEGA644_INT_T0OVF,
|
||||
ATMEGA644_INT_SPI_STC,
|
||||
ATMEGA644_INT_USART_RX,
|
||||
ATMEGA644_INT_USART_UDRE,
|
||||
ATMEGA644_INT_USART_TX,
|
||||
ATMEGA644_INT_ADC,
|
||||
ATMEGA644_INT_EE_RDY,
|
||||
ATMEGA644_INT_ANALOG_COMP,
|
||||
ATMEGA644_INT_TWI,
|
||||
ATMEGA644_INT_SPM_RDY,
|
||||
};
|
||||
|
||||
// Used by I/O register handling
|
||||
|
@ -1,3 +1,15 @@
|
||||
/***************************************************************************
|
||||
|
||||
Belogic Uzebox
|
||||
|
||||
driver by Sandro Ronco
|
||||
|
||||
TODO:
|
||||
- Sound
|
||||
- SDCard
|
||||
- Mouse
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/avr8/avr8.h"
|
||||
@ -5,30 +17,10 @@
|
||||
#include "imagedev/cartslot.h"
|
||||
|
||||
// overclocked to 8 * NTSC burst frequency
|
||||
|
||||
#define VERBOSE_LEVEL (0)
|
||||
|
||||
#define ENABLE_VERBOSE_LOG (0)
|
||||
|
||||
#if ENABLE_VERBOSE_LOG
|
||||
INLINE void verboselog(running_machine &machine, 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", machine.device("maincpu")->safe_pc(), buf );
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define verboselog(x,y,z,...)
|
||||
#endif
|
||||
|
||||
#define MASTER_CLOCK 28618180
|
||||
|
||||
#define INTERLACED 0
|
||||
|
||||
class uzebox_state : public driver_device
|
||||
{
|
||||
public:
|
||||
@ -38,30 +30,150 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual void machine_start();
|
||||
|
||||
required_device<avr8_device> m_maincpu;
|
||||
|
||||
DECLARE_READ8_MEMBER(port_r);
|
||||
DECLARE_WRITE8_MEMBER(port_w);
|
||||
DECLARE_DRIVER_INIT(uzebox);
|
||||
DECLARE_READ8_MEMBER(port_a_r);
|
||||
DECLARE_WRITE8_MEMBER(port_a_w);
|
||||
DECLARE_READ8_MEMBER(port_b_r);
|
||||
DECLARE_WRITE8_MEMBER(port_b_w);
|
||||
DECLARE_READ8_MEMBER(port_c_r);
|
||||
DECLARE_WRITE8_MEMBER(port_c_w);
|
||||
DECLARE_READ8_MEMBER(port_d_r);
|
||||
DECLARE_WRITE8_MEMBER(port_d_w);
|
||||
|
||||
virtual void machine_start();
|
||||
virtual void machine_reset();
|
||||
void line_update();
|
||||
UINT32 screen_update_uzebox(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
private:
|
||||
int m_vpos;
|
||||
UINT64 m_line_start_cycles;
|
||||
UINT32 m_line_pos_cycles;
|
||||
UINT8 m_port_a;
|
||||
UINT8 m_port_b;
|
||||
UINT8 m_port_c;
|
||||
UINT8 m_port_d;
|
||||
UINT16 m_joy_data[2];
|
||||
bitmap_rgb32 m_bitmap;
|
||||
};
|
||||
|
||||
void uzebox_state::machine_start()
|
||||
{
|
||||
machine().primary_screen->register_screen_bitmap(m_bitmap);
|
||||
}
|
||||
|
||||
READ8_MEMBER(uzebox_state::port_r)
|
||||
void uzebox_state::machine_reset()
|
||||
{
|
||||
return 0;
|
||||
m_vpos = 0;
|
||||
m_line_start_cycles = 0;
|
||||
m_line_pos_cycles = 0;
|
||||
m_port_a = 0;
|
||||
m_port_b = 0;
|
||||
m_port_c = 0;
|
||||
m_port_d = 0;
|
||||
m_joy_data[0] = m_joy_data[1] = 0;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(uzebox_state::port_w)
|
||||
|
||||
WRITE8_MEMBER(uzebox_state::port_a_w)
|
||||
{
|
||||
// xxxx ---- NC
|
||||
// ---- x--- SNES controller clk
|
||||
// ---- -x-- SNES controller latch
|
||||
// ---- --x- SNES controller P2 data
|
||||
// ---- ---x SNES controller P1 data
|
||||
|
||||
UINT8 changed = m_port_a ^ data;
|
||||
|
||||
if (changed & data & 0x04)
|
||||
{
|
||||
m_joy_data[0] = ioport("P1")->read();
|
||||
m_joy_data[1] = ioport("P2")->read();
|
||||
}
|
||||
else if (changed & 0x08)
|
||||
{
|
||||
if (changed & data & 0x08)
|
||||
{
|
||||
m_joy_data[0] >>= 1;
|
||||
m_joy_data[1] >>= 1;
|
||||
}
|
||||
|
||||
m_port_a = (m_joy_data[0] & 0x01) | ((m_joy_data[1] & 0x01) << 1);
|
||||
}
|
||||
|
||||
m_port_a = (data & 0x0c) | (m_port_a & 0x03);
|
||||
}
|
||||
|
||||
READ8_MEMBER(uzebox_state::port_a_r)
|
||||
{
|
||||
return m_port_a | 0xf0;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(uzebox_state::port_b_w)
|
||||
{
|
||||
// xxx- ---- SDCard
|
||||
// ---x ---- AD725 CE
|
||||
// ---- x--- AD725 4FSC
|
||||
// ---- -xx- NC
|
||||
// ---- ---x AD725 HSYNC
|
||||
|
||||
if (m_port_b & 0x10)
|
||||
if ((m_port_b ^ data) & m_port_b & 0x01)
|
||||
{
|
||||
line_update();
|
||||
|
||||
UINT32 cycles = (UINT32)(m_maincpu->get_elapsed_cycles() - m_line_start_cycles);
|
||||
if (cycles < 1000 && m_vpos >= 448)
|
||||
m_vpos = INTERLACED ? ((m_vpos ^ 0x01) & 0x01) : 0;
|
||||
else if (cycles > 1000)
|
||||
m_vpos += 2;
|
||||
|
||||
m_line_start_cycles = m_maincpu->get_elapsed_cycles();
|
||||
m_line_pos_cycles = 0;
|
||||
}
|
||||
|
||||
m_port_b = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER(uzebox_state::port_b_r)
|
||||
{
|
||||
return m_port_b;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(uzebox_state::port_c_w)
|
||||
{
|
||||
// xx-- ---- blue
|
||||
// --xx x--- green
|
||||
// ---- -xxx red
|
||||
|
||||
line_update();
|
||||
m_port_c = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER(uzebox_state::port_c_r)
|
||||
{
|
||||
return m_port_c;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(uzebox_state::port_d_w)
|
||||
{
|
||||
// x--- ---- sound
|
||||
// -x-- ---- SDCard CS
|
||||
// ---x ---- LED
|
||||
// --x- x--- NC
|
||||
// ---- -x-- power
|
||||
// ---- --xx UART MIDI
|
||||
|
||||
m_port_d = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER(uzebox_state::port_d_r)
|
||||
{
|
||||
return m_port_d;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************\
|
||||
* Address maps *
|
||||
\****************************************************/
|
||||
@ -75,7 +187,10 @@ static ADDRESS_MAP_START( uzebox_data_map, AS_DATA, 8, uzebox_state )
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( uzebox_io_map, AS_IO, 8, uzebox_state )
|
||||
AM_RANGE(0x00, 0x03) AM_READWRITE( port_r, port_w )
|
||||
AM_RANGE(AVR8_REG_A, AVR8_REG_A) AM_READWRITE( port_a_r, port_a_w )
|
||||
AM_RANGE(AVR8_REG_B, AVR8_REG_B) AM_READWRITE( port_b_r, port_b_w )
|
||||
AM_RANGE(AVR8_REG_C, AVR8_REG_C) AM_READWRITE( port_c_r, port_c_w )
|
||||
AM_RANGE(AVR8_REG_D, AVR8_REG_D) AM_READWRITE( port_d_r, port_d_w )
|
||||
ADDRESS_MAP_END
|
||||
|
||||
/****************************************************\
|
||||
@ -83,14 +198,60 @@ ADDRESS_MAP_END
|
||||
\****************************************************/
|
||||
|
||||
static INPUT_PORTS_START( uzebox )
|
||||
PORT_START( "P1" )
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 Button B") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 Button Y") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT ) PORT_NAME("P1 Select") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START1 ) PORT_NAME("P1 Start") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P1 Button A") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P1 Button X") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P2 Button L") PORT_PLAYER(1)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P2 Button R") PORT_PLAYER(1)
|
||||
PORT_BIT( 0xf000, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
|
||||
PORT_START( "P2" )
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 Button B") PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("P1 Button Y") PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SELECT ) PORT_NAME("P1 Select") PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START2 ) PORT_NAME("P1 Start") PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("P1 Button A") PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("P1 Button X") PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("P2 Button L") PORT_PLAYER(2)
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("P2 Button R") PORT_PLAYER(2)
|
||||
PORT_BIT( 0xf000, IP_ACTIVE_LOW, IPT_UNUSED )
|
||||
INPUT_PORTS_END
|
||||
|
||||
/****************************************************\
|
||||
* Video hardware *
|
||||
\****************************************************/
|
||||
|
||||
void uzebox_state::line_update()
|
||||
{
|
||||
UINT32 cycles = (UINT32)(m_maincpu->get_elapsed_cycles() - m_line_start_cycles) / 2;
|
||||
|
||||
for (UINT32 x = m_line_pos_cycles; x < cycles; x++)
|
||||
{
|
||||
if (m_bitmap.cliprect().contains(x, m_vpos))
|
||||
m_bitmap.pix32(m_vpos, x) = MAKE_RGB(pal3bit(m_port_c >> 0), pal3bit(m_port_c >> 3), pal2bit(m_port_c >> 6));
|
||||
if (!INTERLACED)
|
||||
if (m_bitmap.cliprect().contains(x, m_vpos + 1))
|
||||
m_bitmap.pix32(m_vpos + 1, x) = MAKE_RGB(pal3bit(m_port_c >> 0), pal3bit(m_port_c >> 3), pal2bit(m_port_c >> 6));
|
||||
}
|
||||
|
||||
m_line_pos_cycles = cycles;
|
||||
}
|
||||
|
||||
UINT32 uzebox_state::screen_update_uzebox(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -98,14 +259,6 @@ UINT32 uzebox_state::screen_update_uzebox(screen_device &screen, bitmap_rgb32 &b
|
||||
* Machine definition *
|
||||
\****************************************************/
|
||||
|
||||
DRIVER_INIT_MEMBER(uzebox_state,uzebox)
|
||||
{
|
||||
}
|
||||
|
||||
void uzebox_state::machine_reset()
|
||||
{
|
||||
}
|
||||
|
||||
const avr8_config atmega644_config =
|
||||
{
|
||||
"eeprom"
|
||||
@ -122,14 +275,12 @@ static MACHINE_CONFIG_START( uzebox, uzebox_state )
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_REFRESH_RATE(60.08)
|
||||
MCFG_SCREEN_REFRESH_RATE(59.99)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(1395))
|
||||
MCFG_SCREEN_SIZE(634, 480)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0, 633, 0, 479)
|
||||
MCFG_SCREEN_SIZE(870, 525)
|
||||
MCFG_SCREEN_VISIBLE_AREA(150, 870-1, 40, 488-1)
|
||||
MCFG_SCREEN_UPDATE_DRIVER(uzebox_state, screen_update_uzebox)
|
||||
|
||||
MCFG_PALETTE_LENGTH(0x1000)
|
||||
|
||||
/* sound hardware */
|
||||
MCFG_SPEAKER_STANDARD_MONO("avr8")
|
||||
MCFG_SOUND_ADD("dac", DAC, 0)
|
||||
@ -142,11 +293,11 @@ static MACHINE_CONFIG_START( uzebox, uzebox_state )
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ROM_START( uzebox )
|
||||
ROM_REGION( 0x10000, "maincpu", 0 ) /* Main program store */
|
||||
ROM_CART_LOAD("cart1", 0x0000, 0x10000, ROM_OPTIONAL)
|
||||
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF ) /* Main program store */
|
||||
ROM_CART_LOAD("cart1", 0x0000, 0x10000, ROM_OPTIONAL | ROM_FILL_FF)
|
||||
|
||||
ROM_REGION( 0x200, "eeprom", ROMREGION_ERASE00 ) /* on-die eeprom */
|
||||
ROM_END
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
|
||||
CONS(2010, uzebox, 0, 0, uzebox, uzebox, uzebox_state, uzebox, "Belogic", "Uzebox", GAME_NO_SOUND | GAME_NOT_WORKING)
|
||||
CONS(2010, uzebox, 0, 0, uzebox, uzebox, driver_device, 0, "Belogic", "Uzebox", GAME_NO_SOUND | GAME_NOT_WORKING)
|
||||
|
Loading…
Reference in New Issue
Block a user