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

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

unix.superglobalmegacorp.com

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