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

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

unix.superglobalmegacorp.com

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