Annotation of uae/src/drawing.c, revision 1.1.1.11

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * Screen drawing functions
                      5:   *
1.1.1.8   root        6:   * Copyright 1995-2000 Bernd Schmidt
1.1       root        7:   * Copyright 1995 Alessandro Bissacco
                      8:   */
                      9: 
1.1.1.8   root       10: /* There are a couple of concepts of "coordinates" in this file.
                     11:    - DIW coordinates
                     12:    - DDF coordinates (essentially cycles, resolution lower than lores by a factor of 2)
                     13:    - Pixel coordinates
                     14:      * in the Amiga's resolution as determined by BPLCON0 ("Amiga coordinates")
                     15:      * in the window resolution as determined by the preferences ("window coordinates").
                     16:      * in the window resolution, and with the origin being the topmost left corner of
                     17:        the window ("native coordinates")
                     18:    One note about window coordinates.  The visible area depends on the width of the
                     19:    window, and the centering code.  The first visible horizontal window coordinate is
                     20:    often _not_ 0, but the value of VISIBLE_LEFT_BORDER instead.
                     21: 
                     22:    One important thing to remember: DIW coordinates are in the lowest possible
                     23:    resolution.
                     24: 
                     25:    To prevent extremely bad things (think pixels cut in half by window borders) from
                     26:    happening, all ports should restrict window widths to be multiples of 16 pixels.  */
                     27: 
1.1       root       28: #include "sysconfig.h"
                     29: #include "sysdeps.h"
                     30: 
                     31: #include <ctype.h>
                     32: #include <assert.h>
                     33: 
                     34: #include "config.h"
                     35: #include "options.h"
                     36: #include "threaddep/penguin.h"
                     37: #include "uae.h"
                     38: #include "memory.h"
                     39: #include "custom.h"
                     40: #include "newcpu.h"
                     41: #include "xwin.h"
                     42: #include "autoconf.h"
                     43: #include "gui.h"
                     44: #include "picasso96.h"
                     45: #include "drawing.h"
                     46: 
1.1.1.9   root       47: int lores_factor, lores_shift, sprite_width, borderblank;
                     48: int fetchmode, fetchstart, fetchstart_shift, prefetch, fetchsize;
1.1       root       49: 
1.1.1.8   root       50: /* The shift factor to apply when converting between Amiga coordinates and window
                     51:    coordinates.  Zero if the resolution is the same, positive if window coordinates
                     52:    have a higher resolution (i.e. we're stretching the image), negative if window
                     53:    coordinates have a lower resolution (i.e. we're shrinking the image).  */
                     54: static int res_shift;
                     55: 
1.1       root       56: static int interlace_seen = 0;
                     57: 
1.1.1.11! root       58: /* Lookup tables for dual playfields.  The dblpf_*1 versions are for the case
        !            59:    that playfield 1 has the priority, dbplpf_*2 are used if playfield 2 has
        !            60:    priority.  If we need an array for non-dual playfield mode, it has no number.  */
        !            61: /* The dbplpf_ms? arrays contain a shift value.  plf_spritemask is initialized
        !            62:    to contain two 16 bit words, with the appropriate mask if pf1 is in the
        !            63:    foreground being at bit offset 0, the one used if pf2 is in front being at
        !            64:    offset 16.  */
        !            65: static int dblpf_ms1[256], dblpf_ms2[256], dblpf_ms[256];
        !            66: static int dblpf_ind1[256], dblpf_ind2[256];
        !            67: static int dblpf_aga1[256], dblpf_aga2[256];
1.1       root       68: 
                     69: static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
                     70: 
1.1.1.11! root       71: static int sprite_offs[256];
        !            72: 
1.1       root       73: static uae_u32 clxtab[256];
                     74: 
                     75: /* Video buffer description structure. Filled in by the graphics system
                     76:  * dependent code. */
                     77: 
                     78: struct vidbuf_description gfxvidinfo;
                     79: 
1.1.1.9   root       80: /* OCS/ECS color lookup table. */
1.1       root       81: xcolnr xcolors[4096];
1.1.1.9   root       82: /* AGA mode color lookup tables */
                     83: unsigned int xredcolors[256], xgreencolors[256], xbluecolors[256];
1.1       root       84: 
                     85: struct color_entry colors_for_drawing;
                     86: 
1.1.1.8   root       87: /* The size of these arrays is pretty arbitrary; it was chosen to be "more
                     88:    than enough".  The coordinates used for indexing into these arrays are
                     89:    almost, but not quite, Amiga coordinates (there's a constant offset).  */
1.1       root       90: union {
                     91:     /* Let's try to align this thing. */
                     92:     double uupzuq;
                     93:     long int cruxmedo;
1.1.1.8   root       94:     uae_u8 apixels[1760];
                     95:     uae_u16 apixels_w[880];
                     96:     uae_u32 apixels_l[440];
1.1       root       97: } pixdata;
                     98: 
1.1.1.11! root       99: uae_u16 spixels[2 * MAX_SPR_PIXELS];
        !           100: /* Eight bits for every pixel.  */
        !           101: union sps_union spixstate;
        !           102: 
1.1.1.8   root      103: uae_u32 ham_linebuf[1760];
1.1       root      104: 
                    105: char *xlinebuffer;
                    106: 
                    107: static int *amiga2aspect_line_map, *native2amiga_line_map;
                    108: static char *row_map[2049];
                    109: static int max_drawn_amiga_line;
                    110: 
1.1.1.9   root      111: /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham */
1.1       root      112: typedef void (*line_draw_func)(int, int);
                    113: 
                    114: #define LINE_UNDECIDED 1
                    115: #define LINE_DECIDED 2
                    116: #define LINE_DECIDED_DOUBLE 3
                    117: #define LINE_AS_PREVIOUS 4
1.1.1.2   root      118: #define LINE_BLACK 5
                    119: #define LINE_REMEMBERED_AS_BLACK 6
1.1       root      120: #define LINE_DONE 7
                    121: #define LINE_DONE_AS_PREVIOUS 8
                    122: #define LINE_REMEMBERED_AS_PREVIOUS 9
                    123: 
                    124: static char *line_drawn;
1.1.1.5   root      125: static char linestate[(MAXVPOS + 1)*2 + 1];
1.1       root      126: 
1.1.1.5   root      127: uae_u8 line_data[(MAXVPOS + 1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
1.1       root      128: 
1.1.1.8   root      129: /* Centering variables.  */
                    130: static int min_diwstart, max_diwstop, prev_x_adjust;
                    131: /* The visible window: VISIBLE_LEFT_BORDER contains the left border of the visible
                    132:    area, VISIBLE_RIGHT_BORDER the right border.  These are in window coordinates.  */
                    133: static int visible_left_border, visible_right_border;
1.1       root      134: static int linetoscr_x_adjust_bytes;
                    135: static int thisframe_y_adjust, prev_y_adjust;
                    136: static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen;
                    137: static int extra_y_adjust;
                    138: int thisframe_first_drawn_line, thisframe_last_drawn_line;
                    139: 
1.1.1.8   root      140: /* A frame counter that forces a redraw after at least one skipped frame in
                    141:    interlace mode.  */
1.1       root      142: static int last_redraw_point;
                    143: 
                    144: static int first_drawn_line, last_drawn_line;
                    145: static int first_block_line, last_block_line;
                    146: 
                    147: /* These are generated by the drawing code from the line_decisions array for
1.1.1.8   root      148:    each line that needs to be drawn.  These are basically extracted out of
                    149:    bit fields in the hardware registers.  */
1.1.1.5   root      150: static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplres;
1.1.1.11! root      151: static uae_u32 plf_sprite_mask;
1.1       root      152: 
                    153: int picasso_requested_on;
                    154: int picasso_on;
                    155: 
                    156: uae_sem_t gui_sem;
                    157: int inhibit_frame;
                    158: 
                    159: int framecnt = 0;
                    160: static int frame_redraw_necessary;
                    161: static int picasso_redraw_necessary;
                    162: 
1.1.1.6   root      163: STATIC_INLINE void count_frame (void)
1.1       root      164: {
                    165:     framecnt++;
1.1.1.5   root      166:     if (framecnt >= currprefs.gfx_framerate)
1.1       root      167:        framecnt = 0;
                    168: }
                    169: 
                    170: int coord_native_to_amiga_x (int x)
                    171: {
1.1.1.8   root      172:     x += visible_left_border;
1.1       root      173:     x <<= (1 - lores_shift);
1.1.1.11! root      174:     return x + 2*DISPLAY_LEFT_SHIFT - 2*DIW_DDF_OFFSET;
1.1       root      175: }
                    176: 
                    177: int coord_native_to_amiga_y (int y)
                    178: {
                    179:     return native2amiga_line_map[y] + thisframe_y_adjust - minfirstline;
                    180: }
                    181: 
1.1.1.8   root      182: STATIC_INLINE int res_shift_from_window (int x)
                    183: {
                    184:     if (res_shift >= 0)
                    185:        return x >> res_shift;
                    186:     return x << -res_shift;
                    187: }
                    188: 
                    189: STATIC_INLINE int res_shift_from_amiga (int x)
                    190: {
                    191:     if (res_shift >= 0)
                    192:        return x >> res_shift;
                    193:     return x << -res_shift;
                    194: }
                    195: 
1.1       root      196: void notice_screen_contents_lost (void)
                    197: {
                    198:     picasso_redraw_necessary = 1;
                    199:     frame_redraw_necessary = 2;
                    200: }
                    201: 
                    202: static struct decision *dp_for_drawing;
                    203: static struct draw_info *dip_for_drawing;
                    204: 
1.1.1.8   root      205: /* Record DIW of the current line for use by centering code.  */
1.1       root      206: void record_diw_line (int first, int last)
                    207: {
                    208:     if (last > max_diwstop)
                    209:        max_diwstop = last;
                    210:     if (first < min_diwstart)
                    211:        min_diwstart = first;
                    212: }
                    213: 
                    214: /*
                    215:  * Screen update macros/functions
                    216:  */
                    217: 
1.1.1.8   root      218: /* The important positions in the line: where do we start drawing the left border,
                    219:    where do we start drawing the playfield, where do we start drawing the right border.
                    220:    All of these are forced into the visible window (VISIBLE_LEFT_BORDER .. VISIBLE_RIGHT_BORDER).
                    221:    PLAYFIELD_START and PLAYFIELD_END are in window coordinates.  */
                    222: static int playfield_start, playfield_end;
                    223: 
                    224: static int pixels_offset;
                    225: static int src_pixel;
                    226: /* How many pixels in window coordinates which are to the left of the left border.  */
                    227: static int unpainted;
1.1       root      228: 
1.1.1.8   root      229: /* Initialize the variables necessary for drawing a line.
                    230:  * This involves setting up start/stop positions and display window
                    231:  * borders.  */
                    232: static void pfield_init_linetoscr (void)
1.1       root      233: {
1.1.1.8   root      234:     /* First, get data fetch start/stop in DIW coordinates.  */
1.1.1.11! root      235:     int ddf_left = dp_for_drawing->plfleft * 2 + DIW_DDF_OFFSET;
        !           236:     int ddf_right = dp_for_drawing->plfright * 2 + DIW_DDF_OFFSET;
1.1.1.8   root      237:     /* Compute datafetch start/stop in pixels; native display coordinates.  */
1.1.1.11! root      238:     int native_ddf_left = coord_hw_to_window_x (ddf_left);
        !           239:     int native_ddf_right = coord_hw_to_window_x (ddf_right);
1.1.1.8   root      240: 
                    241:     int linetoscr_diw_start = dp_for_drawing->diwfirstword;
                    242:     int linetoscr_diw_end = dp_for_drawing->diwlastword;
                    243: 
                    244:     if (dip_for_drawing->nr_sprites == 0) {
                    245:        if (linetoscr_diw_start < native_ddf_left)
                    246:            linetoscr_diw_start = native_ddf_left;
                    247:        if (linetoscr_diw_end > native_ddf_right)
                    248:            linetoscr_diw_end = native_ddf_right;
1.1       root      249:     }
                    250: 
1.1.1.8   root      251:     /* Perverse cases happen. */
                    252:     if (linetoscr_diw_end < linetoscr_diw_start)
                    253:        linetoscr_diw_end = linetoscr_diw_start;
1.1       root      254: 
1.1.1.8   root      255:     playfield_start = linetoscr_diw_start;
                    256:     playfield_end = linetoscr_diw_end;
1.1       root      257: 
1.1.1.8   root      258:     if (playfield_start < visible_left_border)
                    259:        playfield_start = visible_left_border;
                    260:     if (playfield_start > visible_right_border)
                    261:        playfield_start = visible_right_border;
                    262:     if (playfield_end < visible_left_border)
                    263:        playfield_end = visible_left_border;
                    264:     if (playfield_end > visible_right_border)
                    265:        playfield_end = visible_right_border;
                    266: 
                    267:     /* Now, compute some offsets.  */
                    268: 
                    269:     res_shift = lores_shift - bplres;
1.1.1.11! root      270:     ddf_left -= DISPLAY_LEFT_SHIFT;
        !           271:     ddf_left <<= bplres;
1.1.1.8   root      272:     pixels_offset = 880 - ddf_left;
1.1.1.11! root      273: 
1.1.1.8   root      274:     unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start;
                    275:     src_pixel = 880 + res_shift_from_window (playfield_start - native_ddf_left + unpainted);
1.1       root      276: 
1.1.1.8   root      277:     if (dip_for_drawing->nr_sprites == 0)
1.1       root      278:        return;
1.1.1.8   root      279:     /* Must clear parts of apixels.  */
                    280:     if (linetoscr_diw_start < native_ddf_left) {
                    281:        int size = res_shift_from_window (native_ddf_left - linetoscr_diw_start);
                    282:        linetoscr_diw_start = native_ddf_left;
                    283:        memset (pixdata.apixels + 880 - size, 0, size);
                    284:     }
                    285:     if (linetoscr_diw_end > native_ddf_right) {
                    286:        int pos = res_shift_from_window (native_ddf_right - native_ddf_left);
                    287:        int size = res_shift_from_window (linetoscr_diw_end - native_ddf_right);
                    288:        linetoscr_diw_start = native_ddf_left;
                    289:        memset (pixdata.apixels + 880 + pos, 0, size);
1.1       root      290:     }
                    291: }
1.1.1.2   root      292: 
1.1.1.8   root      293: /* If C++ compilers didn't suck, we'd use templates.  */
                    294: 
                    295: #define TYPE uae_u8
                    296: #define LNAME linetoscr_8
                    297: #define SRC_INC 1
                    298: #define HDOUBLE 0
1.1.1.9   root      299: #define AGA 0
1.1.1.8   root      300: #include "linetoscr.c"
1.1.1.9   root      301: #define LNAME linetoscr_8_stretch1
1.1.1.8   root      302: #define SRC_INC 1
                    303: #define HDOUBLE 1
1.1.1.9   root      304: #define AGA 0
1.1.1.8   root      305: #include "linetoscr.c"
1.1.1.9   root      306: #define LNAME linetoscr_8_shrink1
1.1.1.8   root      307: #define SRC_INC 2
                    308: #define HDOUBLE 0
1.1.1.9   root      309: #define AGA 0
                    310: #include "linetoscr.c"
                    311: 
                    312: #define LNAME linetoscr_8_aga
                    313: #define SRC_INC 1
                    314: #define HDOUBLE 0
                    315: #define AGA 1
                    316: #include "linetoscr.c"
                    317: #define LNAME linetoscr_8_stretch1_aga
                    318: #define SRC_INC 1
                    319: #define HDOUBLE 1
                    320: #define AGA 1
                    321: #include "linetoscr.c"
                    322: #define LNAME linetoscr_8_shrink1_aga
                    323: #define SRC_INC 2
                    324: #define HDOUBLE 0
                    325: #define AGA 1
1.1.1.8   root      326: #include "linetoscr.c"
                    327: 
                    328: #undef TYPE
1.1.1.9   root      329: 
1.1.1.8   root      330: #define TYPE uae_u16
                    331: #define LNAME linetoscr_16
                    332: #define SRC_INC 1
                    333: #define HDOUBLE 0
1.1.1.9   root      334: #define AGA 0
1.1.1.8   root      335: #include "linetoscr.c"
1.1.1.9   root      336: #define LNAME linetoscr_16_stretch1
1.1.1.8   root      337: #define SRC_INC 1
                    338: #define HDOUBLE 1
1.1.1.9   root      339: #define AGA 0
1.1.1.8   root      340: #include "linetoscr.c"
1.1.1.9   root      341: #define LNAME linetoscr_16_shrink1
1.1.1.8   root      342: #define SRC_INC 2
                    343: #define HDOUBLE 0
1.1.1.9   root      344: #define AGA 0
                    345: #include "linetoscr.c"
                    346: 
                    347: #define LNAME linetoscr_16_aga
                    348: #define SRC_INC 1
                    349: #define HDOUBLE 0
                    350: #define AGA 1
                    351: #include "linetoscr.c"
                    352: #define LNAME linetoscr_16_stretch1_aga
                    353: #define SRC_INC 1
                    354: #define HDOUBLE 1
                    355: #define AGA 1
                    356: #include "linetoscr.c"
                    357: #define LNAME linetoscr_16_shrink1_aga
                    358: #define SRC_INC 2
                    359: #define HDOUBLE 0
                    360: #define AGA 1
1.1.1.8   root      361: #include "linetoscr.c"
                    362: 
                    363: #undef TYPE
1.1.1.9   root      364: 
1.1.1.8   root      365: #define TYPE uae_u32
                    366: #define LNAME linetoscr_32
                    367: #define SRC_INC 1
                    368: #define HDOUBLE 0
1.1.1.9   root      369: #define AGA 0
1.1.1.8   root      370: #include "linetoscr.c"
1.1.1.9   root      371: #define LNAME linetoscr_32_stretch1
1.1.1.8   root      372: #define SRC_INC 1
                    373: #define HDOUBLE 1
1.1.1.9   root      374: #define AGA 0
1.1.1.8   root      375: #include "linetoscr.c"
1.1.1.9   root      376: #define LNAME linetoscr_32_shrink1
1.1.1.8   root      377: #define SRC_INC 2
                    378: #define HDOUBLE 0
1.1.1.9   root      379: #define AGA 0
                    380: #include "linetoscr.c"
                    381: 
                    382: #define LNAME linetoscr_32_aga
                    383: #define SRC_INC 1
                    384: #define HDOUBLE 0
                    385: #define AGA 1
                    386: #include "linetoscr.c"
                    387: #define LNAME linetoscr_32_stretch1_aga
                    388: #define SRC_INC 1
                    389: #define HDOUBLE 1
                    390: #define AGA 1
                    391: #include "linetoscr.c"
                    392: #define LNAME linetoscr_32_shrink1_aga
                    393: #define SRC_INC 2
                    394: #define HDOUBLE 0
                    395: #define AGA 1
1.1.1.8   root      396: #include "linetoscr.c"
1.1       root      397: 
1.1.1.9   root      398: #undef TYPE
                    399: 
1.1.1.8   root      400: static void fill_line_8 (char *buf, int start, int stop)
1.1       root      401: {
1.1.1.8   root      402:     uae_u8 *b = (uae_u8 *)buf;
1.1       root      403:     int i;
1.1.1.8   root      404:     xcolnr col = colors_for_drawing.acolors[0];
                    405:     for (i = start; i < stop; i++)
                    406:        b[i] = col;
1.1       root      407: }
1.1.1.8   root      408: static void fill_line_16 (char *buf, int start, int stop)
1.1       root      409: {
1.1.1.8   root      410:     uae_u16 *b = (uae_u16 *)buf;
1.1       root      411:     int i;
1.1.1.8   root      412:     xcolnr col = colors_for_drawing.acolors[0];
                    413:     for (i = start; i < stop; i++)
                    414:        b[i] = col;
1.1       root      415: }
1.1.1.8   root      416: static void fill_line_32 (char *buf, int start, int stop)
1.1       root      417: {
1.1.1.8   root      418:     uae_u32 *b = (uae_u32 *)buf;
1.1       root      419:     int i;
1.1.1.8   root      420:     xcolnr col = colors_for_drawing.acolors[0];
                    421:     for (i = start; i < stop; i++)
                    422:        b[i] = col;
1.1.1.2   root      423: }
                    424: 
1.1.1.6   root      425: STATIC_INLINE void fill_line (void)
1.1       root      426: {
                    427:     int shift;
                    428:     int nints, nrem;
                    429:     int *start;
                    430:     xcolnr val;
                    431: 
                    432:     shift = 0;
                    433:     if (gfxvidinfo.pixbytes == 2)
                    434:        shift = 1;
                    435:     if (gfxvidinfo.pixbytes == 4)
                    436:        shift = 2;
                    437: 
                    438:     nints = gfxvidinfo.width >> (2-shift);
                    439:     nrem = nints & 7;
                    440:     nints &= ~7;
1.1.1.8   root      441:     start = (int *)(((char *)xlinebuffer) + (visible_left_border << shift));
1.1       root      442:     val = colors_for_drawing.acolors[0];
1.1.1.9   root      443:     if (gfxvidinfo.pixbytes == 2)
                    444:         val |= val << 16;
1.1       root      445:     for (; nints > 0; nints -= 8, start += 8) {
                    446:        *start = val;
                    447:        *(start+1) = val;
                    448:        *(start+2) = val;
                    449:        *(start+3) = val;
                    450:        *(start+4) = val;
                    451:        *(start+5) = val;
                    452:        *(start+6) = val;
                    453:        *(start+7) = val;
                    454:     }
                    455: 
                    456:     switch (nrem) {
                    457:      case 7:
                    458:        *start++ = val;
                    459:      case 6:
                    460:        *start++ = val;
                    461:      case 5:
                    462:        *start++ = val;
                    463:      case 4:
                    464:        *start++ = val;
                    465:      case 3:
                    466:        *start++ = val;
                    467:      case 2:
                    468:        *start++ = val;
                    469:      case 1:
                    470:        *start = val;
                    471:     }
                    472: }
                    473: 
1.1.1.8   root      474: static int linetoscr_double_offset;
1.1       root      475: 
1.1.1.8   root      476: static void pfield_do_linetoscr (int start, int stop)
                    477: {
1.1.1.9   root      478:     if (currprefs.chipset_mask & CSMASK_AGA) {
                    479:        if (res_shift == 0)
                    480:            switch (gfxvidinfo.pixbytes) {
                    481:            case 1: src_pixel = linetoscr_8_aga (src_pixel, start, stop); break;
                    482:            case 2: src_pixel = linetoscr_16_aga (src_pixel, start, stop); break;
                    483:            case 4: src_pixel = linetoscr_32_aga (src_pixel, start, stop); break;
                    484:            }
                    485:        else if (res_shift == 1)
                    486:            switch (gfxvidinfo.pixbytes) {
                    487:            case 1: src_pixel = linetoscr_8_stretch1_aga (src_pixel, start, stop); break;
                    488:            case 2: src_pixel = linetoscr_16_stretch1_aga (src_pixel, start, stop); break;
                    489:            case 4: src_pixel = linetoscr_32_stretch1_aga (src_pixel, start, stop); break;
                    490:            }
                    491:        else if (res_shift == -1)
                    492:            switch (gfxvidinfo.pixbytes) {
                    493:            case 1: src_pixel = linetoscr_8_shrink1_aga (src_pixel, start, stop); break;
                    494:            case 2: src_pixel = linetoscr_16_shrink1_aga (src_pixel, start, stop); break;
                    495:            case 4: src_pixel = linetoscr_32_shrink1_aga (src_pixel, start, stop); break;
                    496:            }
                    497:         else
                    498:            abort ();
                    499: 
                    500:     } else {
                    501: 
                    502:         if (res_shift == 0)
                    503:            switch (gfxvidinfo.pixbytes) {
                    504:            case 1: src_pixel = linetoscr_8 (src_pixel, start, stop); break;
                    505:            case 2: src_pixel = linetoscr_16 (src_pixel, start, stop); break;
                    506:            case 4: src_pixel = linetoscr_32 (src_pixel, start, stop); break;
                    507:            }
                    508:        else if (res_shift == 1)
                    509:            switch (gfxvidinfo.pixbytes) {
                    510:            case 1: src_pixel = linetoscr_8_stretch1 (src_pixel, start, stop); break;
                    511:            case 2: src_pixel = linetoscr_16_stretch1 (src_pixel, start, stop); break;
                    512:            case 4: src_pixel = linetoscr_32_stretch1 (src_pixel, start, stop); break;
                    513:            }
                    514:        else if (res_shift == -1)
                    515:            switch (gfxvidinfo.pixbytes) {
                    516:            case 1: src_pixel = linetoscr_8_shrink1 (src_pixel, start, stop); break;
                    517:            case 2: src_pixel = linetoscr_16_shrink1 (src_pixel, start, stop); break;
                    518:            case 4: src_pixel = linetoscr_32_shrink1 (src_pixel, start, stop); break;
                    519:            }
                    520:        else
                    521:            abort ();
                    522:     }
1.1       root      523: }
                    524: 
1.1.1.8   root      525: static void pfield_do_fill_line (int start, int stop)
1.1       root      526: {
1.1.1.8   root      527:     switch (gfxvidinfo.pixbytes) {
                    528:     case 1: fill_line_8 (xlinebuffer, start, stop); break;
                    529:     case 2: fill_line_16 (xlinebuffer, start, stop); break;
                    530:     case 4: fill_line_32 (xlinebuffer, start, stop); break;
1.1       root      531:     }
                    532: }
                    533: 
1.1.1.8   root      534: static void pfield_do_linetoscr_full (int double_line)
1.1       root      535: {
                    536:     char *oldxlb = (char *)xlinebuffer;
1.1.1.8   root      537:     int old_src_pixel = src_pixel;
                    538: 
                    539:     pfield_do_linetoscr (playfield_start, playfield_end);
1.1       root      540:     xlinebuffer = oldxlb + linetoscr_double_offset;
1.1.1.8   root      541:     src_pixel = old_src_pixel;
                    542:     pfield_do_linetoscr (playfield_start, playfield_end);
1.1       root      543: }
1.1.1.8   root      544: 
                    545: static void dummy_worker (int start, int stop)
1.1       root      546: {
                    547: }
                    548: 
1.1.1.8   root      549: static unsigned int ham_lastcolor;
1.1.1.2   root      550: 
1.1.1.8   root      551: static int ham_decode_pixel;
1.1       root      552: 
1.1.1.8   root      553: /* Decode HAM in the invisible portion of the display (left of VISIBLE_LEFT_BORDER),
                    554:    but don't draw anything in.  This is done to prepare HAM_LASTCOLOR for later,
1.1.1.9   root      555:    when decode_ham runs.  */
1.1.1.8   root      556: static void init_ham_decoding (void)
1.1       root      557: {
1.1.1.8   root      558:     int unpainted_amiga = res_shift_from_window (unpainted);
                    559:     ham_decode_pixel = src_pixel;
1.1.1.9   root      560:     ham_lastcolor = color_reg_get (&colors_for_drawing, 0);
                    561: 
                    562:     if (currprefs.chipset_mask & CSMASK_AGA) {
                    563:        if (bplplanecnt == 8) { /* AGA mode HAM8 */
                    564:            while (unpainted_amiga-- > 0) {
                    565:                int pv = pixdata.apixels[ham_decode_pixel++];
                    566:                switch (pv & 0x3) {
                    567:                case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
                    568:                case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
                    569:                case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
                    570:                case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
                    571:                }
                    572:            }
                    573:        } else if(bplplanecnt == 6) { /* AGA mode HAM6 */
                    574:            while (unpainted_amiga-- > 0) {
                    575:                int pv = pixdata.apixels[ham_decode_pixel++];
                    576:                switch (pv & 0x30) {
                    577:                case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
                    578:                case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
                    579:                case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
                    580:                case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
                    581:                }
                    582:            }
                    583:        }
                    584:     } else {
                    585:         if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */
                    586:            while (unpainted_amiga-- > 0) {
                    587:                int pv = pixdata.apixels[ham_decode_pixel++];
                    588:                switch (pv & 0x30) {
                    589:                case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
                    590:                case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
                    591:                case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
                    592:                case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
                    593:                }
                    594:            }
1.1       root      595:        }
                    596:     }
                    597: }
                    598: 
1.1.1.9   root      599: static void decode_ham (int pix, int stoppos)
1.1       root      600: {
1.1.1.8   root      601:     int todraw_amiga = res_shift_from_window (stoppos - pix);
1.1.1.9   root      602:     if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8))
1.1.1.8   root      603:        abort ();
1.1       root      604: 
1.1.1.9   root      605:     if (currprefs.chipset_mask & CSMASK_AGA) {
                    606:        if (bplplanecnt == 8) { /* AGA mode HAM8 */
                    607:            while (todraw_amiga-- > 0) {
                    608:                int pv = pixdata.apixels[ham_decode_pixel];
                    609:                switch (pv & 0x3) {
                    610:                case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
                    611:                case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
                    612:                case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
                    613:                case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
                    614:                }
                    615:                ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
                    616:            }
                    617:        } else if(bplplanecnt == 6) { /* AGA mode HAM6 */
                    618:            while (todraw_amiga-- > 0) {
                    619:                int pv = pixdata.apixels[ham_decode_pixel];
                    620:                switch (pv & 0x30) {
                    621:                case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
                    622:                case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
                    623:                case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
                    624:                case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
                    625:                }
                    626:                ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
                    627:            }
                    628:        }
                    629:     } else {
                    630:         if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */
                    631:            while (todraw_amiga-- > 0) {
                    632:                int pv = pixdata.apixels[ham_decode_pixel];
                    633:                switch (pv & 0x30) {
                    634:                case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
                    635:                case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
                    636:                case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
                    637:                case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
                    638:                }
                    639:                ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
                    640:            }
1.1       root      641:        }
                    642:     }
                    643: }
                    644: 
1.1.1.2   root      645: static void gen_pfield_tables (void)
1.1       root      646: {
                    647:     int i;
                    648: 
                    649:     /* For now, the AGA stuff is broken in the dual playfield case. We encode
                    650:      * sprites in dpf mode by ORing the pixel value with 0x80. To make dual
                    651:      * playfield rendering easy, the lookup tables contain are made linear for
                    652:      * values >= 128. That only works for OCS/ECS, though. */
                    653: 
                    654:     for (i = 0; i < 256; i++) {
                    655:        int plane1 = (i & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8);
                    656:        int plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8);
1.1.1.11! root      657: 
        !           658:        dblpf_ms1[i] = plane1 == 0 ? (plane2 == 0 ? 16 : 8) : 0;
        !           659:        dblpf_ms2[i] = plane2 == 0 ? (plane1 == 0 ? 16 : 0) : 8;
        !           660:        dblpf_ms[i] = i == 0 ? 16 : 8;
1.1       root      661:        if (plane2 > 0)
                    662:            plane2 += 8;
                    663:        dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1);
                    664:        dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2);
                    665: 
1.1.1.11! root      666:        sprite_offs[i] = (i & 15) ? 0 : 2;
1.1       root      667: 
                    668:        clxtab[i] = ((((i & 3) && (i & 12)) << 9)
                    669:                     | (((i & 3) && (i & 48)) << 10)
                    670:                     | (((i & 3) && (i & 192)) << 11)
                    671:                     | (((i & 12) && (i & 48)) << 12)
                    672:                     | (((i & 12) && (i & 192)) << 13)
                    673:                     | (((i & 48) && (i & 192)) << 14));
                    674:     }
                    675: }
                    676: 
1.1.1.11! root      677: /* When looking at this function and the ones that inline it, bear in mind
        !           678:    what an optimizing compiler will do with this code.  All callers of this
        !           679:    function only pass in constant arguments (except for E).  This means
        !           680:    that many of the if statements will go away completely after inlining.  */
        !           681: STATIC_INLINE void draw_sprites_1 (struct sprite_entry *e, int ham, int dualpf, int shift, int has_attach)
        !           682: {
        !           683:     int *shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms;
        !           684:     uae_u16 *buf = spixels + e->first_pixel;
        !           685:     uae_u8 *stbuf = spixstate.bytes + e->first_pixel;
        !           686:     int pos, last;
        !           687: 
        !           688:     buf -= e->pos;
        !           689:     stbuf -= e->pos;
        !           690: 
        !           691:     for (pos = e->pos; pos < e->max; pos++) {
        !           692:        int maskshift, plfmask;
        !           693:        unsigned int v = buf[pos];
        !           694: 
        !           695:        /* The value in the shift lookup table is _half_ the shift count we
        !           696:           need.  This is because we can't shift 32 bits at once (undefined
        !           697:           behaviour in C).  */
        !           698:        maskshift = shift_lookup[pixdata.apixels[(pos << shift) + pixels_offset]];
        !           699:        plfmask = (plf_sprite_mask >> maskshift) >> maskshift;
        !           700:        v &= ~plfmask;
        !           701:        if (v != 0) {
        !           702:            unsigned int vlo, vhi, col, col_off;
        !           703:            unsigned int v1 = v & 255;
        !           704:            /* OFFS determines the sprite pair with the highest priority that has
        !           705:               any bits set.  E.g. if we have 0xFF00 in the buffer, we have sprite
        !           706:               pairs 01 and 23 cleared, and pairs 45 and 67 set, so OFFS will
        !           707:               have a value of 4.
        !           708:               2 * OFFS is the bit number in V of the sprite pair, and it also
        !           709:               happens to be the color offset for that pair.  */
        !           710:            int offs;
        !           711:            if (v1 == 0)
        !           712:                offs = 4 + sprite_offs[v >> 8];
        !           713:            else
        !           714:                offs = sprite_offs[v1];
        !           715: 
        !           716:            /* Shift highest priority sprite pair down to bit zero.  */
        !           717:            v >>= offs * 2;
        !           718:            v &= 15;
        !           719:  
        !           720:            if (has_attach && (stbuf[pos] & (1 << offs))) {
        !           721:                col = v;
        !           722:            } else {
        !           723:                /* This sequence computes the correct color value.  We have to select
        !           724:                   either the lower-numbered or the higher-numbered sprite in the pair.
        !           725:                   We have to select the high one if the low one has all bits zero.
        !           726:                   If the lower-numbered sprite has any bits nonzero, (VLO - 1) is in
        !           727:                   the range of 0..2, and with the mask and shift, VHI will be zero.
        !           728:                   If the lower-numbered sprite is zero, (VLO - 1) is a mask of
        !           729:                   0xFFFFFFFF, and we select the bits of the higher numbered sprite
        !           730:                   in VHI.
        !           731:                   This is _probably_ more efficient than doing it with branches.  */
        !           732:                vlo = v & 3;
        !           733:                vhi = (v & (vlo - 1)) >> 2;
        !           734:                col = vlo | vhi;
        !           735:                col += (offs * 2);
        !           736:            }
        !           737:            col += dualpf ? 128 + 16 : 16;
1.1       root      738:            if (ham) {
1.1.1.9   root      739:                col = color_reg_get (&colors_for_drawing, col);
1.1.1.11! root      740:                ham_linebuf[(pos << shift) + pixels_offset] = col;
        !           741:                if (shift == 1) {
        !           742:                    ham_linebuf[(pos << shift) + pixels_offset + 1] = col;
1.1       root      743:                }
                    744:            } else {
1.1.1.11! root      745:                if (shift == 1)
        !           746:                    pixdata.apixels_w[pos + (pixels_offset >> 1)] = col | (col << 8);
        !           747:                else
        !           748:                    pixdata.apixels[(pos << shift) + pixels_offset] = col;
1.1       root      749:            }
                    750:        }
                    751:     }
                    752: }
1.1.1.11! root      753:   
        !           754: /* See comments above.  Do not touch if you don't know what's going on.
        !           755:  * (We do _not_ want the following to be inlined themselves).  */
        !           756: static void draw_sprites_normal_sp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 0, 0); }
        !           757: static void draw_sprites_normal_dp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 0, 0); }
        !           758: static void draw_sprites_ham_sp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 0, 0); }
        !           759: static void draw_sprites_normal_sp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 1, 0); }
        !           760: static void draw_sprites_normal_dp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 1, 0); }
        !           761: static void draw_sprites_ham_sp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 1, 0); }
        !           762: static void draw_sprites_normal_sp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 0, 1); }
        !           763: static void draw_sprites_normal_dp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 0, 1); }
        !           764: static void draw_sprites_ham_sp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 0, 1); }
        !           765: static void draw_sprites_normal_sp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 1, 1); }
        !           766: static void draw_sprites_normal_dp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 1, 1); }
        !           767: static void draw_sprites_ham_sp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 1, 1); }
        !           768: 
        !           769: STATIC_INLINE void draw_sprites (struct sprite_entry *e)
        !           770: {
        !           771:     if (e->has_attached)
        !           772:        if (bplres == 1)
        !           773:            if (bplham)
        !           774:                draw_sprites_ham_sp_hi_at (e);
        !           775:            else
        !           776:                if (bpldualpf)
        !           777:                    draw_sprites_normal_dp_hi_at (e);
        !           778:                else
        !           779:                    draw_sprites_normal_sp_hi_at (e);
        !           780:        else
        !           781:            if (bplham)
        !           782:                draw_sprites_ham_sp_lo_at (e);
        !           783:            else
        !           784:                if (bpldualpf)
        !           785:                    draw_sprites_normal_dp_lo_at (e);
        !           786:                else
        !           787:                    draw_sprites_normal_sp_lo_at (e);
        !           788:     else
        !           789:        if (bplres == 1)
        !           790:            if (bplham)
        !           791:                draw_sprites_ham_sp_hi_nat (e);
        !           792:            else
        !           793:                if (bpldualpf)
        !           794:                    draw_sprites_normal_dp_hi_nat (e);
        !           795:                else
        !           796:                    draw_sprites_normal_sp_hi_nat (e);
        !           797:        else
        !           798:            if (bplham)
        !           799:                draw_sprites_ham_sp_lo_nat (e);
        !           800:            else
        !           801:                if (bpldualpf)
        !           802:                    draw_sprites_normal_dp_lo_nat (e);
        !           803:                else
        !           804:                    draw_sprites_normal_sp_lo_nat (e);
1.1       root      805: }
                    806: 
1.1.1.8   root      807: #define MERGE(a,b,mask,shift) do {\
                    808:     uae_u32 tmp = mask & (a ^ (b >> shift)); \
                    809:     a ^= tmp; \
                    810:     b ^= (tmp << shift); \
                    811: } while (0)
                    812: 
1.1.1.11! root      813: #define GETLONG(P) (*(uae_u32 *)P)
        !           814: 
        !           815: /* We use the compiler's inlining ability to ensure that PLANES is in effect a compile time
        !           816:    constant.  That will cause some unnecessary code to be optimized away.
1.1.1.8   root      817:    Don't touch this if you don't know what you are doing.  */
1.1.1.11! root      818: STATIC_INLINE void pfield_doline_1 (uae_u32 *pixels, int wordcount, int planes)
1.1.1.8   root      819: {
                    820:     while (wordcount-- > 0) {
                    821:        uae_u32 b0, b1, b2, b3, b4, b5, b6, b7;
                    822: 
                    823:        b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0;
                    824:        switch (planes) {
1.1.1.11! root      825:        case 8: b0 = GETLONG ((uae_u32 *)real_bplpt[7]); real_bplpt[7] += 4;
        !           826:        case 7: b1 = GETLONG ((uae_u32 *)real_bplpt[6]); real_bplpt[6] += 4;
        !           827:        case 6: b2 = GETLONG ((uae_u32 *)real_bplpt[5]); real_bplpt[5] += 4;
        !           828:        case 5: b3 = GETLONG ((uae_u32 *)real_bplpt[4]); real_bplpt[4] += 4;
        !           829:        case 4: b4 = GETLONG ((uae_u32 *)real_bplpt[3]); real_bplpt[3] += 4;
        !           830:        case 3: b5 = GETLONG ((uae_u32 *)real_bplpt[2]); real_bplpt[2] += 4;
        !           831:        case 2: b6 = GETLONG ((uae_u32 *)real_bplpt[1]); real_bplpt[1] += 4;
        !           832:        case 1: b7 = GETLONG ((uae_u32 *)real_bplpt[0]); real_bplpt[0] += 4;
1.1.1.8   root      833:        }
                    834: 
                    835:        MERGE (b0, b1, 0x55555555, 1);
                    836:        MERGE (b2, b3, 0x55555555, 1);
                    837:        MERGE (b4, b5, 0x55555555, 1);
                    838:        MERGE (b6, b7, 0x55555555, 1);
                    839: 
                    840:        MERGE (b0, b2, 0x33333333, 2);
                    841:        MERGE (b1, b3, 0x33333333, 2);
                    842:        MERGE (b4, b6, 0x33333333, 2);
                    843:        MERGE (b5, b7, 0x33333333, 2);
                    844: 
                    845:        MERGE (b0, b4, 0x0f0f0f0f, 4);
                    846:        MERGE (b1, b5, 0x0f0f0f0f, 4);
                    847:        MERGE (b2, b6, 0x0f0f0f0f, 4);
                    848:        MERGE (b3, b7, 0x0f0f0f0f, 4);
                    849: 
                    850:        MERGE (b0, b1, 0x00ff00ff, 8);
                    851:        MERGE (b2, b3, 0x00ff00ff, 8);
                    852:        MERGE (b4, b5, 0x00ff00ff, 8);
                    853:        MERGE (b6, b7, 0x00ff00ff, 8);
                    854: 
                    855:        MERGE (b0, b2, 0x0000ffff, 16);
                    856:        do_put_mem_long (pixels, b0);
                    857:        do_put_mem_long (pixels + 4, b2);
                    858:        MERGE (b1, b3, 0x0000ffff, 16);
                    859:        do_put_mem_long (pixels + 2, b1);
                    860:        do_put_mem_long (pixels + 6, b3);
                    861:        MERGE (b4, b6, 0x0000ffff, 16);
                    862:        do_put_mem_long (pixels + 1, b4);
                    863:        do_put_mem_long (pixels + 5, b6);
                    864:        MERGE (b5, b7, 0x0000ffff, 16);
                    865:        do_put_mem_long (pixels + 3, b5);
                    866:        do_put_mem_long (pixels + 7, b7);
                    867:        pixels += 8;
                    868:     }
                    869: }
                    870: 
                    871: /* See above for comments on inlining.  These functions should _not_
                    872:    be inlined themselves.  */
1.1.1.11! root      873: static void pfield_doline_n1 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 1); }
        !           874: static void pfield_doline_n2 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 2); }
        !           875: static void pfield_doline_n3 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 3); }
        !           876: static void pfield_doline_n4 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 4); }
        !           877: static void pfield_doline_n5 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 5); }
        !           878: static void pfield_doline_n6 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 6); }
        !           879: static void pfield_doline_n7 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 7); }
        !           880: static void pfield_doline_n8 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 8); }
1.1.1.8   root      881: 
                    882: static void pfield_doline (int lineno)
                    883: {
1.1.1.11! root      884:     int wordcount = dp_for_drawing->plflinelen;
1.1.1.8   root      885:     uae_u32 *data = pixdata.apixels_l + 220;
                    886:     int dsub1, dsub2;
1.1       root      887: 
                    888: #ifdef SMART_UPDATE
1.1.1.8   root      889: #define DATA_POINTER(n) (line_data[lineno] + (n)*MAX_WORDS_PER_LINE*2)
                    890:     real_bplpt[0] = DATA_POINTER (0);
                    891:     real_bplpt[1] = DATA_POINTER (1);
                    892:     real_bplpt[2] = DATA_POINTER (2);
                    893:     real_bplpt[3] = DATA_POINTER (3);
                    894:     real_bplpt[4] = DATA_POINTER (4);
                    895:     real_bplpt[5] = DATA_POINTER (5);
                    896:     real_bplpt[6] = DATA_POINTER (6);
                    897:     real_bplpt[7] = DATA_POINTER (7);
                    898: #endif
                    899: 
1.1.1.11! root      900:     switch (bplplanecnt) {
        !           901:     default: break;
        !           902:     case 0: memset (data, 0, wordcount * 32); break;
        !           903:     case 1: pfield_doline_n1 (data, wordcount); break;
        !           904:     case 2: pfield_doline_n2 (data, wordcount); break;
        !           905:     case 3: pfield_doline_n3 (data, wordcount); break;
        !           906:     case 4: pfield_doline_n4 (data, wordcount); break;
        !           907:     case 5: pfield_doline_n5 (data, wordcount); break;
        !           908:     case 6: pfield_doline_n6 (data, wordcount); break;
        !           909:     case 7: pfield_doline_n7 (data, wordcount); break;
        !           910:     case 8: pfield_doline_n8 (data, wordcount); break;
1.1       root      911:     }
                    912: }
                    913: 
                    914: void init_row_map (void)
                    915: {
                    916:     int i;
                    917:     if (gfxvidinfo.height > 2048) {
                    918:        write_log ("Resolution too high, aborting\n");
                    919:        abort ();
                    920:     }
                    921:     for (i = 0; i < gfxvidinfo.height + 1; i++)
                    922:        row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i;
                    923: }
                    924: 
                    925: static void init_aspect_maps (void)
                    926: {
                    927:     int i, maxl;
                    928:     double native_lines_per_amiga_line;
                    929: 
                    930:     if (native2amiga_line_map)
                    931:        free (native2amiga_line_map);
                    932:     if (amiga2aspect_line_map)
                    933:        free (amiga2aspect_line_map);
                    934: 
                    935:     /* At least for this array the +1 is necessary. */
1.1.1.5   root      936:     amiga2aspect_line_map = (int *)malloc (sizeof (int) * (MAXVPOS + 1)*2 + 1);
1.1       root      937:     native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height);
                    938: 
                    939:     if (currprefs.gfx_correct_aspect)
                    940:        native_lines_per_amiga_line = ((double)gfxvidinfo.height
                    941:                                       * (currprefs.gfx_lores ? 320 : 640)
                    942:                                       / (currprefs.gfx_linedbl ? 512 : 256)
                    943:                                       / gfxvidinfo.width);
                    944:     else
                    945:        native_lines_per_amiga_line = 1;
                    946: 
1.1.1.5   root      947:     maxl = (MAXVPOS + 1) * (currprefs.gfx_linedbl ? 2 : 1);
1.1       root      948:     min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0);
                    949:     max_drawn_amiga_line = -1;
                    950:     for (i = 0; i < maxl; i++) {
1.1.1.9   root      951:        int v = (int) ((i - min_ypos_for_screen) * native_lines_per_amiga_line);
1.1       root      952:        if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1)
                    953:            max_drawn_amiga_line = i - min_ypos_for_screen;
                    954:        if (i < min_ypos_for_screen || v >= gfxvidinfo.height)
                    955:            v = -1;
                    956:        amiga2aspect_line_map[i] = v;
                    957:     }
                    958:     if (currprefs.gfx_linedbl)
                    959:        max_drawn_amiga_line >>= 1;
                    960: 
                    961:     if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) {
1.1.1.5   root      962:        /* @@@ verify maxvpos vs. MAXVPOS */
1.1       root      963:        extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1;
                    964:        if (extra_y_adjust < 0)
                    965:            extra_y_adjust = 0;
                    966:     }
                    967: 
                    968:     for (i = 0; i < gfxvidinfo.height; i++)
                    969:        native2amiga_line_map[i] = -1;
                    970: 
                    971:     if (native_lines_per_amiga_line < 1) {
                    972:        /* Must omit drawing some lines. */
                    973:        for (i = maxl - 1; i > min_ypos_for_screen; i--) {
                    974:            if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) {
                    975:                if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) {
                    976:                    /* If only the first line of a line pair would be omitted,
                    977:                     * omit the second one instead to avoid problems with line
                    978:                     * doubling. */
                    979:                    amiga2aspect_line_map[i] = amiga2aspect_line_map[i+1];
                    980:                    amiga2aspect_line_map[i+1] = -1;
                    981:                } else
                    982:                    amiga2aspect_line_map[i] = -1;
                    983:            }
                    984:        }
                    985:     }
                    986: 
                    987:     for (i = maxl-1; i >= min_ypos_for_screen; i--) {
                    988:        int j;
                    989:        if (amiga2aspect_line_map[i] == -1)
                    990:            continue;
                    991:        for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++)
                    992:            native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0);
                    993:     }
                    994: }
                    995: 
                    996: /*
                    997:  * A raster line has been built in the graphics buffer. Tell the graphics code
                    998:  * to do anything necessary to display it.
                    999:  */
                   1000: static void do_flush_line_1 (int lineno)
                   1001: {
                   1002:     if (lineno < first_drawn_line)
                   1003:        first_drawn_line = lineno;
                   1004:     if (lineno > last_drawn_line)
                   1005:        last_drawn_line = lineno;
                   1006: 
                   1007:     if (gfxvidinfo.maxblocklines == 0)
1.1.1.11! root     1008:        flush_line (lineno);
1.1       root     1009:     else {
                   1010:        if ((last_block_line+1) != lineno) {
                   1011:            if (first_block_line != -2)
                   1012:                flush_block (first_block_line, last_block_line);
                   1013:            first_block_line = lineno;
                   1014:        }
                   1015:        last_block_line = lineno;
                   1016:        if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
                   1017:            flush_block (first_block_line, last_block_line);
                   1018:            first_block_line = last_block_line = -2;
                   1019:        }
                   1020:     }
                   1021: }
                   1022: 
1.1.1.6   root     1023: STATIC_INLINE void do_flush_line (int lineno)
1.1       root     1024: {
                   1025:     do_flush_line_1 (lineno);
                   1026: }
                   1027: 
                   1028: /*
                   1029:  * One drawing frame has been finished. Tell the graphics code about it.
                   1030:  * Note that the actual flush_screen() call is a no-op for all reasonable
                   1031:  * systems.
                   1032:  */
                   1033: 
1.1.1.6   root     1034: STATIC_INLINE void do_flush_screen (int start, int stop)
1.1       root     1035: {
1.1.1.6   root     1036:     /* TODO: this flush operation is executed outside locked state!
                   1037:        Should be corrected.
                   1038:        (sjo 26.9.99) */
                   1039: 
1.1       root     1040:     if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
                   1041:        flush_block (first_block_line, last_block_line);
                   1042:     }
                   1043:     if (start <= stop)
                   1044:        flush_screen (start, stop);
                   1045: }
                   1046: 
                   1047: static int drawing_color_matches;
                   1048: static enum { color_match_acolors, color_match_full } color_match_type;
                   1049: 
1.1.1.8   root     1050: /* Set up colors_for_drawing to the state at the beginning of the currently drawn
                   1051:    line.  Try to avoid copying color tables around whenever possible.  */
1.1       root     1052: static void adjust_drawing_colors (int ctable, int bplham)
                   1053: {
                   1054:     if (drawing_color_matches != ctable) {
                   1055:        if (bplham) {
1.1.1.9   root     1056:            color_reg_cpy (&colors_for_drawing, curr_color_tables + ctable);
1.1       root     1057:            color_match_type = color_match_full;
                   1058:        } else {
                   1059:            memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
1.1.1.9   root     1060:                sizeof colors_for_drawing.acolors);
1.1       root     1061:            color_match_type = color_match_acolors;
                   1062:        }
                   1063:        drawing_color_matches = ctable;
                   1064:     } else if (bplham && color_match_type != color_match_full) {
1.1.1.9   root     1065:        color_reg_cpy (&colors_for_drawing, &curr_color_tables[ctable]);
1.1       root     1066:        color_match_type = color_match_full;
                   1067:     }
                   1068: }
                   1069: 
1.1.1.8   root     1070: STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_func worker_pfield)
1.1       root     1071: {
1.1.1.8   root     1072:     int i;
                   1073:     int lastpos = visible_left_border;
1.1.1.9   root     1074: 
1.1.1.8   root     1075:     for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) {
                   1076:        int regno = curr_color_changes[i].regno;
                   1077:        unsigned int value = curr_color_changes[i].value;
                   1078:        int nextpos, nextpos_in_range;
1.1       root     1079:        if (i == dip_for_drawing->last_color_change)
                   1080:            nextpos = max_diwlastword;
                   1081:        else
1.1.1.11! root     1082:            nextpos = coord_hw_to_window_x (curr_color_changes[i].linepos * 2);
1.1.1.8   root     1083: 
                   1084:        nextpos_in_range = nextpos;
                   1085:        if (nextpos > visible_right_border)
                   1086:            nextpos_in_range = visible_right_border;
                   1087: 
                   1088:        if (nextpos_in_range > lastpos) {
                   1089:            if (lastpos < playfield_start) {
                   1090:                int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start;
                   1091:                (*worker_border) (lastpos, t);
                   1092:                lastpos = t;
                   1093:            }
                   1094:        }
                   1095:        if (nextpos_in_range > lastpos) {
                   1096:            if (lastpos >= playfield_start && lastpos < playfield_end) {
                   1097:                int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
                   1098:                (*worker_pfield) (lastpos, t);
                   1099:                lastpos = t;
                   1100:            }
                   1101:        }
                   1102:        if (nextpos_in_range > lastpos) {
                   1103:            if (lastpos >= playfield_end)
                   1104:                (*worker_border) (lastpos, nextpos_in_range);
                   1105:            lastpos = nextpos_in_range;
                   1106:        }
1.1       root     1107:        if (i != dip_for_drawing->last_color_change) {
1.1.1.9   root     1108:            color_reg_set (&colors_for_drawing, regno, value);
                   1109:            colors_for_drawing.acolors[regno] = getxcolor (value);
1.1       root     1110:        }
1.1.1.8   root     1111:        if (lastpos >= visible_right_border)
1.1.1.11! root     1112:            break;
        !          1113:     }
1.1       root     1114: }
                   1115: 
                   1116: /* We only save hardware registers during the hardware frame. Now, when
                   1117:  * drawing the frame, we expand the data into a slightly more useful
                   1118:  * form. */
                   1119: static void pfield_expand_dp_bplcon (void)
                   1120: {
1.1.1.11! root     1121:     int plf1pri, plf2pri;
        !          1122:     bplres = dp_for_drawing->bplres;
        !          1123:     bplplanecnt = dp_for_drawing->nr_planes;
1.1       root     1124:     bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800;
1.1.1.9   root     1125:     if (currprefs.chipset_mask & CSMASK_AGA) {
                   1126:        /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock
                   1127:         * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */
                   1128:        bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200));
                   1129:     } else {
                   1130:        bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000;
                   1131:     }
1.1.1.11! root     1132:     plf1pri = dp_for_drawing->bplcon2 & 7;
        !          1133:     plf2pri = (dp_for_drawing->bplcon2 >> 3) & 7;
        !          1134:     plf_sprite_mask = 0xFFFF0000 << (4 * plf2pri);
        !          1135:     plf_sprite_mask |= (0xFFFF << (4 * plf1pri)) & 0xFFFF;
1.1       root     1136:     bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
                   1137:     bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
                   1138: }
                   1139: 
                   1140: enum double_how {
                   1141:     dh_buf,
                   1142:     dh_line,
                   1143:     dh_emerg
                   1144: };
                   1145: 
1.1.1.6   root     1146: STATIC_INLINE void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos)
1.1       root     1147: {
1.1.1.8   root     1148:     static int warned = 0;
1.1       root     1149:     int border = 0;
                   1150:     int do_double = 0;
                   1151:     enum double_how dh;
                   1152: 
1.1.1.2   root     1153:     dp_for_drawing = line_decisions + lineno;
                   1154:     dip_for_drawing = curr_drawinfo + lineno;
1.1       root     1155:     switch (linestate[lineno]) {
1.1.1.8   root     1156:     case LINE_REMEMBERED_AS_PREVIOUS:
                   1157:        if (!warned)
                   1158:            write_log ("Shouldn't get here... this is a bug.\n"), warned++;
1.1       root     1159:        return;
                   1160: 
1.1.1.8   root     1161:     case LINE_BLACK:
1.1.1.2   root     1162:        linestate[lineno] = LINE_REMEMBERED_AS_BLACK;
                   1163:        border = 2;
1.1       root     1164:        break;
                   1165: 
1.1.1.8   root     1166:     case LINE_REMEMBERED_AS_BLACK:
1.1.1.2   root     1167:        return;
                   1168: 
1.1.1.8   root     1169:     case LINE_AS_PREVIOUS:
1.1.1.2   root     1170:        dp_for_drawing--;
                   1171:        dip_for_drawing--;
1.1.1.11! root     1172:        if (dp_for_drawing->plfleft == -1)
1.1.1.2   root     1173:            border = 1;
                   1174:        linestate[lineno] = LINE_DONE_AS_PREVIOUS;
1.1       root     1175:        break;
                   1176: 
1.1.1.8   root     1177:     case LINE_DONE_AS_PREVIOUS:
1.1       root     1178:        /* fall through */
1.1.1.8   root     1179:     case LINE_DONE:
1.1       root     1180:        return;
                   1181: 
1.1.1.8   root     1182:     case LINE_DECIDED_DOUBLE:
1.1       root     1183:        if (follow_ypos != -1) {
                   1184:            do_double = 1;
                   1185:            linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos);
1.1.1.2   root     1186:            linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
1.1       root     1187:        }
                   1188: 
                   1189:        /* fall through */
1.1.1.8   root     1190:     default:
1.1.1.11! root     1191:        if (dp_for_drawing->plfleft == -1)
1.1       root     1192:            border = 1;
                   1193:        linestate[lineno] = LINE_DONE;
1.1.1.2   root     1194:        break;
1.1       root     1195:     }
                   1196: 
                   1197:     dh = dh_line;
                   1198:     xlinebuffer = gfxvidinfo.linemem;
1.1.1.10  root     1199:     if (xlinebuffer == 0 && do_double
                   1200:        && (border == 0 || (border != 1 && dip_for_drawing->nr_color_changes > 0)))
1.1       root     1201:        xlinebuffer = gfxvidinfo.emergmem, dh = dh_emerg;
                   1202:     if (xlinebuffer == 0)
                   1203:        xlinebuffer = row_map[gfx_ypos], dh = dh_buf;
                   1204:     xlinebuffer -= linetoscr_x_adjust_bytes;
                   1205: 
1.1.1.11! root     1206:     if (border == 0) {
1.1       root     1207:        pfield_expand_dp_bplcon ();
                   1208: 
1.1.1.8   root     1209:        if (bplres == RES_LORES && !currprefs.gfx_lores)
1.1       root     1210:            currprefs.gfx_lores = 2;
                   1211:        pfield_init_linetoscr ();
1.1.1.8   root     1212: 
1.1.1.11! root     1213:        pfield_doline (lineno);
1.1       root     1214: 
                   1215:        adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
                   1216: 
1.1.1.9   root     1217:        /* The problem is that we must call decode_ham() BEFORE we do the
1.1.1.8   root     1218:           sprites. */
                   1219:        if (! border && bplham) {
                   1220:            init_ham_decoding ();
1.1       root     1221:            if (dip_for_drawing->nr_color_changes == 0) {
                   1222:                /* The easy case: need to do HAM decoding only once for the
                   1223:                 * full line. */
1.1.1.9   root     1224:                decode_ham (visible_left_border, visible_right_border);
1.1       root     1225:            } else /* Argh. */ {
1.1.1.9   root     1226:                do_color_changes (dummy_worker, decode_ham);
1.1       root     1227:                adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
                   1228:            }
                   1229:        }
                   1230: 
1.1.1.11! root     1231:        {
        !          1232:            int i;
        !          1233:            for (i = 0; i < dip_for_drawing->nr_sprites; i++)
        !          1234:                draw_sprites (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i);
        !          1235:        }
1.1       root     1236: 
1.1.1.8   root     1237:        do_color_changes (pfield_do_fill_line, pfield_do_linetoscr);
1.1       root     1238: 
1.1.1.8   root     1239:        if (dh == dh_emerg)
                   1240:            memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
1.1       root     1241: 
1.1.1.8   root     1242:        do_flush_line (gfx_ypos);
                   1243:        if (do_double) {
                   1244:            if (dh == dh_emerg)
                   1245:                memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
                   1246:            else if (dh == dh_buf)
                   1247:                memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
                   1248:            do_flush_line (follow_ypos);
1.1       root     1249:        }
                   1250:        if (currprefs.gfx_lores == 2)
                   1251:            currprefs.gfx_lores = 0;
1.1.1.2   root     1252:     } else if (border == 1) {
1.1       root     1253:        adjust_drawing_colors (dp_for_drawing->ctable, 0);
                   1254: 
                   1255:        if (dip_for_drawing->nr_color_changes == 0) {
                   1256:            fill_line ();
                   1257:            do_flush_line (gfx_ypos);
                   1258: #if 0
                   1259:            if (dh == dh_emerg)
                   1260:                abort ();
                   1261: #endif
                   1262:            if (do_double) {
                   1263:                if (dh == dh_buf) {
                   1264:                    xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
                   1265:                    fill_line ();
                   1266:                }
                   1267:                /* If dh == dh_line, do_flush_line will re-use the rendered line
                   1268:                 * from linemem.  */
                   1269:                do_flush_line (follow_ypos);
                   1270:            }
                   1271:            return;
                   1272:        }
                   1273: 
1.1.1.8   root     1274:        playfield_start = visible_right_border;
                   1275:        playfield_end = visible_right_border;
                   1276: 
                   1277:        do_color_changes (pfield_do_fill_line, pfield_do_fill_line);
1.1       root     1278: 
                   1279:        if (dh == dh_emerg)
                   1280:            memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
                   1281: 
                   1282:        do_flush_line (gfx_ypos);
                   1283:        if (do_double) {
                   1284:            if (dh == dh_emerg)
                   1285:                memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
                   1286:            else if (dh == dh_buf)
                   1287:                memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
                   1288:            /* If dh == dh_line, do_flush_line will re-use the rendered line
                   1289:             * from linemem.  */
                   1290:            do_flush_line (follow_ypos);
                   1291:        }
1.1.1.2   root     1292:     } else {
                   1293:        xcolnr tmp = colors_for_drawing.acolors[0];
1.1.1.9   root     1294:        colors_for_drawing.acolors[0] = getxcolor (0);
1.1.1.2   root     1295:        fill_line ();
                   1296:        do_flush_line (gfx_ypos);
                   1297:        colors_for_drawing.acolors[0] = tmp;
1.1       root     1298:     }
                   1299: }
                   1300: 
                   1301: static void center_image (void)
                   1302: {
1.1.1.8   root     1303:     prev_x_adjust = visible_left_border;
1.1       root     1304:     prev_y_adjust = thisframe_y_adjust;
                   1305: 
                   1306:     if (currprefs.gfx_xcenter) {
                   1307:        if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2)
                   1308:            /* Try to center. */
1.1.1.8   root     1309:            visible_left_border = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1;
1.1       root     1310:        else
1.1.1.8   root     1311:            visible_left_border = max_diwstop - gfxvidinfo.width;
1.1       root     1312: 
                   1313:        /* Would the old value be good enough? If so, leave it as it is if we want to
                   1314:         * be clever. */
                   1315:        if (currprefs.gfx_xcenter == 2) {
1.1.1.8   root     1316:            if (visible_left_border < prev_x_adjust && prev_x_adjust < min_diwstart)
                   1317:                visible_left_border = prev_x_adjust;
1.1       root     1318:        }
                   1319:     } else
1.1.1.8   root     1320:        visible_left_border = max_diwlastword - gfxvidinfo.width;
                   1321:     if (visible_left_border < 0)
                   1322:        visible_left_border = 0;
                   1323: 
                   1324:     linetoscr_x_adjust_bytes = visible_left_border * gfxvidinfo.pixbytes;
                   1325: 
                   1326:     visible_right_border = visible_left_border + gfxvidinfo.width;
                   1327:     if (visible_right_border > max_diwlastword)
                   1328:        visible_right_border = max_diwlastword;
1.1       root     1329: 
                   1330:     thisframe_y_adjust = minfirstline;
                   1331:     if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) {
                   1332:        if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2)
                   1333:            thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
                   1334:        else
                   1335:            thisframe_y_adjust = thisframe_first_drawn_line;
                   1336:        /* Would the old value be good enough? If so, leave it as it is if we want to
                   1337:         * be clever. */
                   1338:        if (currprefs.gfx_ycenter == 2) {
                   1339:            if (thisframe_y_adjust != prev_y_adjust
                   1340:                && prev_y_adjust <= thisframe_first_drawn_line
                   1341:                && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)
                   1342:                thisframe_y_adjust = prev_y_adjust;
                   1343:        }
                   1344:        /* Make sure the value makes sense */
                   1345:        if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos)
                   1346:            thisframe_y_adjust = maxvpos - max_drawn_amiga_line;
                   1347:        if (thisframe_y_adjust < minfirstline)
                   1348:            thisframe_y_adjust = minfirstline;
                   1349:     }
                   1350:     thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0);
                   1351:     max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0);
                   1352: 
                   1353:     /* @@@ interlace_seen used to be (bplcon0 & 4), but this is probably
                   1354:      * better.  */
1.1.1.8   root     1355:     if (prev_x_adjust != visible_left_border || prev_y_adjust != thisframe_y_adjust)
1.1       root     1356:        frame_redraw_necessary |= interlace_seen && currprefs.gfx_linedbl ? 2 : 1;
                   1357: 
                   1358:     max_diwstop = 0;
                   1359:     min_diwstart = 10000;
                   1360: }
                   1361: 
                   1362: static void init_drawing_frame (void)
                   1363: {
                   1364:     int i, maxline;
                   1365: 
                   1366:     init_hardware_for_drawing_frame ();
                   1367: 
                   1368:     if (thisframe_first_drawn_line == -1)
                   1369:        thisframe_first_drawn_line = minfirstline;
                   1370:     if (thisframe_first_drawn_line > thisframe_last_drawn_line)
                   1371:        thisframe_last_drawn_line = thisframe_first_drawn_line;
                   1372: 
                   1373:     maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1;
                   1374: #ifdef SMART_UPDATE
1.1.1.2   root     1375:     for (i = 0; i < maxline; i++) {
                   1376:        switch (linestate[i]) {
                   1377:         case LINE_DONE_AS_PREVIOUS:
                   1378:            linestate[i] = LINE_REMEMBERED_AS_PREVIOUS;
                   1379:            break;
                   1380:         case LINE_REMEMBERED_AS_BLACK:
                   1381:            break;
                   1382:         default:
                   1383:            linestate[i] = LINE_UNDECIDED;
                   1384:            break;
                   1385:        }
                   1386:     }
1.1       root     1387: #else
                   1388:     memset (linestate, LINE_UNDECIDED, maxline);
                   1389: #endif
                   1390:     last_drawn_line = 0;
                   1391:     first_drawn_line = 32767;
                   1392: 
                   1393:     first_block_line = last_block_line = -2;
                   1394:     if (currprefs.test_drawing_speed)
                   1395:        frame_redraw_necessary = 1;
                   1396:     else if (frame_redraw_necessary)
                   1397:        frame_redraw_necessary--;
                   1398: 
                   1399:     center_image ();
                   1400: 
                   1401:     thisframe_first_drawn_line = -1;
                   1402:     thisframe_last_drawn_line = -1;
                   1403: 
                   1404:     drawing_color_matches = -1;
                   1405: }
                   1406: 
                   1407: void finish_drawing_frame (void)
                   1408: {
                   1409:     int i;
                   1410: 
                   1411: #ifndef SMART_UPDATE
                   1412:     /* @@@ This isn't exactly right yet. FIXME */
                   1413:     if (!interlace_seen) {
                   1414:        do_flush_screen (first_drawn_line, last_drawn_line);
                   1415:        return;
                   1416:     }
                   1417: #endif
                   1418:     if (! lockscr ()) {
                   1419:        notice_screen_contents_lost ();
                   1420:        return;
                   1421:     }
                   1422:     for (i = 0; i < max_ypos_thisframe; i++) {
                   1423:        int where;
                   1424:        int line = i + thisframe_y_adjust_real;
                   1425: 
                   1426:        if (linestate[line] == LINE_UNDECIDED)
                   1427:            break;
                   1428: 
                   1429:        where = amiga2aspect_line_map[i+min_ypos_for_screen];
                   1430:        if (where >= gfxvidinfo.height)
                   1431:            break;
                   1432:        if (where == -1)
                   1433:            continue;
                   1434: 
                   1435:        pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
                   1436:     }
                   1437:     unlockscr ();
                   1438:     do_flush_screen (first_drawn_line, last_drawn_line);
                   1439: }
                   1440: 
                   1441: void hardware_line_completed (int lineno)
                   1442: {
                   1443: #ifndef SMART_UPDATE
                   1444:     {
                   1445:        int i, where;
                   1446:        /* l is the line that has been finished for drawing. */
                   1447:        i = lineno - thisframe_y_adjust_real;
                   1448:        if (i >= 0 && i < max_ypos_thisframe) {
                   1449:            where = amiga2aspect_line_map[i+min_ypos_for_screen];
                   1450:            if (where < gfxvidinfo.height && where != -1)
                   1451:                pfield_draw_line (lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
                   1452:        }
                   1453:     }
                   1454: #endif
                   1455: }
                   1456: 
1.1.1.6   root     1457: STATIC_INLINE void check_picasso (void)
1.1       root     1458: {
                   1459: #ifdef PICASSO96
                   1460:     if (picasso_on && picasso_redraw_necessary)
                   1461:        picasso_refresh ();
                   1462:     picasso_redraw_necessary = 0;
                   1463: 
                   1464:     if (picasso_requested_on == picasso_on)
                   1465:        return;
                   1466: 
                   1467:     picasso_on = picasso_requested_on;
                   1468: 
                   1469:     if (!picasso_on)
1.1.1.3   root     1470:        clear_inhibit_frame (IHF_PICASSO);
1.1       root     1471:     else
1.1.1.3   root     1472:        set_inhibit_frame (IHF_PICASSO);
1.1       root     1473: 
                   1474:     gfx_set_picasso_state (picasso_on);
                   1475:     picasso_enablescreen (picasso_requested_on);
                   1476: 
                   1477:     notice_screen_contents_lost ();
                   1478:     notice_new_xcolors ();
                   1479: #endif
                   1480: }
                   1481: 
                   1482: void vsync_handle_redraw (int long_frame, int lof_changed)
                   1483: {
                   1484:     last_redraw_point++;
                   1485:     if (lof_changed || ! interlace_seen || last_redraw_point >= 2 || long_frame) {
                   1486:        last_redraw_point = 0;
                   1487:        interlace_seen = 0;
                   1488: 
                   1489:        if (framecnt == 0)
                   1490:            finish_drawing_frame ();
                   1491: 
                   1492:        /* At this point, we have finished both the hardware and the
                   1493:         * drawing frame. Essentially, we are outside of all loops and
                   1494:         * can do some things which would cause confusion if they were
                   1495:         * done at other times.
                   1496:         */
                   1497: 
                   1498:        if (quit_program < 0) {
                   1499:            quit_program = -quit_program;
1.1.1.3   root     1500:            set_inhibit_frame (IHF_QUIT_PROGRAM);
1.1.1.11! root     1501:            set_special (SPCFLAG_BRK);
1.1       root     1502:            filesys_prepare_reset ();
                   1503:            return;
                   1504:        }
                   1505: 
                   1506:        count_frame ();
                   1507:        check_picasso ();
                   1508: 
1.1.1.2   root     1509:        check_prefs_changed_audio ();
1.1       root     1510:        check_prefs_changed_custom ();
                   1511:        check_prefs_changed_cpu ();
                   1512:        if (check_prefs_changed_gfx ()) {
                   1513:            init_row_map ();
                   1514:            init_aspect_maps ();
                   1515:            notice_screen_contents_lost ();
                   1516:            notice_new_xcolors ();
                   1517:        }
                   1518: 
                   1519:        if (inhibit_frame != 0)
                   1520:            framecnt = 1;
                   1521: 
                   1522:        if (framecnt == 0)
                   1523:            init_drawing_frame ();
                   1524:     }
                   1525: }
                   1526: 
1.1.1.2   root     1527: void hsync_record_line_state (int lineno, enum nln_how how, int changed)
1.1       root     1528: {
1.1.1.2   root     1529:     char *state;
1.1       root     1530:     if (framecnt != 0)
                   1531:        return;
1.1.1.2   root     1532: 
                   1533:     state = linestate + lineno;
                   1534:     changed += frame_redraw_necessary;
                   1535: 
1.1       root     1536:     switch (how) {
                   1537:      case nln_normal:
1.1.1.2   root     1538:        *state = changed ? LINE_DECIDED : LINE_DONE;
1.1       root     1539:        break;
                   1540:      case nln_doubled:
1.1.1.2   root     1541:        *state = changed ? LINE_DECIDED_DOUBLE : LINE_DONE;
                   1542:        changed += state[1] != LINE_REMEMBERED_AS_PREVIOUS;
                   1543:        state[1] = changed ? LINE_AS_PREVIOUS : LINE_DONE_AS_PREVIOUS;
                   1544:        break;
                   1545:      case nln_nblack:
                   1546:        *state = changed ? LINE_DECIDED : LINE_DONE;
                   1547:        if (state[1] != LINE_REMEMBERED_AS_BLACK)
                   1548:            state[1] = LINE_BLACK;
1.1       root     1549:        break;
                   1550:      case nln_lower:
1.1.1.2   root     1551:        if (state[-1] == LINE_UNDECIDED)
                   1552:            state[-1] = LINE_BLACK;
                   1553:        *state = changed ? LINE_DECIDED : LINE_DONE;
1.1       root     1554:        break;
                   1555:      case nln_upper:
1.1.1.2   root     1556:        *state = changed ? LINE_DECIDED : LINE_DONE;
                   1557:        if (state[1] == LINE_UNDECIDED
                   1558:            || state[1] == LINE_REMEMBERED_AS_PREVIOUS
                   1559:            || state[1] == LINE_AS_PREVIOUS)
                   1560:            state[1] = LINE_BLACK;
1.1       root     1561:        break;
                   1562:     }
                   1563: }
                   1564: 
                   1565: void notice_interlace_seen (void)
                   1566: {
                   1567:     interlace_seen = 1;
                   1568: }
                   1569: 
                   1570: void reset_drawing (void)
                   1571: {
                   1572:     int i;
                   1573: 
                   1574:     inhibit_frame = 0;
                   1575:     uae_sem_init (&gui_sem, 0, 1);
                   1576: 
                   1577: #ifdef PICASSO96
                   1578:     InitPicasso96 ();
                   1579:     picasso_on = 0;
                   1580:     picasso_requested_on = 0;
                   1581:     gfx_set_picasso_state (0);
                   1582: #endif
                   1583:     max_diwstop = 0;
                   1584: 
                   1585:     lores_factor = currprefs.gfx_lores ? 1 : 2;
                   1586:     lores_shift = currprefs.gfx_lores ? 0 : 1;
                   1587:     sprite_width = currprefs.gfx_lores ? 16 : 32;
                   1588: 
                   1589:     /*memset(blitcount, 0, sizeof(blitcount));  blitter debug */
                   1590:     for (i = 0; i < sizeof linestate / sizeof *linestate; i++)
                   1591:        linestate[i] = LINE_UNDECIDED;
                   1592: 
                   1593:     xlinebuffer = gfxvidinfo.bufmem;
                   1594: 
                   1595:     init_aspect_maps ();
                   1596: 
                   1597:     if (line_drawn == 0)
                   1598:        line_drawn = (char *)malloc (gfxvidinfo.height);
                   1599: 
                   1600:     init_row_map();
                   1601: 
                   1602:     last_redraw_point = 0;
                   1603: 
1.1.1.11! root     1604:     memset (spixels, 0, sizeof spixels);
        !          1605:     memset (&spixstate, 0, sizeof spixstate);
        !          1606: 
1.1       root     1607:     init_drawing_frame ();
                   1608: }
                   1609: 
                   1610: void drawing_init ()
                   1611: {
                   1612:     native2amiga_line_map = 0;
                   1613:     amiga2aspect_line_map = 0;
                   1614:     line_drawn = 0;
                   1615: 
                   1616:     gen_pfield_tables();
                   1617: }
                   1618: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.