summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Juergen Buchmueller <pullmoll@t-online.de>2016-08-19 22:05:12 +0200
committer Juergen Buchmueller <pullmoll@t-online.de>2016-08-19 22:09:27 +0200
commit0b89614f16eca16406262ac728a4033761bf0523 (patch)
tree0bd6fd6ccc54b94df5cdc375b1cf5445f52cbe10
parentfe29ea1c765f6fd60b9c20b7ba3f9ee114d3f987 (diff)
alto2: Refactor videotiming + use attoseconds_t
Use MAME's type attoseconds_t and handle the timing accus in attoseconds instead of nanoseconds. Try to solve the video timing issues by using an emu_timer running at the field rate of 60Hz, which the video state machine synchronizes to.
-rw-r--r--src/devices/cpu/alto2/a2disk.cpp8
-rw-r--r--src/devices/cpu/alto2/a2disk.h2
-rw-r--r--src/devices/cpu/alto2/a2disp.cpp68
-rw-r--r--src/devices/cpu/alto2/a2disp.h38
-rw-r--r--src/devices/cpu/alto2/a2dwt.cpp10
-rw-r--r--src/devices/cpu/alto2/alto2cpu.cpp80
-rw-r--r--src/devices/cpu/alto2/alto2cpu.h9
-rw-r--r--src/mame/drivers/alto2.cpp35
8 files changed, 135 insertions, 115 deletions
diff --git a/src/devices/cpu/alto2/a2disk.cpp b/src/devices/cpu/alto2/a2disk.cpp
index c4658726492..0d0d43c0ceb 100644
--- a/src/devices/cpu/alto2/a2disk.cpp
+++ b/src/devices/cpu/alto2/a2disk.cpp
@@ -1638,8 +1638,8 @@ void alto2_cpu_device::next_sector(int unit)
{
diablo_hd_device* dhd = m_drive[unit];
LOG((this,LOG_DISK,0,"%s dhd=%p\n", __FUNCTION__, dhd));
- // get bit time in pico seconds
- m_dsk.bitclk_time[unit] = static_cast<int>(dhd->bit_time().as_attoseconds() / 1000000);
+ // get bit time in attoseconds
+ m_dsk.bitclk_time[unit] = dhd->bit_time().as_attoseconds();
if (m_bitclk_time >= 0) {
LOG((this,LOG_DISK,0," unit #%d stop bitclk\n", unit));
m_bitclk_time = -1;
@@ -1796,8 +1796,8 @@ void alto2_cpu_device::reset_disk()
m_dsk.strobe = 0;
m_dsk.strobon_timer->reset();
m_dsk.bitclk = 0;
- m_dsk.bitclk_time[0] = static_cast<int>(attotime::from_nsec(300).as_attoseconds() / 1000000);
- m_dsk.bitclk_time[1] = static_cast<int>(attotime::from_nsec(300).as_attoseconds() / 1000000);
+ m_dsk.bitclk_time[0] = attotime::from_nsec(300).as_attoseconds();
+ m_dsk.bitclk_time[1] = attotime::from_nsec(300).as_attoseconds();
m_dsk.datin = 0;
m_dsk.bitcount = 0;
m_dsk.seclate = 0;
diff --git a/src/devices/cpu/alto2/a2disk.h b/src/devices/cpu/alto2/a2disk.h
index a3f8c7755fc..e000ad7cfc4 100644
--- a/src/devices/cpu/alto2/a2disk.h
+++ b/src/devices/cpu/alto2/a2disk.h
@@ -37,7 +37,7 @@ struct {
UINT8 strobe; //!< strobe (still) active
emu_timer* strobon_timer; //!< set strobe on timer
UINT8 bitclk; //!< current bitclk state (either crystal clock, or rdclk from the drive)
- int bitclk_time[2]; //!< per drive time in clocks per bit
+ attoseconds_t bitclk_time[2]; //!< per drive time in attoseconds per bit
UINT8 datin; //!< current datin from the drive
UINT8 bitcount; //!< bit counter
UINT8 carry; //!< carry output of the bitcounter
diff --git a/src/devices/cpu/alto2/a2disp.cpp b/src/devices/cpu/alto2/a2disp.cpp
index f2c5b06a77f..df8ac15f3a5 100644
--- a/src/devices/cpu/alto2/a2disp.cpp
+++ b/src/devices/cpu/alto2/a2disp.cpp
@@ -245,11 +245,13 @@ static const UINT16 double_bits[256] = {
//! update the internal frame buffer and draw the scanline segment if changed
void alto2_cpu_device::update_framebuf_word(UINT16* framebuf, int x, int y, UINT16 word)
{
+ if (y >= A2_DISP_TOTAL_HEIGHT)
+ return;
int xpword = (m_dsp.xpreg ^ 01777) / 16;
// mixing with the cursor
if (x == xpword++)
word ^= (m_dsp.csr << (m_dsp.xpreg % 16)) >> 16;
- if (x == xpword)
+ if (x == xpword)
word ^= (m_dsp.csr << (m_dsp.xpreg % 16)) & 0xffff;
// no change?
if (word == framebuf[x])
@@ -266,12 +268,11 @@ void alto2_cpu_device::unload_word()
int x = m_unload_word;
int y = m_dsp.scanline;
- if (y < 0 || y >= ALTO2_DISPLAY_TOTAL_HEIGHT || x >= ALTO2_DISPLAY_VISIBLE_WORDS)
- {
+ if (x >= A2_DISP_VISIBLE_WORDS) {
m_unload_time = -1;
return;
}
- UINT16* framebuf = m_dsp.framebuf.get() + y * ALTO2_DISPLAY_SCANLINE_WORDS;
+ UINT16* framebuf = m_dsp.framebuf.get() + y * A2_DISP_SCANLINE_WORDS;
UINT16 word = m_dsp.inverse;
UINT8 a38 = m_disp_a38[m_dsp.ra * 16 + m_dsp.wa];
if (FIFO_MBEMPTY(a38))
@@ -281,9 +282,9 @@ void alto2_cpu_device::unload_word()
else
{
word ^= m_dsp.fifo[m_dsp.ra];
- m_dsp.ra = (m_dsp.ra + 1) % ALTO2_DISPLAY_FIFO;
+ m_dsp.ra = (m_dsp.ra + 1) % A2_DISP_FIFO;
LOG((this,LOG_DISPL,3, " DSP pull %04x from FIFO[%02o] y:%d x:%d\n",
- word, (m_dsp.ra - 1) & (ALTO2_DISPLAY_FIFO - 1), y, x));
+ word, (m_dsp.ra - 1) & (A2_DISP_FIFO - 1), y, x));
}
if (m_dsp.halfclock)
@@ -291,21 +292,21 @@ void alto2_cpu_device::unload_word()
const UINT16 word1 = double_bits[word / 256];
update_framebuf_word(framebuf, x, y, word1);
x++;
- if (x < ALTO2_DISPLAY_VISIBLE_WORDS)
+ if (x < A2_DISP_VISIBLE_WORDS)
{
const UINT16 word2 = double_bits[word % 256];
update_framebuf_word(framebuf, x, y, word2);
x++;
}
- m_unload_time += ALTO2_DISPLAY_BITTIME(32);
+ m_unload_time += A2_DISP_BITTIME(32);
}
else
{
update_framebuf_word(framebuf, x, y, word);
x++;
- m_unload_time += ALTO2_DISPLAY_BITTIME(16);
+ m_unload_time += A2_DISP_BITTIME(16);
}
- if (x < ALTO2_DISPLAY_VISIBLE_WORDS)
+ if (x < A2_DISP_VISIBLE_WORDS)
m_unload_word = x;
else
m_unload_time = -1;
@@ -330,13 +331,11 @@ void alto2_cpu_device::display_state_machine()
{
// count horizontal line counters and wrap
m_dsp.hlc += 1;
- if (m_dsp.hlc > ALTO2_DISPLAY_HLC_END) {
- m_dsp.hlc = ALTO2_DISPLAY_HLC_START;
- m_dsp.scanline = 30;
- m_dsp.vsync = true;
+ if (m_dsp.hlc > A2_DISP_HLC_END) {
+ m_dsp.hlc = A2_DISP_HLC_START;
+ m_dsp.scanline = 0;
} else if (m_dsp.hlc == 1024) {
- m_dsp.vsync = true;
- m_dsp.scanline = 31;
+ m_dsp.scanline = 1;
}
// wake up the memory refresh task _twice_ on each scanline
m_task_wakeup |= 1 << task_mrt;
@@ -350,6 +349,15 @@ void alto2_cpu_device::display_state_machine()
if (A66_VBLANK(a66))
{
LOG((this,LOG_DISPL,1, " VBLANK"));
+ // Rising edge of VBLANK?
+ if (!A66_VBLANK(m_dsp.a66)) {
+ // synchronize on MAME video timing
+ if (!m_dsp.vblank) {
+ m_display_time += A2_DISP_BITTIME(1);
+ return;
+ }
+ m_dsp.vblank = false;
+ }
// VSYNC is always within VBLANK, thus we handle it only here
if (A66_VSYNC(a66) && !A66_VSYNC(m_dsp.a66))
@@ -393,7 +401,7 @@ void alto2_cpu_device::display_state_machine()
m_dsp.scanline += 2;
// Falling edge of a63 HBLANK starts unloading of FIFO words
LOG((this,LOG_DISPL,1, " HBLANK\\ UNLOAD"));
- m_unload_time = ALTO2_DISPLAY_BITTIME(m_dsp.halfclock ? 40+32 : 40+16);
+ m_unload_time = A2_DISP_BITTIME(m_dsp.halfclock ? 40+32 : 40+16);
m_unload_word = 0;
}
}
@@ -466,7 +474,7 @@ void alto2_cpu_device::display_state_machine()
m_dsp.a63 = a63;
m_dsp.a66 = a66;
m_dsp.state = next;
- m_dsp_time += ALTO2_DISPLAY_BITTIME(32);
+ m_display_time += A2_DISP_BITTIME(32);
}
/**
@@ -476,7 +484,7 @@ void alto2_cpu_device::display_state_machine()
*/
void alto2_cpu_device::f2_late_evenfield()
{
- UINT16 r = m_dsp.odd ? 0 : 1;
+ UINT16 r = HLC1024 ^ 1;
LOG((this,LOG_DISPL,2," EVENFIELD branch (%#o | %#o)\n", m_next2, r));
m_next2 |= r;
}
@@ -512,9 +520,9 @@ void alto2_cpu_device::init_disp()
m_disp_a63 = prom_load(machine(), &pl_displ_a63, memregion("displ_a63")->base());
m_disp_a66 = prom_load(machine(), &pl_displ_a66, memregion("displ_a66")->base());
- m_dsp.hlc = ALTO2_DISPLAY_HLC_START;
+ m_dsp.hlc = A2_DISP_HLC_START;
- m_dsp.framebuf = std::make_unique<UINT16[]>(ALTO2_DISPLAY_TOTAL_HEIGHT * ALTO2_DISPLAY_SCANLINE_WORDS);
+ m_dsp.framebuf = std::make_unique<UINT16[]>(A2_DISP_TOTAL_HEIGHT * A2_DISP_SCANLINE_WORDS);
m_dsp.patterns = auto_alloc_array(machine(), UINT8, 65536 * 16);
for (int y = 0; y < 65536; y++) {
UINT8* dst = m_dsp.patterns + y * 16;
@@ -523,7 +531,7 @@ void alto2_cpu_device::init_disp()
}
// Allocate a bitmap including the V/H blank areas
- m_dsp.bitmap = std::make_unique<bitmap_ind16>(ALTO2_DISPLAY_TOTAL_WIDTH, ALTO2_DISPLAY_TOTAL_HEIGHT);
+ m_dsp.bitmap = std::make_unique<bitmap_ind16>(A2_DISP_TOTAL_WIDTH, A2_DISP_TOTAL_HEIGHT);
m_dsp.state = 0;
}
@@ -535,12 +543,12 @@ void alto2_cpu_device::exit_disp()
void alto2_cpu_device::reset_disp()
{
m_dsp.state = 0;
- m_dsp.hlc = ALTO2_DISPLAY_HLC_START;
+ m_dsp.hlc = A2_DISP_HLC_START;
m_dsp.a63 = 0;
m_dsp.a66 = 0;
m_dsp.setmode = 0;
m_dsp.inverse = 0;
- m_dsp.scanline = 30;
+ m_dsp.scanline = 0;
m_dsp.halfclock = false;
m_dsp.wa = 0;
m_dsp.ra = 0;
@@ -548,18 +556,20 @@ void alto2_cpu_device::reset_disp()
m_dsp.dwt_blocks = false;
m_dsp.curt_blocks = false;
m_dsp.curt_wakeup = false;
- m_dsp.vsync = false;
- m_dsp.odd = false;
+ m_dsp.vblank = false;
m_dsp.xpreg = 0;
m_dsp.csr = 0;
- memset(m_dsp.framebuf.get(), 1, sizeof(UINT16) * ALTO2_DISPLAY_HEIGHT * ALTO2_DISPLAY_SCANLINE_WORDS);
+ memset(m_dsp.framebuf.get(), 1, sizeof(UINT16) * A2_DISP_HEIGHT * A2_DISP_SCANLINE_WORDS);
}
/* Video update */
UINT32 alto2_cpu_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
copybitmap(bitmap, *m_dsp.bitmap, 0, 0, 0, 0, cliprect);
- m_dsp.vsync = false;
- m_dsp.odd = !m_dsp.odd;
return 0;
}
+
+void alto2_cpu_device::screen_vblank()
+{
+ m_dsp.vblank = true;
+}
diff --git a/src/devices/cpu/alto2/a2disp.h b/src/devices/cpu/alto2/a2disp.h
index 823114e3066..c2c321583e6 100644
--- a/src/devices/cpu/alto2/a2disp.h
+++ b/src/devices/cpu/alto2/a2disp.h
@@ -18,7 +18,7 @@
*
* The value is 2+4+16+128 = 150
*/
-#define ALTO2_DISPLAY_HLC_START (2+4+16+128)
+#define A2_DISP_HLC_START (2+4+16+128)
/**
* @brief End value for the horizontal line counter.
@@ -30,7 +30,7 @@
* Note: The horizontal line counts 150 ... 1023 for the even field,
* and 1024 ... 1899 for the odd field.
*/
-#define ALTO2_DISPLAY_HLC_END (1+2+8+32+64+256+512+1024)
+#define A2_DISP_HLC_END (1+2+8+32+64+256+512+1024)
/**
* @brief display total height, including overscan (vertical blanking and synch)
@@ -39,7 +39,7 @@
* scanlines to the monitor. The frame rate is 60Hz, which is actually the rate
* of the half-frames. The rate for full frames is thus 30Hz.
*/
-#define ALTO2_DISPLAY_TOTAL_HEIGHT ((ALTO2_DISPLAY_HLC_END + 1 - ALTO2_DISPLAY_HLC_START) / 2)
+#define A2_DISP_TOTAL_HEIGHT (static_cast<double>(A2_DISP_HLC_END - A2_DISP_HLC_START) / 2)
/**
* @brief display total width, including horizontal blanking
@@ -68,40 +68,39 @@
* as its own next address A0-A3!
*
*/
-#define ALTO2_DISPLAY_TOTAL_WIDTH 768
+#define A2_DISP_TOTAL_WIDTH 768
//! The display fifo has 16 words.
-#define ALTO2_DISPLAY_FIFO 16
+#define A2_DISP_FIFO 16
//! Words per scanline.
-#define ALTO2_DISPLAY_SCANLINE_WORDS (ALTO2_DISPLAY_TOTAL_WIDTH/16)
+#define A2_DISP_SCANLINE_WORDS (A2_DISP_TOTAL_WIDTH/16)
-//! Number of visible scanlines per frame; 808 really, but there are some empty lines?
-#define ALTO2_DISPLAY_HEIGHT 808
+//! Number of visible scanlines per frame
+#define A2_DISP_HEIGHT 808
//! Visible width of the display; 38 x 16 bit words - 2 pixels.
-//#define ALTO2_DISPLAY_WIDTH 606
-#define ALTO2_DISPLAY_WIDTH 608
+#define A2_DISP_WIDTH 606
//! Visible words per scanline.
-#define ALTO2_DISPLAY_VISIBLE_WORDS ((ALTO2_DISPLAY_WIDTH+15)/16)
+#define A2_DISP_VISIBLE_WORDS ((A2_DISP_WIDTH+15)/16)
//! Display bit clock in Hertz (20.16MHz).
-#define ALTO2_DISPLAY_BITCLOCK 20160000ll
+#define A2_DISP_BITCLOCK 20160000ll
//! Display bit time in pico seconds (~= 49.6031ns).
-#define ALTO2_DISPLAY_BITTIME(n) (U64(1000000000000)*(n)/ALTO2_DISPLAY_BITCLOCK)
+#define A2_DISP_BITTIME(n) DOUBLE_TO_ATTOSECONDS(static_cast<double>(n)/A2_DISP_BITCLOCK)
//! Time for a scanline in pico seconds (768 * 49.6031ns ~= 38095.1808ns).
-#define ALTO2_DISPLAY_SCANLINE_TIME ALTO2_DISPLAY_BITTIME(ALTO2_DISPLAY_TOTAL_WIDTH)
+#define A2_DISP_SCANLINE_TIME A2_DISP_BITTIME(A2_DISP_TOTAL_WIDTH)
//!< Time of the visible part of a scanline in pico seconds (606 * 49.6031ns ~= 30059.4786ns).
-#define ALTO2_DISPLAY_VISIBLE_TIME ALTO2_DISPLAY_BITTIME(ALTO2_DISPLAY_WIDTH)
+#define A2_DISP_VISIBLE_TIME A2_DISP_BITTIME(A2_DISP_WIDTH)
//!< Time for a word in pico seconds (16 pixels * 49.6031ns ~= 793.6496ns).
-#define ALTO2_DISPLAY_WORD_TIME ALTO2_DISPLAY_BITTIME(16)
+#define A2_DISP_WORD_TIME A2_DISP_BITTIME(16)
-#define ALTO2_DISPLAY_VBLANK_TIME ((ALTO2_DISPLAY_TOTAL_HEIGHT-ALTO2_DISPLAY_HEIGHT)*HZ_TO_ATTOSECONDS(26250))
+#define A2_DISP_VBLANK_TIME (static_cast<double>(-A2_DISP_HEIGHT)*HZ_TO_ATTOSECONDS(26250))
#else // ALTO2_DEFINE_CONSTANTS
/**
@@ -200,9 +199,8 @@ struct {
UINT32 inverse; //!< set to 0xffff if line is inverse, 0x0000 otherwise
UINT32 scanline; //!< current scanline
bool halfclock; //!< false for normal pixel clock, true for half pixel clock
- bool vsync; //!< true after vsync, false when end_of_frame was called
- bool odd; //!< true if odd field
- UINT16 fifo[ALTO2_DISPLAY_FIFO]; //!< display word fifo
+ bool vblank; //!< true during vblank, false otherwise
+ UINT16 fifo[A2_DISP_FIFO]; //!< display word fifo
UINT32 wa; //!< fifo input pointer (write address; 4-bit)
UINT32 ra; //!< fifo output pointer (read address; 4-bit)
UINT32 a63; //!< most recent value read from the PROM a63
diff --git a/src/devices/cpu/alto2/a2dwt.cpp b/src/devices/cpu/alto2/a2dwt.cpp
index c3ac954b432..81601138e91 100644
--- a/src/devices/cpu/alto2/a2dwt.cpp
+++ b/src/devices/cpu/alto2/a2dwt.cpp
@@ -11,15 +11,15 @@
* Copied from ALTOCODE24.MU
*
* ;Display Word Task
- *
+ *
* DWT: T← DWA;
* T←-3+T+1;
* L← AECL+T,BUS=0,TASK; AECL CONTAINS NWRDS AT THIS TIME
* AECL←L, :DWTZ;
- *
+ *
* DWTY: BLOCK;
* TASK, :DWTF;
- *
+ *
* DWTZ: L←HTAB-1, BUS=0,TASK;
* HTAB←L, :DOTAB;
*
@@ -66,12 +66,12 @@ void alto2_cpu_device::f2_late_load_ddr()
{
LOG((this,LOG_DWT,2," DDR<- BUS (%#o)\n", m_bus));
m_dsp.fifo[m_dsp.wa] = m_bus;
- m_dsp.wa = (m_dsp.wa + 1) % ALTO2_DISPLAY_FIFO;
+ m_dsp.wa = (m_dsp.wa + 1) % A2_DISP_FIFO;
UINT8 a38 = m_disp_a38[m_dsp.ra * 16 + m_dsp.wa];
if (FIFO_STOPWAKE(a38))
m_task_wakeup &= ~(1 << task_dwt);
LOG((this,LOG_DWT,2, " DWT push %04x into FIFO[%02o]%s\n",
- m_bus, (m_dsp.wa - 1) & (ALTO2_DISPLAY_FIFO - 1),
+ m_bus, (m_dsp.wa - 1) & (A2_DISP_FIFO - 1),
FIFO_STOPWAKE(a38) ? " STOPWAKE" : ""));
}
diff --git a/src/devices/cpu/alto2/alto2cpu.cpp b/src/devices/cpu/alto2/alto2cpu.cpp
index 6a4438c973c..4361539af97 100644
--- a/src/devices/cpu/alto2/alto2cpu.cpp
+++ b/src/devices/cpu/alto2/alto2cpu.cpp
@@ -157,7 +157,7 @@ alto2_cpu_device::alto2_cpu_device(const machine_config& mconfig, const char* ta
m_wrtram_flag(false),
m_ether_enable(false),
m_ewfct(false),
- m_dsp_time(0),
+ m_display_time(0),
m_unload_time(0),
m_unload_word(0),
m_bitclk_time(0),
@@ -872,7 +872,7 @@ void alto2_cpu_device::device_start()
save_item(NAME(m_bank_reg));
save_item(NAME(m_ether_enable));
save_item(NAME(m_ewfct));
- save_item(NAME(m_dsp_time));
+ save_item(NAME(m_display_time));
save_item(NAME(m_unload_time));
save_item(NAME(m_unload_word));
save_item(NAME(m_bitclk_time));
@@ -2275,11 +2275,42 @@ void alto2_cpu_device::execute_run()
{
m_next = m_task_mpc[m_task]; // get current task's next mpc and address modifier
m_next2 = m_task_next2[m_task];
+ attoseconds_t ucycle = DOUBLE_TO_ATTOSECONDS(1.0/m_clock);
do {
- if (m_dsp.vsync) {
- // synchronizing to the vsync signal
- continue;
+ if (m_display_time >= 0) {
+ /**
+ * Subtract the microcycle time from the display time accu.
+ * If it underflows, call the display state machine which
+ * adds the time for 32 pixel clocks to the accu.
+ * This is very close to every seventh CPU cycle
+ */
+ m_display_time -= ucycle;
+ if (m_display_time < 0)
+ display_state_machine();
+ }
+
+ if (m_unload_time >= 0) {
+ /**
+ * Subtract the microcycle time from the unload time accu.
+ * If it underflows, call the unload word function which adds
+ * the time for 16 or 32 pixel clocks to the accu, or ends
+ * the FIFO unloading by leaving m_unload_time at -1.
+ */
+ m_unload_time -= ucycle;
+ if (m_unload_time < 0)
+ unload_word();
+ }
+
+ if (m_bitclk_time >= 0) {
+ /**
+ * Subtract the microcycle time from the bitclk time accu.
+ * If it underflows, call the disk bitclk function which adds
+ * the time for one bit as clock cycles to the accu, or ends
+ * the bitclk sequence by leaving m_bitclk_time at -1.
+ */
+ m_bitclk_time -= ucycle;
+ disk_bitclk(nullptr, m_bitclk_index);
}
m_mpc = m_next; // next instruction's micro program counter
@@ -2859,41 +2890,6 @@ void alto2_cpu_device::execute_run()
}
}
}
-
- if (m_dsp_time >= 0) {
- /**
- * Subtract the microcycle time from the display time accu.
- * If it underflows, call the display state machine which
- * adds the time for 32 pixel clocks to the accu.
- * This is very close to every seventh CPU cycle
- */
- m_dsp_time -= ALTO2_UCYCLE;
- if (m_dsp_time < 0)
- display_state_machine();
- }
-
- if (m_unload_time >= 0) {
- /**
- * Subtract the microcycle time from the unload time accu.
- * If it underflows, call the unload word function which adds
- * the time for 16 or 32 pixel clocks to the accu, or ends
- * the FIFO unloading by leaving m_unload_time at -1.
- */
- m_unload_time -= ALTO2_UCYCLE;
- if (m_unload_time < 0)
- unload_word();
- }
-
- if (m_bitclk_time >= 0) {
- /**
- * Subtract the microcycle time from the bitclk time accu.
- * If it underflows, call the disk bitclk function which adds
- * the time for one bit as clock cycles to the accu, or ends
- * the bitclk sequence by leaving m_bitclk_time at -1.
- */
- m_bitclk_time -= ALTO2_UCYCLE;
- disk_bitclk(nullptr, m_bitclk_index);
- }
} while (m_icount-- > 0);
// Save this task's mpc and address modifier
@@ -2935,7 +2931,7 @@ void alto2_cpu_device::hard_reset()
init_part();
init_kwd();
- m_dsp_time = 0; // reset the display state timing
+ m_display_time = 0; // reset the display state timing
m_unload_time = 0; // reset the word unload timing accu
m_bitclk_time = 0; // reset the bitclk timing accu
m_task = task_emu; // start with task 0 (emulator)
@@ -2981,7 +2977,7 @@ void alto2_cpu_device::soft_reset()
m_task = task_emu; // set current task to emulator
m_task_wakeup = 1 << task_emu; // set only the emulator task wakeup flag
- m_dsp_time = 0; // reset the display state machine timing accu
+ m_display_time = 0; // reset the display state machine timing accu
m_unload_time = 0; // reset the word unload timing accu
m_bitclk_time = 0; // reset the bitclk timing accu
}
diff --git a/src/devices/cpu/alto2/alto2cpu.h b/src/devices/cpu/alto2/alto2cpu.h
index 3993e79d816..036f709dae0 100644
--- a/src/devices/cpu/alto2/alto2cpu.h
+++ b/src/devices/cpu/alto2/alto2cpu.h
@@ -195,6 +195,9 @@ public:
//! update the screen bitmap
UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ //! set the vblank bit for the display to synch upon
+ void screen_vblank();
+
DECLARE_ADDRESS_MAP( ucode_map, 32 );
DECLARE_ADDRESS_MAP( const_map, 16 );
DECLARE_ADDRESS_MAP( iomem_map, 16 );
@@ -584,10 +587,10 @@ private:
UINT8 m_bank_reg[ALTO2_TASKS]; //!< normal and extended RAM banks per task
bool m_ether_enable; //!< set to true, if the ethernet should be simulated
bool m_ewfct; //!< set by Ether task when it want's a wakeup at switch to task_mrt
- int m_dsp_time; //!< display_state_machine() time accu
- int m_unload_time; //!< unload word time accu
+ attoseconds_t m_display_time; //!< display time accu (display state machine)
+ attoseconds_t m_unload_time; //!< unload word time accu (display FIFO)
int m_unload_word; //!< unload word number
- int m_bitclk_time; //!< bitclk call time accu
+ attoseconds_t m_bitclk_time; //!< bitclk call time accu (disk shift register)
int m_bitclk_index; //!< bitclk index (bit number in sector)
static const char *task_name(int task); //!< human readable task names
diff --git a/src/mame/drivers/alto2.cpp b/src/mame/drivers/alto2.cpp
index 809303922ca..11669bceb2a 100644
--- a/src/mame/drivers/alto2.cpp
+++ b/src/mame/drivers/alto2.cpp
@@ -44,6 +44,9 @@ protected:
required_ioport m_io_row6;
required_ioport m_io_row7;
optional_ioport m_io_config;
+ static const device_timer_id TIMER_VBLANK = 0;
+ emu_timer* m_vblank_timer;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
};
/* Input Ports */
@@ -269,7 +272,7 @@ ADDRESS_MAP_START( alto2_iomem_map, AS_2, 16, alto2_state )
ADDRESS_MAP_END
static MACHINE_CONFIG_START( alto2, alto2_state )
- /* basic machine hardware */
+ // Basic machine hardware
// SYSCLK is Display Control part A51 (tagged 29.4MHz) divided by 5(?)
// 5.8MHz according to de.wikipedia.org/wiki/Xerox_Alto
MCFG_CPU_ADD("maincpu", ALTO2, XTAL_29_4912MHz/5)
@@ -277,16 +280,13 @@ static MACHINE_CONFIG_START( alto2, alto2_state )
MCFG_CPU_DATA_MAP(alto2_const_map)
MCFG_CPU_IO_MAP(alto2_iomem_map)
- /* video hardware */
+ // Video hardware
MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::white)
MCFG_SCREEN_RAW_PARAMS(XTAL_20_16MHz,
- ALTO2_DISPLAY_TOTAL_WIDTH,
- 0,
- ALTO2_DISPLAY_WIDTH,
- ALTO2_DISPLAY_TOTAL_HEIGHT,
- 16, // some scalines of vblank period before
- 16+ALTO2_DISPLAY_HEIGHT+8) // and after the usual range
- MCFG_SCREEN_REFRESH_RATE(30) // two interlaced fields at 60Hz
+ A2_DISP_TOTAL_WIDTH, 0, A2_DISP_WIDTH,
+ A2_DISP_TOTAL_HEIGHT, 0, A2_DISP_HEIGHT)
+ // Two interlaced fields at 60Hz => 30Hz frame rate
+ MCFG_SCREEN_REFRESH_RATE(30)
MCFG_SCREEN_UPDATE_DEVICE("maincpu", alto2_cpu_device, screen_update)
MCFG_SCREEN_PALETTE("palette")
@@ -294,7 +294,7 @@ static MACHINE_CONFIG_START( alto2, alto2_state )
MCFG_PALETTE_ADD_MONOCHROME("palette")
- /* sound hardware */
+ // Sound hardware
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
@@ -306,11 +306,24 @@ MACHINE_CONFIG_END
DRIVER_INIT_MEMBER( alto2_state, alto2 )
{
- // make the diablo drives known to the CPU core
+ // Make the diablo drives known to the CPU core
alto2_cpu_device* cpu = downcast<alto2_cpu_device *>(m_maincpu.target());
cpu->set_diablo(0, downcast<diablo_hd_device *>(machine().device(DIABLO_HD_0)));
cpu->set_diablo(1, downcast<diablo_hd_device *>(machine().device(DIABLO_HD_1)));
cpu->set_speaker(m_speaker);
+ // Create a timer which fires twice per frame, once for each field
+ m_vblank_timer = timer_alloc(TIMER_VBLANK);
+ m_vblank_timer->adjust(attotime::from_hz(30),0,attotime::from_hz(30*2));
+}
+
+void alto2_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ alto2_cpu_device* cpu = downcast<alto2_cpu_device *>(m_maincpu.target());
+ switch (id) {
+ case TIMER_VBLANK:
+ cpu->screen_vblank();
+ break;
+ }
}
/* Game Drivers */