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

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

unix.superglobalmegacorp.com

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