Previous 199869 Revisions Next

r41415 Wednesday 28th October, 2015 at 08:59:47 UTC by Olivier Galibert
zx: Start of an hardware-correct rewrite [O. Galibert]

Missing:
- hsync is not handled as it should yet, especially missing on the zx80
- the versions with an external charrom are not handled yet
- the zx97 is weird

On the other hand, the zx81 ain't bad and the hires modes work.
[src/devices/cpu/z80]z80.c z80.h
[src/mame/drivers]zx.c
[src/mame/includes]zx.h
[src/mame/machine]zx.c
[src/mame/video]zx.c

trunk/src/devices/cpu/z80/z80.c
r249926r249927
473473{
474474   unsigned pc = PCD;
475475   PC++;
476   return m_decrypted_opcodes_direct->read_byte(pc);
476   UINT8 res = m_decrypted_opcodes_direct->read_byte(pc);
477   m_icount -= 2;
478   m_refresh_cb((m_i << 8) | (m_r2 & 0x80) | ((m_r-1) & 0x7f));
479   m_icount += 2;
480   return res;
477481}
478482
479483/****************************************************************
r249926r249927
31413145   else
31423146      irq_vector = m_irq_callback(*this, 0);
31433147
3148   /* Say hi */
3149   m_irqack_cb(true);
3150
31443151   LOG(("Z80 '%s' single int. irq_vector $%02x\n", tag(), irq_vector));
31453152
31463153   /* Interrupt mode 2. Call [i:databyte] */
r249926r249927
34293436   m_cc_xy = cc_xy;
34303437   m_cc_xycb = cc_xycb;
34313438   m_cc_ex = cc_ex;
3439
3440   m_irqack_cb.resolve_safe();
3441   m_refresh_cb.resolve_safe();
34323442}
34333443
34343444void nsc800_device::device_start()
r249926r249927
37053715   cpu_device(mconfig, Z80, "Z80", tag, owner, clock, "z80", __FILE__),
37063716   m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0),
37073717   m_decrypted_opcodes_config("decrypted_opcodes", ENDIANNESS_LITTLE, 8, 16, 0),
3708   m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0)
3718   m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0),
3719   m_irqack_cb(*this),
3720   m_refresh_cb(*this)
37093721{
37103722}
37113723
r249926r249927
37133725   cpu_device(mconfig, type, name, tag, owner, clock, shortname, source),
37143726   m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0),
37153727   m_decrypted_opcodes_config("decrypted_opcodes", ENDIANNESS_LITTLE, 8, 16, 0),
3716   m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0)
3728   m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0),
3729   m_irqack_cb(*this),
3730   m_refresh_cb(*this)
37173731{
37183732}
37193733
trunk/src/devices/cpu/z80/z80.h
r249926r249927
77
88#include "z80daisy.h"
99
10#define MCFG_Z80_SET_IRQACK_CALLBACK(_devcb) \
11   devcb = &z80_device::set_irqack_cb(*device, DEVCB_##_devcb);
12
13#define MCFG_Z80_SET_REFRESH_CALLBACK(_devcb) \
14   devcb = &z80_device::set_refresh_cb(*device, DEVCB_##_devcb);
15
1016enum
1117{
1218   NSC800_RSTA = INPUT_LINE_IRQ0 + 1,
r249926r249927
3844   DECLARE_WRITE_LINE_MEMBER( irq_line );
3945
4046   void z80_set_cycle_tables(const UINT8 *op, const UINT8 *cb, const UINT8 *ed, const UINT8 *xy, const UINT8 *xycb, const UINT8 *ex);
47   template<class _Object> static devcb_base &set_irqack_cb(device_t &device, _Object object) { return downcast<z80_device &>(device).m_irqack_cb.set_callback(object); }
48   template<class _Object> static devcb_base &set_refresh_cb(device_t &device, _Object object) { return downcast<z80_device &>(device).m_refresh_cb.set_callback(object); }
4149
4250protected:
4351   z80_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
r249926r249927
240248   address_space *m_io;
241249   direct_read_data *m_direct;
242250   direct_read_data *m_decrypted_opcodes_direct;
251   devcb_write_line m_irqack_cb;
252   devcb_write16 m_refresh_cb;
243253
244254   PAIR            m_prvpc;
245255   PAIR            m_pc;
trunk/src/mame/drivers/zx.c
r249926r249927
11// license:GPL-2.0+
2// copyright-holders:Juergen Buchmueller, Krzysztof Strzecha, Robbbert
2// copyright-holders: Olivier Galibert, Juergen Buchmueller, Krzysztof Strzecha, Robbbert
33/***************************************************************************
44    zx.c
55
r249926r249927
99    Fixes and additions by Krzysztof Strzecha:
1010    07.06.2004 Tape loading added. Some cleanups of debug code.
1111           Fixed stupid bug in timings (vblank duration).
12           MACHINE_NOT_WORKING flag removed.
12           GAME_NOT_WORKING flag removed.
1313        29.05.2004 CPU clock, number of scanlines, vblank duration corrected.
1414           Some cleanups. Two non-working TESTDRIVERS added.
1515        14.05.2004 Finally fixed and readded.
r249926r249927
3131    - Modernised.
3232
3333    To do / problems:
34    - Halt-on-nmi emulation needs a cycle-exact z80
3435    - Some memory areas are not mirrored as they should.
35    - Video hardware is not fully emulated, so it does not support pseudo hi-res and hi-res modes.
3636    - The screen in pc8300/pow3000/lambda jumps when you type something.
3737    - lambda/pow3000 32k memory pack is unemulated, because where is the upper 16k mirror going to be?
3838    - h4th and tree4th need their address maps worked out (eg, the stack is set to FB80)
r249926r249927
4747/* Memory Maps */
4848
4949static ADDRESS_MAP_START( zx80_map, AS_PROGRAM, 8, zx_state )
50   AM_RANGE(0x0000, 0x0fff) AM_ROM AM_MIRROR(0x3000)
51   AM_RANGE(0x4000, 0xffff) AM_RAM
52ADDRESS_MAP_END
53
54static ADDRESS_MAP_START( zx81_map, AS_PROGRAM, 8, zx_state )
5055   AM_RANGE(0x0000, 0x1fff) AM_ROM AM_MIRROR(0x2000)
51   AM_RANGE(0xc000, 0xffff) AM_RAM_READ(zx_ram_r)
56   AM_RANGE(0x4000, 0xffff) AM_RAM
5257ADDRESS_MAP_END
5358
59static ADDRESS_MAP_START( ula_map, AS_DECRYPTED_OPCODES, 8, zx_state )
60   AM_RANGE(0x0000, 0x7fff) AM_READ(ula_low_r)
61   AM_RANGE(0x8000, 0xffff) AM_READ(ula_high_r)
62ADDRESS_MAP_END
63
5464static ADDRESS_MAP_START( zx80_io_map, AS_IO, 8, zx_state )
5565   AM_RANGE(0x0000, 0xffff) AM_READWRITE(zx80_io_r, zx80_io_w)
5666ADDRESS_MAP_END
r249926r249927
291301INPUT_PORTS_END
292302
293303
294/* F4 character display */
295
296static const gfx_layout zx_gfx_layout =
297{
298   8, 8,                              /* 8x8 pixels */
299   64,                                /* 64 codes */
300   1,                                 /* 1 bit per pixel */
301   {0},                               /* no bitplanes */
302   /* x offsets */
303   {0, 1, 2, 3, 4, 5, 6, 7},
304   /* y offsets */
305   {0 * 8, 1 * 8, 2 * 8, 3 * 8, 4 * 8, 5 * 8, 6 * 8, 7 * 8},
306   8 * 8                              /* eight bytes per code */
307};
308
309
310/* Graphics Decode Information */
311
312static GFXDECODE_START( zx80 )
313   GFXDECODE_ENTRY( "maincpu", 0x0e00, zx_gfx_layout,  0, 2 )
314GFXDECODE_END
315
316static GFXDECODE_START( zx81 )
317   GFXDECODE_ENTRY( "maincpu", 0x1e00, zx_gfx_layout,  0, 2 )
318GFXDECODE_END
319
320static GFXDECODE_START( pc8300 )
321   GFXDECODE_ENTRY( "gfx1", 0, zx_gfx_layout,  0, 2 )
322GFXDECODE_END
323
324
325
326304/* Palette Initialization */
327305
328306
r249926r249927
330308{
331309   palette.set_pen_color(0,rgb_t::white); /* white */
332310   palette.set_pen_color(1,rgb_t::black); /* black */
333   palette.set_pen_color(2,rgb_t::black); /* black */
334   palette.set_pen_color(3,rgb_t::white); /* white */
335311}
336312
337313PALETTE_INIT_MEMBER(zx_state,ts1000)
338314{
339315   palette.set_pen_color(0,rgb_t(64, 244, 244)); /* cyan */
340316   palette.set_pen_color(1,rgb_t::black); /* black */
341   palette.set_pen_color(2,rgb_t::black); /* black */
342   palette.set_pen_color(3,rgb_t(64, 244, 244)); /* cyan */
343317}
344318
345
346#define ZX81_CPU_CLOCK          3250000
347#define ZX81_CYCLES_PER_SCANLINE    207
348#define ZX81_PIXELS_PER_SCANLINE    256
349#define ZX81_CYCLES_PER_VBLANK      1235
350#define ZX81_VBLANK_DURATION        (1.0*ZX81_CYCLES_PER_VBLANK/ZX81_CPU_CLOCK*1000*1000)
351
352#define ZX81_PAL_SCANLINES      304
353#define ZX81_PAL_FRAMES_PER_SECOND  (1.0*ZX81_CPU_CLOCK/(ZX81_PAL_SCANLINES*ZX81_CYCLES_PER_SCANLINE+ZX81_CYCLES_PER_VBLANK))
354
355#define ZX81_NTSC_SCANLINES     256
356#define ZX81_NTSC_FRAMES_PER_SECOND (1.0*ZX81_CPU_CLOCK/(ZX81_NTSC_SCANLINES*ZX81_CYCLES_PER_SCANLINE+ZX81_CYCLES_PER_VBLANK))
357
358/* Machine Drivers */
359
360319static MACHINE_CONFIG_START( zx80, zx_state )
361320   /* basic machine hardware */
362   MCFG_CPU_ADD("maincpu", Z80, ZX81_CPU_CLOCK)
321   MCFG_CPU_ADD("maincpu", Z80, XTAL_6_5MHz/2)
363322   MCFG_CPU_PROGRAM_MAP(zx80_map)
364323   MCFG_CPU_IO_MAP(zx80_io_map)
324   MCFG_CPU_DECRYPTED_OPCODES_MAP(ula_map)
325   MCFG_Z80_SET_REFRESH_CALLBACK(WRITE16(zx_state, refresh_w))
326
365327   MCFG_SCREEN_ADD("screen", RASTER)
366   MCFG_SCREEN_REFRESH_RATE(ZX81_PAL_FRAMES_PER_SECOND)
367   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(ZX81_VBLANK_DURATION))
328   MCFG_SCREEN_REFRESH_RATE(XTAL_6_5MHz/2/64159.0) // 54223 for NTSC
368329
369
370330   /* video hardware */
371331   MCFG_SCREEN_UPDATE_DRIVER(zx_state, screen_update)
372   MCFG_SCREEN_SIZE(ZX81_PIXELS_PER_SCANLINE, ZX81_PAL_SCANLINES)
373   MCFG_SCREEN_VISIBLE_AREA(0, ZX81_PIXELS_PER_SCANLINE-1, 0, ZX81_PAL_SCANLINES-1)
374   MCFG_SCREEN_VBLANK_DRIVER(zx_state, screen_eof_zx)
332   MCFG_SCREEN_SIZE(384, 311)
333   MCFG_SCREEN_VISIBLE_AREA(0, 383, 0, 310)
375334   MCFG_SCREEN_PALETTE("palette")
376335
377   MCFG_GFXDECODE_ADD("gfxdecode", "palette", zx80)
378   MCFG_PALETTE_ADD("palette", 4)
336   MCFG_PALETTE_ADD("palette", 2)
379337   MCFG_PALETTE_INIT_OWNER(zx_state,zx)
380338
381   /* sound hardware */
382   MCFG_SPEAKER_STANDARD_MONO("mono")
383   MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)   /* Used by pc8300/lambda/pow3000 */
384   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75)
385   MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette")
386   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
387
388339   MCFG_CASSETTE_ADD( "cassette" )
389340   MCFG_CASSETTE_FORMATS(zx80_o_format)
390341   MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED)
r249926r249927
392343   /* internal ram */
393344   MCFG_RAM_ADD(RAM_TAG)
394345   MCFG_RAM_DEFAULT_SIZE("1K")
395   MCFG_RAM_EXTRA_OPTIONS("16K")
346   MCFG_RAM_EXTRA_OPTIONS("16K,32K,48K")
396347MACHINE_CONFIG_END
397348
398349static MACHINE_CONFIG_DERIVED( zx81, zx80 )
399
400350   MCFG_CPU_MODIFY("maincpu")
351   MCFG_CPU_PROGRAM_MAP(zx81_map)
401352   MCFG_CPU_IO_MAP(zx81_io_map)
402353
403   MCFG_GFXDECODE_MODIFY("gfxdecode", zx81)
404
405354   MCFG_CASSETTE_MODIFY( "cassette" )
406355   MCFG_CASSETTE_FORMATS(zx81_p_format)
407356MACHINE_CONFIG_END
408357
358static MACHINE_CONFIG_DERIVED( zx81_spk, zx81 )
359   /* sound hardware */
360   /* Used by pc8300/lambda/pow3000 */
361   MCFG_SPEAKER_STANDARD_MONO("mono")
362   MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)
363   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75)
364   MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette")
365   MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
366MACHINE_CONFIG_END
367
409368static MACHINE_CONFIG_DERIVED( ts1000, zx81 )
410369   MCFG_PALETTE_MODIFY("palette")
411   MCFG_PALETTE_INIT_OWNER(zx_state,ts1000)
370   MCFG_PALETTE_INIT_OWNER(zx_state, ts1000)
412371MACHINE_CONFIG_END
413372
414373static MACHINE_CONFIG_DERIVED( ts1500, ts1000 )
415
416374   /* internal ram */
417375   MCFG_RAM_MODIFY(RAM_TAG)
418376   MCFG_RAM_DEFAULT_SIZE("16K")
419377MACHINE_CONFIG_END
420378
421static MACHINE_CONFIG_DERIVED( pc8300, zx81 )
422
379static MACHINE_CONFIG_DERIVED( pc8300, zx81_spk )
423380   MCFG_CPU_MODIFY("maincpu")
424381   MCFG_CPU_IO_MAP(pc8300_io_map)
425382
426   MCFG_MACHINE_RESET_OVERRIDE(zx_state,pc8300)
427
428   MCFG_SCREEN_MODIFY("screen")
429   MCFG_SCREEN_REFRESH_RATE(ZX81_NTSC_FRAMES_PER_SECOND)
430   MCFG_SCREEN_SIZE(ZX81_PIXELS_PER_SCANLINE, ZX81_NTSC_SCANLINES)
431   MCFG_SCREEN_VISIBLE_AREA(0, ZX81_PIXELS_PER_SCANLINE-1, 0, ZX81_NTSC_SCANLINES-1)
432
433   MCFG_GFXDECODE_MODIFY("gfxdecode", pc8300)
434
435383   /* internal ram */
436384   MCFG_RAM_MODIFY(RAM_TAG)
437385   MCFG_RAM_DEFAULT_SIZE("16K")
438386MACHINE_CONFIG_END
439387
440static MACHINE_CONFIG_DERIVED( pow3000, zx81 )
441
388static MACHINE_CONFIG_DERIVED( pow3000, zx81_spk )
442389   MCFG_CPU_MODIFY("maincpu")
443390   MCFG_CPU_IO_MAP(pow3000_io_map)
444391
445   MCFG_MACHINE_RESET_OVERRIDE(zx_state,pow3000)
446
447   MCFG_GFXDECODE_MODIFY("gfxdecode", pc8300)
448
449392   /* internal ram */
450393   MCFG_RAM_MODIFY(RAM_TAG)
451394   MCFG_RAM_DEFAULT_SIZE("2K")
r249926r249927
456399/* ROMs */
457400
458401ROM_START(zx80)
459   ROM_REGION( 0x10000, "maincpu",0 )
402   ROM_REGION( 0x1000, "maincpu",0 )
460403   ROM_SYSTEM_BIOS(0, "default", "BASIC")
461404   ROMX_LOAD( "zx80.rom",   0x0000, 0x1000, CRC(4c7fc597) SHA1(b6769a3197c77009e0933e038c15b43cf4c98c7a), ROM_BIOS(1) )
462405   ROM_SYSTEM_BIOS(1, "aszmic", "ASZMIC")
r249926r249927
464407ROM_END
465408
466409ROM_START(zx81)
467   ROM_REGION( 0x10000, "maincpu",0 )
410   ROM_REGION( 0x2000, "maincpu",0 )
468411   ROM_SYSTEM_BIOS(0, "3rd", "3rd rev.")
469412   ROMX_LOAD( "zx81b.rom",   0x0000, 0x2000, CRC(522c37b8) SHA1(c6d8e06cb936989f6e1cc7a56d1f092da854a515), ROM_BIOS(1) )
470413   ROM_SYSTEM_BIOS(1, "1st", "1st rev.")
r249926r249927
478421ROM_END
479422
480423ROM_START(ts1000)
481   ROM_REGION( 0x10000, "maincpu",0 )
424   ROM_REGION( 0x2000, "maincpu",0 )
482425   ROM_LOAD( "zx81a.rom", 0x0000, 0x2000, CRC(4b1dd6eb) SHA1(7b143ee964e9ada89d1f9e88f0bd48d919184cfc) )
483426ROM_END
484427
485428ROM_START(ts1500)
486   ROM_REGION( 0x10000, "maincpu",0 )
429   ROM_REGION( 0x2000, "maincpu",0 )
487430   ROM_LOAD( "d2364c_649.u2", 0x0000, 0x2000, CRC(7dd19c48) SHA1(3eb437359221b4406d236085ec66fa02278e7495) )
488431ROM_END
489432
490433ROM_START(ringo470)
491   ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
434   ROM_REGION( 0x2000, "maincpu", ROMREGION_ERASEFF )
492435   ROM_LOAD( "ringo470.rom", 0x0000, 0x2000, CRC(b9c5abec) SHA1(191c4994adfffe4f83b98dc3959dde2724b1dbac) )
493436ROM_END
494437
495438ROM_START(pc8300)
496   ROM_REGION( 0x10000, "maincpu",0 )
439   ROM_REGION( 0x2000, "maincpu",0 )
497440   ROM_LOAD( "8300_org.rom", 0x0000, 0x2000, CRC(a350f2b1) SHA1(6a9be484556cc27a9cd9d71085d2027c6243333f) )
498441
499442   ROM_REGION( 0x200, "gfx1", 0 )
r249926r249927
501444ROM_END
502445
503446ROM_START(pow3000)
504   ROM_REGION( 0x10000, "maincpu",0 )
447   ROM_REGION( 0x2000, "maincpu",0 )
505448   ROM_LOAD( "pow3000.rom", 0x0000, 0x2000, CRC(8a49b2c3) SHA1(9b22daf2f3a991aa6a358ef95b091654c3ca1bdf) )
506449
507450   ROM_REGION( 0x200, "gfx1", 0 )
r249926r249927
509452ROM_END
510453
511454ROM_START(lambda)
512   ROM_REGION( 0x10000, "maincpu",0 )
455   ROM_REGION( 0x2000, "maincpu",0 )
513456   ROM_LOAD( "lambda.rom", 0x0000, 0x2000, CRC(8a49b2c3) SHA1(9b22daf2f3a991aa6a358ef95b091654c3ca1bdf) )
514457
515458   ROM_REGION( 0x200, "gfx1", 0 )
r249926r249927
517460ROM_END
518461
519462ROM_START( tk85 )
520   ROM_REGION( 0x10000, "maincpu", 0 )
463   ROM_REGION( 0x2800, "maincpu", 0 )
521464   ROM_LOAD( "tk85.rom", 0x0000, 0x2800, CRC(8972d756) SHA1(7b961a1733fc047eb682150a32e17bca10a018d2) )
522465ROM_END
523466
524467/* This homebrew has 192k of RAM and 32k of ROM via bankswitching. One of the primary bankswitching lines is /M1,
525468    which is not emulated by MAME's z80. */
526469ROM_START( zx97 )
527   ROM_REGION( 0x10000, "maincpu", 0 )
528   ROM_LOAD( "zx97.rom", 0x0000, 0x2000, CRC(5cf49744) SHA1(b2a486efdc7b2bc3dc8e5a441ea5532bfa3207bd) )
529   ROM_IGNORE( 0x6000 )    /* Unemulated bankswitched part */
470   ROM_REGION( 0x8000, "maincpu", 0 )
471   ROM_LOAD( "zx97.rom", 0x0000, 0x8000, CRC(5cf49744) SHA1(b2a486efdc7b2bc3dc8e5a441ea5532bfa3207bd) )
530472ROM_END
531473
532474/* Game Drivers */
533475
534/*    YEAR  NAME        PARENT  COMPAT  MACHINE     INPUT       INIT    COMPANY                     FULLNAME                FLAGS */
535COMP( 1980, zx80,       0,      0,      zx80,       zx80, zx_state,       zx,     "Sinclair Research Ltd",    "ZX-80",               0 )
536COMP( 1981, zx81,       0,      0,      zx81,       zx81, zx_state,       zx,     "Sinclair Research Ltd",    "ZX-81",               0 )
537COMP( 1982, ts1000,     zx81,   0,      ts1000,     zx81, zx_state,       zx,     "Timex Sinclair",           "Timex Sinclair 1000", 0 )
538COMP( 1983, ts1500,     zx81,   0,      ts1500,     zx81, zx_state,       zx,     "Timex Sinclair",           "Timex Sinclair 1500", 0 )
539COMP( 1983, tk85,       zx81,   0,      ts1000,     zx81, zx_state,       zx,     "Microdigital",             "TK85",                0 )
540COMP( 1983, ringo470,   zx81,   0,      ts1000,     zx81, zx_state,       zx,     "Ritas do Brasil Ltda",     "Ringo 470",           0 )
541COMP( 1984, pc8300,     zx81,   0,      pc8300,     pc8300, zx_state,     zx,     "Your Computer",            "PC8300",              0 )
476COMP( 1980, zx80,       0,      0,      zx80,       zx80,    zx_state,    zx,     "Sinclair Research Ltd",    "ZX-80",               MACHINE_NO_SOUND )
477COMP( 1981, zx81,       0,      0,      zx81,       zx81,    zx_state,    zx,     "Sinclair Research Ltd",    "ZX-81",               MACHINE_NO_SOUND )
478COMP( 1982, ts1000,     zx81,   0,      ts1000,     zx81,    zx_state,    zx,     "Timex Sinclair",           "Timex Sinclair 1000", MACHINE_NO_SOUND )
479COMP( 1983, ts1500,     zx81,   0,      ts1500,     zx81,    zx_state,    zx,     "Timex Sinclair",           "Timex Sinclair 1500", MACHINE_NO_SOUND )
480COMP( 1983, tk85,       zx81,   0,      ts1000,     zx81,    zx_state,    zx,     "Microdigital",             "TK85",                MACHINE_NO_SOUND )
481COMP( 1983, ringo470,   zx81,   0,      ts1000,     zx81,    zx_state,    zx,     "Ritas do Brasil Ltda",     "Ringo 470",           MACHINE_NO_SOUND )
482COMP( 1984, pc8300,     zx81,   0,      pc8300,     pc8300,  zx_state,    zx,     "Your Computer",            "PC8300",              0 )
542483COMP( 1983, pow3000,    zx81,   0,      pow3000,    pow3000, zx_state,    zx,     "Creon Enterprises",        "Power 3000",          0 )
543484COMP( 1982, lambda,     zx81,   0,      pow3000,    pow3000, zx_state,    zx,     "Lambda Electronics Ltd",   "Lambda 8300",         0 )
544COMP( 1997, zx97,       zx81,   0,      zx81,       zx81, zx_state,       zx,     "Wilf Rigter",              "ZX97", MACHINE_NOT_WORKING | MACHINE_UNOFFICIAL )
485COMP( 1997, zx97,       zx81,   0,      zx81,       zx81,    zx_state,    zx,     "Wilf Rigter",              "ZX97", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_UNOFFICIAL )
trunk/src/mame/includes/zx.h
r249926r249927
2121class zx_state : public driver_device
2222{
2323public:
24   enum
25   {
26      TIMER_TAPE_PULSE,
27      TIMER_ULA_NMI,
28      TIMER_ULA_IRQ
29   };
30
3124   zx_state(const machine_config &mconfig, device_type type, const char *tag)
3225      : driver_device(mconfig, type, tag),
3326      m_maincpu(*this, "maincpu"),
r249926r249927
4942
5043   UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
5144
52   bitmap_ind16 m_bitmap;
53
54   DECLARE_READ8_MEMBER(zx_ram_r);
45   DECLARE_READ8_MEMBER(ula_high_r);
46   DECLARE_READ8_MEMBER(ula_low_r);
47   DECLARE_WRITE16_MEMBER(refresh_w);
5548   DECLARE_READ8_MEMBER(zx80_io_r);
5649   DECLARE_READ8_MEMBER(zx81_io_r);
5750   DECLARE_READ8_MEMBER(pc8300_io_r);
5851   DECLARE_READ8_MEMBER(pow3000_io_r);
5952   DECLARE_WRITE8_MEMBER(zx80_io_w);
6053   DECLARE_WRITE8_MEMBER(zx81_io_w);
61   emu_timer *m_ula_nmi;
62   int m_ula_irq_active;
63   int m_ula_frame_vsync;
64   int m_ula_scanline_count;
65   UINT8 m_tape_bit;
66   UINT8 m_speaker_state;
67   int m_old_x;
68   int m_old_y;
69   UINT8 m_old_c;
70   UINT8 m_charline[32];
71   UINT8 m_charline_ptr;
72   int m_offs1;
73   void zx_ula_bkgnd(UINT8 color);
74   DECLARE_WRITE8_MEMBER(zx_ram_w);
75   DECLARE_DIRECT_UPDATE_MEMBER(zx_setdirect);
76   DECLARE_DIRECT_UPDATE_MEMBER(pc8300_setdirect);
77   DECLARE_DIRECT_UPDATE_MEMBER(pow3000_setdirect);
7854   DECLARE_DRIVER_INIT(zx);
7955   virtual void machine_reset();
8056   virtual void video_start();
8157   DECLARE_PALETTE_INIT(zx);
8258   DECLARE_PALETTE_INIT(ts1000);
83   DECLARE_MACHINE_RESET(pc8300);
84   DECLARE_MACHINE_RESET(pow3000);
85   void screen_eof_zx(screen_device &screen, bool state);
86   TIMER_CALLBACK_MEMBER(zx_tape_pulse);
87   TIMER_CALLBACK_MEMBER(zx_ula_nmi);
88   TIMER_CALLBACK_MEMBER(zx_ula_irq);
59   void zx_tape_input();
60   void zx_ula_hsync();
8961
62   UINT32 get_ram_size();
63
9064protected:
65   enum
66   {
67      TIMER_TAPE_INPUT,
68      TIMER_ULA_HSYNC
69   };
70
9171   required_device<cpu_device> m_maincpu;
9272   required_device<ram_device> m_ram;
9373   required_device<cassette_image_device> m_cassette;
94   required_device<speaker_sound_device> m_speaker;
74   optional_device<speaker_sound_device> m_speaker;
9575   required_memory_region m_region_maincpu;
9676   optional_memory_region m_region_gfx1;
9777   required_ioport m_io_row0;
r249926r249927
10585   optional_ioport m_io_config;
10686   required_device<screen_device> m_screen;
10787
108   void zx_ula_r(int offs, memory_region *region, const UINT8 param);
88   address_space *m_program;
89   emu_timer *m_tape_input, *m_ula_hsync;
90
91   bool m_vsync_active, m_hsync_active, m_nmi_on, m_nmi_generator_active;
92   UINT64 m_base_vsync_clock, m_vsync_start_time;
93   UINT32 m_ypos;
94
95   UINT8 m_prev_refresh;
96   UINT8 m_speaker_state;
97
98   bitmap_ind16 *m_bitmap_render, *m_bitmap_buffer;
99
100   UINT16 m_ula_char_buffer;
101   double m_cassette_cur_level;
102
109103   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
104
105   void drop_sync();
106   void recalc_hsync();
110107};
111108
112109#endif /* ZX_H_ */
trunk/src/mame/machine/zx.c
r249926r249927
11// license:GPL-2.0+
2// copyright-holders:Juergen Buchmueller, Krzysztof Strzecha, Robbbert
2// copyright Olivier Galibert, Buchmueller, Krzysztof Strzecha, Robbbert
33/***************************************************************************
44    zx.c
55
r249926r249927
1010
1111#include "includes/zx.h"
1212
13#define video_screen_get_refresh(screen)    (((screen_config *)(screen)->inline_config)->refresh)
14
15#define DEBUG_ZX81_PORTS    1
16#define DEBUG_ZX81_VSYNC    1
17
18#define LOG_ZX81_IOR(_comment) do { if (DEBUG_ZX81_PORTS) logerror("ZX81 IOR: %04x, Data: %02x, Scanline: %d (%s)\n", offset, data, space.machine().first_screen()->vpos(), _comment); } while (0)
19#define LOG_ZX81_IOW(_comment) do { if (DEBUG_ZX81_PORTS) logerror("ZX81 IOW: %04x, Data: %02x, Scanline: %d (%s)\n", offset, data, space.machine().first_screen()->vpos(), _comment); } while (0)
20#define LOG_ZX81_VSYNC do { if (DEBUG_ZX81_VSYNC) logerror("VSYNC starts in scanline: %d\n", space.machine().first_screen()->vpos()); } while (0)
21
22
23WRITE8_MEMBER(zx_state::zx_ram_w)
13DRIVER_INIT_MEMBER(zx_state,zx)
2414{
25   UINT8 *RAM = m_region_maincpu->base();
26   RAM[offset + 0x4000] = data;
15   m_program = &m_maincpu->space(AS_PROGRAM);
16   m_tape_input = timer_alloc(TIMER_TAPE_INPUT);
2717
28   if (data & 0x40)
29   {
30      space.write_byte(offset | 0xc000, data);
31      RAM[offset | 0xc000] = data;
32   }
33   else
34   {
35      space.write_byte(offset | 0xc000, 0);
36      RAM[offset | 0xc000] = 0;
37   }
18   if(m_ram->size() == 32768)
19      m_program->unmap_readwrite(0x8000, 0xbfff);
20   else if(m_ram->size() == 16384)
21      m_program->unmap_readwrite(0x8000, 0xffff);
22   else if(m_ram->size() < 16384)
23      m_program->unmap_readwrite(0x4000 + m_ram->size(), 0xffff);
3824}
3925
40/* I know this looks really pointless... but it has to be here */
41READ8_MEMBER( zx_state::zx_ram_r )
26void zx_state::machine_reset()
4227{
43   UINT8 *RAM = m_region_maincpu->base();
44   return RAM[offset | 0xc000];
45}
28   m_prev_refresh = 0xff;
4629
47DRIVER_INIT_MEMBER(zx_state,zx)
48{
49   address_space &space = m_maincpu->space(AS_PROGRAM);
30   m_vsync_active = false;
31   m_base_vsync_clock = 0;
32   m_ypos = 0;
5033
51   space.install_read_bank(0x4000, 0x4000 + m_ram->size() - 1, "bank1");
52   space.install_write_handler(0x4000, 0x4000 + m_ram->size() - 1, write8_delegate(FUNC(zx_state::zx_ram_w),this));
53   membank("bank1")->set_base(m_region_maincpu->base() + 0x4000);
54}
34   m_nmi_on = false;
35   m_nmi_generator_active = false;
5536
56DIRECT_UPDATE_MEMBER(zx_state::zx_setdirect)
57{
58   if (address & 0xc000)
59      zx_ula_r(address, m_region_maincpu, 0);
60   return address;
61}
37   m_cassette_cur_level = 0;
6238
63DIRECT_UPDATE_MEMBER(zx_state::pc8300_setdirect)
64{
65   if (address & 0xc000)
66      zx_ula_r(address, m_region_gfx1, 0);
67   return address;
39   m_tape_input->adjust(attotime::from_hz(44100), 0, attotime::from_hz(44100));
6840}
6941
70DIRECT_UPDATE_MEMBER(zx_state::pow3000_setdirect)
42void zx_state::zx_tape_input()
7143{
72   if (address & 0xc000)
73      zx_ula_r(address, m_region_gfx1, 1);
74   return address;
44   m_cassette_cur_level = m_cassette->input();
7545}
7646
77void zx_state::machine_reset()
47void zx_state::drop_sync()
7848{
79   m_maincpu->space(AS_PROGRAM).set_direct_update_handler(direct_update_delegate(FUNC(zx_state::zx_setdirect), this));
80   m_tape_bit = 0x80;
81}
49   if (m_vsync_active) {
50      UINT64 time = m_maincpu->total_cycles();
51      m_vsync_active = false;
52      m_cassette->output(-1.0);
8253
83MACHINE_RESET_MEMBER(zx_state,pow3000)
84{
85   m_maincpu->space(AS_PROGRAM).set_direct_update_handler(direct_update_delegate(FUNC(zx_state::pow3000_setdirect), this));
86   m_tape_bit = 0x80;
87}
54      int xs = 2*((m_vsync_start_time - m_base_vsync_clock) % 207);
55      int ys = (m_vsync_start_time - m_base_vsync_clock) / 207;
56      int xe = 2*((time - m_base_vsync_clock) % 207);
57      int ye = (time - m_base_vsync_clock) / 207;
58      if(xs >= 384) {
59         xs = 0;
60         ys++;
61      }
62      if(xe >= 384) {
63         xe = 0;
64         ye++;
65      }
66      if(ys < 311) {
67         if(ye > 310) {
68            ye = 311;
69            xe = 0;
70         }
71         if(ys == ye) {
72            UINT16 *dest = &m_bitmap_render->pix16(ys, xs);
73            for(int x = xs; x < xe; x++)
74               *dest++ = 1;
75         } else {
76            UINT16 *dest = &m_bitmap_render->pix16(ys, xs);
77            for(int x = xs; x < 384; x++)
78               *dest++ = 1;
79            for(int y = ys+1; y < ye; y++) {
80               dest = &m_bitmap_render->pix16(y, 0);
81               for(int x = 0; x<384; x++)
82                  *dest++ = 1;
83            }
84            dest = &m_bitmap_render->pix16(ye, 0);
85            for(int x = 0; x < xe; x++)
86               *dest++ = 1;
87         }
88      }
8889
89MACHINE_RESET_MEMBER(zx_state,pc8300)
90{
91   m_maincpu->space(AS_PROGRAM).set_direct_update_handler(direct_update_delegate(FUNC(zx_state::pc8300_setdirect), this));
92   m_tape_bit = 0x80;
90      // Short is hsync
91      if(time - m_vsync_start_time > 1000) {
92         // Ignore too short frame times, they're cassette output
93         if(time - m_base_vsync_clock > 52000) {
94            logerror("frame time %d\n", int(time - m_base_vsync_clock));
95           
96            rectangle rect(0, 383, 0, 310);
97            copybitmap(*m_bitmap_buffer, *m_bitmap_render, 0, 0, 0, 0, rect);
98            m_bitmap_render->fill(0);         
99            m_base_vsync_clock = time;
100            m_ypos = 0;
101         }
102         if(m_nmi_on)
103            m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
104         m_nmi_on = m_hsync_active = false;
105         recalc_hsync();
106      } else
107         m_ypos = ((time-m_base_vsync_clock)%207) < 192 ? 0 : -1;
108   }
93109}
94110
95TIMER_CALLBACK_MEMBER(zx_state::zx_tape_pulse)
96{
97   m_tape_bit = 0x80;
98}
99
100111READ8_MEMBER( zx_state::zx80_io_r )
101112{
102/* port FE = read keyboard, NTSC/PAL diode, and cass bit; turn off HSYNC-generator/cass-out
103    The upper 8 bits are used to select a keyboard scan line */
113   /* port FE = read keyboard, NTSC/PAL diode, and cass bit; turn off HSYNC-generator/cass-out
114       The upper 8 bits are used to select a keyboard scan line */
104115
105116   UINT8 data = 0xff;
106   UINT8 offs = offset & 0xff;
107117
108   if (offs == 0xfe)
118   if (!(offset & 0x01))
109119   {
110120      if ((offset & 0x0100) == 0)
111121         data &= m_io_row0->read();
r249926r249927
129139
130140      m_cassette->output(+1.0);
131141
132      if (m_ula_irq_active)
133      {
134         zx_ula_bkgnd(0);
135         m_ula_irq_active = 0;
142      if (!m_vsync_active && !m_nmi_generator_active) {
143         m_vsync_active = true;
144         m_vsync_start_time = m_maincpu->total_cycles();
136145      }
137//      else
138//      {
139         if ((m_cassette->input() < -0.75) && m_tape_bit)
140         {
141            m_tape_bit = 0x00;
142            timer_set(attotime::from_usec(362), TIMER_TAPE_PULSE);
143         }
144146
145         data &= ~m_tape_bit;
146//      }
147      if (m_ula_frame_vsync == 3)
148      {
149         m_ula_frame_vsync = 2;
150      }
147      if(m_cassette_cur_level <= 0)
148         data &= 0x7f;
151149   }
152150
153151   return data;
r249926r249927
160158    The upper 8 bits are used to select a keyboard scan line */
161159
162160   UINT8 data = 0xff;
163   UINT8 offs = offset & 0xff;
164161
165   if (offs == 0xfe)
162   if (!(offset & 0x01))
166163   {
167164      if ((offset & 0x0100) == 0)
168165         data &= m_io_row0->read();
r249926r249927
186183
187184      m_cassette->output(+1.0);
188185
189      if (m_ula_irq_active)
190      {
191         zx_ula_bkgnd(0);
192         m_ula_irq_active = 0;
186      if (!m_vsync_active && !m_nmi_generator_active) {
187         m_vsync_active = true;
188         m_vsync_start_time = m_maincpu->total_cycles();
193189      }
194      else
195      {
196         if ((m_cassette->input() < -0.75) && m_tape_bit)
197         {
198            m_tape_bit = 0x00;
199            timer_set(attotime::from_usec(362), TIMER_TAPE_PULSE);
200         }
201190
202         data &= ~m_tape_bit;
203      }
204      if (m_ula_frame_vsync == 3)
205      {
206         m_ula_frame_vsync = 2;
207      }
191      if(m_cassette_cur_level <= 0)
192         data &= 0x7f;
208193   }
209194
210195   return data;
r249926r249927
248233         data &= m_io_row7->read();
249234
250235      m_cassette->output(+1.0);
251
252      if (m_ula_irq_active)
253      {
254         zx_ula_bkgnd(0);
255         m_ula_irq_active = 0;
256      }
257      else
258      {
259         if ((m_cassette->input() < -0.75) && m_tape_bit)
260         {
261            m_tape_bit = 0x00;
262            timer_set(attotime::from_usec(362), TIMER_TAPE_PULSE);
263         }
264
265         data &= ~m_tape_bit;
266      }
267      if (m_ula_frame_vsync == 3)
268      {
269         m_ula_frame_vsync = 2;
270      }
236      if(m_cassette_cur_level <= 0)
237         data &= 0x7f;
271238   }
272239
273240   return data;
r249926r249927
316283         data &= m_io_row7->read();
317284
318285      m_cassette->output(+1.0);
319
320      if (m_ula_irq_active)
321      {
322         zx_ula_bkgnd(0);
323         m_ula_irq_active = 0;
324      }
325      else
326      {
327         if ((m_cassette->input() < -0.75) && m_tape_bit)
328         {
329            m_tape_bit = 0x00;
330            timer_set(attotime::from_usec(362), TIMER_TAPE_PULSE);
331         }
332
333         data &= ~m_tape_bit;
334      }
335      if (m_ula_frame_vsync == 3)
336      {
337         m_ula_frame_vsync = 2;
338      }
286      if(m_cassette_cur_level <= 0)
287         data &= 0x7f;
339288   }
340289
341290   return data;
r249926r249927
360309    FE = turn on NMI generator
361310    FF = write HSYNC and cass data */
362311
363   int height = m_screen->height();
364   UINT8 offs = offset & 0xff;
365
366   if (offs == 0xfd)
367   {
368      m_ula_nmi->reset();
312   if (!(offset & 0x01) && !m_nmi_generator_active) {
313      m_nmi_generator_active = true;
314      m_nmi_on = m_hsync_active;
315      m_maincpu->set_input_line(INPUT_LINE_NMI, m_nmi_on ? ASSERT_LINE : CLEAR_LINE);
316      recalc_hsync();
369317   }
370   else
371   if (offs == 0xfe)
372   {
373      m_ula_nmi->adjust(attotime::zero, 0, m_maincpu->cycles_to_attotime(207));
374318
375      /* remove the IRQ */
376      m_ula_irq_active = 0;
377   }
378   else
379   if (offs == 0xff)
380   {
381      m_cassette->output(-1.0);
382      zx_ula_bkgnd(1);
383      if (m_ula_frame_vsync == 2)
384      {
385         m_maincpu->spin_until_time(m_screen->time_until_pos(height - 1, 0));
386         m_ula_scanline_count = height - 1;
387         logerror ("S: %d B: %d\n", m_screen->vpos(), m_screen->hpos());
319   if (!(offset & 0x02) && m_nmi_generator_active) {
320      m_nmi_generator_active = false;
321      if(m_nmi_on) {
322         m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
323         m_nmi_on = false;
388324      }
389325   }
326
327   drop_sync();
390328}
trunk/src/mame/video/zx.c
r249926r249927
11// license:GPL-2.0+
2// copyright-holders:Juergen Buchmueller, Krzysztof Strzecha, Robbbert
2// copyright-holders: Olivier Galibert, Juergen Buchmueller, Krzysztof Strzecha, Robbbert
33/***************************************************************************
44    zx.c
55
r249926r249927
2525{
2626   switch (id)
2727   {
28   case TIMER_TAPE_PULSE:
29      zx_tape_pulse(ptr, param);
28   case TIMER_TAPE_INPUT:
29      zx_tape_input();
3030      break;
31   case TIMER_ULA_NMI:
32      zx_ula_nmi(ptr, param);
31   case TIMER_ULA_HSYNC:
32      zx_ula_hsync();
3333      break;
34   case TIMER_ULA_IRQ:
35      zx_ula_irq(ptr, param);
36      break;
3734   default:
3835      assert_always(FALSE, "Unknown id in zx_state::device_timer");
3936   }
4037}
4138
4239
43/*
44 * Toggle the video output between black and white.
45 * This happens whenever the ULA scanline IRQs are enabled/disabled.
46 * Normally this is done during the synchronized zx_ula_r() function,
47 * which outputs 8 pixels per code, but if the video sync is off
48 * (during tape IO or sound output) zx_ula_bkgnd() is used to
49 * simulate the display of a ZX80/ZX81.
50 */
51void zx_state::zx_ula_bkgnd(UINT8 color)
40void zx_state::zx_ula_hsync()
5241{
53   int width = m_screen->width();
54   int height = m_screen->height();
55   const rectangle &visarea = m_screen->visible_area();
42   m_hsync_active = !m_hsync_active;
43   if(m_hsync_active)
44      m_ypos++;
45   if(m_nmi_generator_active) {
46      m_nmi_on = m_hsync_active;
47      m_maincpu->set_input_line(INPUT_LINE_NMI, m_nmi_on ? ASSERT_LINE : CLEAR_LINE);
48   }
49   recalc_hsync();
50}
5651
57   if (m_ula_frame_vsync == 0 && color != m_old_c)
58   {
59      int y, new_x, new_y;
60      rectangle r;
61      bitmap_ind16 &bitmap = m_bitmap;
62
63      new_y = machine().first_screen()->vpos();
64      new_x = machine().first_screen()->hpos();
65/*      logerror("zx_ula_bkgnd: %3d,%3d - %3d,%3d\n", state->m_old_x, state->m_old_y, new_x, new_y);*/
66      y = m_old_y;
67      for (;;)
68      {
69         if (y == new_y)
70         {
71            r.set(m_old_x, new_x, y, y);
72            bitmap.fill(color, r);
73            break;
74         }
75         else
76         {
77            r.set(m_old_x, visarea.max_x, y, y);
78            bitmap.fill(color, r);
79            m_old_x = 0;
80         }
81         if (++y == height)
82            y = 0;
52WRITE16_MEMBER(zx_state::refresh_w)
53{
54   if((data ^ m_prev_refresh) & 0x40)
55      m_maincpu->set_input_line(INPUT_LINE_IRQ0, data & 0x40 ? CLEAR_LINE : ASSERT_LINE);
56   m_prev_refresh = data;
57   if(m_ula_char_buffer != 0xffff) {
58      UINT64 time = m_maincpu->total_cycles();
59      int x = 2*((time-m_base_vsync_clock) % 207);
60      int y = (time-m_base_vsync_clock) / 207;
61      UINT8 pixels;
62      if(m_region_gfx1)
63         pixels = m_region_gfx1->base()[((m_ula_char_buffer & 0x3f) << 3) | (m_ypos & 7)];
64      else
65         pixels = m_program->read_byte((data & 0xfe00) | ((m_ula_char_buffer & 0x3f) << 3) | (m_ypos & 7));
66      if(m_ula_char_buffer & 0x80)
67         pixels = ~pixels;
68      if(x < 384-8 && y < 311) {
69         UINT16 *dest = &m_bitmap_render->pix16(y, x);
70         for(int i=0; i<8; i++)
71            *dest++ |= pixels & (0x80 >> i) ? 1 : 0;
8372      }
84      m_old_x = (new_x + 1) % width;
85      m_old_y = new_y;
86      m_old_c = color;
73      m_ula_char_buffer = 0xffff;
8774   }
8875}
8976
90/*
91 * PAL:  310 total lines,
92 *            0.. 55 vblank
93 *           56..247 192 visible lines
94 *          248..303 vblank
95 *          304...   vsync
96 * NTSC: 262 total lines
97 *            0.. 31 vblank
98 *           32..223 192 visible lines
99 *          224..233 vblank
100 */
101TIMER_CALLBACK_MEMBER(zx_state::zx_ula_nmi)
77void zx_state::recalc_hsync()
10278{
103   /*
104    * An NMI is issued on the ZX81 every 64us for the blanked
105    * scanlines at the top and bottom of the display.
106    */
107   int height = m_screen->height();
108   const rectangle& r1 = m_screen->visible_area();
109   rectangle r;
79   UINT64 time = machine().time().as_ticks(m_maincpu->clock());
80   UINT32 step = (time - m_base_vsync_clock) % 207;
81   UINT32 delta;
82   if (m_hsync_active)
83      delta = 207 - step;
84   else {
85      if(step < 192)
86         delta = 192 - step;
87      else
88         delta = 399 - step;
89   }   
11090
111   bitmap_ind16 &bitmap = m_bitmap;
112   r.set(r1.min_x, r1.max_x, m_ula_scanline_count, m_ula_scanline_count);
113   bitmap.fill(1, r);
114//  logerror("ULA %3d[%d] NMI, R:$%02X, $%04x\n", machine().first_screen()->vpos(), ula_scancode_count, (unsigned) m_maincpu->state_int(Z80_R), (unsigned) m_maincpu->state_int(Z80_PC));
115   m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE);
116   if (++m_ula_scanline_count == height)
117      m_ula_scanline_count = 0;
91   m_ula_hsync->adjust(m_maincpu->cycles_to_attotime(delta));
11892}
11993
120TIMER_CALLBACK_MEMBER(zx_state::zx_ula_irq)
94READ8_MEMBER(zx_state::ula_low_r)
12195{
122   /*
123    * An IRQ is issued on the ZX80/81 whenever the R registers
124    * bit 6 goes low. In MESS this IRQ timed from the first read
125    * from the copy of the DFILE in the upper 32K in zx_ula_r().
126    */
127   if (m_ula_irq_active)
128   {
129//      logerror("ULA %3d[%d] IRQ, R:$%02X, $%04x\n", machine().first_screen()->vpos(), ula_scancode_count, (unsigned) m_maincpu->state_int(Z80_R), (unsigned) m_maincpu->state_int(Z80_PC));
96   UINT8 cdata = m_program->read_byte(offset);
97   if(space.debugger_access())
98      return cdata;
13099
131      m_ula_irq_active = 0;
132      m_maincpu->set_input_line(0, HOLD_LINE);
100   if(m_maincpu->state_int(Z80_HALT))
101      return cdata;
102
103   if(m_nmi_on) {
104      UINT64 time = m_maincpu->total_cycles();
105      int pos = (time-m_base_vsync_clock) % 207;
106      if(pos >= 192)
107         m_maincpu->adjust_icount(pos - 207);
133108   }
109   return cdata;
134110}
135111
136void zx_state::zx_ula_r(int offs, memory_region *region, const UINT8 param)
112READ8_MEMBER(zx_state::ula_high_r)
137113{
138   int offs0 = offs & 0x7fff;
139   UINT8 *rom = m_region_maincpu->base();
140   UINT8 chr = rom[offs0];
114   UINT8 cdata = m_program->read_byte(offset);
141115
142   if ((!m_ula_irq_active) && (chr == 0x76))
143   {
144      bitmap_ind16 &bitmap = m_bitmap;
145      UINT16 y, *scanline;
146      UINT16 ireg = m_maincpu->state_int(Z80_I) << 8;
147      UINT8 data, *chrgen, creg;
116   if(space.debugger_access())
117      return cdata;
148118
149      if (param)
150         creg = m_maincpu->state_int(Z80_B);
151      else
152         creg = m_maincpu->state_int(Z80_C);
119   if(m_maincpu->state_int(Z80_HALT))
120      return cdata;
153121
154      chrgen = region->base();
122   if(m_nmi_on) {
123      UINT64 time = m_maincpu->total_cycles();
124      int pos = (time-m_base_vsync_clock) % 207;
125      if(pos >= 192)
126         m_maincpu->adjust_icount(pos - 207);
127   }
155128
156      if ((++m_ula_scanline_count == m_screen->height()) || (creg == 32))
157      {
158         m_ula_scanline_count = 0;
159         m_offs1 = offs0;
160      }
129   if(cdata & 0x40)
130      return cdata;
161131
162      m_ula_frame_vsync = 3;
163
164      m_charline_ptr = 0;
165
166      for (y = m_offs1+1; ((y < offs0) && (m_charline_ptr < ARRAY_LENGTH(m_charline))); y++)
167      {
168         m_charline[m_charline_ptr] = rom[y];
169         m_charline_ptr++;
170      }
171      for (y = m_charline_ptr; y < ARRAY_LENGTH(m_charline); y++)
172         m_charline[y] = 0;
173
174      timer_set(m_maincpu->cycles_to_attotime(((32 - m_charline_ptr) << 2)), TIMER_ULA_IRQ);
175      m_ula_irq_active++;
176
177      scanline = &bitmap.pix16(m_ula_scanline_count);
178      y = 0;
179
180      for (m_charline_ptr = 0; m_charline_ptr < ARRAY_LENGTH(m_charline); m_charline_ptr++)
181      {
182         chr = m_charline[m_charline_ptr];
183         data = chrgen[ireg | ((chr & 0x3f) << 3) | ((8 - creg)&7) ];
184         if (chr & 0x80) data ^= 0xff;
185
186         scanline[y++] = (data >> 7) & 1;
187         scanline[y++] = (data >> 6) & 1;
188         scanline[y++] = (data >> 5) & 1;
189         scanline[y++] = (data >> 4) & 1;
190         scanline[y++] = (data >> 3) & 1;
191         scanline[y++] = (data >> 2) & 1;
192         scanline[y++] = (data >> 1) & 1;
193         scanline[y++] = (data >> 0) & 1;
194         m_charline[m_charline_ptr] = 0;
195      }
196
197      if (creg == 1) m_offs1 = offs0;
198   }
132   m_ula_char_buffer = cdata;
133   return 0x00; // nop
199134}
200135
201136void zx_state::video_start()
202137{
203   m_ula_nmi = timer_alloc(TIMER_ULA_NMI);
204   m_ula_irq_active = 0;
205   m_screen->register_screen_bitmap(m_bitmap);
206}
138   m_ula_hsync = timer_alloc(TIMER_ULA_HSYNC);
139   m_ula_char_buffer = 0xffff;
207140
208void zx_state::screen_eof_zx(screen_device &screen, bool state)
209{
210   // rising edge
211   if (state)
212   {
213      /* decrement video synchronization counter */
214      if (m_ula_frame_vsync)
215         --m_ula_frame_vsync;
216   }
141   m_bitmap_render = auto_bitmap_ind16_alloc(machine(), 384, 311);
142   m_bitmap_buffer = auto_bitmap_ind16_alloc(machine(), 384, 311);
217143}
218144
219145UINT32 zx_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
220146{
221   copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect);
147   copybitmap(bitmap, *m_bitmap_buffer, 0, 0, 0, 0, cliprect);
222148   return 0;
223149}


Previous 199869 Revisions Next


© 1997-2024 The MAME Team