src/mess/video/zx.c
| r2632 | r2633 | |
| 25 | 25 | //emu_timer *ula_irq = NULL; |
| 26 | 26 | int ula_nmi_active, ula_irq_active; |
| 27 | 27 | int ula_frame_vsync = 0; |
| 28 | | int ula_scancode_count = 0; |
| 28 | //int ula_scancode_count = 0; |
| 29 | 29 | int ula_scanline_count = 0; |
| 30 | 30 | static int old_x = 0; |
| 31 | 31 | static int old_y = 0; |
| 32 | 32 | static int old_c = 0; |
| 33 | static UINT8 charline[32]; |
| 34 | static UINT8 charline_ptr; |
| 35 | static int offs1 = 0; |
| 33 | 36 | |
| 34 | 37 | /* |
| 35 | 38 | * Toggle the video output between black and white. |
| r2632 | r2633 | |
| 106 | 109 | rectangle r = *video_screen_get_visible_area(screen); |
| 107 | 110 | bitmap_t *bitmap = tmpbitmap; |
| 108 | 111 | |
| 109 | | r.min_y = r.max_y = video_screen_get_vpos(machine->primary_screen); |
| 112 | r.min_y = r.max_y = ula_scanline_count; |
| 110 | 113 | fillbitmap(bitmap, 1, &r); |
| 111 | | logerror("ULA %3d[%d] NMI, R:$%02X, $%04x\n", video_screen_get_vpos(machine->primary_screen), ula_scancode_count, (unsigned) cpunum_get_reg(0, Z80_R), (unsigned) cpunum_get_reg(0, Z80_PC)); |
| 114 | // logerror("ULA %3d[%d] NMI, R:$%02X, $%04x\n", video_screen_get_vpos(machine->primary_screen), ula_scancode_count, (unsigned) cpunum_get_reg(0, Z80_R), (unsigned) cpunum_get_reg(0, Z80_PC)); |
| 112 | 115 | cpunum_set_input_line(machine, 0, INPUT_LINE_NMI, PULSE_LINE); |
| 113 | 116 | if (++ula_scanline_count == height) |
| 114 | 117 | ula_scanline_count = 0; |
| r2632 | r2633 | |
| 116 | 119 | |
| 117 | 120 | static TIMER_CALLBACK(zx_ula_irq) |
| 118 | 121 | { |
| 119 | | const device_config *screen = video_screen_first(machine->config); |
| 120 | | int height = video_screen_get_height(screen); |
| 121 | 122 | |
| 122 | 123 | /* |
| 123 | 124 | * An IRQ is issued on the ZX80/81 whenever the R registers |
| r2632 | r2633 | |
| 126 | 127 | */ |
| 127 | 128 | if (ula_irq_active) |
| 128 | 129 | { |
| 129 | | logerror("ULA %3d[%d] IRQ, R:$%02X, $%04x\n", video_screen_get_vpos(machine->primary_screen), ula_scancode_count, (unsigned) cpunum_get_reg(0, Z80_R), (unsigned) cpunum_get_reg(0, Z80_PC)); |
| 130 | // logerror("ULA %3d[%d] IRQ, R:$%02X, $%04x\n", video_screen_get_vpos(machine->primary_screen), ula_scancode_count, (unsigned) cpunum_get_reg(0, Z80_R), (unsigned) cpunum_get_reg(0, Z80_PC)); |
| 130 | 131 | |
| 131 | 132 | ula_irq_active = 0; |
| 132 | | if (++ula_scancode_count == 8) |
| 133 | | ula_scancode_count = 0; |
| 134 | 133 | cpunum_set_input_line(machine, 0, 0, HOLD_LINE); |
| 135 | | if (++ula_scanline_count == height) |
| 136 | | ula_scanline_count = 0; |
| 137 | 134 | } |
| 138 | 135 | } |
| 139 | 136 | |
| 140 | | int zx_ula_r(running_machine *machine, int offs, int region) |
| 137 | void zx_ula_r(running_machine *machine, int offs, int region) |
| 141 | 138 | { |
| 142 | | bitmap_t *bitmap = tmpbitmap; |
| 143 | | int x, y, chr, data, ireg, rreg, cycles, offs0 = offs, halted = 0; |
| 144 | | UINT8 *chrgen, *rom = memory_region(REGION_CPU1); |
| 145 | | UINT16 *scanline; |
| 139 | const device_config *screen = video_screen_first(machine->config); |
| 140 | int offs0 = offs & 0x7fff; |
| 141 | UINT8 *rom = memory_region(REGION_CPU1); |
| 142 | UINT8 chr = rom[offs0]; |
| 146 | 143 | |
| 147 | | if (!ula_irq_active) |
| 144 | if ((!ula_irq_active) && (chr == 0x76)) |
| 148 | 145 | { |
| 146 | bitmap_t *bitmap = tmpbitmap; |
| 147 | UINT16 y, *scanline; |
| 148 | UINT16 ireg = cpunum_get_reg(0, Z80_I) << 8; |
| 149 | UINT8 creg = cpunum_get_reg(0, Z80_C); |
| 150 | UINT8 data, *chrgen; |
| 151 | chrgen = memory_region(region); |
| 152 | |
| 153 | if ((++ula_scanline_count == video_screen_get_height(screen)) || (creg == 32)) |
| 154 | { |
| 155 | ula_scanline_count = 0; |
| 156 | offs1 = offs0; |
| 157 | } |
| 158 | |
| 149 | 159 | ula_frame_vsync = 3; |
| 150 | 160 | |
| 151 | | chrgen = memory_region(region); |
| 152 | | ireg = cpunum_get_reg(0, Z80_I) << 8; |
| 153 | | rreg = cpunum_get_reg(0, Z80_R); |
| 154 | | y = video_screen_get_vpos(machine->primary_screen); |
| 161 | charline_ptr = 0; |
| 155 | 162 | |
| 156 | | cycles = 4 * (64 - (rreg & 63)); |
| 157 | | timer_set(ATTOTIME_IN_CYCLES(cycles, 0), NULL, 0, zx_ula_irq); |
| 158 | | ula_irq_active = 1; |
| 159 | | scanline = BITMAP_ADDR16(bitmap, y, 0); |
| 163 | for (y = offs1+1; ((y < offs0) && (charline_ptr < ARRAY_LENGTH(charline))); y++) |
| 164 | { |
| 165 | charline[charline_ptr] = rom[y]; |
| 166 | charline_ptr++; |
| 167 | } |
| 168 | for (y = charline_ptr; y < ARRAY_LENGTH(charline); y++) |
| 169 | charline[y] = 0; |
| 160 | 170 | |
| 161 | | for (x = 0; x < 256; x += 8) |
| 171 | timer_set(ATTOTIME_IN_CYCLES(((32 - charline_ptr) << 2), 0), NULL, 0, zx_ula_irq); |
| 172 | ula_irq_active++; |
| 173 | |
| 174 | scanline = BITMAP_ADDR16(bitmap, ula_scanline_count, 0); |
| 175 | y = 0; |
| 176 | |
| 177 | for (charline_ptr = 0; charline_ptr < ARRAY_LENGTH(charline); charline_ptr++) |
| 162 | 178 | { |
| 163 | | chr = rom[offs & 0x7fff]; |
| 164 | | /* if (!halted) |
| 165 | | logerror("ULA %3d[%d] VID, R:$%02X, PC:$%04x, CHR:%02x\n", y, ula_scancode_count, rreg, offs & 0x7fff, chr);*/ |
| 166 | | if (chr & 0x40) |
| 167 | | { |
| 168 | | halted = 1; |
| 169 | | rom[offs] = chr; |
| 170 | | data = 0x00; |
| 171 | | } |
| 172 | | else |
| 173 | | { |
| 174 | | data = chrgen[ireg | ((chr & 0x3f) << 3) | ula_scancode_count]; |
| 175 | | rom[offs] = 0x00; |
| 176 | | if (chr & 0x80) |
| 177 | | data ^= 0xff; |
| 178 | | offs++; |
| 179 | | } |
| 179 | chr = charline[charline_ptr]; |
| 180 | data = chrgen[ireg | ((chr & 0x3f) << 3) | ((8 - creg)&7) ]; |
| 181 | if (chr & 0x80) data ^= 0xff; |
| 180 | 182 | |
| 181 | | scanline[x + 0] = (data >> 7) & 1; |
| 182 | | scanline[x + 1] = (data >> 6) & 1; |
| 183 | | scanline[x + 2] = (data >> 5) & 1; |
| 184 | | scanline[x + 3] = (data >> 4) & 1; |
| 185 | | scanline[x + 4] = (data >> 3) & 1; |
| 186 | | scanline[x + 5] = (data >> 2) & 1; |
| 187 | | scanline[x + 6] = (data >> 1) & 1; |
| 188 | | scanline[x + 7] = (data >> 0) & 1; |
| 183 | scanline[y++] = (data >> 7) & 1; |
| 184 | scanline[y++] = (data >> 6) & 1; |
| 185 | scanline[y++] = (data >> 5) & 1; |
| 186 | scanline[y++] = (data >> 4) & 1; |
| 187 | scanline[y++] = (data >> 3) & 1; |
| 188 | scanline[y++] = (data >> 2) & 1; |
| 189 | scanline[y++] = (data >> 1) & 1; |
| 190 | scanline[y++] = (data >> 0) & 1; |
| 191 | charline[charline_ptr] = 0; |
| 189 | 192 | } |
| 193 | |
| 194 | if (creg == 1) offs1 = offs0; |
| 190 | 195 | } |
| 191 | | |
| 192 | | return rom[offs0]; |
| 193 | 196 | } |
| 194 | 197 | |
| 195 | 198 | VIDEO_START( zx ) |
src/mess/machine/zx.c
| r2632 | r2633 | |
| 22 | 22 | |
| 23 | 23 | static UINT8 zx_tape_bit = 0x80; |
| 24 | 24 | |
| 25 | WRITE8_HANDLER( zx_ram_w ) |
| 26 | { |
| 27 | UINT8 *rom = memory_region(REGION_CPU1); |
| 28 | |
| 29 | rom[offset | 0x4000] = data; |
| 30 | |
| 31 | if ((offset > 0x29) && (offset < 0x300)) |
| 32 | { |
| 33 | if (data & 0x40) |
| 34 | program_write_byte (offset | 0xc000, data); |
| 35 | else |
| 36 | program_write_byte (offset | 0xc000, 0); |
| 37 | } |
| 38 | } |
| 39 | |
| 25 | 40 | DRIVER_INIT ( zx ) |
| 26 | 41 | { |
| 27 | | memory_install_read8_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x4000, 0x4000 + mess_ram_size - 1, 0, 0x8000, SMH_BANK1); |
| 28 | | memory_install_write8_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x4000, 0x4000 + mess_ram_size - 1, 0, 0x8000, SMH_BANK1); |
| 42 | memory_install_read8_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x4000, 0x4000 + mess_ram_size - 1, 0, 0, SMH_BANK1); |
| 43 | memory_install_write8_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x4000, 0x4000 + mess_ram_size - 1, 0, 0, zx_ram_w); |
| 29 | 44 | memory_set_bankptr(1, memory_region(REGION_CPU1) + 0x4000); |
| 30 | 45 | } |
| 31 | 46 | |
| 47 | #if 0 |
| 32 | 48 | static OPBASE_HANDLER ( zx_setopbase ) |
| 33 | 49 | { |
| 50 | if ((address > 0xc029) && (address < 0xc300)) |
| 51 | { |
| 52 | int byte = program_read_byte( address & 0x7fff ); |
| 53 | |
| 54 | if (byte & 0x40) |
| 55 | program_write_byte( address, byte ); |
| 56 | else |
| 57 | program_write_byte( address, 0 ); |
| 58 | |
| 59 | zx_ula_r(machine, address, REGION_CPU1); |
| 60 | } |
| 61 | return address; |
| 62 | } |
| 63 | #endif |
| 64 | |
| 65 | static OPBASE_HANDLER ( zx_setopbase ) |
| 66 | { |
| 34 | 67 | if (address & 0x8000) |
| 35 | | return zx_ula_r(machine, address, REGION_CPU1); |
| 68 | zx_ula_r(machine, address, REGION_CPU1); |
| 36 | 69 | return address; |
| 37 | 70 | } |
| 38 | 71 | |
| 39 | 72 | static OPBASE_HANDLER ( pc8300_setopbase ) |
| 40 | 73 | { |
| 41 | 74 | if (address & 0x8000) |
| 42 | | return zx_ula_r(machine, address, REGION_GFX1); |
| 75 | zx_ula_r(machine, address, REGION_GFX1); |
| 43 | 76 | return address; |
| 44 | 77 | } |
| 45 | 78 | |
| r2632 | r2633 | |
| 113 | 146 | int extra1 = input_port_read_indexed(machine, 9); |
| 114 | 147 | int extra2 = input_port_read_indexed(machine, 10); |
| 115 | 148 | |
| 116 | | ula_scancode_count = 0; |
| 149 | // ula_scancode_count = 0; |
| 117 | 150 | if ((offset & 0x0100) == 0) |
| 118 | 151 | { |
| 119 | 152 | data &= input_port_read_indexed(machine, 1); |
| r2632 | r2633 | |
| 179 | 212 | int extra1 = input_port_read_indexed(machine, 9); |
| 180 | 213 | int extra2 = input_port_read_indexed(machine, 10); |
| 181 | 214 | |
| 182 | | ula_scancode_count = 0; |
| 215 | // ula_scancode_count = 0; |
| 183 | 216 | if ((offset & 0x0100) == 0) |
| 184 | 217 | { |
| 185 | 218 | data &= input_port_read_indexed(machine, 1) & extra1; |
src/mess/drivers/zx.c
| r2632 | r2633 | |
| 19 | 19 | hi-res and hi-res modes. |
| 20 | 20 | Some memory packs are unemulated. |
| 21 | 21 | |
| 22 | | Current issues: 4th and tree4th need their address maps worked out (eg, the stack is set to FD80) |
| 23 | | All drivers: Broken screen |
| 22 | Current issues: 4th and tree4th need their address maps worked out (eg, the stack is set to FB80) |
| 23 | All drivers: Screen issues, and run extremely slowly |
| 24 | 24 | |
| 25 | 25 | |
| 26 | 26 | ****************************************************************************/ |
| r2632 | r2633 | |
| 35 | 35 | |
| 36 | 36 | static ADDRESS_MAP_START( zx80_map, ADDRESS_SPACE_PROGRAM, 8 ) |
| 37 | 37 | AM_RANGE(0x0000, 0x0fff) AM_ROM |
| 38 | | AM_RANGE(0x8000, 0xffff) AM_NOP |
| 38 | AM_RANGE(0xc000, 0xc2ff) AM_RAM // dummy space for screen memory |
| 39 | 39 | ADDRESS_MAP_END |
| 40 | 40 | |
| 41 | 41 | static ADDRESS_MAP_START( zx81_map, ADDRESS_SPACE_PROGRAM, 8 ) |
| 42 | 42 | AM_RANGE(0x0000, 0x1fff) AM_ROM |
| 43 | | AM_RANGE(0x8000, 0xffff) AM_NOP |
| 43 | AM_RANGE(0xc000, 0xc2ff) AM_RAM // dummy space for screen memory |
| 44 | 44 | ADDRESS_MAP_END |
| 45 | 45 | |
| 46 | 46 | static ADDRESS_MAP_START( pc8300_map, ADDRESS_SPACE_PROGRAM, 8 ) |
| 47 | 47 | AM_RANGE(0x0000, 0x1fff) AM_ROM |
| 48 | | AM_RANGE(0x4000, 0x7fff) AM_RAM // PC8300 comes with 16K RAM |
| 49 | | AM_RANGE(0x8000, 0xffff) AM_NOP |
| 48 | AM_RANGE(0xc000, 0xc2ff) AM_RAM // dummy space for screen memory |
| 50 | 49 | ADDRESS_MAP_END |
| 51 | 50 | |
| 52 | 51 | static ADDRESS_MAP_START( zx80_io_map, ADDRESS_SPACE_IO, 8 ) |
| r2632 | r2633 | |
| 386 | 385 | MDRV_SCREEN_SIZE(ZX81_PIXELS_PER_SCANLINE, ZX81_PAL_SCANLINES) |
| 387 | 386 | MDRV_SCREEN_VISIBLE_AREA(0, ZX81_PIXELS_PER_SCANLINE-1, 0, ZX81_PAL_SCANLINES-1) |
| 388 | 387 | MDRV_GFXDECODE(zx80) |
| 389 | | MDRV_PALETTE_LENGTH(6) |
| 388 | MDRV_PALETTE_LENGTH(4) |
| 390 | 389 | MDRV_PALETTE_INIT(zx80) |
| 391 | 390 | |
| 392 | 391 | MDRV_VIDEO_START(zx) |
| 392 | MDRV_VIDEO_EOF(zx) |
| 393 | 393 | MDRV_VIDEO_UPDATE(generic_bitmapped) |
| 394 | 394 | |
| 395 | 395 | // sound hardware |