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

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

unix.superglobalmegacorp.com

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