diff --git a/src/emu/cpu/avr8/avr8.c b/src/emu/cpu/avr8/avr8.c index 71c8c1936a8..10aefec61aa 100644 --- a/src/emu/cpu/avr8/avr8.c +++ b/src/emu/cpu/avr8/avr8.c @@ -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; diff --git a/src/emu/cpu/avr8/avr8.h b/src/emu/cpu/avr8/avr8.h index a1509641d37..5d5629ba2ae 100644 --- a/src/emu/cpu/avr8/avr8.h +++ b/src/emu/cpu/avr8/avr8.h @@ -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 diff --git a/src/mess/drivers/uzebox.c b/src/mess/drivers/uzebox.c index 9dd11e8ad92..8e0766d3a86 100644 --- a/src/mess/drivers/uzebox.c +++ b/src/mess/drivers/uzebox.c @@ -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 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)