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

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * Screen drawing functions
                      5:   *
                      6:   * Copyright 1995-1998 Bernd Schmidt
                      7:   * Copyright 1995 Alessandro Bissacco
                      8:   */
                      9: 
                     10: #include "sysconfig.h"
                     11: #include "sysdeps.h"
                     12: 
                     13: #include <ctype.h>
                     14: #include <assert.h>
                     15: 
                     16: #include "config.h"
                     17: #include "options.h"
                     18: #include "threaddep/penguin.h"
                     19: #include "uae.h"
                     20: #include "memory.h"
                     21: #include "custom.h"
                     22: #include "readcpu.h"
                     23: #include "newcpu.h"
                     24: #include "xwin.h"
                     25: #include "autoconf.h"
                     26: #include "gui.h"
                     27: #include "picasso96.h"
                     28: #include "drawing.h"
                     29: #include "p2c.h"
                     30: 
                     31: #if defined X86_ASSEMBLY
                     32: #define LORES_HACK
                     33: #endif
                     34: 
                     35: int lores_factor, lores_shift, sprite_width;
                     36: 
                     37: static int interlace_seen = 0;
                     38: 
                     39: static int dblpf_ind1[256], dblpf_ind2[256], dblpf_2nd1[256], dblpf_2nd2[256];
                     40: static int dblpf_aga1[256], dblpf_aga2[256], linear_map_256[256], lots_of_twos[256];
                     41: 
                     42: static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
                     43: 
                     44: /* Big lookup tables for planar to chunky conversion. */
                     45: 
                     46: uae_u32 hirestab_h[256][2];
                     47: uae_u32 lorestab_h[256][4];
                     48: 
                     49: uae_u32 hirestab_l[256][1];
                     50: uae_u32 lorestab_l[256][2];
                     51: 
                     52: static uae_u32 clxtab[256];
                     53: 
                     54: /* Video buffer description structure. Filled in by the graphics system
                     55:  * dependent code. */
                     56: 
                     57: struct vidbuf_description gfxvidinfo;
                     58: 
                     59: /* The color lookup table. */
                     60: 
                     61: xcolnr xcolors[4096];
                     62: 
                     63: struct color_entry colors_for_drawing;
                     64: 
                     65: /* 880 isn't a magic number, it's a safe number with some padding at the end.
                     66:  * This used to be 1000, but that's excessive. (840 is too low). I'm too lazy
                     67:  * to figure out the exact space needed. */
                     68: union {
                     69:     /* Let's try to align this thing. */
                     70:     double uupzuq;
                     71:     long int cruxmedo;
                     72:     unsigned char apixels[880];
                     73: } pixdata;
                     74: 
                     75: uae_u32 ham_linebuf[880];
                     76: uae_u32 aga_linebuf[880], *aga_lbufptr;
                     77: 
                     78: char *xlinebuffer;
                     79: 
                     80: static int *amiga2aspect_line_map, *native2amiga_line_map;
                     81: static char *row_map[2049];
                     82: static int max_drawn_amiga_line;
                     83: 
                     84: /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham6 */
                     85: typedef void (*line_draw_func)(int, int);
                     86: 
                     87: #define LINE_UNDECIDED 1
                     88: #define LINE_DECIDED 2
                     89: #define LINE_DECIDED_DOUBLE 3
                     90: #define LINE_AS_PREVIOUS 4
1.1.1.2 ! root       91: #define LINE_BLACK 5
        !            92: #define LINE_REMEMBERED_AS_BLACK 6
1.1       root       93: #define LINE_DONE 7
                     94: #define LINE_DONE_AS_PREVIOUS 8
                     95: #define LINE_REMEMBERED_AS_PREVIOUS 9
                     96: 
                     97: static char *line_drawn;
                     98: static char linestate[(maxvpos + 1)*2 + 1];
                     99: 
                    100: uae_u8 line_data[(maxvpos+1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
                    101: 
                    102: static int min_diwstart, max_diwstop, prev_x_adjust, linetoscr_x_adjust, linetoscr_right_x;
                    103: static int linetoscr_x_adjust_bytes;
                    104: static int thisframe_y_adjust, prev_y_adjust;
                    105: static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen;
                    106: static int extra_y_adjust;
                    107: int thisframe_first_drawn_line, thisframe_last_drawn_line;
                    108: 
                    109: static int last_redraw_point;
                    110: 
                    111: static int first_drawn_line, last_drawn_line;
                    112: static int first_block_line, last_block_line;
                    113: 
                    114: /* These are generated by the drawing code from the line_decisions array for
                    115:  * each line that needs to be drawn. */
                    116: static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplhires;
                    117: static int bpldelay1, bpldelay2;
                    118: static int plfpri[3];
                    119: 
                    120: int picasso_requested_on;
                    121: int picasso_on;
                    122: 
                    123: uae_sem_t gui_sem;
                    124: int inhibit_frame;
                    125: 
                    126: int framecnt = 0;
                    127: static int frame_redraw_necessary;
                    128: static int picasso_redraw_necessary;
                    129: 
                    130: static __inline__ void count_frame (void)
                    131: {
                    132:     framecnt++;
                    133:     if (framecnt >= currprefs.framerate)
                    134:        framecnt = 0;
                    135: }
                    136: 
                    137: int coord_native_to_amiga_x (int x)
                    138: {
                    139:     x += linetoscr_x_adjust;
                    140:     x <<= (1 - lores_shift);
                    141:     return x + 2*DISPLAY_LEFT_SHIFT;
                    142: }
                    143: 
                    144: int coord_native_to_amiga_y (int y)
                    145: {
                    146:     return native2amiga_line_map[y] + thisframe_y_adjust - minfirstline;
                    147: }
                    148: 
                    149: void notice_screen_contents_lost (void)
                    150: {
                    151:     picasso_redraw_necessary = 1;
                    152:     frame_redraw_necessary = 2;
                    153: }
                    154: 
                    155: static struct decision *dp_for_drawing;
                    156: static struct draw_info *dip_for_drawing;
                    157: 
                    158: void record_diw_line (int first, int last)
                    159: {
                    160:     if (last > max_diwstop)
                    161:        max_diwstop = last;
                    162:     if (first < min_diwstart)
                    163:        min_diwstart = first;
                    164: }
                    165: 
                    166: /*
                    167:  * Screen update macros/functions
                    168:  */
                    169: 
                    170: static unsigned int ham_lastcolor;
                    171: 
                    172: static void init_ham_decoding(int first)
                    173: {
                    174:     int pix = dp_for_drawing->diwfirstword;
                    175:     ham_lastcolor = colors_for_drawing.color_regs[0];
                    176:     while (pix < first) {
                    177:        int pv = pixdata.apixels[pix];
                    178:        switch(pv & 0x30) {
                    179:         case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
                    180:         case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
                    181:         case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
                    182:         case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
                    183:        }
                    184:        pix++;
                    185:     }
                    186: }
                    187: 
                    188: static void decode_ham6 (int pix, int stoppos)
                    189: {
                    190:     uae_u32 *buf = ham_linebuf;
                    191: 
                    192:     if (!bplham || bplplanecnt != 6)
                    193:        return;
                    194: 
                    195:     if (stoppos > dp_for_drawing->diwlastword)
                    196:        stoppos = dp_for_drawing->diwlastword;
                    197:     if (pix < dp_for_drawing->diwfirstword) {
                    198:        ham_lastcolor = colors_for_drawing.color_regs[0];
                    199:        pix = dp_for_drawing->diwfirstword;
                    200:     }
                    201: #ifdef LORES_HACK
                    202:     if (currprefs.gfx_lores == 2)
                    203:        pix <<= 1, stoppos <<= 1;
                    204: #endif
                    205:     while (pix < stoppos) {
                    206:        int pv = pixdata.apixels[pix];
                    207:        switch(pv & 0x30) {
                    208:         case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
                    209:         case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
                    210:         case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
                    211:         case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
                    212:        }
                    213: 
                    214:        buf[pix++] = ham_lastcolor;
                    215:     }
                    216: }
                    217: #if 0
                    218: static void decode_ham_aga (int pix, int stoppos)
                    219: {
                    220:     static uae_u32 lastcolor;
                    221:     uae_u32 *buf = ham_linebuf;
                    222: 
                    223:     if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8))
                    224:        return;
                    225: 
                    226:     if (pix <= dp_for_drawing->diwfirstword) {
                    227:        pix = dp_for_drawing->diwfirstword;
                    228:        lastcolor = colors_for_drawing.color_regs[0];
                    229:     }
                    230: 
                    231:     if (dp_for_drawing->bplplanecnt == 6) {
                    232:        /* HAM 6 */
                    233:        while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
                    234:            int pv = pixdata.apixels[pix];
                    235:            switch(pv & 0x30) {
                    236:             case 0x00: lastcolor = colors_for_drawing.color_regs[pv]; break;
                    237:             case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break;
                    238:             case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break;
                    239:             case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break;
                    240:            }
                    241:            buf[pix++] = lastcolor;
                    242:        }
                    243:     } else if (dp_for_drawing->bplplanecnt == 8) {
                    244:        /* HAM 8 */
                    245:        while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
                    246:            int pv = pixdata.apixels[pix];
                    247:            switch(pv & 0x3) {
                    248:             case 0x0: lastcolor = colors_for_drawing.color_regs[pv >> 2]; break;
                    249:             case 0x1: lastcolor &= 0xFFFF03; lastcolor |= (pv & 0xFC); break;
                    250:             case 0x2: lastcolor &= 0x03FFFF; lastcolor |= (pv & 0xFC) << 16; break;
                    251:             case 0x3: lastcolor &= 0xFF03FF; lastcolor |= (pv & 0xFC) << 8; break;
                    252:            }
                    253:            buf[pix++] = lastcolor;
                    254:        }
                    255:     }
                    256: }
                    257: #endif
                    258: 
1.1.1.2 ! root      259: static int linetoscr_double_offset;
        !           260: 
1.1       root      261: #if AGA_CHIPSET != 0
                    262: /* WARNING: Not too much of this will work correctly yet. */
                    263: 
1.1.1.2 ! root      264: static void pfield_linetoscr_aga (int pix, int lframe_end, int diw_end, int stoppos)
1.1       root      265: {
                    266:     uae_u32 *buf = aga_lbufptr;
                    267:     int i;
1.1.1.2 ! root      268:     int xor = (uae_u8)(dp_for_drawing->bplcon4 >> 8);
        !           269:     int oldpix = pix;
1.1       root      270: 
1.1.1.2 ! root      271:     buf -= pix;
1.1       root      272: 
                    273:     for (i = 0; i < stoppos; i++)
                    274:        pixdata.apixels[i] ^= xor;
                    275: 
1.1.1.2 ! root      276:     while (pix < lframe_end) {
1.1       root      277:        buf[pix++] = colors_for_drawing.color_regs[0];
                    278:     }
                    279:     if (bplham) {
1.1.1.2 ! root      280:        while (pix < diw_end) {
1.1       root      281:            uae_u32 d = ham_linebuf[pix];
                    282:            buf[pix] = d;
                    283:            pix++;
                    284:        }
                    285:     } else if (bpldualpf) {
1.1.1.2 ! root      286: #if 0 /* FIXME */
1.1       root      287:        /* Dual playfield */
                    288:        int *lookup = bpldualpfpri ? dblpf_aga2 : dblpf_aga1;
                    289:        int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1;
1.1.1.2 ! root      290:        while (pix < diw_end) {
1.1       root      291:            int pixcol = pixdata.apixels[pix];
                    292:            int pfno = lookup_no[pixcol];
                    293: 
                    294:            if (spixstate[pix]) {
                    295:                buf[pix] = colors_for_drawing.color_regs[pixcol];
                    296:            } else {
                    297:                int val = lookup[pixdata.apixels[pix]];
                    298:                if (pfno == 2)
1.1.1.2 ! root      299:                    val += dblpfofs[(dp_for_drawing->bplcon2 >> 10) & 7];
1.1       root      300:                buf[pix] = colors_for_drawing.color_regs[val];
                    301:            }
                    302:            pix++;
                    303:        }
1.1.1.2 ! root      304: #endif
1.1       root      305:     } else if (bplehb) {
1.1.1.2 ! root      306:        while (pix < diw_end) {
1.1       root      307:            int pixcol = pixdata.apixels[pix];
                    308:            uae_u32 d = colors_for_drawing.color_regs[pixcol];
                    309:            /* What about sprites? */
                    310:            if (pixcol & 0x20)
                    311:                d = (d & 0x777777) >> 1;
                    312:            buf[pix] = d;
                    313:            pix++;
                    314:        }
                    315:     } else {
1.1.1.2 ! root      316:        while (pix < diw_end) {
1.1       root      317:            int pixcol = pixdata.apixels[pix];
                    318:            buf[pix] = colors_for_drawing.color_regs[pixcol];
                    319:            pix++;
                    320:        }
                    321:     }
                    322:     while (pix < stoppos) {
                    323:        buf[pix++] = colors_for_drawing.color_regs[0];
                    324:     }
                    325:     aga_lbufptr += pix - oldpix;
                    326: }
                    327: 
1.1.1.2 ! root      328: static void aga_translate32 (int start, int stop)
1.1       root      329: {
1.1.1.2 ! root      330:     memcpy (((uae_u32 *)xlinebuffer) + start, aga_lbufptr, 4*(stop-start));
        !           331:     aga_lbufptr += stop - start;
1.1       root      332: }
                    333: 
1.1.1.2 ! root      334: static void aga_translate16 (int start, int stop)
1.1       root      335: {
                    336:     int i;
                    337:     for (i = start; i < stop; i++) {
                    338:        uae_u32 d = aga_linebuf[i];
                    339:        uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
                    340:        ((uae_u16 *)xlinebuffer)[i] = xcolors[v];
                    341:     }
                    342: }
                    343: 
1.1.1.2 ! root      344: static void aga_translate8 (int start, int stop)
1.1       root      345: {
                    346:     int i;
                    347:     for (i = start; i < stop; i++) {
                    348:        uae_u32 d = aga_linebuf[i];
                    349:        uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
                    350:        ((uae_u8 *)xlinebuffer)[i] = xcolors[v];
                    351:     }
                    352: }
                    353: 
1.1.1.2 ! root      354: static void aga_fill_line_32 (char *buf, int start, int stop)
        !           355: {
        !           356:     int i;
        !           357:     for (i = start; i < stop; i++) {
        !           358:        ((uae_u32 *)buf)[i] = colors_for_drawing.color_regs[0];
        !           359:     }
        !           360: }
        !           361: 
        !           362: static void fill_line (void)
        !           363: {
        !           364:     aga_fill_line_32 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width);
        !           365: }
        !           366: 
        !           367: #else /* no AGA_CHIPSET */
1.1       root      368: 
                    369: #define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE, CONVERT) \
                    370: static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \
                    371: { \
                    372:     TYPE *buf = ((TYPE *)xlinebuffer); \
                    373: /*    int oldpix = pix;*/ \
                    374:     /* These are different for register-allocation purposes. */ \
                    375:     TYPE d1, d2; \
                    376:     int offset; \
                    377: \
                    378:     if (DO_DOUBLE) offset = linetoscr_double_offset / sizeof(TYPE); \
                    379: \
                    380:     d1 = CONVERT(colors_for_drawing.acolors[0]); \
                    381:     while (pix < lframe_end) { \
                    382:        buf[pix] = d1; if (DO_DOUBLE) buf[pix+offset] = d1; \
                    383:        pix++; \
                    384:     } \
                    385:     if (bplham && bplplanecnt == 6) { \
                    386:        /* HAM 6 */ \
                    387:        while (pix < diw_end) { \
                    388:            TYPE d = CONVERT(xcolors[ham_linebuf[pix]]); \
                    389:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                    390:            pix++; \
                    391:        } \
                    392:     } else if (bpldualpf) { \
                    393:        /* Dual playfield */ \
                    394:        int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; \
                    395:        while (pix < diw_end) { \
                    396:            int pixcol = pixdata.apixels[pix]; \
                    397:            TYPE d; \
                    398:            d = CONVERT(colors_for_drawing.acolors[lookup[pixcol]]); \
                    399:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                    400:            pix++; \
                    401:        } \
                    402:     } else if (bplehb) { \
                    403:        while (pix < diw_end) { \
                    404:            int p = pixdata.apixels[pix]; \
                    405:            TYPE d = CONVERT (colors_for_drawing.acolors[p]); \
                    406:            if (p >= 32) d = CONVERT(xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]); \
                    407:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                    408:            pix++; \
                    409:        } \
                    410:     } else { \
                    411:        while (pix < diw_end) { \
                    412:            TYPE d = CONVERT (colors_for_drawing.acolors[pixdata.apixels[pix]]); \
                    413:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
                    414:            pix++; \
                    415:        } \
                    416:     } \
                    417:     d2 = CONVERT (colors_for_drawing.acolors[0]); \
                    418:     while (pix < stoppos) { \
                    419:        buf[pix] = d2; if (DO_DOUBLE) buf[pix+offset] = d2; \
                    420:        pix++; \
                    421:     } \
                    422: }
                    423: 
                    424: #define FILL_LINE(NAME, TYPE, CONVERT) \
1.1.1.2 ! root      425: static void NAME (char *buf, int start, int stop) \
1.1       root      426: { \
                    427:     TYPE *b = (TYPE *)buf; \
                    428:     int i;\
                    429:     xcolnr col = colors_for_drawing.acolors[0]; \
                    430:     for (i = start; i < stop; i++) \
                    431:        b[i] = CONVERT (col); \
                    432: }
                    433: 
                    434: LINE_TO_SCR(pfield_linetoscr_8, uae_u8, 0,)
                    435: LINE_TO_SCR(pfield_linetoscr_16, uae_u16, 0,)
                    436: LINE_TO_SCR(pfield_linetoscr_32, uae_u32, 0,)
                    437: LINE_TO_SCR(pfield_linetoscr_8_double_slow, uae_u8, 1,)
                    438: LINE_TO_SCR(pfield_linetoscr_16_double_slow, uae_u16, 1,)
                    439: LINE_TO_SCR(pfield_linetoscr_32_double_slow, uae_u32, 1,)
                    440: 
                    441: FILL_LINE(fill_line_8, uae_u8,)
                    442: FILL_LINE(fill_line_16, uae_u16,)
                    443: FILL_LINE(fill_line_32, uae_u32,)
                    444: 
                    445: #ifdef HAVE_UAE_U24
                    446: LINE_TO_SCR(pfield_linetoscr_24, uae_u24, 0, uae24_convert)
                    447: LINE_TO_SCR(pfield_linetoscr_24_double_slow, uae_u24, 1, uae24_convert)
                    448: FILL_LINE(fill_line_24, uae_u24, uae24_convert)
                    449: #else
                    450: /* Dummy versions */
                    451: static void pfield_linetoscr_24 (int pix, int lframe_end, int diw_end, int stoppos)
                    452: {
                    453: }
                    454: static void pfield_linetoscr_24_double_slow (int pix, int lframe_end, int diw_end, int stoppos)
                    455: {
                    456: }
                    457: static void fill_line_24 (char *buf, int start, int stop)
                    458: {
                    459: }
                    460: #endif
                    461: 
                    462: static __inline__ void fill_line_full (void)
                    463: {
                    464:     switch (gfxvidinfo.pixbytes) {
1.1.1.2 ! root      465:      case 1: fill_line_8 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
        !           466:      case 2: fill_line_16 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
        !           467:      case 3: fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
        !           468:      case 4: fill_line_32 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
1.1       root      469:     }
                    470: }
                    471: 
                    472: #define fill_line fill_line_full
                    473: 
                    474: #define pfield_linetoscr_full8 pfield_linetoscr_8
                    475: #define pfield_linetoscr_full16 pfield_linetoscr_16
                    476: #define pfield_linetoscr_full24 pfield_linetoscr_24
                    477: #define pfield_linetoscr_full32 pfield_linetoscr_32
                    478: 
                    479: #define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow
                    480: #define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow
                    481: #define pfield_linetoscr_full24_double pfield_linetoscr_24_double_slow
                    482: #define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow
                    483: 
                    484: #if 1
                    485: #undef fill_line
                    486: static __inline__ void fill_line (void)
                    487: {
                    488:     int shift;
                    489:     int nints, nrem;
                    490:     int *start;
                    491:     xcolnr val;
                    492: 
                    493: #ifdef HAVE_UAE_U24
                    494:     if (gfxvidinfo.pixbytes == 3) {
                    495:        fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width);
                    496:        return;
                    497:     }
                    498: #endif
                    499:     
                    500:     shift = 0;
                    501:     if (gfxvidinfo.pixbytes == 2)
                    502:        shift = 1;
                    503:     if (gfxvidinfo.pixbytes == 4)
                    504:        shift = 2;
                    505: 
                    506:     nints = gfxvidinfo.width >> (2-shift);
                    507:     nrem = nints & 7;
                    508:     nints &= ~7;
                    509:     start = (int *)(((char *)xlinebuffer) + (linetoscr_x_adjust << shift));
                    510:     val = colors_for_drawing.acolors[0];
                    511:     for (; nints > 0; nints -= 8, start += 8) {
                    512:        *start = val;
                    513:        *(start+1) = val;
                    514:        *(start+2) = val;
                    515:        *(start+3) = val;
                    516:        *(start+4) = val;
                    517:        *(start+5) = val;
                    518:        *(start+6) = val;
                    519:        *(start+7) = val;
                    520:     }
                    521: 
                    522:     switch (nrem) {
                    523:      case 7:
                    524:        *start++ = val;
                    525:      case 6:
                    526:        *start++ = val;
                    527:      case 5:
                    528:        *start++ = val;
                    529:      case 4:
                    530:        *start++ = val;
                    531:      case 3:
                    532:        *start++ = val;
                    533:      case 2:
                    534:        *start++ = val;
                    535:      case 1:
                    536:        *start = val;
                    537:     }
                    538: }
                    539: 
                    540: #ifdef X86_ASSEMBLY
                    541: 
                    542: #undef pfield_linetoscr_full8
                    543: /* The types are lies, of course. */
1.1.1.2 ! root      544: extern void pfield_linetoscr_normal_asm8 (void) __asm__("pfield_linetoscr_normal_asm8");
        !           545: extern void pfield_linetoscr_ehb_asm8 (void) __asm__("pfield_linetoscr_ehb_asm8");
        !           546: extern void pfield_linetoscr_ham6_asm8 (void) __asm__("pfield_linetoscr_ham6_asm8");
        !           547: extern void pfield_linetoscr_dualpf_asm8 (void) __asm__("pfield_linetoscr_dualpf_asm8");
        !           548: extern void pfield_linetoscr_hdouble_asm8 (void) __asm__("pfield_linetoscr_hdouble_asm8");
        !           549: extern void pfield_linetoscr_hdouble_dpf_asm8 (void) __asm__("pfield_linetoscr_hdouble_dpf_asm8");
        !           550: extern void pfield_linetoscr_hdouble_ehb_asm8 (void) __asm__("pfield_linetoscr_hdouble_ehb_asm8");
        !           551: extern void pfield_linetoscr_asm8 (void (*) (void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm8");
1.1       root      552: 
1.1.1.2 ! root      553: static void pfield_linetoscr_full8 (int pix, int lframe_end, int diw_end, int stoppos)
1.1       root      554: {
                    555:     int lframe_end_1, diw_end_1;
                    556: 
                    557:     lframe_end_1 = pix + ((lframe_end - pix) & ~3);
                    558:     diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
                    559: 
                    560:     if (bplham && bplplanecnt == 6) {
1.1.1.2 ! root      561:        pfield_linetoscr_asm8 (pfield_linetoscr_ham6_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1       root      562:     } else if (bpldualpf) {
                    563: #ifdef LORES_HACK
                    564:        if (currprefs.gfx_lores == 2)
1.1.1.2 ! root      565:            pfield_linetoscr_asm8 (pfield_linetoscr_hdouble_dpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
1.1       root      566:                                   bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
                    567:        else
                    568: #endif
1.1.1.2 ! root      569:            pfield_linetoscr_asm8 (pfield_linetoscr_dualpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
1.1       root      570:                                  bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
                    571:     } else if (bplehb) {
                    572: #ifdef LORES_HACK
                    573:        if (currprefs.gfx_lores == 2)
1.1.1.2 ! root      574:            pfield_linetoscr_asm8 (pfield_linetoscr_hdouble_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1       root      575:        else
                    576: #endif
1.1.1.2 ! root      577:            pfield_linetoscr_asm8 (pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1       root      578:     } else {
                    579: #ifdef LORES_HACK
                    580:        if (currprefs.gfx_lores == 2)
1.1.1.2 ! root      581:            pfield_linetoscr_asm8 (pfield_linetoscr_hdouble_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1       root      582:        else
                    583: #endif
1.1.1.2 ! root      584:            pfield_linetoscr_asm8 (pfield_linetoscr_normal_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1       root      585:     }
                    586: 
                    587:     /* The assembly functions work on aligned data, so we may have to do some
                    588:      * additional work at the edges. */
                    589:     if (lframe_end != lframe_end_1) {
                    590:        int i, c = colors_for_drawing.acolors[0];
                    591:        for (i = lframe_end_1; i < lframe_end; i++)
                    592:            xlinebuffer[i] = c;
                    593:     }
                    594:     if (diw_end != diw_end_1) {
                    595:        int i, c = colors_for_drawing.acolors[0];
                    596:        for (i = diw_end; i < diw_end_1; i++)
                    597:            xlinebuffer[i] = c;
                    598:     }
                    599: }
                    600: 
                    601: #undef pfield_linetoscr_full16
1.1.1.2 ! root      602: extern void pfield_linetoscr_normal_asm16 (void) __asm__("pfield_linetoscr_normal_asm16");
        !           603: extern void pfield_linetoscr_ehb_asm16 (void) __asm__("pfield_linetoscr_ehb_asm16");
        !           604: extern void pfield_linetoscr_ham6_asm16 (void) __asm__("pfield_linetoscr_ham6_asm16");
        !           605: extern void pfield_linetoscr_dualpf_asm16 (void) __asm__("pfield_linetoscr_dualpf_asm16");
        !           606: extern void pfield_linetoscr_hdouble_asm16 (void) __asm__("pfield_linetoscr_hdouble_asm16");
        !           607: extern void pfield_linetoscr_hdouble_dpf_asm16 (void) __asm__("pfield_linetoscr_hdouble_dpf_asm16");
        !           608: extern void pfield_linetoscr_hdouble_ehb_asm16 (void) __asm__("pfield_linetoscr_hdouble_ehb_asm16");
        !           609: extern void pfield_linetoscr_asm16 (void (*) (void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm16");
1.1       root      610: 
1.1.1.2 ! root      611: static void pfield_linetoscr_full16 (int pix, int lframe_end, int diw_end, int stoppos)
1.1       root      612: {
                    613:     int lframe_end_1, diw_end_1;
                    614: 
                    615:     lframe_end_1 = pix + ((lframe_end - pix) & ~3);
                    616:     diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
                    617: 
                    618:     if (bplham && bplplanecnt == 6) {
1.1.1.2 ! root      619:        pfield_linetoscr_asm16 (pfield_linetoscr_ham6_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1       root      620:     } else if (bpldualpf) {
                    621: #ifdef LORES_HACK
                    622:        if (currprefs.gfx_lores == 2)
1.1.1.2 ! root      623:            pfield_linetoscr_asm16 (pfield_linetoscr_hdouble_dpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
1.1       root      624:                                   bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
                    625:        else
                    626: #endif
1.1.1.2 ! root      627:            pfield_linetoscr_asm16 (pfield_linetoscr_dualpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
1.1       root      628:                                   bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
                    629:     } else if (bplehb) {
                    630: #ifdef LORES_HACK
                    631:        if (currprefs.gfx_lores == 2)
1.1.1.2 ! root      632:            pfield_linetoscr_asm16 (pfield_linetoscr_hdouble_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1       root      633:        else
                    634: #endif
1.1.1.2 ! root      635:            pfield_linetoscr_asm16 (pfield_linetoscr_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1       root      636:     } else {
                    637: #ifdef LORES_HACK
                    638:        if (currprefs.gfx_lores == 2)
1.1.1.2 ! root      639:            pfield_linetoscr_asm16 (pfield_linetoscr_hdouble_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1       root      640:        else
                    641: #endif
1.1.1.2 ! root      642:            pfield_linetoscr_asm16 (pfield_linetoscr_normal_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1       root      643:     }
                    644: 
                    645:     /* The assembly functions work on aligned data, so we may have to do some
                    646:      * additional work at the edges. */
                    647:     if (lframe_end != lframe_end_1) {
                    648:        int i, c = colors_for_drawing.acolors[0];
                    649:        for (i = lframe_end_1; i < lframe_end; i++)
                    650:            ((uae_u16 *)xlinebuffer)[i] = c;
                    651:     }
                    652:     if (diw_end != diw_end_1) {
                    653:        int i, c = colors_for_drawing.acolors[0];
                    654:        for (i = diw_end; i < diw_end_1; i++)
                    655:            ((uae_u16 *)xlinebuffer)[i] = c;
                    656:     }
                    657: }
                    658: #endif
                    659: 
                    660: #ifndef NO_DOUBLING_LINETOSCR
                    661: #define NO_DOUBLING_LINETOSCR
                    662: #endif
                    663: 
                    664: #endif
                    665: 
                    666: #ifdef NO_DOUBLING_LINETOSCR
                    667: #undef pfield_linetoscr_full8_double
                    668: #undef pfield_linetoscr_full16_double
1.1.1.2 ! root      669: static void pfield_linetoscr_full8_double (int start, int lframe_end, int diw_end, int stop)
1.1       root      670: {
                    671:     char *oldxlb = (char *)xlinebuffer;
1.1.1.2 ! root      672:     pfield_linetoscr_full8 (start, lframe_end, diw_end, stop);
1.1       root      673:     xlinebuffer = oldxlb + linetoscr_double_offset;
1.1.1.2 ! root      674:     pfield_linetoscr_full8 (start, lframe_end, diw_end, stop);
1.1       root      675: }
1.1.1.2 ! root      676: static void pfield_linetoscr_full16_double (int start, int lframe_end, int diw_end, int stop)
1.1       root      677: {
                    678:     char *oldxlb = (char *)xlinebuffer;
1.1.1.2 ! root      679:     pfield_linetoscr_full16 (start, lframe_end, diw_end, stop);
1.1       root      680:     xlinebuffer = oldxlb + linetoscr_double_offset;
1.1.1.2 ! root      681:     pfield_linetoscr_full16 (start, lframe_end, diw_end, stop);
1.1       root      682: }
                    683: #endif
                    684: 
1.1.1.2 ! root      685: #endif /* no AGA_CHIPSET */
        !           686: 
1.1       root      687: static int linetoscr_diw_end, linetoscr_diw_start;
                    688: 
                    689: /* Initialize the variables necessary for drawing a line.
                    690:  * This involves setting up start/stop positions and display window
                    691:  * borders. Also, since the drawing code may not fully overwrite all
                    692:  * releveant areas in the pixdata.apixels array for speed reasons, parts of
                    693:  * it must possibly be cleared here. */
                    694: static void pfield_init_linetoscr (void)
                    695: {
                    696:     int ddf_left, ddf_right;
                    697:     int mindelay = bpldelay1, maxdelay = bpldelay2;
                    698:     if (bpldelay1 > bpldelay2)
                    699:        maxdelay = bpldelay1, mindelay = bpldelay2;
                    700: 
                    701:     linetoscr_diw_start = dp_for_drawing->diwfirstword;
                    702:     linetoscr_diw_end = dp_for_drawing->diwlastword;
                    703: 
                    704:     /* We should really look at DDF also when calculating max_diwstop/min_diwstrt,
                    705:      * so that centering works better, but I'm afraid that might cost too many
                    706:      * cycles. Plus it's dangerous, see the code below that handles the case
                    707:      * with sprites. */
                    708:     if (dip_for_drawing->nr_sprites == 0) {
                    709:        int hiresadjust = bplhires ? 4 : 8;
                    710:        ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
                    711:        ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
                    712: 
                    713:        if (linetoscr_diw_start < ddf_left)
                    714:            linetoscr_diw_start = ddf_left;
                    715:        if (linetoscr_diw_end > ddf_right)
                    716:            linetoscr_diw_end = ddf_right;
                    717: 
                    718:        if (mindelay != maxdelay) {
                    719:            /* Raahh...
                    720:             * We just clear the maximum amount of space that may need to be
                    721:             * cleared. We could do this exactly, but it would come out slower
                    722:             * because of the overhead. */
                    723:            if (currprefs.gfx_lores == 2) {
                    724:                fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_left>>1), 15);
                    725:                fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_right>>1) - 15, 15);
                    726:            } else if (currprefs.gfx_lores) {
                    727:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 15);
                    728:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 15, 15);
                    729:            } else {
                    730:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 30);
                    731:                fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 30, 30);
                    732:            }
                    733:        }
                    734:     } else {
                    735:        int hiresadjust = bplhires ? 4 : 8;
                    736:        /* We swap mindelay and maxdelay here to get rid of the mindelay != maxdelay check.
                    737:         * Since we have to do a memset anyway (because there may be sprites),
                    738:         * we might as well clear all at once. */
                    739:        ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
                    740:        ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
                    741:        if (linetoscr_diw_start < ddf_left) {
                    742:            int strt = linetoscr_diw_start;
                    743:            int stop = ddf_left;
                    744: #ifdef LORES_HACK
                    745:            if (currprefs.gfx_lores == 2)
                    746:                strt >>= 1, stop >>= 1;
                    747: #endif
                    748:            if (strt < stop)
                    749:                fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
                    750:        }
                    751: 
                    752:        if (linetoscr_diw_end > ddf_right) {
                    753:            int strt = ddf_right;
                    754:            int stop = linetoscr_diw_end;
                    755: #ifdef LORES_HACK
                    756:            if (currprefs.gfx_lores == 2)
                    757:                strt >>= 1, stop >>= 1;
                    758: #endif
                    759:            if (strt < stop)
                    760:                fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
                    761:        }
                    762:     }
                    763:     /* Perverse cases happen. */
                    764:     if (linetoscr_diw_end < linetoscr_diw_start)
                    765:        linetoscr_diw_end = linetoscr_diw_start;
                    766: }
                    767: 
                    768: static void pfield_do_linetoscr(int start, int stop)
                    769: {
                    770:     int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
                    771: 
                    772:     if (stop > linetoscr_right_x)
                    773:        stop = linetoscr_right_x;
                    774:     if (start < linetoscr_x_adjust)
                    775:        start = linetoscr_x_adjust;
                    776: 
                    777:     if (lframe_end < start)
                    778:        lframe_end = start;
                    779:     if (diw_end > stop)
                    780:        diw_end = stop;
                    781: 
                    782:     if (start >= stop)
                    783:        return;
                    784: 
                    785: #if AGA_CHIPSET == 0
                    786:     if (start == linetoscr_x_adjust && stop == linetoscr_right_x) {
                    787:        switch (gfxvidinfo.pixbytes) {
                    788:         case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
                    789:         case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
                    790:         case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
                    791:         case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
                    792:        }
                    793:     } else {
                    794:        switch (gfxvidinfo.pixbytes) {
                    795:         case 1: pfield_linetoscr_8 (start, lframe_end, diw_end, stop); break;
                    796:         case 2: pfield_linetoscr_16 (start, lframe_end, diw_end, stop); break;
                    797:         case 3: pfield_linetoscr_24 (start, lframe_end, diw_end, stop); break;
                    798:         case 4: pfield_linetoscr_32 (start, lframe_end, diw_end, stop); break;
                    799:        }
                    800:     }
                    801: #else
1.1.1.2 ! root      802:     pfield_linetoscr_aga (start, lframe_end, diw_end, stop);
1.1       root      803: #endif
                    804: }
                    805: 
1.1.1.2 ! root      806: static void pfield_do_fill_line (int start, int stop)
1.1       root      807: {
                    808:     if (stop > linetoscr_right_x)
                    809:        stop = linetoscr_right_x;
                    810:     if (start < linetoscr_x_adjust)
                    811:        start = linetoscr_x_adjust;
                    812: 
                    813:     if (start >= stop)
                    814:        return;
                    815: 
1.1.1.2 ! root      816: #if AGA_CHIPSET == 0
1.1       root      817:     switch (gfxvidinfo.pixbytes) {
                    818:      case 1: fill_line_8 (xlinebuffer, start, stop); break;
                    819:      case 2: fill_line_16 (xlinebuffer, start, stop); break;
                    820:      case 3: fill_line_24 (xlinebuffer, start, stop); break;
                    821:      case 4: fill_line_32 (xlinebuffer, start, stop); break;
                    822:     }
1.1.1.2 ! root      823: #else
        !           824:     aga_fill_line_32 (xlinebuffer, start, stop);
        !           825:     /* FIXME */
        !           826: #endif
1.1       root      827: }
                    828: 
1.1.1.2 ! root      829: static void pfield_do_linetoscr_full (int double_line)
1.1       root      830: {
                    831:     int start = linetoscr_x_adjust, stop = start + gfxvidinfo.width;
                    832:     int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
                    833:     if (lframe_end < start)
                    834:        lframe_end = start;
                    835:     if (diw_end > stop)
                    836:        diw_end = stop;
                    837: 
                    838: #if AGA_CHIPSET == 0
                    839:     if (double_line) {
                    840:        switch (gfxvidinfo.pixbytes) {
                    841:         case 1: pfield_linetoscr_full8_double (start, lframe_end, diw_end, stop); break;
                    842:         case 2: pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); break;
                    843:         case 3: pfield_linetoscr_full24_double (start, lframe_end, diw_end, stop); break;
                    844:         case 4: pfield_linetoscr_full32_double (start, lframe_end, diw_end, stop); break;
                    845:        }
                    846:     } else
                    847:        switch (gfxvidinfo.pixbytes) {
                    848:         case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
                    849:         case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
                    850:         case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
                    851:         case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
                    852:        }
                    853: #else
1.1.1.2 ! root      854:     pfield_linetoscr_aga (start, lframe_end, diw_end, stop);
1.1       root      855: #endif
                    856: }
                    857: 
1.1.1.2 ! root      858: static void gen_pfield_tables (void)
1.1       root      859: {
                    860:     int i;
                    861:     union {
                    862:        struct {
                    863:            uae_u8 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
                    864:        } foo;
                    865:        struct {
                    866:            uae_u32 a, b, c, d;
                    867:        } bar;
                    868:     } baz;
                    869: 
                    870:     /* For now, the AGA stuff is broken in the dual playfield case. We encode
                    871:      * sprites in dpf mode by ORing the pixel value with 0x80. To make dual
                    872:      * playfield rendering easy, the lookup tables contain are made linear for
                    873:      * values >= 128. That only works for OCS/ECS, though. */
                    874: 
                    875:     for (i = 0; i < 256; i++) {
                    876:        int plane1 = (i & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8);
                    877:        int plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8);
                    878:        dblpf_2nd1[i] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
                    879:        dblpf_2nd2[i] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
                    880:        if (plane2 > 0)
                    881:            plane2 += 8;
                    882:        dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1);
                    883:        dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2);
                    884: 
                    885:        lots_of_twos[i] = i == 0 ? 0 : 2;
                    886:        linear_map_256[i] = i;
                    887:     }
                    888: 
                    889:     for (i = 0; i < 256; i++) {
                    890:        /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */
                    891:        baz.foo.a = i & 64 ? 1 : 0;
                    892:        baz.foo.b = i & 16 ? 1 : 0;
                    893:        baz.foo.c = i & 4 ? 1 : 0;
                    894:        baz.foo.d = i & 1 ? 1 : 0;
                    895:        hirestab_l[i][0] = baz.bar.a;
                    896: 
                    897:        baz.foo.a = i & 128 ? 1 : 0;
                    898:        baz.foo.b = i & 64 ? 1 : 0;
                    899:        baz.foo.c = i & 32 ? 1 : 0;
                    900:        baz.foo.d = i & 16 ? 1 : 0;
                    901:        baz.foo.e = i & 8 ? 1 : 0;
                    902:        baz.foo.f = i & 4 ? 1 : 0;
                    903:        baz.foo.g = i & 2 ? 1 : 0;
                    904:        baz.foo.h = i & 1 ? 1 : 0;
                    905:        lorestab_l[i][0] = baz.bar.a;
                    906:        lorestab_l[i][1] = baz.bar.b;
                    907:        clxtab[i] = ((((i & 3) && (i & 12)) << 9)
                    908:                     | (((i & 3) && (i & 48)) << 10)
                    909:                     | (((i & 3) && (i & 192)) << 11)
                    910:                     | (((i & 12) && (i & 48)) << 12)
                    911:                     | (((i & 12) && (i & 192)) << 13)
                    912:                     | (((i & 48) && (i & 192)) << 14));
                    913:     }
                    914: 
                    915:     for (i = 0; i < 256; i++) {
                    916:        baz.foo.a = i & 128 ? 1 : 0;
                    917:        baz.foo.b = i & 64 ? 1 : 0;
                    918:        baz.foo.c = i & 32 ? 1 : 0;
                    919:        baz.foo.d = i & 16 ? 1 : 0;
                    920:        baz.foo.e = i & 8 ? 1 : 0;
                    921:        baz.foo.f = i & 4 ? 1 : 0;
                    922:        baz.foo.g = i & 2 ? 1 : 0;
                    923:        baz.foo.h = i & 1 ? 1 : 0;
                    924:        hirestab_h[i][0] = baz.bar.a;
                    925:        hirestab_h[i][1] = baz.bar.b;
                    926: 
                    927:        baz.foo.a = i & 128 ? 1 : 0;
                    928:        baz.foo.b = i & 128 ? 1 : 0;
                    929:        baz.foo.c = i & 64 ? 1 : 0;
                    930:        baz.foo.d = i & 64 ? 1 : 0;
                    931:        baz.foo.e = i & 32 ? 1 : 0;
                    932:        baz.foo.f = i & 32 ? 1 : 0;
                    933:        baz.foo.g = i & 16 ? 1 : 0;
                    934:        baz.foo.h = i & 16 ? 1 : 0;
                    935:        baz.foo.i = i & 8 ? 1 : 0;
                    936:        baz.foo.j = i & 8 ? 1 : 0;
                    937:        baz.foo.k = i & 4 ? 1 : 0;
                    938:        baz.foo.l = i & 4 ? 1 : 0;
                    939:        baz.foo.m = i & 2 ? 1 : 0;
                    940:        baz.foo.n = i & 2 ? 1 : 0;
                    941:        baz.foo.o = i & 1 ? 1 : 0;
                    942:        baz.foo.p = i & 1 ? 1 : 0;
                    943:        lorestab_h[i][0] = baz.bar.a;
                    944:        lorestab_h[i][1] = baz.bar.b;
                    945:        lorestab_h[i][2] = baz.bar.c;
                    946:        lorestab_h[i][3] = baz.bar.d;
                    947:     }
                    948: }
                    949: 
                    950: static uae_u32 attach_2nd;
                    951: 
                    952: static uae_u32 do_sprite_collisions (struct sprite_draw *spd, int prev_overlap, int i, int nr_spr)
                    953: {
                    954:     int j;
                    955:     int sprxp = spd[i].linepos;
                    956:     uae_u32 datab = spd[i].datab;
                    957:     uae_u32 mask2 = 0;
                    958:     int sbit = 1 << spd[i].num;
                    959:     int sprx_shift = 1;
                    960:     int attach_compare = -1;
                    961:     if (currprefs.gfx_lores != 1)
                    962:        sprx_shift = 0;
                    963: 
                    964:     attach_2nd = 0;
                    965:     if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80)
                    966:        attach_compare = spd[i].num - 1;
                    967: 
                    968:     for (j = prev_overlap; j < i; j++) {
                    969:        uae_u32 mask1;
                    970:        int off;
                    971: 
                    972:        if (spd[i].num < spd[j].num)
                    973:            continue;
                    974: 
                    975:        off = sprxp - spd[j].linepos;
                    976:        off <<= sprx_shift;
                    977:        mask1 = spd[j].datab >> off;
                    978: 
                    979:        /* If j is an attachment for i, then j doesn't block i */
                    980:        if (spd[j].num == attach_compare) {
                    981:            attach_2nd |= mask1;
                    982:        } else {
                    983:            mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
                    984:            mask1 |= (mask1 & 0x55555555) << 1;
                    985:            if (datab & mask1)
                    986:                clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
                    987:            mask2 |= mask1;
                    988:        }
                    989:     }
                    990:     for (j = i+1; j < nr_spr; j++) {
                    991:        uae_u32 mask1;
                    992:        int off = spd[j].linepos - sprxp;
                    993: 
                    994:        if (off >= sprite_width || spd[i].num < spd[j].num)
                    995:            break;
                    996: 
                    997:        off <<= sprx_shift;
                    998:        mask1 = spd[j].datab << off;
                    999: 
                   1000:        /* If j is an attachment for i, then j doesn't block i */
                   1001:        if (spd[j].num == attach_compare) {
                   1002:            attach_2nd |= mask1;
                   1003:        } else {
                   1004:            mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
                   1005:            mask1 |= (mask1 & 0x55555555) << 1;
                   1006:            if (datab & mask1)
                   1007:                clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
                   1008:            mask2 |= mask1;
                   1009:        }
                   1010:     }
                   1011:     datab &= ~mask2;
                   1012:     return datab;
                   1013: }
                   1014: 
                   1015: static __inline__ void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc)
                   1016: {
                   1017:     uae_u32 datcd;
                   1018:     int basecol = 16;
                   1019:     if (!attch)
                   1020:        basecol += (spr & ~1)*2;
                   1021:     if (bpldualpf)
                   1022:        basecol |= 128;
                   1023:     if (attch)
                   1024:        datcd = attach_2nd;
                   1025: 
                   1026:     for(; attch ? datab | datcd : datab; sprxp += sprx_inc) {
                   1027:        int col;
                   1028: 
                   1029:        if (attch) {
                   1030:            col = ((datab & 3) << 2) | (datcd & 3);
                   1031:            datcd >>= 2;
                   1032:        } else
                   1033:            col = datab & 3;
                   1034:        datab >>= 2;
                   1035:        if (col) {
                   1036:            col |= basecol;
                   1037:            if (ham) {
                   1038:                col = colors_for_drawing.color_regs[col];
                   1039:                ham_linebuf[sprxp] = col;
                   1040:                if (sprx_inc == 2) {
                   1041:                    ham_linebuf[sprxp+1] = col;
                   1042:                }
                   1043:            } else {
                   1044:                pixdata.apixels[sprxp] = col;
                   1045:                if (sprx_inc == 2) {
                   1046:                    pixdata.apixels[sprxp+1] = col;
                   1047:                }
                   1048:            }
                   1049:        }
                   1050:     }
                   1051: }
                   1052: 
                   1053: static void walk_sprites (struct sprite_draw *spd, int nr_spr)
                   1054: {
                   1055:     int i, prev_overlap;
                   1056:     int last_sprite_pos = -64;
                   1057:     uae_u32 plane1 = 0, plane2 = 0;
                   1058:     int sprx_inc = 1, sprx_shift = 1;
                   1059: 
                   1060:     if (currprefs.gfx_lores == 0)
                   1061:        sprx_inc = 2, sprx_shift = 0;
                   1062: 
                   1063:     prev_overlap = 0;
                   1064:     for (i = 0; i < nr_spr; i++) {
                   1065:        int sprxp = spd[i].linepos;
                   1066:        int m = 1 << spd[i].num;
                   1067:        uae_u32 datab;
                   1068:        while (prev_overlap < i && spd[prev_overlap].linepos + sprite_width <= sprxp)
                   1069:            prev_overlap++;
                   1070: 
                   1071:        datab = do_sprite_collisions (spd, prev_overlap, i, nr_spr);
                   1072: #ifdef LORES_HACK
                   1073:        if (currprefs.gfx_lores == 2)
                   1074:            sprxp >>= 1;
                   1075: #endif
                   1076:        if ((bpldualpf && plfpri[1] < 256) || (plfpri[2] < 256)) {
                   1077:            if (sprxp != last_sprite_pos) {
                   1078:                int ok = last_sprite_pos-sprxp+16;
                   1079:                int ok2;
                   1080:                if (ok <= 0) {
                   1081:                    ok = ok2 = 0;
                   1082:                    plane1 = 0;
                   1083:                    plane2 = 0;
                   1084:                } else {
                   1085:                    ok2 = ok << sprx_shift;
                   1086:                    plane1 >>= 32 - ok2;
                   1087:                    plane2 >>= 32 - ok2;
                   1088:                }
                   1089:                last_sprite_pos = sprxp;
                   1090: 
                   1091:                if (bpldualpf) {
                   1092:                    uae_u32 mask = 3 << ok2;
                   1093:                    int p = sprxp+ok;
                   1094: 
                   1095:                    for (; mask; mask <<= 2, p += sprx_inc) {
                   1096:                        int data = pixdata.apixels[p];
                   1097:                        if (dblpf_2nd2[data] == 2)
                   1098:                            plane2 |= mask;
                   1099:                        if (dblpf_2nd1[data] == 1)
                   1100:                            plane1 |= mask;
                   1101:                    }
                   1102:                } else {
                   1103:                    uae_u32 mask = 3 << ok2;
                   1104:                    int p = sprxp+ok;
                   1105: 
                   1106:                    for (; mask; mask <<= 2, p += sprx_inc) {
                   1107:                        if (pixdata.apixels[p])
                   1108:                            plane2 |= mask;
                   1109:                    }
                   1110:                }
                   1111:            }
                   1112:            if (bpldualpf && m >= plfpri[1]) {
                   1113:                datab &= ~plane1;
                   1114:                attach_2nd &= ~plane1;
                   1115:            }
                   1116:            if (m >= plfpri[2]) {
                   1117:                datab &= ~plane2;
                   1118:                attach_2nd &= ~plane2;
                   1119:            }
                   1120:        }
                   1121:        if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) {
                   1122:            /* Attached sprite */
                   1123:            if (bplham) {
                   1124:                if (sprx_inc == 1) {
                   1125:                    render_sprite (spd[i].num, sprxp, datab, 1, 1, 1);
                   1126:                } else {
                   1127:                    render_sprite (spd[i].num, sprxp, datab, 1, 1, 2);
                   1128:                }
                   1129:            } else {
                   1130:                if (sprx_inc == 1) {
                   1131:                    render_sprite (spd[i].num, sprxp, datab, 0, 1, 1);
                   1132:                } else {
                   1133:                    render_sprite (spd[i].num, sprxp, datab, 0, 1, 2);
                   1134:                }
                   1135:            }
                   1136:            /* This still leaves one attached sprite bug, but at the moment I'm too lazy */
                   1137:            if (i + 1 < nr_spr && spd[i+1].num == spd[i].num - 1 && spd[i+1].linepos == spd[i].linepos)
                   1138:                i++;
                   1139:        } else {
                   1140:            if (bplham) {
                   1141:                if (sprx_inc == 1) {
                   1142:                    render_sprite (spd[i].num, sprxp, datab, 1, 0, 1);
                   1143:                } else {
                   1144:                    render_sprite (spd[i].num, sprxp, datab, 1, 0, 2);
                   1145:                }
                   1146:            } else {
                   1147:                if (sprx_inc == 1) {
                   1148:                    render_sprite (spd[i].num, sprxp, datab, 0, 0, 1);
                   1149:                } else {
                   1150:                    render_sprite (spd[i].num, sprxp, datab, 0, 0, 2);
                   1151:                }
                   1152:            }
                   1153:        }
                   1154:     }
                   1155: }
                   1156: 
                   1157: #ifndef SMART_UPDATE
                   1158: #undef UNALIGNED_PROFITABLE
                   1159: #endif
                   1160: 
                   1161: #ifdef UNALIGNED_PROFITABLE
                   1162: 
                   1163: static void pfield_doline_unaligned_h (int lineno)
                   1164: {
                   1165:     int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
                   1166: 
                   1167:     if (bplhires) {
                   1168:        int xpos1 = xpos + 16 + bpldelay1*2;
                   1169:        int xpos2;
                   1170:        uae_u8 *dataptr = line_data[lineno];
                   1171:        int len = dp_for_drawing->plflinelen >> 1;
                   1172: 
                   1173:        if (len <= 0)
                   1174:            return;
                   1175: 
                   1176:        if (bpldelay1 == bpldelay2) {
                   1177:            switch (bplplanecnt) {
                   1178:             case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1179:             case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1180:             case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1181:             case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1182:             case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1183:             case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1184:             case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1185:             case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1186:            }
                   1187:        } else {
                   1188:            switch (bplplanecnt) {
                   1189:             case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1190:             case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1191:             case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1192:             case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1193:            }
                   1194: 
                   1195:            xpos2 = xpos + 16 + bpldelay2*2;
                   1196:            switch (bplplanecnt) {
                   1197:             case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1198:             case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1199:             case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1200:             case 8:         set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1201:            }
                   1202:        }
                   1203:     } else {
                   1204:        int xpos1 = xpos + 32 + bpldelay1*2;
                   1205:        int xpos2;
                   1206:        uae_u8 *dataptr = line_data[lineno];
                   1207:        int len = dp_for_drawing->plflinelen >> 2;
                   1208: 
                   1209:        if (len <= 0)
                   1210:            return;
                   1211: 
                   1212:        if (bpldelay1 == bpldelay2) {
                   1213:            switch (bplplanecnt) {
                   1214:             case 1: set_lores_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1215:             case 2: set_lores_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1216:             case 3: set_lores_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1217:             case 4: set_lores_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1218:             case 5: set_lores_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1219:             case 6: set_lores_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1220:             case 7: set_lores_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1221:             case 8: set_lores_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1222:            }
                   1223:        } else {
                   1224:            switch (bplplanecnt) {
                   1225:             case 1: case 2: set_lores_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1226:             case 3: case 4: set_lores_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1227:             case 5: case 6: set_lores_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1228:             case 7: case 8: set_lores_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1229:            }
                   1230: 
                   1231:            xpos2 = xpos + 32 + bpldelay2*2;
                   1232:            switch (bplplanecnt) {
                   1233:             case 2: case 3: set_lores_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1234:             case 4: case 5: set_lores_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1235:             case 6: case 7: set_lores_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1236:             case 8:         set_lores_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1237:            }
                   1238:        }
                   1239:     }
                   1240: }
                   1241: 
                   1242: static void pfield_doline_unaligned_l (int lineno)
                   1243: {
                   1244:     int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
                   1245: 
                   1246:     if (bplhires) {
                   1247:        int xpos1 = xpos + 8 + bpldelay1;
                   1248:        int xpos2;
                   1249:        uae_u8 *dataptr = line_data[lineno];
                   1250:        int len = dp_for_drawing->plflinelen >> 1;
                   1251: 
                   1252:        if (len <= 0)
                   1253:            return;
                   1254: 
                   1255:        if (bpldelay1 == bpldelay2) {
                   1256:            switch (bplplanecnt) {
                   1257:             case 1: set_hires_l_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1258:             case 2: set_hires_l_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1259:             case 3: set_hires_l_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1260:             case 4: set_hires_l_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1261:             case 5: set_hires_l_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1262:             case 6: set_hires_l_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1263:             case 7: set_hires_l_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1264:             case 8: set_hires_l_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1265:            }
                   1266:        } else {
                   1267:            switch (bplplanecnt) {
                   1268:             case 1: case 2: set_hires_l_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1269:             case 3: case 4: set_hires_l_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1270:             case 5: case 6: set_hires_l_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1271:             case 7: case 8: set_hires_l_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1272:            }
                   1273: 
                   1274:            xpos2 = xpos + 8 + bpldelay2;
                   1275:            switch (bplplanecnt) {
                   1276:             case 2: case 3: set_hires_l_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1277:             case 4: case 5: set_hires_l_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1278:             case 6: case 7: set_hires_l_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1279:             case 8:         set_hires_l_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1280:            }
                   1281:        }
                   1282:     } else {
                   1283:        int xpos1 = xpos + 16 + bpldelay1;
                   1284:        int xpos2;
                   1285:        uae_u8 *dataptr = line_data[lineno];
                   1286:        int len = dp_for_drawing->plflinelen >> 2;
                   1287: 
                   1288:        if (len <= 0)
                   1289:            return;
                   1290: 
                   1291:        if (bpldelay1 == bpldelay2) {
                   1292:            switch (bplplanecnt) {
                   1293:             case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1294:             case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1295:             case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1296:             case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1297:             case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1298:             case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1299:             case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1300:             case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1301:            }
                   1302:        } else {
                   1303:            switch (bplplanecnt) {
                   1304:             case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1305:             case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1306:             case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1307:             case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
                   1308:            }
                   1309: 
                   1310:            xpos2 = xpos + 16 + bpldelay2;
                   1311:            switch (bplplanecnt) {
                   1312:             case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1313:             case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1314:             case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1315:             case 8:         set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
                   1316:            }
                   1317:        }
                   1318:     }
                   1319: }
                   1320: 
                   1321: #define pfield_doline_h pfield_doline_unaligned_h
                   1322: #define pfield_doline_l pfield_doline_unaligned_l
                   1323: 
                   1324: #else /* not UNALIGNED_PROFITABLE */
                   1325: 
                   1326: 
                   1327: static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit)
                   1328: {
                   1329:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1330: 
                   1331:     *pixptr |= hirestab_h[data >> 8][0] << bit;
                   1332:     *(pixptr+1) |= hirestab_h[data >> 8][1] << bit;
                   1333:     *(pixptr+2) |= hirestab_h[data & 255][0] << bit;
                   1334:     *(pixptr+3) |= hirestab_h[data & 255][1] << bit;
                   1335: }
                   1336: 
                   1337: static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit)
                   1338: {
                   1339:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1340: 
                   1341:     *pixptr |= lorestab_h[data >> 8][0] << bit;
                   1342:     *(pixptr+1) |= lorestab_h[data >> 8][1] << bit;
                   1343:     *(pixptr+2) |= lorestab_h[data >> 8][2] << bit;
                   1344:     *(pixptr+3) |= lorestab_h[data >> 8][3] << bit;
                   1345:     *(pixptr+4) |= lorestab_h[data & 255][0] << bit;
                   1346:     *(pixptr+5) |= lorestab_h[data & 255][1] << bit;
                   1347:     *(pixptr+6) |= lorestab_h[data & 255][2] << bit;
                   1348:     *(pixptr+7) |= lorestab_h[data & 255][3] << bit;
                   1349: }
                   1350: 
                   1351: static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit)
                   1352: {
                   1353:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1354: 
                   1355:     *pixptr = hirestab_h[data >> 8][0] << bit;
                   1356:     *(pixptr+1) = hirestab_h[data >> 8][1] << bit;
                   1357:     *(pixptr+2) = hirestab_h[data & 255][0] << bit;
                   1358:     *(pixptr+3) = hirestab_h[data & 255][1] << bit;
                   1359: }
                   1360: 
                   1361: static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit)
                   1362: {
                   1363:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1364: 
                   1365:     *pixptr = lorestab_h[data >> 8][0] << bit;
                   1366:     *(pixptr+1) = lorestab_h[data >> 8][1] << bit;
                   1367:     *(pixptr+2) = lorestab_h[data >> 8][2] << bit;
                   1368:     *(pixptr+3) = lorestab_h[data >> 8][3] << bit;
                   1369:     *(pixptr+4) = lorestab_h[data & 255][0] << bit;
                   1370:     *(pixptr+5) = lorestab_h[data & 255][1] << bit;
                   1371:     *(pixptr+6) = lorestab_h[data & 255][2] << bit;
                   1372:     *(pixptr+7) = lorestab_h[data & 255][3] << bit;
                   1373: }
                   1374: 
                   1375: static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit)
                   1376: {
                   1377:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1378: 
                   1379:     *pixptr |= hirestab_l[data >> 8][0] << bit;
                   1380:     *(pixptr+1) |= hirestab_l[data & 255][0] << bit;
                   1381: }
                   1382: 
                   1383: static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit)
                   1384: {
                   1385:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1386: 
                   1387:     *pixptr |= lorestab_l[data >> 8][0] << bit;
                   1388:     *(pixptr+1) |= lorestab_l[data >> 8][1] << bit;
                   1389:     *(pixptr+2) |= lorestab_l[data & 255][0] << bit;
                   1390:     *(pixptr+3) |= lorestab_l[data & 255][1] << bit;
                   1391: }
                   1392: 
                   1393: static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit)
                   1394: {
                   1395:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1396: 
                   1397:     *pixptr = hirestab_l[data >> 8][0] << bit;
                   1398:     *(pixptr+1) = hirestab_l[data & 255][0] << bit;
                   1399: }
                   1400: 
                   1401: static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit)
                   1402: {
                   1403:     uae_u32 *pixptr = (uae_u32 *)dp;
                   1404: 
                   1405:     *pixptr = lorestab_l[data >> 8][0] << bit;
                   1406:     *(pixptr+1) = lorestab_l[data >> 8][1] << bit;
                   1407:     *(pixptr+2) = lorestab_l[data & 255][0] << bit;
                   1408:     *(pixptr+3) = lorestab_l[data & 255][1] << bit;
                   1409: }
                   1410: 
                   1411: #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \
                   1412:     int i; \
                   1413:     unsigned int bpldat1; \
                   1414:     uae_u16 data; \
                   1415:     unsigned int bpldat2 = 0; \
                   1416:     uae_u8 *ptr = (POINTER); \
                   1417:     for (i = dp_for_drawing->plflinelen; i > 0; i -= LL_SUB) { \
                   1418:        bpldat1 = bpldat2; \
                   1419:        bpldat2 = do_get_mem_word ((uae_u16 *)ptr); \
                   1420:        ptr+=2; \
                   1421:        data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \
                   1422:        FUNC(data, app, MULT); \
                   1423:        app += P_ADD; \
                   1424:     } \
                   1425:     data = bpldat2 << (16 - DELAY); \
                   1426:     FUNC(data, app, MULT); \
                   1427: }
                   1428: 
                   1429: #ifdef SMART_UPDATE
                   1430: #define DATA_POINTER(n) (dataptr + (n)*MAX_WORDS_PER_LINE*2)
                   1431: #else
                   1432: #define DATA_POINTER(n) (real_bplpt[n])
                   1433: #endif
                   1434: 
                   1435: static void pfield_doline_aligned_h (int lineno)
                   1436: {
                   1437:     int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
                   1438: 
                   1439:     if (bplhires) {
                   1440:        if (bplplanecnt > 0) {
                   1441:            int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0);
                   1442:            int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0);
                   1443:            int delay1 = 2*(bpldelay1 & 7);
                   1444:            int delay2 = 2*(bpldelay2 & 7);
                   1445:            unsigned char *app = pixdata.apixels + xpos1;
                   1446:            uae_u8 *dataptr = line_data[lineno];
                   1447: 
                   1448:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_h, delay1, 4, 16);
                   1449:            if (bplplanecnt > 2) {
                   1450:                app = pixdata.apixels + xpos1;
                   1451:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_h, delay1, 4, 16);
                   1452:            }
                   1453: #if AGA_CHIPSET == 1
                   1454:            if (bplplanecnt > 4) {
                   1455:                app = pixdata.apixels + xpos1;
                   1456:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_h, delay1, 4, 16);
                   1457:            }
                   1458:            if (bplplanecnt > 6) {
                   1459:                app = pixdata.apixels + xpos1;
                   1460:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_h, delay1, 4, 16);
                   1461:            }
                   1462: #endif
                   1463:            if (bplplanecnt > 1) {
                   1464:                app = pixdata.apixels + xpos2;
                   1465:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_h, delay2, 4, 16);
                   1466:            }
                   1467:            if (bplplanecnt > 3) {
                   1468:                app = pixdata.apixels + xpos2;
                   1469:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_h, delay2, 4, 16);
                   1470:            }
                   1471: #if AGA_CHIPSET == 1
                   1472:            if (bplplanecnt > 5) {
                   1473:                app = pixdata.apixels + xpos2;
                   1474:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_h, delay2, 4, 16);
                   1475:            }
                   1476:            if (bplplanecnt > 7) {
                   1477:                app = pixdata.apixels + xpos2;
                   1478:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_h, delay2, 4, 16);
                   1479:            }
                   1480: #endif
                   1481:        } else {
                   1482:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   1483:        }
                   1484:     } else {
                   1485:        if (bplplanecnt > 0) {
                   1486:            int x = xpos + 32;
                   1487:            unsigned char *app = pixdata.apixels + x;
                   1488:            uae_u8 *dataptr = line_data[lineno];
                   1489: 
                   1490:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_h, bpldelay1, 8, 32);
                   1491:            if (bplplanecnt > 2) {
                   1492:                app = pixdata.apixels + x;
                   1493:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_h, bpldelay1, 8, 32);
                   1494:            }
                   1495:            if (bplplanecnt > 4) {
                   1496:                app = pixdata.apixels + x;
                   1497:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_h, bpldelay1, 8, 32);
                   1498:            }
                   1499: #if AGA_CHIPSET == 1
                   1500:            if (bplplanecnt > 6) {
                   1501:                app = pixdata.apixels + x;
                   1502:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_h, bpldelay1, 8, 32);
                   1503:            }
                   1504: #endif
                   1505:            if (bplplanecnt > 1) {
                   1506:                app = pixdata.apixels + x;
                   1507:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_h, bpldelay2, 8, 32);
                   1508:            }
                   1509:            if (bplplanecnt > 3) {
                   1510:                app = pixdata.apixels + x;
                   1511:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_h, bpldelay2, 8, 32);
                   1512:            }
                   1513:            if (bplplanecnt > 5) {
                   1514:                app = pixdata.apixels + x;
                   1515:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_h, bpldelay2, 8, 32);
                   1516:            }
                   1517: #if AGA_CHIPSET == 1
                   1518:            if (bplplanecnt > 7) {
                   1519:                app = pixdata.apixels + x;
                   1520:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_h, bpldelay2, 8, 32);
                   1521:            }
                   1522: #endif
                   1523:        } else {
                   1524:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   1525:        }
                   1526:     }
                   1527: }
                   1528: 
                   1529: static void pfield_doline_aligned_l (int lineno)
                   1530: {
                   1531:     int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
                   1532: 
                   1533:     if (bplhires) {
                   1534:        if (bplplanecnt > 0) {
                   1535:            int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0);
                   1536:            int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0);
                   1537:            int delay1 = (bpldelay1 & 7) * 2;
                   1538:            int delay2 = (bpldelay2 & 7) * 2;
                   1539:            unsigned char *app = pixdata.apixels + xpos1;
                   1540:            uae_u8 *dataptr = line_data[lineno];
                   1541: 
                   1542:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_l, delay1, 4, 8);
                   1543:            if (bplplanecnt > 2) {
                   1544:                app = pixdata.apixels + xpos1;
                   1545:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_l, delay1, 4, 8);
                   1546:            }
                   1547: #if AGA_CHIPSET == 1
                   1548:            if (bplplanecnt > 4) {
                   1549:                app = pixdata.apixels + xpos1;
                   1550:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_l, delay1, 4, 8);
                   1551:            }
                   1552:            if (bplplanecnt > 6) {
                   1553:                app = pixdata.apixels + xpos1;
                   1554:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_l, delay1, 4, 8);
                   1555:            }
                   1556: #endif
                   1557:            if (bplplanecnt > 1) {
                   1558:                app = pixdata.apixels + xpos2;
                   1559:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_l, delay2, 4, 8);
                   1560:            }
                   1561:            if (bplplanecnt > 3) {
                   1562:                app = pixdata.apixels + xpos2;
                   1563:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_l, delay2, 4, 8);
                   1564:            }
                   1565: #if AGA_CHIPSET == 1
                   1566:            if (bplplanecnt > 5) {
                   1567:                app = pixdata.apixels + xpos2;
                   1568:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_l, delay2, 4, 8);
                   1569:            }
                   1570:            if (bplplanecnt > 7) {
                   1571:                app = pixdata.apixels + xpos2;
                   1572:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_l, delay2, 4, 8);
                   1573:            }
                   1574: #endif
                   1575:        } else {
                   1576:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   1577:        }
                   1578:     } else {
                   1579:        if (bplplanecnt > 0) {
                   1580:            int x = xpos + 16;
                   1581:            int delay1 = bpldelay1;
                   1582:            int delay2 = bpldelay2;
                   1583:            unsigned char *app = pixdata.apixels + x;
                   1584:            uae_u8 *dataptr = line_data[lineno];
                   1585: 
                   1586:            DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_l, delay1, 8, 16);
                   1587:            if (bplplanecnt > 2) {
                   1588:                app = pixdata.apixels + x;
                   1589:                DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_l, delay1, 8, 16);
                   1590:            }
                   1591:            if (bplplanecnt > 4) {
                   1592:                app = pixdata.apixels + x;
                   1593:                DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_l, delay1, 8, 16);
                   1594:            }
                   1595: #if AGA_CHIPSET == 1
                   1596:            if (bplplanecnt > 6) {
                   1597:                app = pixdata.apixels + x;
                   1598:                DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_l, delay1, 8, 16);
                   1599:            }
                   1600: #endif
                   1601:            if (bplplanecnt > 1) {
                   1602:                app = pixdata.apixels + x;
                   1603:                DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_l, delay2, 8, 16);
                   1604:            }
                   1605:            if (bplplanecnt > 3) {
                   1606:                app = pixdata.apixels + x;
                   1607:                DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_l, delay2, 8, 16);
                   1608:            }
                   1609:            if (bplplanecnt > 5) {
                   1610:                app = pixdata.apixels + x;
                   1611:                DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_l, delay2, 8, 16);
                   1612:            }
                   1613: #if AGA_CHIPSET == 1
                   1614:            if (bplplanecnt > 7) {
                   1615:                app = pixdata.apixels + x;
                   1616:                DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_l, delay2, 8, 16);
                   1617:            }
                   1618: #endif
                   1619:        } else {
                   1620:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
                   1621:        }
                   1622:     }
                   1623: }
                   1624: 
                   1625: #define pfield_doline_h pfield_doline_aligned_h
                   1626: #define pfield_doline_l pfield_doline_aligned_l
                   1627: 
                   1628: #endif /* UNALIGNED_PROFITABLE */
                   1629: 
                   1630: static void pfield_adjust_delay (void)
                   1631: {
                   1632:     int ddf_left = dp_for_drawing->plfstrt;
                   1633:     int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen;
                   1634:     int i;
                   1635: 
                   1636:     for (i = dip_for_drawing->last_delay_change-1; i >= dip_for_drawing->first_delay_change-1; i--) {
                   1637:        int delayreg = i < dip_for_drawing->first_delay_change ? dp_for_drawing->bplcon1 : delay_changes[i].value;
                   1638:        int delay1 = delayreg & 0xF;
                   1639:        int delay2 = (delayreg >> 4) & 0xF;
                   1640:        int startpos = i == dip_for_drawing->last_delay_change - 1 ? ddf_right + 8 : delay_changes[i+1].linepos;
                   1641:        int stoppos = i < dip_for_drawing->first_delay_change ? ddf_left : delay_changes[i].linepos;
                   1642:        int j;
                   1643:        startpos = PIXEL_XPOS (startpos + (bplhires ? 4 : 8));
                   1644:        stoppos = PIXEL_XPOS (stoppos + (bplhires ? 4 : 8));
                   1645:        if (currprefs.gfx_lores == 0)
                   1646:            delay1 <<= 1, delay2 <<= 1;
                   1647:        else if (currprefs.gfx_lores == 2)
                   1648:            startpos >>= 1, stoppos >>= 1;
                   1649:        for (j = startpos-1; j >= stoppos; j--) {
                   1650:            pixdata.apixels [j] = (pixdata.apixels[j-delay1] & 0x55) | (pixdata.apixels[j-delay2] & 0xAA);
                   1651:        }
                   1652:     }
                   1653: }
                   1654: 
                   1655: void init_row_map (void)
                   1656: {
                   1657:     int i;
                   1658:     if (gfxvidinfo.height > 2048) {
                   1659:        write_log ("Resolution too high, aborting\n");
                   1660:        abort ();
                   1661:     }
                   1662:     for (i = 0; i < gfxvidinfo.height + 1; i++)
                   1663:        row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i;
                   1664: }
                   1665: 
                   1666: static void init_aspect_maps (void)
                   1667: {
                   1668:     int i, maxl;
                   1669:     double native_lines_per_amiga_line;
                   1670: 
                   1671:     if (native2amiga_line_map)
                   1672:        free (native2amiga_line_map);
                   1673:     if (amiga2aspect_line_map)
                   1674:        free (amiga2aspect_line_map);
                   1675: 
                   1676:     /* At least for this array the +1 is necessary. */
                   1677:     amiga2aspect_line_map = (int *)malloc (sizeof (int) * (maxvpos+1)*2 + 1);
                   1678:     native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height);
                   1679: 
                   1680:     if (currprefs.gfx_correct_aspect)
                   1681:        native_lines_per_amiga_line = ((double)gfxvidinfo.height
                   1682:                                       * (currprefs.gfx_lores ? 320 : 640)
                   1683:                                       / (currprefs.gfx_linedbl ? 512 : 256)
                   1684:                                       / gfxvidinfo.width);
                   1685:     else
                   1686:        native_lines_per_amiga_line = 1;
                   1687: 
                   1688:     maxl = (maxvpos+1) * (currprefs.gfx_linedbl ? 2 : 1);
                   1689:     min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0);
                   1690:     max_drawn_amiga_line = -1;
                   1691:     for (i = 0; i < maxl; i++) {
                   1692:        int v = (i - min_ypos_for_screen) * native_lines_per_amiga_line;
                   1693:        if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1)
                   1694:            max_drawn_amiga_line = i - min_ypos_for_screen;
                   1695:        if (i < min_ypos_for_screen || v >= gfxvidinfo.height)
                   1696:            v = -1;
                   1697:        amiga2aspect_line_map[i] = v;
                   1698:     }
                   1699:     if (currprefs.gfx_linedbl)
                   1700:        max_drawn_amiga_line >>= 1;
                   1701: 
                   1702:     if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) {
                   1703:        extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1;
                   1704:        if (extra_y_adjust < 0)
                   1705:            extra_y_adjust = 0;
                   1706:     }
                   1707: 
                   1708:     for (i = 0; i < gfxvidinfo.height; i++)
                   1709:        native2amiga_line_map[i] = -1;
                   1710: 
                   1711:     if (native_lines_per_amiga_line < 1) {
                   1712:        /* Must omit drawing some lines. */
                   1713:        for (i = maxl - 1; i > min_ypos_for_screen; i--) {
                   1714:            if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) {
                   1715:                if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) {
                   1716:                    /* If only the first line of a line pair would be omitted,
                   1717:                     * omit the second one instead to avoid problems with line
                   1718:                     * doubling. */
                   1719:                    amiga2aspect_line_map[i] = amiga2aspect_line_map[i+1];
                   1720:                    amiga2aspect_line_map[i+1] = -1;
                   1721:                } else
                   1722:                    amiga2aspect_line_map[i] = -1;
                   1723:            }
                   1724:        }
                   1725:     }
                   1726: 
                   1727:     for (i = maxl-1; i >= min_ypos_for_screen; i--) {
                   1728:        int j;
                   1729:        if (amiga2aspect_line_map[i] == -1)
                   1730:            continue;
                   1731:        for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++)
                   1732:            native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0);
                   1733:     }
                   1734: }
                   1735: 
                   1736: /*
                   1737:  * A raster line has been built in the graphics buffer. Tell the graphics code
                   1738:  * to do anything necessary to display it.
                   1739:  */
                   1740: static void do_flush_line_1 (int lineno)
                   1741: {
                   1742:     if (lineno < first_drawn_line)
                   1743:        first_drawn_line = lineno;
                   1744:     if (lineno > last_drawn_line)
                   1745:        last_drawn_line = lineno;
                   1746: 
                   1747:     if (gfxvidinfo.maxblocklines == 0)
                   1748:        flush_line(lineno);
                   1749:     else {
                   1750:        if ((last_block_line+1) != lineno) {
                   1751:            if (first_block_line != -2)
                   1752:                flush_block (first_block_line, last_block_line);
                   1753:            first_block_line = lineno;
                   1754:        }
                   1755:        last_block_line = lineno;
                   1756:        if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
                   1757:            flush_block (first_block_line, last_block_line);
                   1758:            first_block_line = last_block_line = -2;
                   1759:        }
                   1760:     }
                   1761: }
                   1762: 
                   1763: static __inline__ void do_flush_line (int lineno)
                   1764: {
                   1765:     /* We don't want to call X libraries from the second thread right now. */
                   1766: #ifndef SUPPORT_PENGUINS
                   1767:     do_flush_line_1 (lineno);
                   1768: #else
                   1769:     line_drawn[lineno] = 1;
                   1770: #endif
                   1771: }
                   1772: 
                   1773: /*
                   1774:  * One drawing frame has been finished. Tell the graphics code about it.
                   1775:  * Note that the actual flush_screen() call is a no-op for all reasonable
                   1776:  * systems.
                   1777:  */
                   1778: 
                   1779: static __inline__ void do_flush_screen (int start, int stop)
                   1780: {
                   1781: #ifdef SUPPORT_PENGUINS
                   1782:     int i;
                   1783:     for (i = 0; i < gfxvidinfo.height; i++) {
                   1784:        if (line_drawn[i])
                   1785:            do_flush_line_1 (i);
                   1786:     }
                   1787: #endif
                   1788:     if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
                   1789:        flush_block (first_block_line, last_block_line);
                   1790:     }
                   1791:     if (start <= stop)
                   1792:        flush_screen (start, stop);
                   1793: }
                   1794: 
1.1.1.2 ! root     1795: static __inline__ void finish_line_aga (void)
        !          1796: {
        !          1797: #if AGA_CHIPSET != 0
        !          1798:     aga_lbufptr = aga_linebuf;
        !          1799:     aga_translate32 (linetoscr_x_adjust_bytes, linetoscr_x_adjust_bytes + gfxvidinfo.width);
        !          1800: #endif
        !          1801: }
        !          1802: 
1.1       root     1803: static int drawing_color_matches;
                   1804: static enum { color_match_acolors, color_match_full } color_match_type;
                   1805: 
                   1806: static void adjust_drawing_colors (int ctable, int bplham)
                   1807: {
1.1.1.2 ! root     1808: #if AGA_CHIPSET == 0
1.1       root     1809:     if (drawing_color_matches != ctable) {
                   1810:        if (bplham) {
                   1811:            memcpy (&colors_for_drawing, curr_color_tables + ctable,
                   1812:                    sizeof colors_for_drawing);
                   1813:            color_match_type = color_match_full;
                   1814:        } else {
                   1815:            memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
                   1816:                    sizeof colors_for_drawing.acolors);
                   1817:            color_match_type = color_match_acolors;
                   1818:        }
                   1819:        drawing_color_matches = ctable;
                   1820:     } else if (bplham && color_match_type != color_match_full) {
                   1821:        memcpy (colors_for_drawing.color_regs, curr_color_tables[ctable].color_regs,
                   1822:                sizeof colors_for_drawing.color_regs);
                   1823:        color_match_type = color_match_full;
                   1824:     }
1.1.1.2 ! root     1825: #else
        !          1826:     if (drawing_color_matches != ctable) {
        !          1827:        memcpy (&colors_for_drawing, curr_color_tables + ctable,
        !          1828:                sizeof colors_for_drawing);
        !          1829:        drawing_color_matches = ctable;
        !          1830:     }
        !          1831: #endif
1.1       root     1832: }
                   1833: 
                   1834: static __inline__ void adjust_color0_for_color_change (void)
                   1835: {
                   1836:     drawing_color_matches = -1;
                   1837:     if (dp_for_drawing->color0 != 0xFFFFFFFFul) {
                   1838:        colors_for_drawing.color_regs[0] = dp_for_drawing->color0;
1.1.1.2 ! root     1839: #if AGA_CHIPSET == 0
1.1       root     1840:        colors_for_drawing.acolors[0] = xcolors[dp_for_drawing->color0];
1.1.1.2 ! root     1841: #endif
1.1       root     1842:     }
                   1843: }
                   1844: 
                   1845: /* Fetched data spends 9 lores pixels somewhere in the chips before it appears
                   1846:  * on-screen. We don't emulate this. Instead, we cheat with the copper to
                   1847:  * compensate (much easier that way). */
                   1848: #define COPPER_MAGIC_FUDGE -9
                   1849: 
                   1850: static __inline__ void do_color_changes (line_draw_func worker)
                   1851: {
                   1852:     int lastpos = 0, nextpos, i;
                   1853:     struct color_change *cc = curr_color_changes + dip_for_drawing->first_color_change;
                   1854: 
                   1855:     for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++, cc++) {
                   1856:        if (i == dip_for_drawing->last_color_change)
                   1857:            nextpos = max_diwlastword;
                   1858:        else
                   1859:            nextpos = PIXEL_XPOS (cc->linepos) + (COPPER_MAGIC_FUDGE << lores_shift);
                   1860:        worker (lastpos, nextpos);
                   1861:        if (i != dip_for_drawing->last_color_change) {
                   1862:            colors_for_drawing.color_regs[cc->regno] = cc->value;
1.1.1.2 ! root     1863: #if AGA_CHIPSET == 0
1.1       root     1864:            colors_for_drawing.acolors[cc->regno] = xcolors[cc->value];
1.1.1.2 ! root     1865: #endif
1.1       root     1866:        }
                   1867:        if (nextpos > lastpos) {
                   1868:            lastpos = nextpos;
                   1869:            if (lastpos >= linetoscr_right_x)
                   1870:                break;
                   1871:        }
                   1872:     }
                   1873: }
                   1874: 
                   1875: /* We only save hardware registers during the hardware frame. Now, when
                   1876:  * drawing the frame, we expand the data into a slightly more useful
                   1877:  * form. */
                   1878: static void pfield_expand_dp_bplcon (void)
                   1879: {
                   1880:     bplhires = (dp_for_drawing->bplcon0 & 0x8000) == 0x8000;
                   1881:     bplplanecnt = (dp_for_drawing->bplcon0 & 0x7000) >> 12;
                   1882:     bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800;
                   1883: #if AGA_CHIPSET == 1 /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock
                   1884:                      * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */
                   1885:     bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200));
                   1886: #else
                   1887:     bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000;
                   1888: #endif
                   1889:     bpldelay1 = dp_for_drawing->bplcon1 & 0xF;
                   1890:     bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF;
                   1891:     plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7);
                   1892:     plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7);
                   1893:     bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
                   1894:     bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
                   1895: }
                   1896: 
                   1897: enum double_how {
                   1898:     dh_buf,
                   1899:     dh_line,
                   1900:     dh_emerg
                   1901: };
                   1902: 
                   1903: static __inline__ void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos)
                   1904: {
                   1905:     int border = 0;
                   1906:     int do_double = 0;
                   1907:     enum double_how dh;
                   1908: 
1.1.1.2 ! root     1909:     dp_for_drawing = line_decisions + lineno;
        !          1910:     dip_for_drawing = curr_drawinfo + lineno;
1.1       root     1911:     switch (linestate[lineno]) {
                   1912:      case LINE_REMEMBERED_AS_PREVIOUS:
                   1913:        {
                   1914:            static int warned = 0;
                   1915:            if (!warned)
                   1916:                write_log ("Shouldn't get here... this is a bug.\n"), warned++;
                   1917:        }
                   1918:        line_decisions[lineno].which = -2;
                   1919:        return;
                   1920: 
1.1.1.2 ! root     1921:      case LINE_BLACK:
        !          1922:        line_decisions[lineno].which = -2;
        !          1923:        linestate[lineno] = LINE_REMEMBERED_AS_BLACK;
        !          1924:        border = 2;
1.1       root     1925:        break;
                   1926: 
1.1.1.2 ! root     1927:      case LINE_REMEMBERED_AS_BLACK:
        !          1928:        return;
        !          1929: 
        !          1930:      case LINE_AS_PREVIOUS:
        !          1931:        dp_for_drawing--;
        !          1932:        dip_for_drawing--;
        !          1933:        if (dp_for_drawing->which != 1)
        !          1934:            border = 1;
        !          1935:        line_decisions[lineno].which = -2;
        !          1936:        linestate[lineno] = LINE_DONE_AS_PREVIOUS;
1.1       root     1937:        break;
                   1938: 
                   1939:      case LINE_DONE_AS_PREVIOUS:
                   1940:        line_decisions[lineno].which = -2;
                   1941:        /* fall through */
                   1942:      case LINE_DONE:
                   1943:        return;
                   1944: 
                   1945:      case LINE_DECIDED_DOUBLE:
                   1946:        line_decisions[lineno+1].which = -2;
                   1947:        if (follow_ypos != -1) {
                   1948:            do_double = 1;
                   1949:            linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos);
1.1.1.2 ! root     1950:            linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
1.1       root     1951:        }
                   1952: 
                   1953:        /* fall through */
                   1954:      default:
                   1955:        if (dp_for_drawing->which != 1)
                   1956:            border = 1;
                   1957:        linestate[lineno] = LINE_DONE;
1.1.1.2 ! root     1958:        break;
1.1       root     1959:     }
                   1960: 
                   1961:     dh = dh_line;
                   1962:     xlinebuffer = gfxvidinfo.linemem;
1.1.1.2 ! root     1963:     if (xlinebuffer == 0 && do_double && border != 2 && dip_for_drawing->nr_color_changes != 0)
1.1       root     1964:        xlinebuffer = gfxvidinfo.emergmem, dh = dh_emerg;
                   1965:     if (xlinebuffer == 0)
                   1966:        xlinebuffer = row_map[gfx_ypos], dh = dh_buf;
                   1967:     xlinebuffer -= linetoscr_x_adjust_bytes;
                   1968:     aga_lbufptr = aga_linebuf;
                   1969: 
1.1.1.2 ! root     1970:     if (border == 0) {
1.1       root     1971:        pfield_expand_dp_bplcon ();
                   1972: 
                   1973: #ifdef LORES_HACK
                   1974:        if (gfxvidinfo.can_double && !bplhires && !currprefs.gfx_lores
                   1975:            && dip_for_drawing->nr_color_changes == 0 && !bplham)
                   1976:            currprefs.gfx_lores = 2;
                   1977: #endif
                   1978:        pfield_init_linetoscr ();
                   1979:        if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) {
                   1980:            bpldelay1 = bpldelay2 = 0;
                   1981:            if (currprefs.gfx_lores)
                   1982:                pfield_doline_l (lineno);
                   1983:            else
                   1984:                pfield_doline_h (lineno);
                   1985:            pfield_adjust_delay ();
                   1986:        } else {
                   1987:            if (currprefs.gfx_lores)
                   1988:                pfield_doline_l (lineno);
                   1989:            else
                   1990:                pfield_doline_h (lineno);
                   1991:        }
                   1992: 
                   1993:        /* Check color0 adjust only if we have color changes - shouldn't happen
                   1994:         * otherwise. */
                   1995:        adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
                   1996: 
                   1997:        /* The problem is that we must call decode_ham6() BEFORE we do the
                   1998:         * sprites. */
                   1999:        if (bplham) {
                   2000:            init_ham_decoding(linetoscr_x_adjust);
                   2001:            if (dip_for_drawing->nr_color_changes == 0) {
                   2002:                /* The easy case: need to do HAM decoding only once for the
                   2003:                 * full line. */
                   2004:                decode_ham6 (linetoscr_x_adjust, linetoscr_right_x);
                   2005:            } else /* Argh. */ {
                   2006:                adjust_color0_for_color_change ();
                   2007:                do_color_changes (decode_ham6);
                   2008:                adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
                   2009:            }
                   2010:        }
                   2011: 
                   2012:        if (dip_for_drawing->nr_sprites != 0)
                   2013:            walk_sprites (curr_sprite_positions + dip_for_drawing->first_sprite_draw, dip_for_drawing->nr_sprites);
                   2014: 
                   2015:        if (dip_for_drawing->nr_color_changes == 0) {
                   2016:            pfield_do_linetoscr_full (dh == dh_buf ? do_double : 0);
1.1.1.2 ! root     2017:            finish_line_aga ();
1.1       root     2018:            do_flush_line (gfx_ypos);
                   2019: #if 0
                   2020:            if (dh == dh_emerg)
                   2021:                abort ();
                   2022: #endif
                   2023:            if (do_double) {
                   2024:                /* If dh == dh_line, do_flush_line will re-use the rendered line
                   2025:                 * from linemem.  If dh == dh_buf, the line will have been doubled
                   2026:                 * by pfield_do_linetoscr_full.  */
                   2027:                do_flush_line (follow_ypos);
                   2028:            }
                   2029:        } else {
                   2030:            adjust_color0_for_color_change ();
                   2031:            do_color_changes (pfield_do_linetoscr);
1.1.1.2 ! root     2032:            finish_line_aga ();
1.1       root     2033: 
                   2034:            if (dh == dh_emerg)
                   2035:                memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
                   2036: 
                   2037:            do_flush_line (gfx_ypos);
                   2038:            if (do_double) {
                   2039:                if (dh == dh_emerg)
                   2040:                    memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
                   2041:                else if (dh == dh_buf)
                   2042:                    memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
                   2043:                line_decisions[lineno + 1].which = -2;
                   2044:                do_flush_line (follow_ypos);
                   2045:            }
                   2046:        }
                   2047: #ifdef LORES_HACK
                   2048:        if (currprefs.gfx_lores == 2)
                   2049:            currprefs.gfx_lores = 0;
                   2050: #endif
1.1.1.2 ! root     2051:     } else if (border == 1) {
1.1       root     2052:        adjust_drawing_colors (dp_for_drawing->ctable, 0);
                   2053: 
                   2054:        /* Check color0 adjust only if we have color changes - shouldn't happen
                   2055:         * otherwise. */
                   2056: 
                   2057:        if (dip_for_drawing->nr_color_changes == 0) {
                   2058:            fill_line ();
                   2059:            do_flush_line (gfx_ypos);
                   2060: #if 0
                   2061:            if (dh == dh_emerg)
                   2062:                abort ();
                   2063: #endif
                   2064:            if (do_double) {
                   2065:                if (dh == dh_buf) {
                   2066:                    xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
                   2067:                    fill_line ();
                   2068:                }
                   2069:                /* If dh == dh_line, do_flush_line will re-use the rendered line
                   2070:                 * from linemem.  */
                   2071:                do_flush_line (follow_ypos);
                   2072:            }
                   2073:            return;
                   2074:        }
                   2075: 
                   2076:        adjust_color0_for_color_change ();
                   2077:        do_color_changes (pfield_do_fill_line);
                   2078: 
                   2079:        if (dh == dh_emerg)
                   2080:            memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
                   2081: 
                   2082:        do_flush_line (gfx_ypos);
                   2083:        if (do_double) {
                   2084:            if (dh == dh_emerg)
                   2085:                memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
                   2086:            else if (dh == dh_buf)
                   2087:                memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
                   2088:            /* If dh == dh_line, do_flush_line will re-use the rendered line
                   2089:             * from linemem.  */
                   2090:            do_flush_line (follow_ypos);
                   2091:            line_decisions[lineno + 1].which = -2;
                   2092:        }
1.1.1.2 ! root     2093:     } else {
        !          2094: #if AGA_CHIPSET == 0
        !          2095:        xcolnr tmp = colors_for_drawing.acolors[0];
        !          2096:        colors_for_drawing.acolors[0] = xcolors[0];
        !          2097:        fill_line ();
        !          2098:        do_flush_line (gfx_ypos);
        !          2099:        colors_for_drawing.acolors[0] = tmp;
        !          2100: #endif
1.1       root     2101:     }
                   2102: }
                   2103: 
                   2104: #ifdef SUPPORT_PENGUINS
                   2105: static smp_comm_pipe drawing_pipe;
                   2106: static uae_sem_t drawing_lock;
                   2107: 
                   2108: static void *drawing_penguin (void *cruxmedo)
                   2109: {
                   2110:     int l;
                   2111:     fprintf (stderr, "Hello, world!\n");
                   2112: 
                   2113:     for (;;) {
                   2114:        /* Start of a frame. */
                   2115:        int k;
                   2116:        new_frame:
                   2117:        k = read_comm_pipe_int_blocking (&drawing_pipe);
                   2118: 
                   2119:        switch (k) {
                   2120:         case -2:
                   2121:            /* Hoopy */
                   2122:            break;
                   2123: 
                   2124:         default:
                   2125:            write_log ("Penguin got out of sync.\n");
                   2126:            /* what can we do? Try to reduce the damage */
                   2127:            for (;;) {
                   2128:                k = read_comm_pipe_int_blocking (&drawing_pipe);
                   2129:                if (k == -3)
                   2130:                    break;
                   2131:                if (k == -1) {
                   2132:                    uae_sem_post (&drawing_lock);
                   2133:                    goto new_frame;
                   2134:                }
                   2135:            }
                   2136:         case -3:
                   2137:            UAE_PENGUIN_EXIT;
                   2138:            /* Can't happen */
                   2139:            return 0;
                   2140:        }
                   2141: 
                   2142:        for (;;) {
                   2143:            int i, where;
                   2144:            int l = read_comm_pipe_int_blocking (&drawing_pipe);
                   2145:            switch (l) {
                   2146:             case -1:
                   2147:                /* End-of-frame synchronization. */
                   2148:                uae_sem_post (&drawing_lock);
                   2149:                goto new_frame;
                   2150:             case -2:
                   2151:                /* customreset called a bit too often. That's harmless. */
                   2152:                continue;
                   2153:             case -3:
                   2154:                write_log ("Penguin got out of sync.\n");
                   2155:                UAE_PENGUIN_EXIT;
                   2156:                return 0;
                   2157:            }
                   2158: 
                   2159:            /* l is the line that has been finished for drawing. */
                   2160:            i = l - thisframe_y_adjust_real;
                   2161:            if (i < 0 || i >= max_ypos_thisframe)
                   2162:                continue;
                   2163: 
                   2164:            if (linestate[l] == LINE_UNDECIDED) {
                   2165:                fprintf (stderr, "Line scheduled for drawing, but undecided %d!?\n", l);
                   2166:                continue;
                   2167:            }
                   2168:            if (inhibit_frame != 0)
                   2169:                continue;
                   2170:            where = amiga2aspect_line_map[i+min_ypos_for_screen];
                   2171:            if (where >= gfxvidinfo.height || where == -1)
                   2172:                continue;
                   2173: 
                   2174:            pfield_draw_line (l, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
                   2175:        }
                   2176:     }
                   2177: }
                   2178: 
                   2179: static penguin_id our_penguin;
                   2180: 
                   2181: static void kill_drawing_penguin (void)
                   2182: {
                   2183:     /* ??? does libpthread do that for us? */
                   2184: }
                   2185: 
                   2186: #endif
                   2187: 
                   2188: static int penguins_enabled_thisframe;
                   2189: 
                   2190: static void center_image (void)
                   2191: {
                   2192:     prev_x_adjust = linetoscr_x_adjust;
                   2193:     prev_y_adjust = thisframe_y_adjust;
                   2194: 
                   2195:     if (currprefs.gfx_xcenter) {
                   2196:        if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2)
                   2197:            /* Try to center. */
                   2198:            linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1;
                   2199:        else
                   2200:            linetoscr_x_adjust = max_diwstop - gfxvidinfo.width;
                   2201: 
                   2202:        /* Would the old value be good enough? If so, leave it as it is if we want to
                   2203:         * be clever. */
                   2204:        if (currprefs.gfx_xcenter == 2) {
                   2205:            if (linetoscr_x_adjust < prev_x_adjust && prev_x_adjust < min_diwstart)
                   2206:                linetoscr_x_adjust = prev_x_adjust;
                   2207:        }
                   2208:     } else
                   2209:        linetoscr_x_adjust = max_diwlastword - gfxvidinfo.width;
                   2210:     if (linetoscr_x_adjust < 0)
                   2211:        linetoscr_x_adjust = 0;
                   2212: 
                   2213:     linetoscr_x_adjust_bytes = linetoscr_x_adjust * gfxvidinfo.pixbytes;
                   2214: 
                   2215:     linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.width;
                   2216:     if (linetoscr_right_x > max_diwlastword)
                   2217:        linetoscr_right_x = max_diwlastword;
                   2218: 
                   2219:     thisframe_y_adjust = minfirstline;
                   2220:     if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) {
                   2221:        if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2)
                   2222:            thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
                   2223:        else
                   2224:            thisframe_y_adjust = thisframe_first_drawn_line;
                   2225:        /* Would the old value be good enough? If so, leave it as it is if we want to
                   2226:         * be clever. */
                   2227:        if (currprefs.gfx_ycenter == 2) {
                   2228:            if (thisframe_y_adjust != prev_y_adjust
                   2229:                && prev_y_adjust <= thisframe_first_drawn_line
                   2230:                && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)
                   2231:                thisframe_y_adjust = prev_y_adjust;
                   2232:        }
                   2233:        /* Make sure the value makes sense */
                   2234:        if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos)
                   2235:            thisframe_y_adjust = maxvpos - max_drawn_amiga_line;
                   2236:        if (thisframe_y_adjust < minfirstline)
                   2237:            thisframe_y_adjust = minfirstline;
                   2238:     }
                   2239:     thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0);
                   2240:     max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0);
                   2241: 
                   2242:     /* @@@ interlace_seen used to be (bplcon0 & 4), but this is probably
                   2243:      * better.  */
                   2244:     if (prev_x_adjust != linetoscr_x_adjust || prev_y_adjust != thisframe_y_adjust)
                   2245:        frame_redraw_necessary |= interlace_seen && currprefs.gfx_linedbl ? 2 : 1;
                   2246: 
                   2247:     max_diwstop = 0;
                   2248:     min_diwstart = 10000;
                   2249: }
                   2250: 
                   2251: static void init_drawing_frame (void)
                   2252: {
                   2253:     int i, maxline;
                   2254: 
                   2255:     init_hardware_for_drawing_frame ();
                   2256: 
                   2257:     if (max_diwstop == 0)
                   2258:        max_diwstop = diwlastword;
                   2259:     if (min_diwstart > max_diwstop)
                   2260:        min_diwstart = 0;
                   2261: 
                   2262:     if (thisframe_first_drawn_line == -1)
                   2263:        thisframe_first_drawn_line = minfirstline;
                   2264:     if (thisframe_first_drawn_line > thisframe_last_drawn_line)
                   2265:        thisframe_last_drawn_line = thisframe_first_drawn_line;
                   2266: 
                   2267:     maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1;
                   2268: #ifdef SMART_UPDATE
1.1.1.2 ! root     2269:     for (i = 0; i < maxline; i++) {
        !          2270:        switch (linestate[i]) {
        !          2271:         case LINE_DONE_AS_PREVIOUS:
        !          2272:            linestate[i] = LINE_REMEMBERED_AS_PREVIOUS;
        !          2273:            break;
        !          2274:         case LINE_REMEMBERED_AS_BLACK:
        !          2275:            break;
        !          2276:         default:
        !          2277:            linestate[i] = LINE_UNDECIDED;
        !          2278:            break;
        !          2279:        }
        !          2280:     }
1.1       root     2281: #else
                   2282:     memset (linestate, LINE_UNDECIDED, maxline);
                   2283: #endif
                   2284:     last_drawn_line = 0;
                   2285:     first_drawn_line = 32767;
                   2286: 
                   2287:     first_block_line = last_block_line = -2;
                   2288:     if (currprefs.test_drawing_speed)
                   2289:        frame_redraw_necessary = 1;
                   2290:     else if (frame_redraw_necessary)
                   2291:        frame_redraw_necessary--;
                   2292: 
                   2293:     center_image ();
                   2294: 
                   2295:     thisframe_first_drawn_line = -1;
                   2296:     thisframe_last_drawn_line = -1;
                   2297: #ifdef SUPPORT_PENGUINS
                   2298:     penguins_enabled_thisframe = 1;
                   2299:     /* Tell the other thread that it can now expect data from us. */
                   2300:     write_comm_pipe_int (&drawing_pipe, -2, 1);
                   2301:     memset (line_drawn, 0, sizeof line_drawn);
                   2302: #endif
                   2303: 
                   2304:     drawing_color_matches = -1;
                   2305: }
                   2306: 
                   2307: void finish_drawing_frame (void)
                   2308: {
                   2309:     int i;
                   2310: 
                   2311: #ifdef SUPPORT_PENGUINS
                   2312:     /* Synchronize with other thread, then see whether there's something left for
                   2313:      * us to draw. @@@ This is probably a big waste of cycles if the two threads
                   2314:      * run at very different speeds - this one could draw stuff as well. */
                   2315:     write_comm_pipe_int (&drawing_pipe, -1, 1);
                   2316:     uae_sem_wait (&drawing_lock);
                   2317: #else
                   2318: 
                   2319: #ifndef SMART_UPDATE
                   2320:     /* @@@ This isn't exactly right yet. FIXME */
                   2321:     if (!interlace_seen) {
                   2322:        do_flush_screen (first_drawn_line, last_drawn_line);
                   2323:        return;
                   2324:     }
                   2325: #endif
                   2326:     if (! lockscr ()) {
                   2327:        notice_screen_contents_lost ();
                   2328:        return;
                   2329:     }
                   2330:     for (i = 0; i < max_ypos_thisframe; i++) {
                   2331:        int where;
                   2332:        int line = i + thisframe_y_adjust_real;
                   2333: 
                   2334:        if (linestate[line] == LINE_UNDECIDED)
                   2335:            break;
                   2336: 
                   2337:        where = amiga2aspect_line_map[i+min_ypos_for_screen];
                   2338:        if (where >= gfxvidinfo.height)
                   2339:            break;
                   2340:        if (where == -1)
                   2341:            continue;
                   2342: 
                   2343:        pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
                   2344:     }
                   2345:     unlockscr ();
                   2346: #endif
                   2347:     do_flush_screen (first_drawn_line, last_drawn_line);
                   2348: }
                   2349: 
                   2350: void hardware_line_completed (int lineno)
                   2351: {
                   2352: #ifdef SUPPORT_PENGUINS
                   2353:     if (framecnt == 0 && penguins_enabled_thisframe) {
                   2354:        write_comm_pipe_int (&drawing_pipe, lineno, 0);
                   2355:     }
                   2356: #endif
                   2357: #ifndef SMART_UPDATE
                   2358:     {
                   2359:        int i, where;
                   2360:        /* l is the line that has been finished for drawing. */
                   2361:        i = lineno - thisframe_y_adjust_real;
                   2362:        if (i >= 0 && i < max_ypos_thisframe) {
                   2363:            where = amiga2aspect_line_map[i+min_ypos_for_screen];
                   2364:            if (where < gfxvidinfo.height && where != -1)
                   2365:                pfield_draw_line (lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
                   2366:        }
                   2367:     }
                   2368: #endif
                   2369: }
                   2370: 
                   2371: static __inline__ void check_picasso (void)
                   2372: {
                   2373: #ifdef PICASSO96
                   2374:     if (picasso_on && picasso_redraw_necessary)
                   2375:        picasso_refresh ();
                   2376:     picasso_redraw_necessary = 0;
                   2377: 
                   2378:     if (picasso_requested_on == picasso_on)
                   2379:        return;
                   2380: 
                   2381:     picasso_on = picasso_requested_on;
                   2382: 
                   2383:     if (!picasso_on)
                   2384:        clear_inhibit_frame (2);
                   2385:     else
                   2386:        set_inhibit_frame (2);
                   2387: 
                   2388:     gfx_set_picasso_state (picasso_on);
                   2389:     picasso_enablescreen (picasso_requested_on);
                   2390: 
                   2391:     notice_screen_contents_lost ();
                   2392:     notice_new_xcolors ();
                   2393: #endif
                   2394: }
                   2395: 
                   2396: void vsync_handle_redraw (int long_frame, int lof_changed)
                   2397: {
                   2398:     last_redraw_point++;
                   2399:     if (lof_changed || ! interlace_seen || last_redraw_point >= 2 || long_frame) {
                   2400:        last_redraw_point = 0;
                   2401:        interlace_seen = 0;
                   2402: 
                   2403:        if (framecnt == 0)
                   2404:            finish_drawing_frame ();
                   2405: 
                   2406:        /* At this point, we have finished both the hardware and the
                   2407:         * drawing frame. Essentially, we are outside of all loops and
                   2408:         * can do some things which would cause confusion if they were
                   2409:         * done at other times.
                   2410:         */
                   2411: 
                   2412:        if (quit_program < 0) {
                   2413:            quit_program = -quit_program;
                   2414:            set_inhibit_frame (1);
                   2415:            regs.spcflags |= SPCFLAG_BRK;
                   2416:            filesys_prepare_reset ();
                   2417: #ifdef SUPPORT_PENGUINS
                   2418:            if (quit_program == 1)
                   2419:                /* Stop eating herring */
                   2420:                write_comm_pipe_int (&drawing_pipe, -3, 1);
                   2421: #endif
                   2422:            return;
                   2423:        }
                   2424: 
                   2425:        count_frame ();
                   2426:        check_picasso ();
                   2427: 
1.1.1.2 ! root     2428:        check_prefs_changed_audio ();
1.1       root     2429:        check_prefs_changed_custom ();
                   2430:        check_prefs_changed_cpu ();
                   2431:        if (check_prefs_changed_gfx ()) {
                   2432:            init_row_map ();
                   2433:            init_aspect_maps ();
                   2434:            notice_screen_contents_lost ();
                   2435:            notice_new_xcolors ();
                   2436:        }
                   2437: 
                   2438:        if (inhibit_frame != 0)
                   2439:            framecnt = 1;
                   2440: 
                   2441:        if (framecnt == 0)
                   2442:            init_drawing_frame ();
                   2443:     }
                   2444: }
                   2445: 
1.1.1.2 ! root     2446: void hsync_record_line_state (int lineno, enum nln_how how, int changed)
1.1       root     2447: {
1.1.1.2 ! root     2448:     char *state;
1.1       root     2449:     if (framecnt != 0)
                   2450:        return;
1.1.1.2 ! root     2451: 
        !          2452:     state = linestate + lineno;
        !          2453:     changed += frame_redraw_necessary;
        !          2454: 
1.1       root     2455:     switch (how) {
                   2456:      case nln_normal:
1.1.1.2 ! root     2457:        *state = changed ? LINE_DECIDED : LINE_DONE;
1.1       root     2458:        break;
                   2459:      case nln_doubled:
1.1.1.2 ! root     2460:        *state = changed ? LINE_DECIDED_DOUBLE : LINE_DONE;
        !          2461:        changed += state[1] != LINE_REMEMBERED_AS_PREVIOUS;
        !          2462:        state[1] = changed ? LINE_AS_PREVIOUS : LINE_DONE_AS_PREVIOUS;
        !          2463:        break;
        !          2464:      case nln_nblack:
        !          2465:        *state = changed ? LINE_DECIDED : LINE_DONE;
        !          2466:        if (state[1] != LINE_REMEMBERED_AS_BLACK)
        !          2467:            state[1] = LINE_BLACK;
1.1       root     2468:        break;
                   2469:      case nln_lower:
1.1.1.2 ! root     2470:        if (state[-1] == LINE_UNDECIDED)
        !          2471:            state[-1] = LINE_BLACK;
        !          2472:        *state = changed ? LINE_DECIDED : LINE_DONE;
1.1       root     2473:        break;
                   2474:      case nln_upper:
1.1.1.2 ! root     2475:        *state = changed ? LINE_DECIDED : LINE_DONE;
        !          2476:        if (state[1] == LINE_UNDECIDED
        !          2477:            || state[1] == LINE_REMEMBERED_AS_PREVIOUS
        !          2478:            || state[1] == LINE_AS_PREVIOUS)
        !          2479:            state[1] = LINE_BLACK;
1.1       root     2480:        break;
                   2481:     }
                   2482: }
                   2483: 
                   2484: void notice_interlace_seen (void)
                   2485: {
                   2486:     interlace_seen = 1;
                   2487:     penguins_enabled_thisframe = 0;
                   2488: }
                   2489: 
                   2490: void reset_drawing (void)
                   2491: {
                   2492:     int i;
                   2493: 
                   2494:     inhibit_frame = 0;
                   2495:     uae_sem_init (&gui_sem, 0, 1);
                   2496: 
                   2497: #ifdef PICASSO96
                   2498:     InitPicasso96 ();
                   2499:     picasso_on = 0;
                   2500:     picasso_requested_on = 0;
                   2501:     gfx_set_picasso_state (0);
                   2502: #endif
                   2503:     max_diwstop = 0;
                   2504: 
                   2505:     lores_factor = currprefs.gfx_lores ? 1 : 2;
                   2506:     lores_shift = currprefs.gfx_lores ? 0 : 1;
                   2507:     sprite_width = currprefs.gfx_lores ? 16 : 32;
                   2508: 
                   2509:     /*memset(blitcount, 0, sizeof(blitcount));  blitter debug */
                   2510:     for (i = 0; i < sizeof linestate / sizeof *linestate; i++)
                   2511:        linestate[i] = LINE_UNDECIDED;
                   2512: 
                   2513:     xlinebuffer = gfxvidinfo.bufmem;
                   2514: 
                   2515:     init_aspect_maps ();
                   2516: 
                   2517:     if (line_drawn == 0)
                   2518:        line_drawn = (char *)malloc (gfxvidinfo.height);
                   2519: 
                   2520:     init_row_map();
                   2521: 
                   2522:     last_redraw_point = 0;
                   2523: 
                   2524:     init_drawing_frame ();
                   2525: }
                   2526: 
                   2527: void drawing_init ()
                   2528: {
                   2529:     native2amiga_line_map = 0;
                   2530:     amiga2aspect_line_map = 0;
                   2531:     line_drawn = 0;
                   2532: 
                   2533:     gen_pfield_tables();
                   2534: 
                   2535: #ifdef SUPPORT_PENGUINS
                   2536:     init_comm_pipe (&drawing_pipe, 800, 5);
                   2537:     uae_sem_init (&drawing_lock, 0, 0);
                   2538:     start_penguin (drawing_penguin, 0, &our_penguin);
                   2539:     /*atexit(kill_drawing_penguin);*/
                   2540: #endif
                   2541: }
                   2542: 

unix.superglobalmegacorp.com

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