trunk/src/mess/drivers/craft.c
| r18714 | r18715 | |
| 29 | 29 | #define verboselog(x,y,z,...) |
| 30 | 30 | #endif |
| 31 | 31 | |
| 32 | | #define MASTER_CLOCK 20000000 |
| 32 | #define MASTER_CLOCK 20000000 |
| 33 | 33 | |
| 34 | #define VISIBLE_CYCLES 480 |
| 35 | #define HSYNC_CYCLES 155 |
| 36 | #define LINE_CYCLES (VISIBLE_CYCLES + HSYNC_CYCLES) |
| 37 | #define VISIBLE_LINES 480 |
| 38 | #define VSYNC_LINES 45 |
| 39 | #define LINES_PER_FRAME (VISIBLE_LINES + VSYNC_LINES) |
| 40 | #define CYCLES_PER_FRAME (LINES_PER_FRAME * LINE_CYCLES) |
| 41 | #define PIXELS_PER_FRAME (CYCLES_PER_FRAME) |
| 42 | |
| 34 | 43 | /****************************************************\ |
| 35 | 44 | * I/O defines * |
| 36 | 45 | \****************************************************/ |
| 37 | 46 | |
| 38 | 47 | #define AVR8_DDRD (state->m_regs[AVR8_REGIDX_DDRD]) |
| 48 | #define AVR8_PORTC (state->m_regs[AVR8_REGIDX_PORTC]) |
| 39 | 49 | #define AVR8_DDRC (state->m_regs[AVR8_REGIDX_DDRC]) |
| 40 | 50 | #define AVR8_PORTB (state->m_regs[AVR8_REGIDX_PORTB]) |
| 41 | 51 | #define AVR8_DDRB (state->m_regs[AVR8_REGIDX_DDRB]) |
| r18714 | r18715 | |
| 72 | 82 | |
| 73 | 83 | UINT8 m_regs[0x100]; |
| 74 | 84 | UINT8* m_eeprom; |
| 85 | UINT32 last_cycles; |
| 75 | 86 | |
| 87 | bool spi_pending; |
| 88 | UINT32 spi_start_cycle; |
| 89 | |
| 90 | UINT8 m_pixels[PIXELS_PER_FRAME + LINE_CYCLES]; // Allocate one extra line for wrapping in the video update |
| 91 | |
| 76 | 92 | required_device<cpu_device> m_maincpu; |
| 77 | 93 | |
| 78 | 94 | DECLARE_READ8_MEMBER(avr8_read); |
| r18714 | r18715 | |
| 141 | 157 | } |
| 142 | 158 | } |
| 143 | 159 | |
| 160 | static void avr8_video_update(running_machine &machine) |
| 161 | { |
| 162 | craft_state *state = machine.driver_data<craft_state>(); |
| 163 | |
| 164 | UINT64 cycles = avr8_get_elapsed_cycles(state->m_maincpu); |
| 165 | UINT32 frame_cycles = (UINT32)(cycles % CYCLES_PER_FRAME); |
| 166 | |
| 167 | if (state->last_cycles < frame_cycles) |
| 168 | { |
| 169 | for (UINT32 pixidx = state->last_cycles; pixidx < frame_cycles; pixidx++) |
| 170 | { |
| 171 | UINT8 value = AVR8_PORTC & 0x3f; |
| 172 | if (state->spi_pending) |
| 173 | { |
| 174 | if (pixidx >= state->spi_start_cycle && pixidx < (state->spi_start_cycle + 16)) |
| 175 | { |
| 176 | UINT8 bitidx = 7 - ((pixidx - state->spi_start_cycle) >> 1); |
| 177 | value = ((state->m_regs[AVR8_REGIDX_SPDR] & (1 << bitidx)) ? value : 0x3f); |
| 178 | if (pixidx == (state->spi_start_cycle + 15)) |
| 179 | { |
| 180 | state->spi_pending = false; |
| 181 | state->m_regs[AVR8_REGIDX_SPDR] = 0; |
| 182 | } |
| 183 | } |
| 184 | } |
| 185 | state->m_pixels[pixidx] = value; |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | state->last_cycles = frame_cycles; |
| 190 | } |
| 191 | |
| 144 | 192 | static void avr8_change_port(running_machine &machine, int reg, UINT8 data) |
| 145 | 193 | { |
| 146 | 194 | craft_state *state = machine.driver_data<craft_state>(); |
| r18714 | r18715 | |
| 156 | 204 | //verboselog(machine, 0, "avr8_change_port: PORT%c lines %02x changed\n", avr8_reg_name[reg], changed); |
| 157 | 205 | } |
| 158 | 206 | |
| 159 | | if (reg == AVR8_REG_D) { |
| 207 | if (reg == AVR8_REG_C) |
| 208 | { |
| 209 | avr8_video_update(machine); |
| 210 | |
| 211 | /*if (frame_cycles >= state->spi_start_cycle && frame_cycles < (state->spi_start_cycle + 16)) |
| 212 | { |
| 213 | UINT8 bitidx = 7 - ((frame_cycles - state->spi_start_cycle) >> 1); |
| 214 | state->m_pixels[frame_cycles] = ((state->m_regs[AVR8_REGIDX_SPDR] & (1 << bitidx)) ? 0x3f : (data & 0x3f)); |
| 215 | } |
| 216 | else |
| 217 | { |
| 218 | state->m_pixels[frame_cycles] = data & 0x3f; |
| 219 | }*/ |
| 220 | |
| 221 | AVR8_PORTC = data; |
| 222 | } |
| 223 | |
| 224 | if (reg == AVR8_REG_D) |
| 225 | { |
| 160 | 226 | UINT8 audio_sample = (data & 0x02) | ((data & 0xf4) >> 2); |
| 161 | 227 | |
| 162 | 228 | state->dac->write_unsigned8(audio_sample << 2); |
| r18714 | r18715 | |
| 289 | 355 | break; |
| 290 | 356 | |
| 291 | 357 | case AVR8_REGIDX_SPDR: |
| 292 | | // TODO |
| 358 | avr8_video_update(machine()); |
| 359 | m_regs[offset] = data; |
| 360 | spi_pending = true; |
| 361 | spi_start_cycle = (UINT32)(avr8_get_elapsed_cycles(m_maincpu) % CYCLES_PER_FRAME); |
| 293 | 362 | break; |
| 294 | 363 | |
| 295 | 364 | case AVR8_REGIDX_EECR: |
| r18714 | r18715 | |
| 363 | 432 | |
| 364 | 433 | UINT32 craft_state::screen_update_craft(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 365 | 434 | { |
| 435 | for(int y = 0; y < LINES_PER_FRAME; y++) |
| 436 | { |
| 437 | UINT32 *line = &bitmap.pix32(y); |
| 438 | for(int x = 0; x < LINE_CYCLES; x++) |
| 439 | { |
| 440 | UINT8 pixel = m_pixels[y * LINE_CYCLES + (x + HSYNC_CYCLES)]; |
| 441 | UINT8 r = 0x55 * ((pixel & 0x30) >> 4); |
| 442 | UINT8 g = 0x55 * ((pixel & 0x0c) >> 2); |
| 443 | UINT8 b = 0x55 * (pixel & 0x03); |
| 444 | line[x] = 0xff000000 | (r << 16) | (g << 8) | b; |
| 445 | |
| 446 | // Clear behind us |
| 447 | m_pixels[y * LINE_CYCLES + (x + HSYNC_CYCLES)] = 0; |
| 448 | } |
| 449 | } |
| 366 | 450 | return 0; |
| 367 | 451 | } |
| 368 | 452 | |
| r18714 | r18715 | |
| 395 | 479 | |
| 396 | 480 | /* video hardware */ |
| 397 | 481 | MCFG_SCREEN_ADD("screen", RASTER) |
| 398 | | //MCFG_SCREEN_RAW_PARAMS( MASTER_CLOCK, 634, 0, 633, 525, 0, 481 ) |
| 399 | | MCFG_SCREEN_REFRESH_RATE(60.08) |
| 400 | | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(1395)) /* accurate */ |
| 401 | | MCFG_SCREEN_SIZE(634, 480) |
| 402 | | MCFG_SCREEN_VISIBLE_AREA(0, 633, 0, 479) |
| 482 | MCFG_SCREEN_REFRESH_RATE(59.99) |
| 483 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(1429)) /* accurate */ |
| 484 | MCFG_SCREEN_SIZE(635, 525) |
| 485 | MCFG_SCREEN_VISIBLE_AREA(0, 634, 0, 524) |
| 403 | 486 | MCFG_SCREEN_UPDATE_DRIVER(craft_state, screen_update_craft) |
| 404 | | |
| 405 | 487 | MCFG_PALETTE_LENGTH(0x1000) |
| 406 | 488 | |
| 407 | 489 | /* sound hardware */ |
trunk/src/emu/cpu/avr8/avr8.c
| r18714 | r18715 | |
| 367 | 367 | return READ_IO_8(cpustate, sp); |
| 368 | 368 | } |
| 369 | 369 | |
| 370 | UINT64 avr8_get_elapsed_cycles(device_t *device) |
| 371 | { |
| 372 | return get_safe_token(device)->elapsed_cycles; |
| 373 | } |
| 374 | |
| 370 | 375 | /*****************************************************************************/ |
| 371 | 376 | // Interrupts |
| 372 | 377 | |
| r18714 | r18715 | |
| 429 | 434 | } |
| 430 | 435 | } |
| 431 | 436 | |
| 432 | | /*static void avr8_poll_interrupt(avr8_state *cpustate) |
| 433 | | { |
| 434 | | for (int idx = 0; idx < AVR8_INTIDX_COUNT; idx++) |
| 435 | | { |
| 436 | | avr8_update_interrupt_internal(cpustate, idx); |
| 437 | | } |
| 438 | | }*/ |
| 439 | | |
| 440 | 437 | void avr8_update_interrupt(device_t *device, int source) |
| 441 | 438 | { |
| 442 | 439 | avr8_state *cpustate = get_safe_token(device); |
| r18714 | r18715 | |
| 1036 | 1033 | case AVR8_REGIDX_TCNT1L: |
| 1037 | 1034 | case AVR8_REGIDX_TCNT1H: |
| 1038 | 1035 | case AVR8_REGIDX_GPIOR0: |
| 1036 | case AVR8_REGIDX_TCNT2: |
| 1039 | 1037 | *data = cpustate->r[offset]; |
| 1040 | 1038 | return true; |
| 1041 | 1039 | |
| r18714 | r18715 | |
| 1100 | 1098 | |
| 1101 | 1099 | cpustate->interrupt_pending = false; |
| 1102 | 1100 | |
| 1101 | cpustate->elapsed_cycles = 0; |
| 1102 | |
| 1103 | 1103 | device->save_item(NAME(cpustate->pc)); |
| 1104 | 1104 | } |
| 1105 | 1105 | |
| r18714 | r18715 | |
| 1113 | 1113 | |
| 1114 | 1114 | cpustate->status = 0; |
| 1115 | 1115 | cpustate->pc = 0; |
| 1116 | cpustate->elapsed_cycles = 0; |
| 1116 | 1117 | |
| 1117 | 1118 | cpustate->interrupt_pending = false; |
| 1118 | 1119 | } |
| r18714 | r18715 | |
| 1160 | 1161 | opcycles = 2; |
| 1161 | 1162 | break; |
| 1162 | 1163 | case 0x0300: // MULSU Rd,Rr |
| 1163 | | sd = (INT8)cpustate->r[16 + RD4(op)] * (UINT8)cpustate->r[16 + RR4(op)]; |
| 1164 | sd = (INT8)cpustate->r[16 + RD3(op)] * (UINT8)cpustate->r[16 + RR3(op)]; |
| 1164 | 1165 | cpustate->r[1] = (sd >> 8) & 0x00ff; |
| 1165 | 1166 | cpustate->r[0] = sd & 0x00ff; |
| 1166 | 1167 | SREG_W(AVR8_SREG_C, (sd & 0x8000) ? 1 : 0); |
| r18714 | r18715 | |
| 1393 | 1394 | pd = ZREG; |
| 1394 | 1395 | pd--; |
| 1395 | 1396 | cpustate->r[RD5(op)] = READ_IO_8(cpustate, pd); |
| 1396 | | cpustate->r[27] = (pd >> 8) & 0x00ff; |
| 1397 | | cpustate->r[26] = pd & 0x00ff; |
| 1397 | cpustate->r[31] = (pd >> 8) & 0x00ff; |
| 1398 | cpustate->r[30] = pd & 0x00ff; |
| 1398 | 1399 | opcycles = 2; |
| 1399 | 1400 | break; |
| 1400 | 1401 | case 0x0004: // LPM Rd,Z |
| r18714 | r18715 | |
| 1429 | 1430 | pd = YREG; |
| 1430 | 1431 | pd--; |
| 1431 | 1432 | cpustate->r[RD5(op)] = READ_IO_8(cpustate, pd); |
| 1432 | | cpustate->r[27] = (pd >> 8) & 0x00ff; |
| 1433 | | cpustate->r[26] = pd & 0x00ff; |
| 1433 | cpustate->r[29] = (pd >> 8) & 0x00ff; |
| 1434 | cpustate->r[28] = pd & 0x00ff; |
| 1434 | 1435 | opcycles = 2; |
| 1435 | 1436 | break; |
| 1436 | 1437 | case 0x000c: // LD Rd,X |
| r18714 | r18715 | |
| 1970 | 1971 | } |
| 1971 | 1972 | else // SBRC Rd, b |
| 1972 | 1973 | { |
| 1973 | | if(!BIT(cpustate->r[RD5(op)], RR3(op))) |
| 1974 | if(NOT(BIT(cpustate->r[RD5(op)], RR3(op)))) |
| 1974 | 1975 | { |
| 1975 | 1976 | op = (UINT32)READ_PRG_16(cpustate, cpustate->pc++); |
| 1976 | 1977 | cpustate->pc += avr8_is_long_opcode(op) ? 1 : 0; |
| r18714 | r18715 | |
| 1986 | 1987 | |
| 1987 | 1988 | cpustate->icount -= opcycles; |
| 1988 | 1989 | |
| 1990 | cpustate->elapsed_cycles += opcycles; |
| 1991 | |
| 1989 | 1992 | avr8_timer_tick(cpustate, opcycles); |
| 1990 | 1993 | } |
| 1991 | 1994 | } |