示例#1
0
/* Redraw the current raster line.  This happens at cycle TED_DRAW_CYCLE
   of each line.  */
void ted_raster_draw_alarm_handler(CLOCK offset, void *data)
{
    int in_visible_area;

    in_visible_area = (ted.tv_current_line
                       >= (unsigned int)ted.first_displayed_line
                       && ted.tv_current_line
                       <= (unsigned int)ted.last_displayed_line);

    if (ted.tv_current_line < ted.screen_height) {
        raster_line_emulate(&ted.raster);
    } else {
        log_debug("Skip line %d %d", ted.tv_current_line, ted.screen_height);
    }

    if (ted.ted_raster_counter == ted.last_dma_line) {
        ted.idle_state = 1;
    }

    ted.tv_current_line++;
    ted.ted_raster_counter++;
    if (ted.ted_raster_counter == ted.screen_height) {
        ted.memptr = 0;
        ted.memptr_col = 0;
        ted.mem_counter = 0;
        ted.chr_pos_count = 0;
        ted.ted_raster_counter = 0;
        if (!ted.raster.blank) {
            ted.character_fetch_on = 1;
        }
        ted.raster.ycounter = 0;
    }
    if (ted.ted_raster_counter == 512) {
        ted.ted_raster_counter = 0;
    }

    if (ted.ted_raster_counter == 0xcc) {
        ted.character_fetch_on = 0;
    }

    if (ted.regs[0x06] & 8) {
        if (ted.ted_raster_counter == ted.row_25_start_line && (!ted.raster.blank
                                                                || ted.raster.blank_off)) {
            ted.raster.blank_enabled = 0;
        }
        if (ted.ted_raster_counter == ted.row_25_stop_line + 1) {
            ted.raster.blank_enabled = 1;
        }
    } else {
        if (ted.ted_raster_counter == ted.row_24_start_line && (!ted.raster.blank
                                                                || ted.raster.blank_off)) {
            ted.raster.blank_enabled = 0;
        }
        if (ted.ted_raster_counter == ted.row_24_stop_line + 1) {
            ted.raster.blank_enabled = 1;
        }
    }

    /* DO VSYNC if the raster_counter in the TED reached the VSYNC signal */
    /* Also do VSYNC if oversized screen reached a certain threashold, this will result in rolling screen just like on the real thing */
    if (((signed int)(ted.tv_current_line - ted.screen_height) > 40) || (ted.ted_raster_counter == ted.vsync_line )) {
        if (ted.tv_current_line < ted.screen_height) {
            ted.raster.current_line = 0;
            raster_canvas_handle_end_of_frame(&ted.raster);
        }

        /*log_debug("Vsync %d %d",ted.tv_current_line, ted.ted_raster_counter);*/

        raster_skip_frame(&ted.raster,
                          vsync_do_vsync(ted.raster.canvas,
                                         ted.raster.skip_frame));
        ted.tv_current_line = 0;

        /* FIXME increment at appropriate cycle */
        ted.cursor_phase = (ted.cursor_phase + 1) & 0x1f;
        ted.cursor_visible = ted.cursor_phase & 0x10;

#ifdef __MSDOS__
        if (ted.raster.canvas->draw_buffer->canvas_width
            <= TED_SCREEN_XPIX
            && ted.raster.canvas->draw_buffer->canvas_height
            <= TED_SCREEN_YPIX) {
            canvas_set_border_color(ted.raster.canvas,
                                    ted.raster.border_color);
        }
#endif
    }

    if (in_visible_area) {
/*        log_debug("Idle state %03x, %03x, %d",ted.ted_raster_counter, ted.idle_state, ted.raster.ycounter);*/
        if (!ted.idle_state) {
            ted.mem_counter = (ted.mem_counter + ted.mem_counter_inc) & 0x3ff;
            ted.chr_pos_count = (ted.chr_pos_count + ted.mem_counter_inc) & 0x3ff;
        }

        ted.mem_counter_inc = TED_SCREEN_TEXTCOLS;
        /* `ycounter' makes the chip go to idle state when it reaches the
           maximum value.  */
        if (ted.raster.ycounter == 6) {
            ted.memptr_col = ted.mem_counter;
        }
        if (ted.raster.ycounter == 7) {
            ted.memptr = ted.chr_pos_count;
/*            ted.idle_state = 1;*/
        }
        if (!ted.idle_state && ted.allow_bad_lines /*|| ted.bad_line*/) {
            ted.raster.ycounter = (ted.raster.ycounter + 1) & 0x7;
            ted.idle_state = 0;
        }
        if (ted.force_display_state) {
            ted.idle_state = 0;
            ted.force_display_state = 0;
        }
        ted.raster.draw_idle_state = ted.idle_state;
        /*ted.bad_line = 0;*/
    }

    ted.ycounter_reset_checked = 0;
    ted.memory_fetch_done = 0;

    if (ted.ted_raster_counter == ted.first_dma_line) {
        ted.allow_bad_lines = !ted.raster.blank;
    }
    if (ted.allow_bad_lines
        && (ted.ted_raster_counter & 7) == (unsigned int)((ted.raster.ysmooth + 1) & 7)) {
        memcpy(ted.cbuf, ted.cbuf_tmp, ted.mem_counter_inc);
    }
    /* FIXME */
    if (ted.idle_state) {
        if (ted.regs[0x6] & 0x40) {
            ted.idle_data_location = IDLE_39FF;
            ted.idle_data = mem_ram[0xffff];
        } else {
            ted.idle_data_location = IDLE_3FFF;
            ted.idle_data = mem_ram[0xffff];
        }
    } else {
        ted.idle_data_location = IDLE_NONE;
    }

    /* Set the next draw event.  */
    ted.last_emulate_line_clk += ted.cycles_per_line;
    ted.draw_clk = ted.last_emulate_line_clk + ted.draw_cycle;
    alarm_set(ted.raster_draw_alarm, ted.draw_clk);
}
示例#2
0
void raster_line_emulate(raster_t *raster)
{
    raster_draw_buffer_ptr_update(raster);

    /* Emulate the vertical blank flip-flops.  (Well, sort of.)  */
    if (raster->current_line == raster->display_ystart && (!raster->blank
        || raster->blank_off))
        raster->blank_enabled = 0;
    if (raster->current_line == raster->display_ystop)
        raster->blank_enabled = 1;

    if ((raster->current_line >= raster->geometry->first_displayed_line
        && raster->current_line <= raster->geometry->last_displayed_line)
        /* handle the case when lines 0+ are displayed in the lower border */
       || (raster->current_line <= raster->geometry->last_displayed_line - raster->geometry->screen_size.height
        && raster->geometry->screen_size.height <= raster->geometry->last_displayed_line)
       )
   {
        /* handle lines with no border or with changes that may affect
           the border as visible lines */
        if (raster->can_disable_border && (raster->border_disable || raster->changes->have_on_this_line)) { 
            handle_visible_line(raster);
        } else {
            if ((raster->blank_this_line || raster->blank_enabled)
                && !raster->open_left_border)
                handle_blank_line(raster);
            else
                handle_visible_line(raster);
        }

        if (++raster->num_cached_lines == (1
            + raster->geometry->last_displayed_line
            - raster->geometry->first_displayed_line)) {
            raster->dont_cache = 0;
            raster->num_cached_lines = 0;
        }

#if 0
        /* this is a fix for the pal emulation bug at the left/right edges */
        /* hacked, but other solutions would cause changes in many places in
           the code */
        memset(raster->draw_buffer_ptr - 4,
               *raster->draw_buffer_ptr, 4);
        memset(raster->draw_buffer_ptr + raster->geometry->screen_size.width,
               *raster->draw_buffer_ptr, 4);
#endif
    } else {
        update_sprite_collisions(raster);

        if (raster->changes->have_on_this_line) {
            raster_changes_apply_all(raster->changes->background);
            raster_changes_apply_all(raster->changes->foreground);
            raster_changes_apply_all(raster->changes->border);
            raster_changes_apply_all(raster->changes->sprites);
            raster->changes->have_on_this_line = 0;
        }
    }

    raster->current_line++;

    if (raster->current_line == raster->geometry->screen_size.height) {
        raster->current_line = 0;
        /* not end of frame on NTSC VIC-II where lines 0+ are */
        /* displayed in the lower border */
        if (raster->geometry->screen_size.height > raster->geometry->last_displayed_line) {
           raster_canvas_handle_end_of_frame(raster);
       }
    }

    /* end of frame on NTSC VIC-II */
    if (raster->geometry->screen_size.height <= raster->geometry->last_displayed_line
        && raster->current_line == raster->geometry->last_displayed_line - raster->geometry->screen_size.height + 1) {
        raster_canvas_handle_end_of_frame(raster);
   }

    raster_changes_apply_all(raster->changes->next_line);

    /* Handle open borders.  */
    raster->open_left_border = raster->open_right_border;
    raster->open_right_border = 0;

    if (raster->sprite_status != NULL)
        raster->sprite_status->dma_msk = raster->sprite_status->new_dma_msk;

    raster->blank_this_line = 0;
}
示例#3
0
文件: crtc.c 项目: SMTDDR/droidsound
/* Redraw the current raster line.  This happens at the last
   cycle of each line.  */
static void crtc_raster_draw_alarm_handler(CLOCK offset, void *data)
{
    int new_sync_diff;
    int new_venable;
    int new_vsync;
    int screen_width = (int)crtc.screen_width;

    new_venable = crtc.venable;
    new_vsync = crtc.vsync;

    /******************************************************************
     * handle one rasterline
     */

    /* first the time between two sync pulses */
    new_sync_diff = (crtc.prev_rl_len + 1 - crtc.prev_rl_sync)
                    + crtc.rl_sync;

    /* compute the horizontal position */
    /* the original PET displays have quite a variety of sync timings
       (or I haven't found the scheme yet). Therefore we cannot simply
       center the part between the syncs. We assume the sync in the
       first rasterline of the screen to be the default for the next
       frame. */

    /* FIXME: crtc.regs[3] & 15 == 0 -> 16 */
    if (crtc.raster.current_line == 0) {
        crtc.screen_xoffset = ((screen_width
                              - (crtc.sync_diff * 8 * crtc.hw_cols)) / 2)
                              + ((crtc.prev_rl_len + 1 - crtc.prev_rl_sync
                              - ((crtc.regs[3] & 0x0f) / 2))
                              * 8 * crtc.hw_cols);
   
        /* FIXME: The 320 is the pixel width of a window with 40 cols.
           make that a define - or measure the visible line length?
           but how to do that reliably? */
        crtc.xoffset = CRTC_SCREEN_BORDERWIDTH + (CRTC_EXTRA_COLS * 4)
                       /* ((screen_width - crtc.rl_visible * 8 * crtc.hw_cols)
                       / 2) */
                       - crtc.screen_xoffset
                       + ((screen_width
                       - (crtc.sync_diff * 8 * crtc.hw_cols)) / 2)
                       + ((crtc.prev_rl_len + 1 - crtc.prev_rl_sync
                       - ((crtc.regs[3] & 0x0f) / 2)) * 8 * crtc.hw_cols);
    }

    /* emulate the line */
    if (crtc.raster.current_line >=
                crtc.screen_height - 2 * CRTC_SCREEN_BORDERHEIGHT) {
        /* FIXFRAME: crtc.raster.current_line ++; */
    } else {
        raster_line_emulate(&crtc.raster);
    }

    /* now add jitter if this is out of phase (sync_diff changes) */
    crtc.hjitter -= (new_sync_diff - crtc.sync_diff) * 4 * crtc.hw_cols;
    if (crtc.hjitter > 16)
        crtc.hjitter = 16;
    if (crtc.hjitter < -16)
        crtc.hjitter = -16;
    /* exponential/sine decay */
    crtc.hjitter = (int)((double)(crtc.hjitter) * -0.5);
/*
    if (crtc.hjitter) {
        printf("rl=%d, jitter=%d, sync_diff=%d, old diff=%d, \n",
               crtc.raster.current_line, crtc.hjitter,
               new_sync_diff, crtc.sync_diff);
    }
*/
    crtc.sync_diff = new_sync_diff;

/*
    if (crtc.raster.current_line == 10) {
        printf("centering=%d, sync2start=%d -> xoff=%d, jitter=%d\n",
                ((screen_width - (sync_diff * crtc.hw_cols * 8)) / 2),
                (crtc.prev_rl_len + 1 - crtc.prev_rl_sync
                - ((crtc.regs[3] & 0x0f) / 2)),
                ((screen_width - (sync_diff * crtc.hw_cols * 8)) / 2)
                + ((crtc.prev_rl_len + 1 - crtc.prev_rl_sync
                - ((crtc.regs[3] & 0x0f) / 2)) * crtc.hw_cols * 8),
                crtc.hjitter);
    }
*/

    crtc.prev_rl_visible = crtc.rl_visible;
    crtc.prev_rl_sync = crtc.rl_sync;
    crtc.prev_rl_len = crtc.rl_len;
    crtc.prev_screen_rel = crtc.screen_rel;

    crtc.rl_visible = crtc.regs[1];
    crtc.rl_sync = crtc.regs[2];
    crtc.rl_len = crtc.regs[0];

    crtc.rl_start = maincpu_clk - offset;

    /******************************************************************
     * handle the rasterline numbering
     */

    crtc.current_line ++;
    /* FIXFRAME; crtc.framelines --;

    if (crtc.framelines == crtc.screen_yoffset) {
*/
    if ((crtc.framelines - crtc.current_line) == crtc.screen_yoffset) {
        crtc.raster.current_line = 0;
        raster_canvas_handle_end_of_frame(&crtc.raster);
        raster_skip_frame(&crtc.raster,
                          vsync_do_vsync(crtc.raster.canvas,
                          crtc.raster.skip_frame));
    }

    {
        /* FIXME: charheight */
        if (crtc.current_charline >= crtc.regs[4] + 1) {
            if ((crtc.raster.ycounter + 1) >= crtc.regs[5]) {
                long cycles;

                /* Do vsync stuff.  */
                /* printf("new screen at clk=%d\n",crtc.rl_start); */
                crtc_reset_screen_ptr();
                crtc.raster.ycounter = 0;
                crtc.current_charline = 0;
                new_venable = 1;

                /* expected number of rasterlines for next frame */
                crtc.framelines = crtc.current_line;
                crtc.current_line = 0;

                /* hardware cursor handling */
                if (crtc.crsrmode & 2) {
                    crtc.crsrcnt --;
                    if (!crtc.crsrcnt) {
                        crtc.crsrcnt = (crtc.crsrmode & 1) ? 16 : 32;
                        crtc.crsrstate ^= 1;
                    }
                }

                /* cycles per frame, for speed adjustments */
                cycles = crtc.rl_start - crtc.frame_start;
                if (crtc.frame_start && (cycles != crtc.cycles_per_frame)) {
                    machine_set_cycles_per_frame(cycles);
                    crtc.cycles_per_frame = cycles;
                }
                crtc.frame_start = crtc.rl_start;

            } else {
                crtc.raster.ycounter ++;
            }
        } else {
            if (crtc.raster.ycounter != crtc.regs[9] ) {
                crtc.raster.ycounter ++;
                crtc.raster.ycounter &= 0x1f;
            } else {
                crtc.raster.ycounter = 0;
                crtc.current_charline ++;
                crtc.current_charline &= 0x7f;

                if (crtc.henable) {
                    crtc.screen_rel += crtc.rl_visible * crtc.hw_cols;
                }
                if (crtc.current_charline == crtc.regs[6]) {
                    new_venable = 0;
                }
                if ((crtc.current_charline == crtc.regs[7])) {
                    /* printf("hsync starts at clk=%d\n",crtc.rl_start); */
                    new_vsync = (crtc.regs[3] >> 4) & 0x0f;
                    if (!new_vsync)
                        new_vsync = 16;
                    new_vsync ++; /* compensate for the first decrease below */
                }
            }
            if (crtc.raster.ycounter == (unsigned int)(crtc.regs[10] & 0x1f)) {
                crtc.cursor_lines = 1;
            } else
            if (crtc.raster.ycounter
                == (unsigned int)((crtc.regs[11] + 1) & 0x1f)) {
                crtc.cursor_lines = 0;
            }

            crtc.henable = 1;
        }
        if (new_vsync) {
            new_vsync --;
        }
    }