/** * @brief load the display data register */ void alto2_cpu_device::f2_late_dwt_load_ddr() { LOG((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; UINT8 a38 = m_disp_a38[m_dsp.ra * 16 + m_dsp.wa]; if (FIFO_STOPWAKE(a38)) m_task_wakeup &= ~(1 << task_dwt); LOG((LOG_DWT,2, " DWT push %04x into FIFO[%02o]%s\n", m_bus, (m_dsp.wa - 1) & (ALTO2_DISPLAY_FIFO - 1), FIFO_STOPWAKE(a38) ? " STOPWAKE" : "")); }
/** * @brief function called by the CPU to enter the next display state * * There are 32 states per scanline and 875 scanlines per frame. */ void alto2_cpu_device::display_state_machine() { LOG((this,LOG_DISPL,5,"DSP%03o:", m_dsp.state)); if (020 == m_dsp.state) { LOG((this,LOG_DISPL,2," HLC=%d", m_dsp.hlc)); } const uint8_t a63 = m_disp_a63[m_dsp.state]; if (A63_HLCGATE(a63)) { // count horizontal line counters and wrap m_dsp.hlc += 1; 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.scanline = 1; } // wake up the memory refresh task _twice_ on each scanline m_task_wakeup |= 1 << task_mrt; } // PROM a66 is disabled, if any of HLC256 or HLC512 are high const uint8_t a66 = (HLC256 | HLC512) ? 017 : m_disp_a66[m_dsp.hlc & 0377]; // next address from PROM a63, use A4 from HLC1 const uint8_t next = ((HLC1 ^ 1) << 4) | A63_NEXT(a63); 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)) { LOG((this,LOG_DISPL,1, " VSYNC/ (wake DVT)")); /* * The display vertical task DVT is woken once per field * at the beginning of vertical retrace. */ m_task_wakeup |= 1 << task_dvt; } m_dsp.inverse = 0xffff; } else { // Falling edge of VBLANK? if (A66_VBLANK(m_dsp.a66)) { /* * VBLANKPULSE: * The display horizontal task DHT is woken once at the * beginning of each field, and thereafter whenever the * display word task blocks. * * The DHT can block itself, in which case neither it nor * the word task can be woken until the start of the * next field. */ LOG((this,LOG_DISPL,1, " VBLANKPULSE (wake DHT)")); m_dsp.dht_blocks = false; m_dsp.dwt_blocks = false; m_task_wakeup |= 1 << task_dht; /* * VBLANKPULSE also resets the cursor task block flip flop, * which is built from two NAND gates a40c and a40d (74H01). */ m_dsp.curt_blocks = false; } if (!A63_HBLANK(a63) && A63_HBLANK(m_dsp.a63)) { m_dsp.scanline += 2; // Falling edge of a63 HBLANK starts unloading of FIFO words LOG((this,LOG_DISPL,1, " HBLANK\\ UNLOAD")); m_unload_time = A2_DISP_BITTIME(m_dsp.halfclock ? 40+32 : 40+16); m_unload_word = 0; } } /* * The wakeup request for the display word task (DWT) is controlled by * the state of the 16 word FIFO. If DWT has not executed a BLOCK, * if DHT is not blocked, and if the buffer is not full, DWT wakeups * are generated. */ uint8_t a38 = m_disp_a38[m_dsp.ra * 16 + m_dsp.wa]; if (!m_dsp.dwt_blocks && !m_dsp.dht_blocks && !FIFO_STOPWAKE(a38)) { m_task_wakeup |= 1 << task_dwt; LOG((this,LOG_DISPL,1, " (wake DWT)")); } // Stop waking up the DWT when SCANEND is active if (A63_SCANEND(a63)) { m_task_wakeup &= ~(1 << task_dwt); LOG((this,LOG_DISPL,1, " SCANEND")); } LOG((this,LOG_DISPL,1, "%s", A63_HBLANK(a63) ? " HBLANK": "")); if (A63_HSYNC(a63)) { // Active HSYNC if (!A63_HSYNC(m_dsp.a63)) { // Rising edge of HSYNC => CLRBUF LOG((this,LOG_DISPL,1, " HSYNC/ (CLRBUF)")); /* * The hardware sets the buffer empty and clears the DWT block * flip-flop at the beginning of horizontal retrace for * every scanline. */ m_dsp.wa = 0; m_dsp.ra = 0; m_dsp.dwt_blocks = false; // now take the new values from the last SETMODE<- m_dsp.inverse = GET_SETMODE_INVERSE(m_dsp.setmode) ? 0xffff : 0x0000; m_dsp.halfclock = GET_SETMODE_SPEEDY(m_dsp.setmode) ? true : false; // stop the CPU execution loop from calling unload_word() m_unload_time = -1; } else { LOG((this,LOG_DISPL,1, " HSYNC")); } } else // Falling edge of HSYNC? if (A63_HSYNC(m_dsp.a63)) { /* * CLRBUF' also resets the 2nd cursor task block flip flop, * which is built from two NAND gates a30c and a30d (74H00). * If both flip flops are reset, the NOR gate a20d (74S02) * decodes this as WAKECURT signal. */ m_dsp.curt_wakeup = true; if (!m_dsp.curt_blocks) m_task_wakeup |= 1 << task_curt; } LOG((this,LOG_DISPL,1, " NEXT:%03o\n", next)); m_dsp.a63 = a63; m_dsp.a66 = a66; m_dsp.state = next; m_display_time += A2_DISP_BITTIME(32); }