|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
1.1.1.3 ! root 3: *
1.1 root 4: * Custom chip emulation
1.1.1.3 ! root 5: *
1.1.1.2 root 6: * Copyright 1995, 1996, 1997 Bernd Schmidt
7: * Copyright 1995 Alessandro Bissacco
1.1 root 8: */
9:
1.1.1.3 ! root 10: /*
! 11: * This file should be split into two parts. There are two concepts of a
! 12: * "frame" here: a hardware frame which emulates the display hardware of
! 13: * the A500, and a "drawing" frame, which renders data on the screen. You
! 14: * can have multiple hardware frames for one drawing frame, or completely
! 15: * inhibit drawing while hardware frames continue to be emulated. There
! 16: * should be a separate file "drawing.c" or something.
! 17: */
1.1 root 18: #include "sysconfig.h"
19: #include "sysdeps.h"
20:
21: #include <ctype.h>
22: #include <assert.h>
23:
24: #include "config.h"
25: #include "options.h"
1.1.1.3 ! root 26: #include "threaddep/penguin.h"
! 27: #include "uae.h"
! 28: #include "gensound.h"
! 29: #include "sounddep/sound.h"
1.1 root 30: #include "events.h"
31: #include "memory.h"
32: #include "custom.h"
1.1.1.2 root 33: #include "readcpu.h"
1.1 root 34: #include "newcpu.h"
35: #include "cia.h"
36: #include "disk.h"
37: #include "blitter.h"
38: #include "xwin.h"
1.1.1.3 ! root 39: #include "joystick.h"
! 40: #include "audio.h"
1.1 root 41: #include "keybuf.h"
42: #include "serial.h"
1.1.1.2 root 43: #include "osemu.h"
1.1.1.3 ! root 44: #include "autoconf.h"
! 45: #include "gui.h"
! 46: #include "picasso96.h"
! 47: #include "p2c.h"
1.1.1.2 root 48:
49: #ifdef X86_ASSEMBLY
50: #define LORES_HACK
51: #endif
1.1.1.3 ! root 52: #define SPRITE_COLLISIONS
1.1.1.2 root 53:
54: /*
55: * Several people have tried this define, with not much success. Turning on
56: * AGA garbles the screen. A place you could start looking is the calcdiw()
57: * function - the AGA timing parameters are different, and apparently I
58: * haven't figured out the correct formula yet. Pity, the current one looks
59: * logical.
1.1.1.3 ! root 60: *
1.1.1.2 root 61: * @@@ Probably won't compile in this version.
62: */
1.1 root 63:
64: /* #define EMULATE_AGA */
65:
66: #ifndef EMULATE_AGA
67: #define AGA_CHIPSET 0
68: #else
69: #define AGA_CHIPSET 1
70: #endif
71:
72: #define SMART_UPDATE 1
73:
1.1.1.2 root 74: #ifdef SUPPORT_PENGUINS
75: #undef SMART_UPDATE
1.1.1.3 ! root 76: #define SMART_UPDATE 1
1.1.1.2 root 77: #endif
78:
79: #if AGA_CHIPSET == 1
1.1 root 80: #define MAX_PLANES 8
1.1.1.2 root 81: #else
82: #define MAX_PLANES 6
83: #endif
84:
85: /* Fetched data spends 9 lores pixels somewhere in the chips before it appears
86: * on-screen. We don't emulate this. Instead, we cheat with the copper to
87: * compensate (much easier that way). */
88: #define COPPER_MAGIC_FUDGE -9
89: /* We ignore that many lores pixels at the start of the display. These are
90: * invisible anyway due to hardware DDF limits. */
91: #define DISPLAY_LEFT_SHIFT 0x38
92: static int lores_factor, lores_shift, sprite_width;
93:
94: #define PIXEL_XPOS(HPOS) (((HPOS)*2 - DISPLAY_LEFT_SHIFT) << lores_shift)
1.1 root 95:
1.1.1.2 root 96: /* @@@ Is maxhpos + 4 - 1 correct? (4 less isn't enough) */
97: #define max_diwlastword (PIXEL_XPOS(maxhpos + 4 -1))
1.1 root 98:
1.1.1.3 ! root 99: /* Mouse and joystick emulation */
1.1.1.2 root 100:
1.1 root 101: #define defstepx (1<<16)
102: #define defstepy (1<<16)
103: #define defxoffs 0
104: #define defyoffs 0
105:
106: static const int docal = 60, xcaloff = 40, ycaloff = 20;
107: static const int calweight = 3;
108: static int lastsampledmx, lastsampledmy;
109:
1.1.1.3 ! root 110: int buttonstate[3];
! 111: int lastmx, lastmy;
! 112: int newmousecounters;
! 113: int ievent_alive = 0;
! 114:
! 115: static enum { normal_mouse, dont_care_mouse, follow_mouse } mousestate;
! 116:
! 117: static int mouse_x, mouse_y;
! 118: int joy0button, joy1button;
! 119: unsigned int joy0dir, joy1dir;
! 120: static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl;
! 121: static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs;
! 122: static int sprvbfl;
! 123:
! 124: /* Video buffer description structure. Filled in by the graphics system
! 125: * dependent code. */
! 126:
! 127: struct vidbuf_description gfxvidinfo;
! 128:
! 129: /* Events */
1.1 root 130:
1.1.1.3 ! root 131: unsigned long int cycles, nextevent, is_lastline, did_reset;
1.1.1.2 root 132: struct ev eventtab[ev_max];
133:
1.1.1.3 ! root 134: frame_time_t vsynctime, vsyncmintime;
! 135:
1.1 root 136: int vpos;
1.1.1.3 ! root 137: uae_u16 lof;
1.1.1.2 root 138: static int lof_changed = 0, interlace_seen = 0;
1.1 root 139:
1.1.1.2 root 140: static int copper_waiting_for_blitter, copper_active;
141: static const int dskdelay = 2; /* FIXME: ??? */
1.1 root 142:
1.1.1.2 root 143: static int dblpf_ind1[256], dblpf_ind2[256], dblpf_2nd1[256], dblpf_2nd2[256];
144: static int dblpf_aga1[256], dblpf_aga2[256], linear_map_256[256], lots_of_twos[256];
1.1 root 145:
1.1.1.2 root 146: static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
1.1 root 147:
1.1.1.3 ! root 148: /* Big lookup tables for planar to chunky conversion. */
! 149:
! 150: uae_u32 hirestab_h[256][2];
! 151: uae_u32 lorestab_h[256][4];
! 152:
! 153: uae_u32 hirestab_l[256][1];
! 154: uae_u32 lorestab_l[256][2];
! 155:
! 156: static uae_u32 sprtaba[256],sprtabb[256];
! 157: static uae_u32 clxtab[256];
! 158:
! 159: /* The color lookup table. */
! 160:
! 161: xcolnr xcolors[4096];
! 162:
1.1.1.2 root 163: /*
164: * Hardware registers of all sorts.
165: */
1.1 root 166:
167: static int fmode;
168:
1.1.1.3 ! root 169: static uae_u16 cregs[256];
1.1 root 170:
1.1.1.3 ! root 171: uae_u16 intena,intreq;
! 172: uae_u16 dmacon;
! 173: uae_u16 adkcon; /* used by audio code */
1.1 root 174:
1.1.1.3 ! root 175: static uae_u32 cop1lc,cop2lc,copcon;
1.1 root 176:
1.1.1.2 root 177: /* This is but an educated guess. It seems to be correct, but this stuff
178: * isn't documented well. */
1.1.1.3 ! root 179: enum sprstate { SPR_stop, SPR_restart, SPR_waiting_start, SPR_waiting_stop };
! 180: static enum sprstate sprst[8];
! 181: static int spron[8];
! 182: static uaecptr sprpt[8];
1.1.1.2 root 183: static int sprxpos[8], sprvstart[8], sprvstop[8];
1.1 root 184:
1.1.1.3 ! root 185: static uae_u32 bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat,bpl7dat,bpl8dat;
! 186: static uae_s16 bpl1mod,bpl2mod;
1.1 root 187:
1.1.1.3 ! root 188: static uaecptr bplpt[8];
1.1.1.2 root 189: #ifndef SMART_UPDATE
190: static char *real_bplpt[8];
191: #endif
1.1 root 192:
193: /*static int blitcount[256]; blitter debug */
194:
1.1.1.2 root 195: struct color_entry {
1.1 root 196: #if AGA_CHIPSET == 0
1.1.1.2 root 197: /* X86.S expects this at the start of the structure. */
198: xcolnr acolors[32];
1.1.1.3 ! root 199: uae_u16 color_regs[32];
1.1 root 200: #else
1.1.1.3 ! root 201: uae_u32 color_regs[256];
1.1 root 202: #endif
203: };
204:
1.1.1.2 root 205: static struct color_entry current_colors;
206: struct color_entry colors_for_drawing;
207: static unsigned int bplcon0,bplcon1,bplcon2,bplcon3,bplcon4;
1.1.1.3 ! root 208: static int nr_planes_from_bplcon0, corrected_nr_planes_from_bplcon0;
1.1.1.2 root 209: static unsigned int diwstrt,diwstop,ddfstrt,ddfstop;
210: static unsigned int sprdata[8], sprdatb[8], sprctl[8], sprpos[8];
211: static int sprarmed[8], sprite_last_drawn_at[8];
1.1.1.3 ! root 212: static int last_sprite_point, nr_armed;
! 213: static uae_u16 clxdat, clxcon;
! 214: static int clx_sprmask;
! 215: static uae_u32 dskpt;
! 216: static uae_u16 dsklen,dsksync;
1.1 root 217:
1.1.1.3 ! root 218: static uae_u32 coplc;
1.1.1.2 root 219: static unsigned int copi1,copi2;
1.1 root 220:
1.1.1.2 root 221: static enum copper_states {
222: COP_stop, COP_read, COP_do_read, COP_read_ignore, COP_do_read_ignore, COP_wait, COP_morewait, COP_move, COP_skip
1.1 root 223: } copstate;
1.1.1.2 root 224: /* The time the copper needs for one cycle depends on bitplane DMA. Whenever
225: * possible, we calculate a fixed value and store it here. */
226: static int copper_cycle_time;
1.1 root 227:
228: static int dsklength;
229:
1.1.1.2 root 230: static int plffirstline,plflastline,plfstrt,plfstop,plflinelen;
231: static int diwfirstword,diwlastword;
1.1.1.3 ! root 232: static enum { DIW_waiting_start, DIW_waiting_stop } diwstate, hdiwstate;
1.1 root 233:
234: int dskdmaen; /* used in cia.c */
235:
1.1.1.2 root 236: /* 880 isn't a magic number, it's a safe number with some padding at the end.
237: * This used to be 1000, but that's excessive. (840 is too low). I'm too lazy
238: * to figure out the exact space needed. */
1.1 root 239: union {
240: /* Let's try to align this thing. */
241: double uupzuq;
242: long int cruxmedo;
1.1.1.2 root 243: unsigned char apixels[880];
1.1 root 244: } pixdata;
245:
1.1.1.3 ! root 246: uae_u32 ham_linebuf[880];
! 247: uae_u32 aga_linebuf[880], *aga_lbufptr;
1.1 root 248:
249: char *xlinebuffer;
1.1.1.2 root 250: int next_lineno;
251: static int nln_how;
252:
253: static int *amiga2aspect_line_map, *native2amiga_line_map;
1.1.1.3 ! root 254: static char *row_map[2049];
1.1.1.2 root 255: static int max_drawn_amiga_line;
1.1 root 256:
257: /*
258: * Statistics
259: */
260:
1.1.1.2 root 261: /* Used also by bebox.cpp */
262: unsigned long int msecs = 0, frametime = 0, timeframes = 0;
1.1 root 263: static unsigned long int seconds_base;
264: int bogusframe;
265:
266: /*
267: * helper functions
268: */
269:
1.1.1.3 ! root 270: int picasso_requested_on;
! 271: int picasso_on;
! 272:
! 273: uae_sem_t frame_sem, gui_sem, ihf_sem;
! 274: volatile int frame_do_semup;
! 275: volatile int inhibit_frame;
! 276:
1.1 root 277: static int framecnt = 0;
1.1.1.3 ! root 278: static int frame_redraw_necessary;
1.1 root 279:
1.1.1.3 ! root 280: static __inline__ void count_frame (void)
1.1 root 281: {
1.1.1.3 ! root 282: framecnt++;
! 283: if (framecnt >= currprefs.framerate)
! 284: framecnt = 0;
! 285: }
! 286:
! 287: void check_prefs_changed_custom (void)
! 288: {
! 289: currprefs.framerate = changed_prefs.framerate;
! 290: /* Not really the right place... */
! 291: if (currprefs.fake_joystick != changed_prefs.fake_joystick) {
! 292: currprefs.fake_joystick = changed_prefs.fake_joystick;
! 293: joystick_setting_changed ();
1.1 root 294: }
1.1.1.3 ! root 295: currprefs.immediate_blits = changed_prefs.immediate_blits;
! 296: currprefs.blits_32bit_enabled = changed_prefs.blits_32bit_enabled;
! 297:
1.1 root 298: }
299:
1.1.1.3 ! root 300: static __inline__ void setclr (uae_u16 *p, uae_u16 val)
1.1 root 301: {
302: if (val & 0x8000) {
303: *p |= val & 0x7FFF;
304: } else {
305: *p &= ~val;
306: }
307: }
308:
1.1.1.3 ! root 309: __inline__ int current_hpos (void)
1.1 root 310: {
311: return cycles - eventtab[ev_hsync].oldcycles;
312: }
313:
1.1.1.3 ! root 314: static __inline__ uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount)
1.1.1.2 root 315: {
316: if (!chipmem_bank.check(plpt,bytecount)) {
317: static int count = 0;
1.1.1.3 ! root 318: if (!count)
! 319: count++, write_log ("Warning: Bad playfield pointer\n");
1.1.1.2 root 320: return NULL;
321: }
322: return chipmem_bank.xlateaddr(plpt);
323: }
324:
325: static void calculate_copper_cycle_time (void)
1.1 root 326: {
1.1.1.2 root 327: if (diwstate == DIW_waiting_start || !dmaen (DMA_BITPLANE)) {
328: copper_cycle_time = 2;
329: return;
330: }
1.1.1.3 ! root 331: copper_cycle_time = corrected_nr_planes_from_bplcon0 <= 4 ? 2 : -1;
1.1.1.2 root 332: }
333:
334: /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham6 */
335: typedef void (*line_draw_func)(int, int);
336:
337: #define LINE_UNDECIDED 1
338: #define LINE_DECIDED 2
339: #define LINE_DECIDED_DOUBLE 3
340: #define LINE_AS_PREVIOUS 4
341: #define LINE_BORDER_NEXT 5
342: #define LINE_BORDER_PREV 6
343: #define LINE_DONE 7
344: #define LINE_DONE_AS_PREVIOUS 8
345: #define LINE_REMEMBERED_AS_PREVIOUS 9
346:
347: static char *line_drawn;
348: static char linestate[(maxvpos + 1)*2 + 1];
349:
350: static int min_diwstart, max_diwstop, prev_x_adjust, linetoscr_x_adjust, linetoscr_right_x;
1.1.1.3 ! root 351: static int linetoscr_x_adjust_bytes;
1.1.1.2 root 352: static int thisframe_y_adjust, prev_y_adjust, thisframe_first_drawn_line, thisframe_last_drawn_line;
353: static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen;
1.1.1.3 ! root 354: static int extra_y_adjust;
1.1.1.2 root 355:
1.1.1.3 ! root 356: static uae_u8 line_data[(maxvpos+1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
1.1.1.2 root 357:
358: /*
359: * The idea behind this code is that at some point during each horizontal
360: * line, we decide how to draw this line. There are many more-or-less
361: * independent decisions, each of which can be taken at a different horizontal
362: * position.
1.1.1.3 ! root 363: * Sprites, color changes and bitplane delay changes are handled specially:
! 364: * There isn't a single decision, but a list of structures containing
1.1.1.2 root 365: * information on how to draw the line.
366: */
367:
368: struct color_change {
369: int linepos;
370: int regno;
371: unsigned long value;
372: };
373:
374: struct sprite_draw {
375: int linepos;
376: int num;
377: int ctl;
1.1.1.3 ! root 378: uae_u32 datab;
1.1.1.2 root 379: };
380:
381: struct delay_change {
382: int linepos;
383: unsigned int value;
384: };
385:
386: /* Way too much... */
387: #define MAX_REG_CHANGE ((maxvpos+1) * 2 * maxhpos)
388: static int current_change_set;
389:
390: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1.1.1.3 ! root 391: /* sam: Those arrays uses around 7Mb of BSS... That seems */
1.1.1.2 root 392: /* too much for AmigaDOS (uae crashes as soon as one loads */
393: /* it. So I use a different strategy here (realloc the */
394: /* arrays when needed. That strategy might be usefull for */
395: /* computer with low memory. */
396: static struct sprite_draw *sprite_positions[2];
1.1.1.3 ! root 397: static int max_sprite_draw = 400;
! 398: static int delta_sprite_draw = 0;
1.1.1.2 root 399: static struct color_change *color_changes[2];
1.1.1.3 ! root 400: static int max_color_change = 400;
! 401: static int delta_color_change = 0;
! 402: static struct delay_change *delay_changes;
! 403: static int max_delay_change = 100;
! 404: static int delta_delay_change = 0;
1.1.1.2 root 405: #else
406: static struct sprite_draw sprite_positions[2][MAX_REG_CHANGE];
407: static struct color_change color_changes[2][MAX_REG_CHANGE];
1.1.1.3 ! root 408: /* We don't remember those across frames, that would be too much effort.
1.1.1.2 root 409: * We simply redraw the line whenever we see one of these. */
410: static struct delay_change delay_changes[MAX_REG_CHANGE];
1.1.1.3 ! root 411: #endif
1.1.1.2 root 412: static struct sprite_draw *curr_sprite_positions, *prev_sprite_positions;
413: static struct color_change *curr_color_changes, *prev_color_changes;
414:
415: static int next_color_change, next_sprite_draw, next_delay_change;
416:
417: static struct color_entry color_tables[2][(maxvpos+1) * 2];
418: static struct color_entry *curr_color_tables, *prev_color_tables;
419: static int next_color_entry, remembered_color_entry, drawing_color_matches;
420: static enum { color_match_acolors, color_match_full } color_match_type;
1.1.1.3 ! root 421: static int color_src_match, color_dest_match, color_compare_result;
1.1.1.2 root 422:
423: static int last_redraw_point;
424:
425: static int first_drawn_line, last_drawn_line;
426: static int first_block_line, last_block_line;
427:
1.1.1.3 ! root 428: static __inline__ void docols(struct color_entry *colentry)
! 429: {
! 430: #if AGA_CHIPSET == 0
! 431: int i;
! 432: for (i = 0; i < 32; i++) {
! 433: int v = colentry->color_regs[i];
! 434: if (v < 0 || v > 4095)
! 435: continue;
! 436: colentry->acolors[i] = xcolors[v];
! 437: }
! 438: #endif
! 439: }
! 440:
! 441: void notice_new_xcolors (void)
! 442: {
! 443: int i;
! 444:
! 445: docols(¤t_colors);
! 446: docols(&colors_for_drawing);
! 447: for (i = 0; i < (maxvpos+1)*2; i++) {
! 448: docols(color_tables[0]+i);
! 449: docols(color_tables[1]+i);
! 450: }
! 451: }
! 452:
! 453: void notice_screen_contents_lost (void)
! 454: {
! 455: frame_redraw_necessary = 2;
! 456: }
! 457:
1.1.1.2 root 458: static void init_regchanges (void)
459: {
460: size_t i;
461:
462: next_color_change = 0;
463: next_sprite_draw = 0;
464: current_change_set = 0;
465: for (i = 0; i < sizeof linestate / sizeof *linestate; i++)
466: linestate[i] = LINE_UNDECIDED;
467: }
468:
469: /* struct decision contains things we save across drawing frames for
470: * comparison (smart update stuff). */
471: struct decision {
472: unsigned long color0;
473: int which;
474: int plfstrt, plflinelen;
475: int diwfirstword, diwlastword;
476: int ctable;
477:
1.1.1.3 ! root 478: uae_u16 bplcon0, bplcon1, bplcon2;
1.1.1.2 root 479: #if 0 /* We don't need this. */
1.1.1.3 ! root 480: uae_u16 bplcon3;
1.1.1.2 root 481: #endif
482: #if AGA_CHIPSET == 1
1.1.1.3 ! root 483: uae_u16 bplcon4;
1.1.1.2 root 484: #endif
485: };
486:
487: /* Anything related to changes in hw registers during the DDF for one
488: * line. */
489: struct draw_info {
490: int first_sprite_draw, last_sprite_draw;
491: int first_color_change, last_color_change;
492: int first_delay_change, last_delay_change;
493: int nr_color_changes, nr_sprites;
494: };
495:
496: /* These few are only needed during/at the end of the scanline, and don't
497: * have to be remembered. */
498: static int decided_bpl1mod, decided_bpl2mod, decided_nr_planes, decided_hires;
499:
500: /* These are generated by the drawing code from the line_decisions array for
501: * each line that needs to be drawn. */
502: static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplhires;
503: static int bpldelay1, bpldelay2;
504: static int plfpri[3];
505:
506: static struct decision line_decisions[2 * (maxvpos+1) + 1];
507: static struct draw_info line_drawinfo[2][2 * (maxvpos+1) + 1];
508: static struct draw_info *curr_drawinfo, *prev_drawinfo;
509: static struct decision *dp_for_drawing;
510: static struct draw_info *dip_for_drawing;
511:
1.1.1.3 ! root 512: static char line_changed[2 * (maxvpos+1)];
1.1.1.2 root 513:
514: #ifdef SMART_UPDATE
515: #define MARK_LINE_CHANGED(l) do { line_changed[l] = 1; } while (0)
516: #else
517: #define MARK_LINE_CHANGED(l) do { } while (0)
518: #endif
519:
520: static struct decision thisline_decision;
521: static int modulos_added, plane_decided, color_decided, very_broken_program;
522:
523: static void do_sprites(int currvp, int currhp);
524:
525: static void remember_ctable (void)
526: {
527: if (remembered_color_entry == -1) {
528: /* The colors changed since we last recorded a color map. Record a
529: * new one. */
530: memcpy (curr_color_tables + next_color_entry, ¤t_colors, sizeof current_colors);
531: remembered_color_entry = next_color_entry++;
532: }
533: thisline_decision.ctable = remembered_color_entry;
534: if (color_src_match == -1 || color_dest_match != remembered_color_entry
535: || line_decisions[next_lineno].ctable != color_src_match)
536: {
537: /* The remembered comparison didn't help us - need to compare again. */
538: int oldctable = line_decisions[next_lineno].ctable;
539: int changed = 0;
540:
1.1.1.3 ! root 541: if (oldctable == -1) {
1.1.1.2 root 542: changed = 1;
543: color_src_match = color_dest_match = -1;
544: } else {
1.1.1.3 ! root 545: color_compare_result = memcmp (&prev_color_tables[oldctable].color_regs,
! 546: ¤t_colors.color_regs,
! 547: sizeof current_colors.color_regs) != 0;
! 548: if (color_compare_result)
! 549: changed = 1;
! 550: color_src_match = oldctable;
1.1.1.2 root 551: color_dest_match = remembered_color_entry;
1.1.1.3 ! root 552: }
! 553: if (changed) {
! 554: line_changed[next_lineno] = 1;
! 555: }
! 556: } else {
! 557: /* We know the result of the comparison */
! 558: if (color_compare_result)
! 559: line_changed[next_lineno] = 1;
! 560: }
! 561: }
! 562:
! 563: static void remember_ctable_for_border (void)
! 564: {
! 565: remember_ctable ();
! 566: #if 0
! 567: if (remembered_color_entry == -1) {
! 568: /* The colors changed since we last recorded a color map. Record a
! 569: * new one. */
! 570: memcpy (curr_color_tables + next_color_entry, ¤t_colors, sizeof current_colors);
! 571: remembered_color_entry = next_color_entry++;
! 572: }
! 573: thisline_decision.ctable = remembered_color_entry;
! 574: if (color_src_match == -1 || color_dest_match != remembered_color_entry
! 575: || line_decisions[next_lineno].ctable != color_src_match)
! 576: {
! 577: /* The remembered comparison didn't help us - need to compare again. */
! 578: int oldctable = line_decisions[next_lineno].ctable;
! 579: int changed = 0;
! 580:
! 581: if (oldctable == -1) {
! 582: changed = 1;
! 583: color_src_match = color_dest_match = -1;
! 584: } else {
! 585: color_compare_result = memcmp (&prev_color_tables[oldctable].color_regs,
! 586: ¤t_colors.color_regs,
! 587: sizeof current_colors.color_regs) != 0;
! 588: if (color_compare_result)
! 589: changed = 1;
1.1.1.2 root 590: color_src_match = oldctable;
1.1.1.3 ! root 591: color_dest_match = remembered_color_entry;
! 592: }
! 593: if (changed) {
! 594: line_changed[next_lineno] = 1;
1.1.1.2 root 595: }
1.1.1.3 ! root 596: } else {
! 597: /* We know the result of the comparison */
! 598: if (color_compare_result)
! 599: line_changed[next_lineno] = 1;
1.1.1.2 root 600: }
1.1.1.3 ! root 601: #endif
1.1.1.2 root 602: }
603:
1.1.1.3 ! root 604: /* Called to determine the state of the horizontal display window state
! 605: * machine at the current position. It might have changed since we last
! 606: * checked. */
1.1.1.2 root 607: static void decide_diw (void)
608: {
1.1.1.3 ! root 609: if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1
! 610: && PIXEL_XPOS (current_hpos ()) >= diwfirstword)
! 611: {
1.1.1.2 root 612: thisline_decision.diwfirstword = diwfirstword;
1.1.1.3 ! root 613: hdiwstate = DIW_waiting_stop;
1.1.1.2 root 614: /* Decide playfield delays only at DIW start, because they don't matter before and
615: * some programs change them after DDF start but before DIW start. */
616: thisline_decision.bplcon1 = bplcon1;
617: if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
618: MARK_LINE_CHANGED (next_lineno);
619: thisline_decision.diwlastword = -1;
620: }
1.1.1.3 ! root 621: if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1
! 622: && PIXEL_XPOS (current_hpos ()) >= diwlastword)
! 623: {
1.1.1.2 root 624: thisline_decision.diwlastword = diwlastword;
1.1.1.3 ! root 625: hdiwstate = DIW_waiting_start;
1.1.1.2 root 626: if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
627: MARK_LINE_CHANGED (next_lineno);
628: }
629: }
630:
1.1.1.3 ! root 631: /* Called when we know that the line is not in the border and we want to it.
! 632: * The data fetch starting position and length are passed as parameters. */
1.1.1.2 root 633: static __inline__ void decide_as_playfield (int startpos, int len)
634: {
635: thisline_decision.which = 1;
636:
637: /* The latter condition might be able to happen in interlaced frames. */
638: if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line))
639: thisframe_first_drawn_line = vpos;
640: thisframe_last_drawn_line = vpos;
641:
642: thisline_decision.plfstrt = startpos;
643: thisline_decision.plflinelen = len;
644:
645: /* These are for comparison. */
646: thisline_decision.bplcon0 = bplcon0;
647: thisline_decision.bplcon2 = bplcon2;
648: #if AGA_CHIPSET == 1
649: thisline_decision.bplcon4 = bplcon4;
650: #endif
651:
652: #ifdef SMART_UPDATE
653: if (line_decisions[next_lineno].plfstrt != thisline_decision.plfstrt
654: || line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen
655: || line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0
656: || line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2
657: #if AGA_CHIPSET == 1
658: || line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4
659: #endif
660: )
661: #endif /* SMART_UPDATE */
662: line_changed[next_lineno] = 1;
663: }
664:
1.1.1.3 ! root 665: /* Called when we already decided whether the line is playfield or border,
! 666: * but are no longer sure that this was such a good idea. This can make a
! 667: * difference only for very badly written software. */
1.1.1.2 root 668: static __inline__ void post_decide_line (void)
669: {
670: static int warned = 0;
671: int tmp;
672:
673: if (thisline_decision.which == 1 && current_hpos () < thisline_decision.plfstrt + thisline_decision.plflinelen
674: && ((bplcon0 & 0x7000) == 0 || !dmaen (DMA_BITPLANE)))
675: {
676: /* This is getting gross... */
677: thisline_decision.plflinelen = current_hpos() - thisline_decision.plfstrt;
678: thisline_decision.plflinelen &= 7;
679: if (thisline_decision.plflinelen == 0)
680: thisline_decision.which = -1;
681: /* ... especially THIS! */
682: modulos_added = 1;
683: return;
684: }
1.1.1.3 ! root 685:
1.1.1.2 root 686: if (thisline_decision.which != -1 || diwstate == DIW_waiting_start || (bplcon0 & 0x7000) == 0
687: || !dmaen (DMA_BITPLANE) || current_hpos () >= thisline_decision.plfstrt + thisline_decision.plflinelen)
688: return;
689: #if 0 /* Can't warn because Kickstart 1.3 does it at reset time ;-) */
690: if (!warned) {
1.1.1.3 ! root 691: write_log ("That program you are running is _really_ broken.\n");
1.1.1.2 root 692: warned = 1;
693: }
694: #endif
695:
696: decided_hires = (bplcon0 & 0x8000) == 0x8000;
1.1.1.3 ! root 697: decided_nr_planes = nr_planes_from_bplcon0;
1.1.1.2 root 698:
699: /* Magic 12, Ray of Hope 2 demo does ugly things. Looks great from the
700: * outside, rotten inside. */
701: if (decided_hires) {
702: tmp = current_hpos () & ~3;
703: very_broken_program = current_hpos () & 3;
704: } else {
705: tmp = current_hpos () & ~7;
706: very_broken_program = current_hpos () & 7;
707: }
708: MARK_LINE_CHANGED (next_lineno); /* Play safe. */
709: decide_as_playfield (tmp, plflinelen + plfstrt - tmp);
710: }
711:
712: static void decide_line_1 (void)
713: {
714: do_sprites(vpos, current_hpos ());
715:
716: /* Surprisingly enough, this seems to be correct here - putting this into
717: * decide_diw() results in garbage. */
718: if (diwstate == DIW_waiting_start && vpos == plffirstline) {
719: diwstate = DIW_waiting_stop;
720: calculate_copper_cycle_time ();
721: }
722: if (diwstate == DIW_waiting_stop && vpos == plflastline) {
723: diwstate = DIW_waiting_start;
724: calculate_copper_cycle_time ();
725: }
726:
727: if (framecnt != 0) {
728: /* thisline_decision.which = -2; This doesn't do anything but hurt, I think. */
729: return;
730: }
1.1.1.3 ! root 731:
! 732: if (!dmaen(DMA_BITPLANE) || diwstate == DIW_waiting_start || nr_planes_from_bplcon0 == 0) {
1.1.1.2 root 733: /* We don't want to draw this one. */
734: thisline_decision.which = -1;
1.1.1.3 ! root 735: thisline_decision.plfstrt = plfstrt;
! 736: thisline_decision.plflinelen = plflinelen;
1.1.1.2 root 737: return;
738: }
739:
740: decided_hires = (bplcon0 & 0x8000) == 0x8000;
1.1.1.3 ! root 741: decided_nr_planes = nr_planes_from_bplcon0;
1.1.1.2 root 742: #if 0
1.1.1.3 ! root 743: /* The blitter gets slower if there's high bitplane activity.
1.1.1.2 root 744: * @@@ but the values must be different. FIXME */
745: if (bltstate != BLT_done
746: && ((decided_hires && decided_nr_planes > 2)
747: || (!decided_hires && decided_nr_planes > 4)))
748: {
749: int pl = decided_nr_planes;
750: unsigned int n = (eventtab[ev_blitter].evtime-cycles);
751: if (n > plflinelen)
752: n = plflinelen;
753: n >>= 1;
754: if (decided_hires)
755: pl <<= 1;
756: if (pl == 8)
757: eventtab[ev_blitter].evtime += plflinelen;
758: else if (pl == 6)
759: eventtab[ev_blitter].evtime += n*2;
760: else if (pl == 5)
761: eventtab[ev_blitter].evtime += n*3/2;
762: events_schedule();
763: }
764: #endif
765: decide_as_playfield (plfstrt, plflinelen);
766: }
767:
1.1.1.3 ! root 768: /* Main entry point for deciding how to draw a line. May either do
! 769: * nothing, decide the line as border, or decide the line as playfield. */
1.1.1.2 root 770: static __inline__ void decide_line (void)
771: {
772: if (thisline_decision.which == 0 && current_hpos() >= plfstrt)
773: decide_line_1 ();
774: }
775:
1.1.1.3 ! root 776: /* Called when a color is about to be changed (write to a color register),
! 777: * but the new color has not been entered into the table yet. */
! 778: static void record_color_change (int regno, unsigned long value)
! 779: {
! 780: /* Early positions don't appear on-screen. */
! 781: if (framecnt != 0 || vpos < minfirstline || current_hpos () < 0x18
! 782: /*|| currprefs.emul_accuracy == 0*/)
! 783: return;
! 784:
! 785: decide_diw ();
! 786: decide_line ();
! 787:
! 788: /* See if we can record the color table, but have not done so yet.
! 789: * @@@ There might be a minimal performance loss in case someone changes
! 790: * a color exactly at the start of the DIW. I don't think it can actually
! 791: * fail to work even in this case, but I'm not 100% sure.
! 792: * @@@ There might be a slightly larger performance loss if we're drawing
! 793: * this line as border... especially if there are changes in colors != 0
! 794: * we might end up setting line_changed for no reason. FIXME */
! 795: if (thisline_decision.diwfirstword >= 0
! 796: && thisline_decision.which != 0)
! 797: {
! 798: if (thisline_decision.ctable == -1)
! 799: remember_ctable ();
! 800: }
! 801:
! 802: /* Changes outside the DIW can be ignored if the modified color is not the
! 803: * background color, or if the accuracy is < 2. */
! 804: if ((regno != 0 || currprefs.emul_accuracy < 2)
! 805: && (diwstate == DIW_waiting_start || thisline_decision.diwfirstword < 0
! 806: || thisline_decision.diwlastword >= 0
! 807: || thisline_decision.which == 0
! 808: || (thisline_decision.which == 1 && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)))
! 809: return;
! 810:
! 811: /* If the border is changed the first time before the DIW, record the
! 812: * original starting border value. */
! 813: if (regno == 0 && thisline_decision.color0 == 0xFFFFFFFFul && thisline_decision.diwfirstword < 0) {
! 814: thisline_decision.color0 = current_colors.color_regs[0];
! 815: if (line_decisions[next_lineno].color0 != value)
! 816: line_changed[next_lineno] = 1;
! 817: }
! 818: /* Anything else gets recorded in the color_changes table. */
! 819: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
! 820: if(next_color_change >= max_color_change) {
! 821: ++delta_color_change;
! 822: return;
! 823: }
! 824: #endif
! 825: curr_color_changes[next_color_change].linepos = current_hpos ();
! 826: curr_color_changes[next_color_change].regno = regno;
! 827: curr_color_changes[next_color_change++].value = value;
! 828: }
! 829:
! 830: /* Stupid hack to get some Sanity demos working. */
1.1.1.2 root 831: static void decide_delay (void)
832: {
833: static int warned;
834:
835: /* Don't do anything if we're outside the DIW. */
836: if (thisline_decision.diwfirstword == -1 || thisline_decision.diwlastword > 0)
837: return;
838: decide_line ();
839: /* Half-hearted attempt to get things right even when post_decide_line() changes
840: * the decision afterwards. */
841: if (thisline_decision.which != 1) {
842: thisline_decision.bplcon1 = bplcon1;
843: return;
844: }
845: /* @@@ Could check here for DDF stopping earlier than DIW */
1.1.1.3 ! root 846:
! 847: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
! 848: if(next_delay_change >= max_delay_change) {
! 849: ++delta_delay_change;
! 850: return;
! 851: }
! 852: #endif
1.1.1.2 root 853: delay_changes[next_delay_change].linepos = current_hpos ();
854: delay_changes[next_delay_change++].value = bplcon1;
855: if (!warned) {
856: warned = 1;
1.1.1.3 ! root 857: write_log ("Program is torturing BPLCON1.\n");
1.1.1.2 root 858: }
859: }
860:
861: /*
862: * The decision which bitplane pointers to use is not taken at plfstrt, since
863: * data fetch does not start for all planes at this point. Therefore, we wait
864: * for the end of the ddf area or the first write to any of the bitplane
865: * pointer registers, whichever comes last, before we decide which plane pointers
866: * to use.
867: * Call decide_line() before this function.
868: */
869: static void decide_plane (void)
870: {
871: int i, bytecount;
872:
873: if (framecnt != 0 || plane_decided)
874: return;
875:
876: if (decided_nr_planes == -1 /* Still undecided */
877: || current_hpos () < thisline_decision.plfstrt + thisline_decision.plflinelen)
878: return;
879:
880: plane_decided = 1;
881:
882: bytecount = plflinelen / (decided_hires ? 4 : 8) * 2;
883:
884: if (bytecount > MAX_WORDS_PER_LINE * 2) {
885: /* Can't happen. */
886: static int warned = 0;
887: if (!warned)
1.1.1.3 ! root 888: write_log ("Mysterious bug in decide_plane(). Please report.\n");
1.1.1.2 root 889: bytecount = 0;
890: }
891: if (!very_broken_program) {
1.1.1.3 ! root 892: uae_u8 *dataptr = line_data[next_lineno];
1.1.1.2 root 893: for (i = 0; i < decided_nr_planes; i++, dataptr += MAX_WORDS_PER_LINE*2) {
1.1.1.3 ! root 894: uaecptr pt = bplpt[i];
! 895: uae_u8 *real_ptr = pfield_xlateptr(pt, bytecount);
1.1.1.2 root 896: if (real_ptr == NULL)
897: real_ptr = pfield_xlateptr(0, 0);
898: #ifdef SMART_UPDATE
1.1.1.3 ! root 899: #if 1
! 900: if (line_changed[next_lineno])
1.1.1.2 root 901: memcpy (dataptr, real_ptr, bytecount);
1.1.1.3 ! root 902: else
! 903: #endif
! 904: line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount);
1.1.1.2 root 905: #else
906: real_bplpt[i] = real_ptr;
907: #endif
908: }
1.1 root 909: } else {
1.1.1.3 ! root 910: uae_u8 *dataptr = line_data[next_lineno];
1.1.1.2 root 911: for (i = 0; i < decided_nr_planes; i++, dataptr += MAX_WORDS_PER_LINE*2) {
1.1.1.3 ! root 912: uaecptr pt = bplpt[i];
! 913: uae_u8 *real_ptr;
! 914:
1.1.1.2 root 915: if (decided_hires) {
916: switch (i) {
917: case 3: pt -= 2;
918: case 2: pt -= (very_broken_program >= 3 ? 2 : 0); break;
919: case 1: pt -= (very_broken_program >= 2 ? 2 : 0); break;
920: case 0: break;
921: }
922: } else {
923: switch (i) {
924: case 5: pt -= (very_broken_program >= 3 ? 2 : 0); break;
925: case 4: pt -= (very_broken_program >= 7 ? 2 : 0); break;
926: case 3: pt -= (very_broken_program >= 2 ? 2 : 0); break;
927: case 2: pt -= (very_broken_program >= 6 ? 2 : 0); break;
928: case 1: pt -= (very_broken_program >= 4 ? 2 : 0); break;
929: case 0: break;
930: }
931: }
932: real_ptr = pfield_xlateptr(pt, bytecount);
933: if (real_ptr == NULL)
934: real_ptr = pfield_xlateptr(0, 0);
935: #ifdef SMART_UPDATE
936: if (!line_changed[next_lineno])
937: line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount);
938: else
939: memcpy (dataptr, real_ptr, bytecount);
940: #else
941: real_bplpt[i] = real_ptr;
942: #endif
943: }
944: }
945: }
946:
947: /*
948: * Called from the BPLxMOD routines, after a new value has been written.
949: * This routine decides whether the new value is already relevant for the
950: * current line.
951: */
952: static void decide_modulos (void)
953: {
954: /* All this effort just for the Sanity WOC demo... */
955: decide_line ();
956: if (decided_nr_planes != -1 && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)
957: return;
958: decided_bpl1mod = bpl1mod;
959: decided_bpl2mod = bpl2mod;
960: }
961:
962: /*
1.1.1.3 ! root 963: * Add the modulos to the bitplane pointers if data fetch is already
! 964: * finished for the current line.
! 965: * Call decide_plane() before calling this, so that we won't use the
! 966: * new values of the plane pointers for the current line.
1.1.1.2 root 967: */
968: static void do_modulos (void)
969: {
970: /* decided_nr_planes is != -1 if this line should be drawn by the
1.1.1.3 ! root 971: * display hardware, regardless of whether it fits on the emulated screen.
1.1.1.2 root 972: */
973: if (decided_nr_planes != -1 && plane_decided && !modulos_added
974: && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)
975: {
976: int bytecount = thisline_decision.plflinelen / (decided_hires ? 4 : 8) * 2;
977: int add1 = bytecount + decided_bpl1mod;
978: int add2 = bytecount + decided_bpl2mod;
979:
980: if (!very_broken_program) {
981: switch (decided_nr_planes) {
982: case 8: bplpt[7] += add2;
983: case 7: bplpt[6] += add1;
984: case 6: bplpt[5] += add2;
985: case 5: bplpt[4] += add1;
986: case 4: bplpt[3] += add2;
987: case 3: bplpt[2] += add1;
988: case 2: bplpt[1] += add2;
989: case 1: bplpt[0] += add1;
990: }
1.1.1.3 ! root 991: } else if (decided_hires) { /* @@@ used to be bplhires which is clearly wrong */
1.1.1.2 root 992: switch (decided_nr_planes) {
993: case 8: bplpt[7] += add2;
994: case 7: bplpt[6] += add1;
995: case 6: bplpt[5] += add2;
996: case 5: bplpt[4] += add1;
997: case 4: bplpt[3] += add2 - 2;
998: case 3: bplpt[2] += add1 - (very_broken_program >= 3 ? 2 : 0);
999: case 2: bplpt[1] += add2 - (very_broken_program >= 2 ? 2 : 0);
1000: case 1: bplpt[0] += add1;
1.1.1.3 ! root 1001: }
1.1.1.2 root 1002: } else {
1003: switch (decided_nr_planes) {
1004: case 8: bplpt[7] += add2;
1005: case 7: bplpt[6] += add1;
1006: case 6: bplpt[5] += add2 - (very_broken_program >= 3 ? 2 : 0);
1007: case 5: bplpt[4] += add1 - (very_broken_program >= 7 ? 2 : 0);
1008: case 4: bplpt[3] += add2 - (very_broken_program >= 2 ? 2 : 0);
1009: case 3: bplpt[2] += add1 - (very_broken_program >= 6 ? 2 : 0);
1010: case 2: bplpt[1] += add2 - (very_broken_program >= 4 ? 2 : 0);
1011: case 1: bplpt[0] += add1;
1.1.1.3 ! root 1012: }
1.1.1.2 root 1013: }
1014:
1015: modulos_added = 1;
1016: }
1017: }
1018:
1.1.1.3 ! root 1019: static __inline__ void record_sprite (int spr, int sprxp)
1.1.1.2 root 1020: {
1.1.1.3 ! root 1021: int pos = next_sprite_draw;
! 1022: unsigned int data, datb;
1.1.1.2 root 1023:
1.1.1.3 ! root 1024: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
! 1025: if(pos >= max_sprite_draw) {
! 1026: ++delta_sprite_draw;
1.1.1.2 root 1027: return;
1.1.1.3 ! root 1028: }
! 1029: #endif
! 1030: data = sprdata[spr];
! 1031: datb = sprdatb[spr];
1.1.1.2 root 1032:
1.1.1.3 ! root 1033: /* XXX FIXME, this isn't very clever, but it might do */
! 1034: for (;;) {
! 1035: if (pos == curr_drawinfo[next_lineno].first_sprite_draw)
! 1036: break;
! 1037: if (curr_sprite_positions[pos-1].linepos < sprxp)
! 1038: break;
! 1039: if (curr_sprite_positions[pos-1].linepos == sprxp
! 1040: && curr_sprite_positions[pos-1].num > spr)
! 1041: break;
! 1042: printf("Foo\n");
! 1043: pos--;
! 1044: }
! 1045: if (pos != next_sprite_draw) {
! 1046: int pos2 = next_sprite_draw;
! 1047: while (pos2 != pos) {
! 1048: curr_sprite_positions[pos2] = curr_sprite_positions[pos2-1];
! 1049: pos2--;
! 1050: }
! 1051: }
! 1052: curr_sprite_positions[pos].linepos = sprxp;
! 1053: curr_sprite_positions[pos].num = spr;
! 1054: curr_sprite_positions[pos].ctl = sprctl[spr];
! 1055: curr_sprite_positions[pos].datab = ((sprtaba[data & 0xFF] << 16) | sprtaba[data >> 8]
! 1056: | (sprtabb[datb & 0xFF] << 16) | sprtabb[datb >> 8]);
! 1057: next_sprite_draw++;
! 1058: }
1.1.1.2 root 1059:
1.1.1.3 ! root 1060: static void decide_sprites (void)
! 1061: {
! 1062: int nrs[8], posns[8], count, i;
! 1063: int point = PIXEL_XPOS (current_hpos ());
1.1.1.2 root 1064:
1.1.1.3 ! root 1065: if (framecnt != 0 || current_hpos() < 0x14 || nr_armed == 0 || point == last_sprite_point)
1.1.1.2 root 1066: return;
1067:
1.1.1.3 ! root 1068: decide_diw ();
! 1069: decide_line ();
! 1070:
! 1071: if (thisline_decision.which != 1)
1.1.1.2 root 1072: return;
1073:
1.1.1.3 ! root 1074: count = 0;
! 1075: for (i = 0; i < 8; i++) {
! 1076: int sprxp = sprxpos[i];
! 1077: int j, bestp;
1.1.1.2 root 1078:
1.1.1.3 ! root 1079: if (!sprarmed[i] || sprxp < 0 || sprxp > point || last_sprite_point >= sprxp)
! 1080: continue;
! 1081: if ((thisline_decision.diwfirstword >= 0 && sprxp + sprite_width < thisline_decision.diwfirstword)
! 1082: || (thisline_decision.diwlastword >= 0 && sprxp > thisline_decision.diwlastword))
! 1083: continue;
1.1.1.2 root 1084:
1.1.1.3 ! root 1085: for (bestp = 0; bestp < count; bestp++) {
! 1086: if (posns[bestp] > sprxp)
! 1087: break;
! 1088: if (posns[bestp] == sprxp && nrs[bestp] < i)
! 1089: break;
! 1090: }
! 1091: for (j = count; j > bestp; j--) {
! 1092: posns[j] = posns[j-1];
! 1093: nrs[j] = nrs[j-1];
! 1094: }
! 1095: posns[j] = sprxp;
! 1096: nrs[j] = i;
! 1097: count++;
! 1098: }
! 1099: for (i = 0; i < count; i++)
! 1100: record_sprite(nrs[i], posns[i]);
! 1101: last_sprite_point = point;
1.1.1.2 root 1102: }
1103:
1.1.1.3 ! root 1104: /* End of a horizontal scan line. Finish off all decisions that were not
! 1105: * made yet. */
1.1.1.2 root 1106: static void finish_decisions (void)
1107: {
1108: struct draw_info *dip;
1109: struct draw_info *dip_old;
1110: struct decision *dp;
1111: int changed;
1112:
1113: if (framecnt != 0)
1114: return;
1115:
1116: decide_diw ();
1117: if (thisline_decision.which == 0)
1118: decide_line_1 ();
1.1.1.3 ! root 1119:
! 1120: /* Large DIWSTOP values can cause the stop position never to be
! 1121: * reached, so the state machine always stays in the same state and
! 1122: * there's a more-or-less full-screen DIW. */
! 1123: if (hdiwstate == DIW_waiting_stop) {
! 1124: thisline_decision.diwlastword = max_diwlastword;
! 1125: if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
! 1126: MARK_LINE_CHANGED (next_lineno);
! 1127: }
! 1128:
1.1.1.2 root 1129: if (line_decisions[next_lineno].which != thisline_decision.which)
1130: line_changed[next_lineno] = 1;
1131: decide_plane ();
1132:
1133: dip = curr_drawinfo + next_lineno;
1134: dip_old = prev_drawinfo + next_lineno;
1135: dp = line_decisions + next_lineno;
1136: changed = line_changed[next_lineno];
1137:
1138: if (thisline_decision.which == 1) {
1139: if (diwlastword > max_diwstop)
1140: max_diwstop = diwlastword;
1141: if (diwfirstword < min_diwstart)
1142: min_diwstart = diwfirstword;
1143:
1.1.1.3 ! root 1144: decide_sprites();
! 1145:
1.1.1.2 root 1146: if (thisline_decision.bplcon1 != line_decisions[next_lineno].bplcon1)
1147: changed = 1;
1148: }
1149:
1150: dip->last_color_change = next_color_change;
1151: dip->last_delay_change = next_delay_change;
1152: dip->last_sprite_draw = next_sprite_draw;
1.1.1.3 ! root 1153:
! 1154: if (thisline_decision.ctable == -1) {
! 1155: if (thisline_decision.which == 1)
! 1156: remember_ctable ();
! 1157: else
! 1158: remember_ctable_for_border ();
! 1159: }
1.1.1.2 root 1160: if (thisline_decision.which == -1 && thisline_decision.color0 == 0xFFFFFFFFul)
1161: thisline_decision.color0 = current_colors.color_regs[0];
1162:
1163: dip->nr_color_changes = next_color_change - dip->first_color_change;
1164: dip->nr_sprites = next_sprite_draw - dip->first_sprite_draw;
1165:
1166: if (dip->first_delay_change != dip->last_delay_change)
1167: changed = 1;
1168: if (!changed
1169: && (dip->nr_color_changes != dip_old->nr_color_changes
1.1.1.3 ! root 1170: || (dip->nr_color_changes > 0
! 1171: && memcmp (curr_color_changes + dip->first_color_change,
! 1172: prev_color_changes + dip_old->first_color_change,
! 1173: dip->nr_color_changes * sizeof *curr_color_changes) != 0)))
1.1.1.2 root 1174: changed = 1;
1175: if (!changed && thisline_decision.which == 1
1176: && (dip->nr_sprites != dip_old->nr_sprites
1177: || (dip->nr_sprites > 0
1.1.1.3 ! root 1178: && memcmp (curr_sprite_positions + dip->first_sprite_draw,
! 1179: prev_sprite_positions + dip_old->first_sprite_draw,
! 1180: dip->nr_sprites * sizeof *curr_sprite_positions) != 0)))
1.1.1.2 root 1181: changed = 1;
1182:
1183: if (changed) {
1184: line_changed[next_lineno] = 1;
1185: *dp = thisline_decision;
1186: } else
1187: /* The only one that may differ: */
1188: dp->ctable = thisline_decision.ctable;
1189: }
1190:
1.1.1.3 ! root 1191: /* Set the state of all decisions to "undecided" for a new scanline. */
1.1.1.2 root 1192: static void reset_decisions (void)
1193: {
1194: if (framecnt != 0)
1195: return;
1196: thisline_decision.which = 0;
1197: decided_bpl1mod = bpl1mod;
1198: decided_bpl2mod = bpl2mod;
1199: decided_nr_planes = -1;
1200:
1201: /* decided_hires shouldn't be touched before it's initialized by decide_line(). */
1202: thisline_decision.diwfirstword = -1;
1203: thisline_decision.diwlastword = -2;
1.1.1.3 ! root 1204: if (hdiwstate == DIW_waiting_stop) {
! 1205: thisline_decision.diwfirstword = PIXEL_XPOS (DISPLAY_LEFT_SHIFT/2);
! 1206: if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
! 1207: MARK_LINE_CHANGED (next_lineno);
! 1208: }
1.1.1.2 root 1209: thisline_decision.ctable = -1;
1210: thisline_decision.color0 = 0xFFFFFFFFul;
1211:
1212: line_changed[next_lineno] = 0;
1213: curr_drawinfo[next_lineno].first_color_change = next_color_change;
1214: curr_drawinfo[next_lineno].first_delay_change = next_delay_change;
1215: curr_drawinfo[next_lineno].first_sprite_draw = next_sprite_draw;
1216:
1.1.1.3 ! root 1217: /* memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); */
! 1218: last_sprite_point = 0;
1.1.1.2 root 1219: modulos_added = 0;
1220: plane_decided = 0;
1221: color_decided = 0;
1222: very_broken_program = 0;
1223: }
1224:
1.1.1.3 ! root 1225: /* Initialize the decision array, once before the emulator really starts. */
1.1.1.2 root 1226: static void init_decisions (void)
1227: {
1228: size_t i;
1229: for (i = 0; i < sizeof line_decisions / sizeof *line_decisions; i++) {
1230: line_decisions[i].which = -2;
1.1 root 1231: }
1.1.1.2 root 1232: }
1233:
1.1.1.3 ! root 1234: /* Calculate display window and data fetch values from the corresponding
! 1235: * hardware registers. */
1.1.1.2 root 1236: static void calcdiw (void)
1237: {
1238: diwfirstword = ((diwstrt & 0xFF) - DISPLAY_LEFT_SHIFT - 1) << lores_shift;
1239: diwlastword = ((diwstop & 0xFF) + 0x100 - DISPLAY_LEFT_SHIFT - 1) << lores_shift;
1240:
1241: if (diwlastword > max_diwlastword)
1242: diwlastword = max_diwlastword;
1243: if (diwfirstword < 0)
1244: diwfirstword = 0;
1245: if (diwlastword < 0)
1246: diwlastword = 0;
1.1.1.3 ! root 1247:
1.1.1.2 root 1248: plffirstline = diwstrt >> 8;
1249: plflastline = diwstop >> 8;
1.1 root 1250: #if 0
1251: /* This happens far too often. */
1252: if (plffirstline < minfirstline) {
1253: fprintf(stderr, "Warning: Playfield begins before line %d!\n", minfirstline);
1254: plffirstline = minfirstline;
1255: }
1256: #endif
1257: if ((plflastline & 0x80) == 0) plflastline |= 0x100;
1258: #if 0 /* Turrican does this */
1259: if (plflastline > 313) {
1260: fprintf(stderr, "Warning: Playfield out of range!\n");
1261: plflastline = 313;
1262: }
1263: #endif
1.1.1.2 root 1264: plfstrt = ddfstrt;
1265: plfstop = ddfstop;
1.1 root 1266: if (plfstrt < 0x18) plfstrt = 0x18;
1.1.1.3 ! root 1267: if (plfstop < 0x18) plfstop = 0x18;
1.1 root 1268: if (plfstop > 0xD8) plfstop = 0xD8;
1269: if (plfstrt > plfstop) plfstrt = plfstop;
1270:
1271: /* ! If the masking operation is changed, the pfield_doline code could break
1272: * on some systems (alignment) */
1273: /* This actually seems to be correct now, at least the non-AGA stuff... */
1274: plfstrt &= ~3;
1275: plfstop &= ~3;
1.1.1.2 root 1276: /* @@@ Start looking for AGA bugs here... (or maybe even in the above masking ops) */
1.1 root 1277: if ((fmode & 3) == 0)
1278: plflinelen = (plfstop-plfstrt+15) & ~7;
1279: else if ((fmode & 3) == 3)
1280: plflinelen = (plfstop-plfstrt+63) & ~31;
1281: else
1282: plflinelen = (plfstop-plfstrt+31) & ~15;
1283: }
1284:
1285: /*
1286: * Screen update macros/functions
1287: */
1288:
1.1.1.3 ! root 1289: static unsigned int ham_lastcolor;
! 1290:
! 1291: static void init_ham_decoding(int first)
! 1292: {
! 1293: int pix = dp_for_drawing->diwfirstword;
! 1294: ham_lastcolor = colors_for_drawing.color_regs[0];
! 1295: while (pix < first) {
! 1296: int pv = pixdata.apixels[pix];
! 1297: switch(pv & 0x30) {
! 1298: case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
! 1299: case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
! 1300: case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
! 1301: case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
! 1302: }
! 1303: pix++;
! 1304: }
! 1305: }
! 1306:
! 1307: static void decode_ham6 (int pix, int stoppos)
! 1308: {
! 1309: uae_u32 *buf = ham_linebuf;
1.1 root 1310:
1311: if (!bplham || bplplanecnt != 6)
1312: return;
1.1.1.3 ! root 1313:
1.1.1.2 root 1314: if (stoppos > dp_for_drawing->diwlastword)
1315: stoppos = dp_for_drawing->diwlastword;
1316: if (pix < dp_for_drawing->diwfirstword) {
1.1.1.3 ! root 1317: ham_lastcolor = colors_for_drawing.color_regs[0];
1.1.1.2 root 1318: pix = dp_for_drawing->diwfirstword;
1319: }
1320: #ifdef LORES_HACK
1.1.1.3 ! root 1321: if (currprefs.gfx_lores == 2)
1.1.1.2 root 1322: pix <<= 1, stoppos <<= 1;
1323: #endif
1324: while (pix < stoppos) {
1.1 root 1325: int pv = pixdata.apixels[pix];
1326: switch(pv & 0x30) {
1.1.1.3 ! root 1327: case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
! 1328: case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
! 1329: case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
! 1330: case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
1.1 root 1331: }
1332:
1.1.1.3 ! root 1333: buf[pix++] = ham_lastcolor;
! 1334: }
1.1 root 1335: }
1.1.1.2 root 1336: #if 0
1.1 root 1337: static void decode_ham_aga (int pix, int stoppos)
1338: {
1.1.1.3 ! root 1339: static uae_u32 lastcolor;
! 1340: uae_u32 *buf = ham_linebuf;
1.1 root 1341:
1342: if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8))
1343: return;
1.1.1.3 ! root 1344:
1.1.1.2 root 1345: if (pix <= dp_for_drawing->diwfirstword) {
1346: pix = dp_for_drawing->diwfirstword;
1347: lastcolor = colors_for_drawing.color_regs[0];
1.1 root 1348: }
1349:
1.1.1.2 root 1350: if (dp_for_drawing->bplplanecnt == 6) {
1.1 root 1351: /* HAM 6 */
1.1.1.2 root 1352: while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
1.1 root 1353: int pv = pixdata.apixels[pix];
1354: switch(pv & 0x30) {
1.1.1.2 root 1355: case 0x00: lastcolor = colors_for_drawing.color_regs[pv]; break;
1.1 root 1356: case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break;
1357: case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break;
1358: case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break;
1.1.1.3 ! root 1359: }
1.1 root 1360: buf[pix++] = lastcolor;
1361: }
1.1.1.2 root 1362: } else if (dp_for_drawing->bplplanecnt == 8) {
1.1 root 1363: /* HAM 8 */
1.1.1.2 root 1364: while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
1.1 root 1365: int pv = pixdata.apixels[pix];
1366: switch(pv & 0x3) {
1.1.1.2 root 1367: case 0x0: lastcolor = colors_for_drawing.color_regs[pv >> 2]; break;
1.1 root 1368: case 0x1: lastcolor &= 0xFFFF03; lastcolor |= (pv & 0xFC); break;
1369: case 0x2: lastcolor &= 0x03FFFF; lastcolor |= (pv & 0xFC) << 16; break;
1370: case 0x3: lastcolor &= 0xFF03FF; lastcolor |= (pv & 0xFC) << 8; break;
1371: }
1372: buf[pix++] = lastcolor;
1373: }
1374: }
1375: }
1.1.1.2 root 1376: #endif
1.1 root 1377:
1.1.1.2 root 1378: #if AGA_CHIPSET != 0
1.1 root 1379: /* WARNING: Not too much of this will work correctly yet. */
1380:
1381: static void pfield_linetoscr_aga(int pix, int stoppos)
1382: {
1.1.1.3 ! root 1383: uae_u32 *buf = aga_lbufptr;
1.1 root 1384: int i;
1.1.1.3 ! root 1385: int xor = (uae_u8)(bplcon4 >> 8);
1.1 root 1386: int oldpix = pix; \
1387:
1388: buf -= pix; \
1389:
1390: for (i = 0; i < stoppos; i++)
1391: pixdata.apixels[i] ^= xor;
1.1.1.3 ! root 1392:
1.1 root 1393: while (pix < diwfirstword && pix < stoppos) {
1.1.1.2 root 1394: buf[pix++] = colors_for_drawing.color_regs[0];
1.1 root 1395: }
1396: if (bplham) {
1397: while (pix < diwlastword && pix < stoppos) {
1.1.1.3 ! root 1398: uae_u32 d = ham_linebuf[pix];
1.1 root 1399: buf[pix] = d;
1400: pix++;
1401: }
1402: } else if (bpldualpf) {
1403: /* Dual playfield */
1404: int *lookup = bpldualpfpri ? dblpf_aga2 : dblpf_aga1;
1405: int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1;
1406: while (pix < diwlastword && pix < stoppos) {
1407: int pixcol = pixdata.apixels[pix];
1408: int pfno = lookup_no[pixcol];
1.1.1.3 ! root 1409:
1.1 root 1410: if (spixstate[pix]) {
1.1.1.3 ! root 1411: buf[pix] = colors_for_drawing.color_regs[pixcol];
1.1 root 1412: } else {
1413: int val = lookup[pixdata.apixels[pix]];
1.1.1.3 ! root 1414: if (pfno == 2)
1.1.1.2 root 1415: val += dblpfofs[(bplcon2 >> 10) & 7];
1416: buf[pix] = colors_for_drawing.color_regs[val];
1.1 root 1417: }
1418: pix++;
1419: }
1420: } else if (bplehb) {
1421: while (pix < diwlastword && pix < stoppos) {
1.1.1.3 ! root 1422: int pixcol = pixdata.apixels[pix];
! 1423: uae_u32 d = colors_for_drawing.color_regs[pixcol];
1.1 root 1424: /* What about sprites? */
1425: if (pixcol & 0x20)
1426: d = (d & 0x777777) >> 1;
1427: buf[pix] = d;
1428: pix++;
1429: }
1430: } else {
1431: while (pix < diwlastword && pix < stoppos) {
1432: int pixcol = pixdata.apixels[pix];
1.1.1.2 root 1433: buf[pix] = colors_for_drawing.color_regs[pixcol];
1.1 root 1434: pix++;
1435: }
1436: }
1437: while (pix < stoppos) {
1.1.1.2 root 1438: buf[pix++] = colors_for_drawing.color_regs[0];
1.1 root 1439: }
1440: aga_lbufptr += pix - oldpix;
1441: }
1442:
1443: static void aga_translate32(int start, int stop)
1444: {
1.1.1.3 ! root 1445: memcpy (((uae_u32 *)xlinebuffer) + start, aga_linebuf + start, 4*(stop-start));
1.1 root 1446: }
1447:
1448: static void aga_translate16(int start, int stop)
1449: {
1450: int i;
1451: for (i = start; i < stop; i++) {
1.1.1.3 ! root 1452: uae_u32 d = aga_linebuf[i];
! 1453: uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
! 1454: ((uae_u16 *)xlinebuffer)[i] = xcolors[v];
1.1 root 1455: }
1456: }
1457:
1458: static void aga_translate8(int start, int stop)
1459: {
1460: int i;
1461: for (i = start; i < stop; i++) {
1.1.1.3 ! root 1462: uae_u32 d = aga_linebuf[i];
! 1463: uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
! 1464: ((uae_u8 *)xlinebuffer)[i] = xcolors[v];
1.1 root 1465: }
1466: }
1.1.1.2 root 1467: #endif
1.1 root 1468:
1.1.1.2 root 1469: static int linetoscr_double_offset;
1.1 root 1470:
1.1.1.3 ! root 1471: #define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE, CONVERT) \
1.1.1.2 root 1472: static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \
1473: { \
1474: TYPE *buf = ((TYPE *)xlinebuffer); \
1475: int oldpix = pix; \
1476: /* These are different for register-allocation purposes. */ \
1477: TYPE d1, d2; \
1478: int offset; \
1479: \
1480: if (DO_DOUBLE) offset = linetoscr_double_offset / sizeof(TYPE); \
1481: \
1.1.1.3 ! root 1482: d1 = CONVERT(colors_for_drawing.acolors[0]); \
1.1.1.2 root 1483: while (pix < lframe_end) { \
1484: buf[pix] = d1; if (DO_DOUBLE) buf[pix+offset] = d1; \
1485: pix++; \
1486: } \
1487: if (bplham && bplplanecnt == 6) { \
1488: /* HAM 6 */ \
1489: while (pix < diw_end) { \
1.1.1.3 ! root 1490: TYPE d = CONVERT(xcolors[ham_linebuf[pix]]); \
1.1.1.2 root 1491: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
1492: pix++; \
1493: } \
1494: } else if (bpldualpf) { \
1495: /* Dual playfield */ \
1496: int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; \
1497: while (pix < diw_end) { \
1498: int pixcol = pixdata.apixels[pix]; \
1499: TYPE d; \
1.1.1.3 ! root 1500: d = CONVERT(colors_for_drawing.acolors[lookup[pixcol]]); \
1.1.1.2 root 1501: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
1502: pix++; \
1503: } \
1504: } else if (bplehb) { \
1505: while (pix < diw_end) { \
1506: int p = pixdata.apixels[pix]; \
1.1.1.3 ! root 1507: TYPE d = CONVERT (colors_for_drawing.acolors[p]); \
! 1508: if (p >= 32) d = CONVERT(xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]); \
1.1.1.2 root 1509: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
1510: pix++; \
1511: } \
1512: } else { \
1513: while (pix < diw_end) { \
1.1.1.3 ! root 1514: TYPE d = CONVERT (colors_for_drawing.acolors[pixdata.apixels[pix]]); \
1.1.1.2 root 1515: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
1516: pix++; \
1517: } \
1518: } \
1.1.1.3 ! root 1519: d2 = CONVERT (colors_for_drawing.acolors[0]); \
1.1.1.2 root 1520: while (pix < stoppos) { \
1521: buf[pix] = d2; if (DO_DOUBLE) buf[pix+offset] = d2; \
1522: pix++; \
1523: } \
1524: }
1.1 root 1525:
1.1.1.3 ! root 1526: #define FILL_LINE(NAME, TYPE, CONVERT) \
1.1.1.2 root 1527: static void NAME(char *buf, int start, int stop) \
1.1 root 1528: { \
1529: TYPE *b = (TYPE *)buf; \
1530: int i;\
1.1.1.2 root 1531: xcolnr col = colors_for_drawing.acolors[0]; \
1532: for (i = start; i < stop; i++) \
1.1.1.3 ! root 1533: b[i] = CONVERT (col); \
! 1534: }
! 1535:
! 1536: LINE_TO_SCR(pfield_linetoscr_8, uae_u8, 0,)
! 1537: LINE_TO_SCR(pfield_linetoscr_16, uae_u16, 0,)
! 1538: LINE_TO_SCR(pfield_linetoscr_32, uae_u32, 0,)
! 1539: LINE_TO_SCR(pfield_linetoscr_8_double_slow, uae_u8, 1,)
! 1540: LINE_TO_SCR(pfield_linetoscr_16_double_slow, uae_u16, 1,)
! 1541: LINE_TO_SCR(pfield_linetoscr_32_double_slow, uae_u32, 1,)
! 1542:
! 1543: FILL_LINE(fill_line_8, uae_u8,)
! 1544: FILL_LINE(fill_line_16, uae_u16,)
! 1545: FILL_LINE(fill_line_32, uae_u32,)
! 1546:
! 1547: #ifdef HAVE_UAE_U24
! 1548: LINE_TO_SCR(pfield_linetoscr_24, uae_u24, 0, uae24_convert)
! 1549: LINE_TO_SCR(pfield_linetoscr_24_double_slow, uae_u24, 1, uae24_convert)
! 1550: FILL_LINE(fill_line_24, uae_u24, uae24_convert)
! 1551: #else
! 1552: /* Dummy versions */
! 1553: static void pfield_linetoscr_24 (int pix, int lframe_end, int diw_end, int stoppos)
! 1554: {
! 1555: }
! 1556: static void pfield_linetoscr_24_double_slow (int pix, int lframe_end, int diw_end, int stoppos)
! 1557: {
! 1558: }
! 1559: static void fill_line_24 (char *buf, int start, int stop)
! 1560: {
! 1561: }
! 1562: #endif
! 1563:
! 1564: static __inline__ void fill_line_full (void)
! 1565: {
! 1566: switch (gfxvidinfo.pixbytes) {
! 1567: case 1: fill_line_8(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
! 1568: case 2: fill_line_16(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
! 1569: case 3: fill_line_24(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
! 1570: case 4: fill_line_32(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
! 1571: }
1.1 root 1572: }
1573:
1.1.1.3 ! root 1574: #define fill_line fill_line_full
1.1 root 1575:
1576: #define pfield_linetoscr_full8 pfield_linetoscr_8
1577: #define pfield_linetoscr_full16 pfield_linetoscr_16
1.1.1.3 ! root 1578: #define pfield_linetoscr_full24 pfield_linetoscr_24
1.1 root 1579: #define pfield_linetoscr_full32 pfield_linetoscr_32
1580:
1581: #define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow
1582: #define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow
1.1.1.3 ! root 1583: #define pfield_linetoscr_full24_double pfield_linetoscr_24_double_slow
1.1 root 1584: #define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow
1585:
1586: #if 1 && defined(X86_ASSEMBLY)
1.1.1.3 ! root 1587: /* This version of fill_line is probably a win on all machines, but for
! 1588: * now I'm cautious */
! 1589: #undef fill_line
! 1590: static __inline__ void fill_line (void)
! 1591: {
! 1592: int shift;
! 1593: int nints, nrem;
! 1594: int *start;
! 1595: xcolnr val;
! 1596:
! 1597: #ifdef HAVE_UAE_U24
! 1598: if (gfxvidinfo.pixbytes == 3) {
! 1599: fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width);
! 1600: return;
! 1601: }
! 1602: #endif
! 1603:
! 1604: shift = 0;
! 1605: if (gfxvidinfo.pixbytes == 2)
! 1606: shift = 1;
! 1607: if (gfxvidinfo.pixbytes == 4)
! 1608: shift = 2;
! 1609:
! 1610: nints = gfxvidinfo.width >> (2-shift);
! 1611: nrem = nints & 7;
! 1612: nints &= ~7;
! 1613: start = (int *)(((char *)xlinebuffer) + (linetoscr_x_adjust << shift));
! 1614: val = colors_for_drawing.acolors[0];
! 1615: for (; nints > 0; nints -= 8, start+=8) {
! 1616: *start = val;
! 1617: *(start+1) = val;
! 1618: *(start+2) = val;
! 1619: *(start+3) = val;
! 1620: *(start+4) = val;
! 1621: *(start+5) = val;
! 1622: *(start+6) = val;
! 1623: *(start+7) = val;
! 1624: }
! 1625:
! 1626: switch (nrem) {
! 1627: case 7:
! 1628: *start++ = val;
! 1629: case 6:
! 1630: *start++ = val;
! 1631: case 5:
! 1632: *start++ = val;
! 1633: case 4:
! 1634: *start++ = val;
! 1635: case 3:
! 1636: *start++ = val;
! 1637: case 2:
! 1638: *start++ = val;
! 1639: case 1:
! 1640: *start = val;
! 1641: }
! 1642: }
! 1643:
1.1 root 1644: #undef pfield_linetoscr_full8
1.1.1.2 root 1645: /* The types are lies, of course. */
1646: extern void pfield_linetoscr_normal_asm8(void) __asm__("pfield_linetoscr_normal_asm8");
1647: extern void pfield_linetoscr_ehb_asm8(void) __asm__("pfield_linetoscr_ehb_asm8");
1648: extern void pfield_linetoscr_ham6_asm8(void) __asm__("pfield_linetoscr_ham6_asm8");
1649: extern void pfield_linetoscr_dualpf_asm8(void) __asm__("pfield_linetoscr_dualpf_asm8");
1650: extern void pfield_linetoscr_hdouble_asm8(void) __asm__("pfield_linetoscr_hdouble_asm8");
1.1.1.3 ! root 1651: extern void pfield_linetoscr_hdouble_dpf_asm8(void) __asm__("pfield_linetoscr_hdouble_dpf_asm8");
! 1652: extern void pfield_linetoscr_hdouble_ehb_asm8(void) __asm__("pfield_linetoscr_hdouble_ehb_asm8");
1.1.1.2 root 1653: extern void pfield_linetoscr_asm8(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm8");
1654:
1655: static void pfield_linetoscr_full8(int pix, int lframe_end, int diw_end, int stoppos)
1656: {
1657: int lframe_end_1, diw_end_1;
1658:
1659: lframe_end_1 = pix + ((lframe_end - pix) & ~3);
1660: diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
1661:
1662: if (bplham && bplplanecnt == 6) {
1663: pfield_linetoscr_asm8(pfield_linetoscr_ham6_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1664: } else if (bpldualpf) {
1.1.1.3 ! root 1665: #ifdef LORES_HACK
! 1666: if (currprefs.gfx_lores == 2)
! 1667: pfield_linetoscr_asm8(pfield_linetoscr_hdouble_dpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
! 1668: bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
! 1669: else
! 1670: #endif
! 1671: pfield_linetoscr_asm8(pfield_linetoscr_dualpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
! 1672: bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
1.1.1.2 root 1673: } else if (bplehb) {
1674: #ifdef LORES_HACK
1.1.1.3 ! root 1675: if (currprefs.gfx_lores == 2)
! 1676: pfield_linetoscr_asm8(pfield_linetoscr_hdouble_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
! 1677: else
1.1.1.2 root 1678: #endif
1.1.1.3 ! root 1679: pfield_linetoscr_asm8(pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1.1.2 root 1680: } else {
1.1.1.3 ! root 1681: #ifdef LORES_HACK
! 1682: if (currprefs.gfx_lores == 2)
! 1683: pfield_linetoscr_asm8(pfield_linetoscr_hdouble_asm8, pix, lframe_end_1, diw_end_1, stoppos);
! 1684: else
! 1685: #endif
! 1686: pfield_linetoscr_asm8(pfield_linetoscr_normal_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1.1.2 root 1687: }
1.1.1.3 ! root 1688:
1.1.1.2 root 1689: /* The assembly functions work on aligned data, so we may have to do some
1690: * additional work at the edges. */
1691: if (lframe_end != lframe_end_1) {
1692: int i, c = colors_for_drawing.acolors[0];
1693: for (i = lframe_end_1; i < lframe_end; i++)
1694: xlinebuffer[i] = c;
1695: }
1696: if (diw_end != diw_end_1) {
1697: int i, c = colors_for_drawing.acolors[0];
1698: for (i = diw_end; i < diw_end_1; i++)
1699: xlinebuffer[i] = c;
1700: }
1701: }
1702:
1.1 root 1703: #undef pfield_linetoscr_full16
1.1.1.2 root 1704: extern void pfield_linetoscr_normal_asm16(void) __asm__("pfield_linetoscr_normal_asm16");
1705: extern void pfield_linetoscr_ehb_asm16(void) __asm__("pfield_linetoscr_ehb_asm16");
1706: extern void pfield_linetoscr_ham6_asm16(void) __asm__("pfield_linetoscr_ham6_asm16");
1707: extern void pfield_linetoscr_dualpf_asm16(void) __asm__("pfield_linetoscr_dualpf_asm16");
1708: extern void pfield_linetoscr_hdouble_asm16(void) __asm__("pfield_linetoscr_hdouble_asm16");
1.1.1.3 ! root 1709: extern void pfield_linetoscr_hdouble_dpf_asm16(void) __asm__("pfield_linetoscr_hdouble_dpf_asm16");
! 1710: extern void pfield_linetoscr_hdouble_ehb_asm16(void) __asm__("pfield_linetoscr_hdouble_ehb_asm16");
1.1.1.2 root 1711: extern void pfield_linetoscr_asm16(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm16");
1712:
1713: static void pfield_linetoscr_full16(int pix, int lframe_end, int diw_end, int stoppos)
1714: {
1715: int lframe_end_1, diw_end_1;
1716:
1717: lframe_end_1 = pix + ((lframe_end - pix) & ~3);
1718: diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
1719:
1720: if (bplham && bplplanecnt == 6) {
1721: pfield_linetoscr_asm16(pfield_linetoscr_ham6_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1722: } else if (bpldualpf) {
1.1.1.3 ! root 1723: #ifdef LORES_HACK
! 1724: if (currprefs.gfx_lores == 2)
! 1725: pfield_linetoscr_asm16(pfield_linetoscr_hdouble_dpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
! 1726: bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
! 1727: else
! 1728: #endif
! 1729: pfield_linetoscr_asm16(pfield_linetoscr_dualpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
! 1730: bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
1.1.1.2 root 1731: } else if (bplehb) {
1732: #ifdef LORES_HACK
1.1.1.3 ! root 1733: if (currprefs.gfx_lores == 2)
! 1734: pfield_linetoscr_asm16(pfield_linetoscr_hdouble_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
! 1735: else
1.1.1.2 root 1736: #endif
1.1.1.3 ! root 1737: pfield_linetoscr_asm16(pfield_linetoscr_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1.1.2 root 1738: } else {
1.1.1.3 ! root 1739: #ifdef LORES_HACK
! 1740: if (currprefs.gfx_lores == 2)
! 1741: pfield_linetoscr_asm16(pfield_linetoscr_hdouble_asm16, pix, lframe_end_1, diw_end_1, stoppos);
! 1742: else
! 1743: #endif
! 1744: pfield_linetoscr_asm16(pfield_linetoscr_normal_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1.1.2 root 1745: }
1746:
1747: /* The assembly functions work on aligned data, so we may have to do some
1748: * additional work at the edges. */
1749: if (lframe_end != lframe_end_1) {
1750: int i, c = colors_for_drawing.acolors[0];
1751: for (i = lframe_end_1; i < lframe_end; i++)
1.1.1.3 ! root 1752: ((uae_u16 *)xlinebuffer)[i] = c;
1.1.1.2 root 1753: }
1754: if (diw_end != diw_end_1) {
1755: int i, c = colors_for_drawing.acolors[0];
1756: for (i = diw_end; i < diw_end_1; i++)
1.1.1.3 ! root 1757: ((uae_u16 *)xlinebuffer)[i] = c;
1.1.1.2 root 1758: }
1759: }
1760:
1761: #ifndef NO_DOUBLING_LINETOSCR
1762: #define NO_DOUBLING_LINETOSCR
1763: #endif
1764:
1765: #endif
1766:
1767: #ifdef NO_DOUBLING_LINETOSCR
1.1 root 1768: #undef pfield_linetoscr_full8_double
1769: #undef pfield_linetoscr_full16_double
1.1.1.2 root 1770: static void pfield_linetoscr_full8_double(int start, int lframe_end, int diw_end, int stop)
1.1 root 1771: {
1772: char *oldxlb = (char *)xlinebuffer;
1.1.1.2 root 1773: pfield_linetoscr_full8(start, lframe_end, diw_end, stop);
1774: xlinebuffer = oldxlb + linetoscr_double_offset;
1775: pfield_linetoscr_full8(start, lframe_end, diw_end, stop);
1.1 root 1776: }
1.1.1.2 root 1777: static void pfield_linetoscr_full16_double(int start, int lframe_end, int diw_end, int stop)
1.1 root 1778: {
1779: char *oldxlb = (char *)xlinebuffer;
1.1.1.2 root 1780: pfield_linetoscr_full16(start, lframe_end, diw_end, stop);
1781: xlinebuffer = oldxlb + linetoscr_double_offset;
1782: pfield_linetoscr_full16(start, lframe_end, diw_end, stop);
1.1 root 1783: }
1784: #endif
1785:
1.1.1.2 root 1786: static int linetoscr_diw_end, linetoscr_diw_start;
1787:
1.1.1.3 ! root 1788: /* Initialize the variables necessary for drawing a line.
! 1789: * This involves setting up start/stop positions and display window
! 1790: * borders. Also, since the drawing code may not fully overwrite all
! 1791: * releveant areas in the pixdata.apixels array for speed reasons, parts of
! 1792: * it must possibly be cleared here. */
1.1.1.2 root 1793: static void pfield_init_linetoscr (void)
1794: {
1795: int ddf_left, ddf_right;
1796: int mindelay = bpldelay1, maxdelay = bpldelay2;
1797: if (bpldelay1 > bpldelay2)
1798: maxdelay = bpldelay1, mindelay = bpldelay2;
1799:
1800: linetoscr_diw_start = dp_for_drawing->diwfirstword;
1801: linetoscr_diw_end = dp_for_drawing->diwlastword;
1802:
1803: /* We should really look at DDF also when calculating max_diwstop/min_diwstrt,
1804: * so that centering works better, but I'm afraid that might cost too many
1.1.1.3 ! root 1805: * cycles. Plus it's dangerous, see the code below that handles the case
1.1.1.2 root 1806: * with sprites. */
1807: if (dip_for_drawing->nr_sprites == 0) {
1808: int hiresadjust = bplhires ? 4 : 8;
1809: ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
1810: ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
1.1.1.3 ! root 1811:
1.1.1.2 root 1812: if (linetoscr_diw_start < ddf_left)
1813: linetoscr_diw_start = ddf_left;
1814: if (linetoscr_diw_end > ddf_right)
1815: linetoscr_diw_end = ddf_right;
1816:
1817: if (mindelay != maxdelay) {
1818: /* Raahh...
1819: * We just clear the maximum amount of space that may need to be
1820: * cleared. We could do this exactly, but it would come out slower
1821: * because of the overhead. */
1822: int strt = ddf_left;
1.1.1.3 ! root 1823: if (currprefs.gfx_lores == 2) {
! 1824: fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_left>>1), 15);
! 1825: fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_right>>1) - 15, 15);
! 1826: } else if (currprefs.gfx_lores) {
1.1.1.2 root 1827: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 15);
1828: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 15, 15);
1829: } else {
1830: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 30);
1831: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 30, 30);
1832: }
1833: }
1834: } else {
1835: int hiresadjust = bplhires ? 4 : 8;
1836: /* We swap mindelay and maxdelay here to get rid of the mindelay != maxdelay check.
1837: * Since we have to do a memset anyway (because there may be sprites),
1838: * we might as well clear all at once. */
1839: ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
1840: ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
1841: if (linetoscr_diw_start < ddf_left) {
1842: int strt = linetoscr_diw_start;
1843: int stop = ddf_left;
1844: #ifdef LORES_HACK
1.1.1.3 ! root 1845: if (currprefs.gfx_lores == 2)
1.1.1.2 root 1846: strt >>= 1, stop >>= 1;
1847: #endif
1848: if (strt < stop)
1849: fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
1850: }
1851:
1852: if (linetoscr_diw_end > ddf_right) {
1853: int strt = ddf_right;
1854: int stop = linetoscr_diw_end;
1855: #ifdef LORES_HACK
1.1.1.3 ! root 1856: if (currprefs.gfx_lores == 2)
1.1.1.2 root 1857: strt >>= 1, stop >>= 1;
1858: #endif
1859: if (strt < stop)
1860: fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
1861: }
1862: }
1863: /* Perverse cases happen. */
1864: if (linetoscr_diw_end < linetoscr_diw_start)
1865: linetoscr_diw_end = linetoscr_diw_start;
1866: }
1867:
1.1 root 1868: static void pfield_do_linetoscr(int start, int stop)
1869: {
1.1.1.2 root 1870: int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
1871:
1872: if (stop > linetoscr_right_x)
1873: stop = linetoscr_right_x;
1874: if (start < linetoscr_x_adjust)
1875: start = linetoscr_x_adjust;
1.1.1.3 ! root 1876:
1.1.1.2 root 1877: if (lframe_end < start)
1878: lframe_end = start;
1879: if (diw_end > stop)
1880: diw_end = stop;
1881:
1.1 root 1882: if (start >= stop)
1883: return;
1884:
1885: #if AGA_CHIPSET == 0
1.1.1.2 root 1886: if (start == linetoscr_x_adjust && stop == linetoscr_right_x) {
1.1 root 1887: switch (gfxvidinfo.pixbytes) {
1.1.1.2 root 1888: case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
1889: case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
1.1.1.3 ! root 1890: case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
1.1.1.2 root 1891: case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
1.1 root 1892: }
1893: } else {
1894: switch (gfxvidinfo.pixbytes) {
1.1.1.2 root 1895: case 1: pfield_linetoscr_8 (start, lframe_end, diw_end, stop); break;
1896: case 2: pfield_linetoscr_16 (start, lframe_end, diw_end, stop); break;
1.1.1.3 ! root 1897: case 3: pfield_linetoscr_24 (start, lframe_end, diw_end, stop); break;
1.1.1.2 root 1898: case 4: pfield_linetoscr_32 (start, lframe_end, diw_end, stop); break;
1.1 root 1899: }
1900: }
1901: #else
1.1.1.2 root 1902: pfield_linetoscr_aga(start, lframe_end, diw_end, stop);
1.1 root 1903: #endif
1904: }
1905:
1.1.1.2 root 1906: static void pfield_do_fill_line(int start, int stop)
1.1 root 1907: {
1.1.1.2 root 1908: if (stop > linetoscr_right_x)
1909: stop = linetoscr_right_x;
1910: if (start < linetoscr_x_adjust)
1911: start = linetoscr_x_adjust;
1912:
1913: if (start >= stop)
1914: return;
1915:
1916: switch (gfxvidinfo.pixbytes) {
1917: case 1: fill_line_8 (xlinebuffer, start, stop); break;
1918: case 2: fill_line_16 (xlinebuffer, start, stop); break;
1.1.1.3 ! root 1919: case 3: fill_line_24 (xlinebuffer, start, stop); break;
1.1.1.2 root 1920: case 4: fill_line_32 (xlinebuffer, start, stop); break;
1.1 root 1921: }
1.1.1.2 root 1922: }
1923:
1924: static void pfield_do_linetoscr_full(int double_line)
1925: {
1.1.1.3 ! root 1926: int start = linetoscr_x_adjust, stop = start + gfxvidinfo.width;
1.1.1.2 root 1927: int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
1928: if (lframe_end < start)
1929: lframe_end = start;
1930: if (diw_end > stop)
1931: diw_end = stop;
1.1 root 1932:
1933: #if AGA_CHIPSET == 0
1934: if (double_line) {
1935: switch (gfxvidinfo.pixbytes) {
1.1.1.2 root 1936: case 1: pfield_linetoscr_full8_double (start, lframe_end, diw_end, stop); break;
1937: case 2: pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); break;
1.1.1.3 ! root 1938: case 3: pfield_linetoscr_full24_double (start, lframe_end, diw_end, stop); break;
1.1.1.2 root 1939: case 4: pfield_linetoscr_full32_double (start, lframe_end, diw_end, stop); break;
1.1 root 1940: }
1.1.1.3 ! root 1941: } else
1.1 root 1942: switch (gfxvidinfo.pixbytes) {
1.1.1.2 root 1943: case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
1944: case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
1.1.1.3 ! root 1945: case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
1.1.1.2 root 1946: case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
1.1 root 1947: }
1948: #else
1.1.1.2 root 1949: pfield_linetoscr_aga(start, lframe_end, diw_end, stop);
1.1 root 1950: #endif
1951: }
1952:
1.1.1.3 ! root 1953: /* Mouse stuff */
! 1954: static void setdontcare(void)
! 1955: {
! 1956: write_log ("Don't care mouse mode set\n");
! 1957: mousestate = dont_care_mouse;
! 1958: lastspr0x = lastmx; lastspr0y = lastmy;
! 1959: mstepx = defstepx; mstepy = defstepy;
! 1960: }
! 1961:
! 1962: static void setfollow(void)
! 1963: {
! 1964: write_log ("Follow sprite mode set\n");
! 1965: mousestate = follow_mouse;
! 1966: lastdiffx = lastdiffy = 0;
! 1967: sprvbfl = 0;
! 1968: spr0ctl=spr0pos = 0;
! 1969: mstepx = defstepx; mstepy = defstepy;
! 1970: }
! 1971:
! 1972: uae_u32 mousehack_helper (void)
! 1973: {
! 1974: int mousexpos, mouseypos;
! 1975:
! 1976: #ifdef PICASSO96
! 1977: if (picasso_on) {
! 1978: mousexpos = lastmx + picasso96_state.XOffset;
! 1979: mouseypos = lastmy + picasso96_state.YOffset;
! 1980: } else
! 1981: #endif
! 1982: {
! 1983: mousexpos = lastmx + linetoscr_x_adjust;
! 1984: if (lastmy >= gfxvidinfo.height)
! 1985: lastmy = gfxvidinfo.height-1;
! 1986: mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline;
! 1987: mouseypos <<= 1;
! 1988: mousexpos <<= (1-lores_shift);
! 1989: mousexpos += 2*DISPLAY_LEFT_SHIFT;
! 1990: }
! 1991:
! 1992: switch (m68k_dreg (regs, 0)) {
! 1993: case 0:
! 1994: return ievent_alive ? -1 : needmousehack ();
! 1995: case 1:
! 1996: ievent_alive = 10;
! 1997: return mousexpos;
! 1998: case 2:
! 1999: return mouseypos;
! 2000: }
! 2001: return 0;
! 2002: }
! 2003:
! 2004: void togglemouse(void)
! 2005: {
! 2006: switch(mousestate) {
! 2007: case dont_care_mouse: setfollow(); break;
! 2008: case follow_mouse: setdontcare(); break;
! 2009: default: break; /* Nnnnnghh! */
! 2010: }
! 2011: }
! 2012:
! 2013: static __inline__ int adjust(int val)
! 2014: {
! 2015: if (val>127)
! 2016: return 127;
! 2017: else if (val<-127)
! 2018: return -127;
! 2019: return val;
! 2020: }
! 2021:
! 2022: static void do_mouse_hack(void)
! 2023: {
! 2024: int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
! 2025: int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
! 2026: int diffx, diffy;
! 2027:
! 2028: if (ievent_alive > 0) {
! 2029: mouse_x = mouse_y = 0;
! 2030: return;
! 2031: }
! 2032: switch (mousestate) {
! 2033: case normal_mouse:
! 2034: diffx = lastmx - lastsampledmx;
! 2035: diffy = lastmy - lastsampledmy;
! 2036: if (!newmousecounters) {
! 2037: if (diffx > 127) diffx = 127;
! 2038: if (diffx < -127) diffx = -127;
! 2039: mouse_x += diffx;
! 2040: if (diffy > 127) diffy = 127;
! 2041: if (diffy < -127) diffy = -127;
! 2042: mouse_y += diffy;
! 2043: }
! 2044: lastsampledmx += diffx; lastsampledmy += diffy;
! 2045: break;
! 2046:
! 2047: case dont_care_mouse:
! 2048: diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16);
! 2049: diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16);
! 2050: lastspr0x=lastmx; lastspr0y=lastmy;
! 2051: mouse_x+=diffx; mouse_y+=diffy;
! 2052: break;
! 2053:
! 2054: case follow_mouse:
! 2055: if (sprvbfl && sprvbfl-- >1) {
! 2056: int mousexpos, mouseypos;
! 2057:
! 2058: if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x
! 2059: && spr0x > plfstrt*4 + 34 + xcaloff && spr0x < plfstop*4 - xcaloff)
! 2060: {
! 2061: int val = (lastdiffx << 16) / (spr0x - lastspr0x);
! 2062: if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight;
! 2063: }
! 2064: if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y
! 2065: && spr0y>plffirstline+ycaloff && spr0y<plflastline-ycaloff)
! 2066: {
! 2067: int val = (lastdiffy<<16) / (spr0y-lastspr0y);
! 2068: if (val>=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight;
! 2069: }
! 2070: mousexpos = lastmx + linetoscr_x_adjust;
! 2071: if (lastmy >= gfxvidinfo.height)
! 2072: lastmy = gfxvidinfo.height-1;
! 2073: mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline;
! 2074: mouseypos <<= 1;
! 2075: mousexpos <<= (1-lores_shift);
! 2076: mousexpos += 2*DISPLAY_LEFT_SHIFT;
! 2077: diffx = adjust ((((mousexpos + xoffs - spr0x) & ~1) * mstepx) >> 16);
! 2078: diffy = adjust ((((mouseypos + yoffs - spr0y) & ~1) * mstepy) >> 16);
! 2079: lastspr0x=spr0x; lastspr0y=spr0y;
! 2080: lastdiffx=diffx; lastdiffy=diffy;
! 2081: mouse_x+=diffx; mouse_y+=diffy;
! 2082: }
! 2083: break;
! 2084: }
! 2085: }
! 2086:
! 2087: /*
1.1 root 2088: * register functions
2089: */
2090:
1.1.1.3 ! root 2091: __inline__ uae_u16 DMACONR(void)
1.1 root 2092: {
2093: return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
2094: | (blt_info.blitzero ? 0x2000 : 0));
2095: }
1.1.1.3 ! root 2096: static __inline__ uae_u16 INTENAR(void) { return intena; }
! 2097: uae_u16 INTREQR(void)
1.1 root 2098: {
1.1.1.3 ! root 2099: return intreq | (currprefs.use_serial ? 0x0001 : 0);
1.1 root 2100: }
1.1.1.3 ! root 2101: static __inline__ uae_u16 ADKCONR(void) { return adkcon; }
! 2102: static __inline__ uae_u16 VPOSR(void)
1.1 root 2103: {
2104: #if AGA_CHIPSET == 1
2105: return (vpos >> 8) | lof | 0x2300;
2106: #elif defined (ECS_AGNUS)
2107: return (vpos >> 8) | lof | 0x2000;
2108: #else
2109: return (vpos >> 8) | lof;
2110: #endif
2111: }
1.1.1.3 ! root 2112: static void VPOSW(uae_u16 v)
1.1.1.2 root 2113: {
2114: if (lof != (v & 0x8000))
2115: lof_changed = 1;
2116: lof = v & 0x8000;
1.1.1.3 ! root 2117: /*
! 2118: * This register is much more fun on a real Amiga. You can program
! 2119: * refresh rates with it ;) But I won't emulate this...
! 2120: */
1.1.1.2 root 2121: }
1.1.1.3 ! root 2122: static __inline__ uae_u16 VHPOSR(void) { return (vpos << 8) | current_hpos(); }
1.1 root 2123:
1.1.1.3 ! root 2124: static __inline__ void COP1LCH(uae_u16 v) { cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16); }
! 2125: static __inline__ void COP1LCL(uae_u16 v) { cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe); }
! 2126: static __inline__ void COP2LCH(uae_u16 v) { cop2lc = (cop2lc & 0xffff) | ((uae_u32)v << 16); }
! 2127: static __inline__ void COP2LCL(uae_u16 v) { cop2lc = (cop2lc & ~0xffff) | (v & 0xfffe); }
1.1 root 2128:
1.1.1.3 ! root 2129: static void COPJMP1(uae_u16 a)
1.1 root 2130: {
1.1.1.3 ! root 2131: coplc = cop1lc; copstate = COP_read;
1.1 root 2132: eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
2133: eventtab[ev_copper].evtime = 4 + cycles; events_schedule();
2134: copper_active = 1;
1.1.1.2 root 2135: copper_waiting_for_blitter = 0;
1.1 root 2136: }
1.1.1.3 ! root 2137: static void COPJMP2(uae_u16 a)
1.1 root 2138: {
1.1.1.3 ! root 2139: coplc = cop2lc; copstate = COP_read;
1.1 root 2140: eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
2141: eventtab[ev_copper].evtime = 4 + cycles; events_schedule();
2142: copper_active = 1;
1.1.1.2 root 2143: copper_waiting_for_blitter = 0;
1.1 root 2144: }
1.1.1.3 ! root 2145: static __inline__ void COPCON(uae_u16 a) { copcon = a; }
! 2146: static void DMACON(uae_u16 v)
1.1 root 2147: {
2148: int i, need_resched = 0;
2149:
1.1.1.3 ! root 2150: uae_u16 oldcon = dmacon;
! 2151:
1.1.1.2 root 2152: decide_line();
1.1 root 2153: setclr(&dmacon,v); dmacon &= 0x1FFF;
1.1.1.3 ! root 2154: /* ??? post_decide_line (); */
! 2155:
! 2156: /* FIXME? Maybe we need to think a bit more about the master DMA enable
1.1 root 2157: * bit in these cases. */
1.1.1.3 ! root 2158: if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) {
1.1 root 2159: COPJMP1(0);
2160: }
2161: if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) {
2162: static int count = 0;
2163: if (!count) {
2164: count = 1;
1.1.1.3 ! root 2165: write_log ("warning: program is doing blitpri hacks.\n");
1.1 root 2166: }
2167: regs.spcflags |= SPCFLAG_BLTNASTY;
2168: }
2169: #ifndef DONT_WANT_SOUND
2170: for (i = 0; i < 4; i++) {
2171: struct audio_channel_data *cdp = audio_channel + i;
1.1.1.3 ! root 2172:
1.1 root 2173: cdp->dmaen = (dmacon & 0x200) && (dmacon & (1<<i));
2174: if (cdp->dmaen) {
2175: if (cdp->state == 0) {
2176: cdp->state = 1;
2177: cdp->pt = cdp->lc;
2178: cdp->wper = cdp->per;
2179: cdp->wlen = cdp->len;
2180: cdp->data_written = 2;
2181: eventtab[ev_aud0 + i].oldcycles = eventtab[ev_hsync].oldcycles;
2182: eventtab[ev_aud0 + i].evtime = eventtab[ev_hsync].evtime;
2183: eventtab[ev_aud0 + i].active = 1;
2184: need_resched = 1; /* not _really_ necessary here, but... */
2185: }
2186: } else {
2187: if (cdp->state == 1 || cdp->state == 5) {
2188: cdp->state = 0;
2189: cdp->current_sample = 0;
2190: eventtab[ev_aud0 + i].active = 0;
2191: need_resched = 1;
2192: }
2193: }
2194: }
2195: #endif
1.1.1.2 root 2196: calculate_copper_cycle_time ();
1.1 root 2197: if (copper_active && !eventtab[ev_copper].active) {
2198: eventtab[ev_copper].active = 1;
2199: eventtab[ev_copper].oldcycles = cycles;
2200: eventtab[ev_copper].evtime = 1 + cycles;
2201: need_resched = 1;
2202: }
2203: if (need_resched)
2204: events_schedule();
2205: }
1.1.1.2 root 2206:
1.1.1.3 ! root 2207: /*static int trace_intena = 0;*/
1.1.1.2 root 2208:
1.1.1.3 ! root 2209: static __inline__ void INTENA (uae_u16 v)
1.1.1.2 root 2210: {
1.1.1.3 ! root 2211: /* if (trace_intena)
! 2212: fprintf(stderr, "INTENA: %04x\n", v);*/
! 2213: setclr(&intena,v); regs.spcflags |= SPCFLAG_INT;
1.1.1.2 root 2214: }
1.1.1.3 ! root 2215: void INTREQ (uae_u16 v)
1.1 root 2216: {
1.1.1.3 ! root 2217: setclr(&intreq,v);
! 2218: regs.spcflags |= SPCFLAG_INT;
! 2219: if ((v&0x8800)==0x0800) serdat&=0xbfff;
! 2220: }
1.1 root 2221:
1.1.1.3 ! root 2222: static void ADKCON (uae_u16 v)
! 2223: {
! 2224: unsigned long t;
! 2225: setclr (&adkcon,v);
! 2226: t = adkcon | (adkcon >> 4);
! 2227: audio_channel[0].adk_mask = (((t >> 0) & 1) - 1);
! 2228: audio_channel[1].adk_mask = (((t >> 1) & 1) - 1);
! 2229: audio_channel[2].adk_mask = (((t >> 2) & 1) - 1);
! 2230: audio_channel[3].adk_mask = (((t >> 3) & 1) - 1);
! 2231: }
1.1 root 2232:
1.1.1.3 ! root 2233: static void BPLPTH (uae_u16 v, int num)
! 2234: {
! 2235: decide_line ();
! 2236: decide_plane();
! 2237: do_modulos();
! 2238: bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16);
! 2239: }
! 2240: static void BPLPTL (uae_u16 v, int num)
! 2241: {
! 2242: decide_line ();
! 2243: decide_plane();
! 2244: do_modulos();
! 2245: bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xfffe);
! 2246: }
1.1 root 2247:
1.1.1.3 ! root 2248: static void BPLCON0 (uae_u16 v)
1.1 root 2249: {
1.1.1.2 root 2250: #if AGA_CHIPSET == 0
2251: v &= 0xFF0E;
2252: /* The Sanity WOC demo needs this at one place (at the end of the "Party Effect")
2253: * Disable bitplane DMA if someone tries to do more than 4 Hires bitplanes. */
2254: if ((v & 0xF000) > 0xC000)
2255: v &= 0xFFF;
2256: /* Don't want 7 lores planes either. */
2257: if ((v & 0x8000) == 0 && (v & 0x7000) == 0x7000)
2258: v &= 0xEFFF;
2259: #endif
2260: if (bplcon0 == v)
1.1 root 2261: return;
1.1.1.2 root 2262: decide_line ();
2263: bplcon0 = v;
1.1.1.3 ! root 2264: nr_planes_from_bplcon0 = (bplcon0 >> 12) & 7;
! 2265: corrected_nr_planes_from_bplcon0 = ((bplcon0 >> 12) & 7) << (bplcon0 & 0x8000 ? 1 : 0);
1.1.1.2 root 2266: post_decide_line ();
2267: calculate_copper_cycle_time ();
2268: #if 0
1.1 root 2269: calcdiw(); /* This should go away. */
1.1.1.2 root 2270: #endif
1.1 root 2271: }
1.1.1.3 ! root 2272: static __inline__ void BPLCON1 (uae_u16 v)
1.1 root 2273: {
1.1.1.2 root 2274: if (bplcon1 == v)
1.1 root 2275: return;
1.1.1.2 root 2276: decide_diw ();
2277: bplcon1 = v;
2278: decide_delay ();
1.1 root 2279: }
1.1.1.3 ! root 2280: static __inline__ void BPLCON2 (uae_u16 v)
1.1 root 2281: {
1.1.1.2 root 2282: if (bplcon2 != v)
2283: decide_line ();
2284: bplcon2 = v;
1.1 root 2285: }
1.1.1.3 ! root 2286: static __inline__ void BPLCON3 (uae_u16 v)
1.1 root 2287: {
1.1.1.2 root 2288: if (bplcon3 != v)
2289: decide_line ();
1.1.1.3 ! root 2290: bplcon3 = v;
1.1 root 2291: }
1.1.1.3 ! root 2292: static __inline__ void BPLCON4 (uae_u16 v)
1.1 root 2293: {
1.1.1.2 root 2294: if (bplcon4 != v)
2295: decide_line ();
1.1.1.3 ! root 2296: bplcon4 = v;
1.1 root 2297: }
2298:
1.1.1.3 ! root 2299: static void BPL1MOD (uae_u16 v)
1.1 root 2300: {
2301: v &= ~1;
1.1.1.3 ! root 2302: if ((uae_s16)bpl1mod == (uae_s16)v)
1.1 root 2303: return;
2304: bpl1mod = v;
1.1.1.2 root 2305: decide_modulos ();
1.1 root 2306: }
1.1.1.2 root 2307:
1.1.1.3 ! root 2308: static void BPL2MOD (uae_u16 v)
! 2309: {
1.1 root 2310: v &= ~1;
1.1.1.3 ! root 2311: if ((uae_s16)bpl2mod == (uae_s16)v)
1.1 root 2312: return;
2313: bpl2mod = v;
1.1.1.2 root 2314: decide_modulos();
1.1 root 2315: }
2316:
1.1.1.2 root 2317: /* We could do as well without those... */
1.1.1.3 ! root 2318: static __inline__ void BPL1DAT (uae_u16 v) { bpl1dat = v; }
! 2319: static __inline__ void BPL2DAT (uae_u16 v) { bpl2dat = v; }
! 2320: static __inline__ void BPL3DAT (uae_u16 v) { bpl3dat = v; }
! 2321: static __inline__ void BPL4DAT (uae_u16 v) { bpl4dat = v; }
! 2322: static __inline__ void BPL5DAT (uae_u16 v) { bpl5dat = v; }
! 2323: static __inline__ void BPL6DAT (uae_u16 v) { bpl6dat = v; }
1.1 root 2324:
1.1.1.3 ! root 2325: static void DIWSTRT (uae_u16 v)
1.1 root 2326: {
1.1.1.2 root 2327: if (diwstrt == v)
1.1 root 2328: return;
1.1.1.2 root 2329: decide_line ();
1.1.1.3 ! root 2330: diwstrt = v;
1.1 root 2331: calcdiw();
2332: }
1.1.1.3 ! root 2333: static void DIWSTOP (uae_u16 v)
1.1 root 2334: {
1.1.1.2 root 2335: if (diwstop == v)
1.1 root 2336: return;
1.1.1.3 ! root 2337: diwstop = v;
1.1 root 2338: calcdiw();
2339: }
1.1.1.3 ! root 2340: static void DDFSTRT (uae_u16 v)
! 2341: {
1.1.1.2 root 2342: v &= 0xFF;
2343: if (ddfstrt == v)
1.1 root 2344: return;
1.1.1.2 root 2345: decide_line ();
1.1.1.3 ! root 2346: ddfstrt = v;
1.1 root 2347: calcdiw();
2348: }
1.1.1.3 ! root 2349: static void DDFSTOP (uae_u16 v)
! 2350: {
1.1.1.2 root 2351: v &= 0xFF;
2352: if (ddfstop == v)
1.1 root 2353: return;
1.1.1.2 root 2354: decide_line ();
2355: ddfstop = v;
1.1 root 2356: calcdiw();
2357: }
2358:
1.1.1.3 ! root 2359: static void BLTADAT(uae_u16 v)
1.1 root 2360: {
1.1.1.2 root 2361: maybe_blit();
2362:
2363: blt_info.bltadat = v;
1.1 root 2364: }
1.1.1.2 root 2365: /*
2366: * "Loading data shifts it immediately" says the HRM. Well, that may
2367: * be true for BLTBDAT, but not for BLTADAT - it appears the A data must be
2368: * loaded for every word so that AFWM and ALWM can be applied.
2369: */
1.1.1.3 ! root 2370: static void BLTBDAT(uae_u16 v)
1.1 root 2371: {
1.1.1.3 ! root 2372: maybe_blit();
1.1.1.2 root 2373:
2374: if (bltcon1 & 2)
2375: blt_info.bltbhold = v << (bltcon1 >> 12);
2376: else
2377: blt_info.bltbhold = v >> (bltcon1 >> 12);
2378: blt_info.bltbdat = v;
1.1 root 2379: }
1.1.1.3 ! root 2380: static void BLTCDAT(uae_u16 v) { maybe_blit(); blt_info.bltcdat = v; }
1.1 root 2381:
1.1.1.3 ! root 2382: static void BLTAMOD(uae_u16 v) { maybe_blit(); blt_info.bltamod = (uae_s16)(v & 0xFFFE); }
! 2383: static void BLTBMOD(uae_u16 v) { maybe_blit(); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); }
! 2384: static void BLTCMOD(uae_u16 v) { maybe_blit(); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); }
! 2385: static void BLTDMOD(uae_u16 v) { maybe_blit(); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); }
1.1 root 2386:
1.1.1.3 ! root 2387: static void BLTCON0(uae_u16 v) { maybe_blit(); bltcon0 = v; blinea_shift = v >> 12; }
! 2388: /* The next category is "Most useless hardware register".
1.1 root 2389: * And the winner is... */
1.1.1.3 ! root 2390: static void BLTCON0L(uae_u16 v) { maybe_blit(); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); }
! 2391: static void BLTCON1(uae_u16 v) { maybe_blit(); bltcon1 = v; }
1.1 root 2392:
1.1.1.3 ! root 2393: static void BLTAFWM(uae_u16 v) { maybe_blit(); blt_info.bltafwm = v; }
! 2394: static void BLTALWM(uae_u16 v) { maybe_blit(); blt_info.bltalwm = v; }
1.1 root 2395:
1.1.1.3 ! root 2396: static void BLTAPTH(uae_u16 v) { maybe_blit(); bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); }
! 2397: static void BLTAPTL(uae_u16 v) { maybe_blit(); bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); }
! 2398: static void BLTBPTH(uae_u16 v) { maybe_blit(); bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); }
! 2399: static void BLTBPTL(uae_u16 v) { maybe_blit(); bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); }
! 2400: static void BLTCPTH(uae_u16 v) { maybe_blit(); bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); }
! 2401: static void BLTCPTL(uae_u16 v) { maybe_blit(); bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); }
! 2402: static void BLTDPTH(uae_u16 v) { maybe_blit(); bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); }
! 2403: static void BLTDPTL(uae_u16 v) { maybe_blit(); bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); }
! 2404: static void BLTSIZE(uae_u16 v)
1.1 root 2405: {
2406: bltsize = v;
1.1.1.3 ! root 2407:
! 2408: maybe_blit();
1.1 root 2409:
2410: blt_info.vblitsize = bltsize >> 6;
2411: blt_info.hblitsize = bltsize & 0x3F;
2412: if (!blt_info.vblitsize) blt_info.vblitsize = 1024;
2413: if (!blt_info.hblitsize) blt_info.hblitsize = 64;
1.1.1.3 ! root 2414:
! 2415: bltstate = BLT_init;
1.1.1.2 root 2416: do_blitter();
1.1 root 2417: }
1.1.1.3 ! root 2418: static void BLTSIZV(uae_u16 v)
1.1 root 2419: {
1.1.1.3 ! root 2420: maybe_blit();
1.1 root 2421: oldvblts = v & 0x7FFF;
2422: }
1.1.1.3 ! root 2423: static void BLTSIZH(uae_u16 v)
1.1 root 2424: {
1.1.1.2 root 2425: maybe_blit();
1.1 root 2426: blt_info.hblitsize = v & 0x7FF;
2427: blt_info.vblitsize = oldvblts;
2428: if (!blt_info.vblitsize) blt_info.vblitsize = 32768;
2429: if (!blt_info.hblitsize) blt_info.hblitsize = 0x800;
1.1.1.2 root 2430: bltstate = BLT_init;
2431: do_blitter();
1.1 root 2432: }
1.1.1.3 ! root 2433: static __inline__ void SPRxCTL_1(uae_u16 v, int num)
1.1 root 2434: {
1.1.1.2 root 2435: int sprxp;
2436: sprctl[num] = v;
1.1.1.3 ! root 2437: nr_armed -= sprarmed[num];
1.1.1.2 root 2438: sprarmed[num] = 0;
1.1.1.3 ! root 2439: if (sprpos[num] == 0 && v == 0) {
! 2440: sprst[num] = SPR_stop;
! 2441: spron[num] = 0;
! 2442: } else
! 2443: sprst[num] = SPR_waiting_start;
1.1.1.2 root 2444:
2445: sprxp = ((sprpos[num] & 0xFF) * 2) + (v & 1) - DISPLAY_LEFT_SHIFT;
1.1.1.3 ! root 2446: if (!currprefs.gfx_lores)
1.1.1.2 root 2447: sprxp *= 2;
2448: sprxpos[num] = sprxp;
2449: sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
2450: sprvstop[num] = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100);
2451: }
1.1.1.3 ! root 2452: static __inline__ void SPRxPOS_1(uae_u16 v, int num)
1.1.1.2 root 2453: {
2454: int sprxp;
2455: sprpos[num] = v;
2456: sprxp = ((v & 0xFF) * 2) + (sprctl[num] & 1) - DISPLAY_LEFT_SHIFT;
1.1.1.3 ! root 2457: if (!currprefs.gfx_lores)
1.1.1.2 root 2458: sprxp *= 2;
2459: sprxpos[num] = sprxp;
2460: sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
2461: }
1.1.1.3 ! root 2462: static __inline__ void SPRxDATA_1(uae_u16 v, int num)
1.1.1.2 root 2463: {
2464: sprdata[num] = v;
1.1.1.3 ! root 2465: nr_armed += 1 - sprarmed[num];
1.1.1.2 root 2466: sprarmed[num] = 1;
2467: }
1.1.1.3 ! root 2468: static __inline__ void SPRxDATB_1(uae_u16 v, int num)
1.1.1.2 root 2469: {
2470: sprdatb[num] = v;
2471: }
1.1.1.3 ! root 2472: static void SPRxDATA(uae_u16 v, int num) { decide_sprites (); SPRxDATA_1 (v, num); }
! 2473: static void SPRxDATB(uae_u16 v, int num) { decide_sprites (); SPRxDATB_1 (v, num); }
! 2474: static void SPRxCTL(uae_u16 v, int num) { decide_sprites (); SPRxCTL_1 (v, num); }
! 2475: static void SPRxPOS(uae_u16 v, int num) { decide_sprites (); SPRxPOS_1 (v, num); }
! 2476: static void SPRxPTH(uae_u16 v, int num)
1.1 root 2477: {
1.1.1.3 ! root 2478: decide_line ();
! 2479: sprpt[num] &= 0xffff;
! 2480: sprpt[num] |= (uae_u32)v << 16;
! 2481:
! 2482: if (sprst[num] == SPR_stop || vpos < vblank_endline)
! 2483: sprst[num] = SPR_restart;
! 2484: spron[num] = 1;
1.1 root 2485: }
1.1.1.3 ! root 2486: static void SPRxPTL(uae_u16 v, int num)
1.1 root 2487: {
1.1.1.3 ! root 2488: decide_line ();
! 2489: sprpt[num] &= ~0xffff;
1.1.1.2 root 2490: sprpt[num] |= v;
1.1 root 2491:
1.1.1.3 ! root 2492: if (sprst[num] == SPR_stop || vpos < vblank_endline)
! 2493: sprst[num] = SPR_restart;
! 2494: spron[num] = 1;
! 2495: }
! 2496: static void CLXCON(uae_u16 v)
! 2497: {
! 2498: clxcon = v;
! 2499: clx_sprmask = (((v >> 15) << 7) | ((v >> 14) << 5) | ((v >> 13) << 3) | ((v >> 12) << 1) | 0x55);
! 2500: }
! 2501: static uae_u16 CLXDAT(void)
! 2502: {
! 2503: uae_u16 v = clxdat;
! 2504: clxdat = 0;
! 2505: return v;
! 2506: }
! 2507: static void COLOR(uae_u16 v, int num)
1.1 root 2508: {
2509: int r,g,b;
2510: int cr,cg,cb;
2511: int colreg;
1.1.1.3 ! root 2512:
1.1 root 2513: v &= 0xFFF;
2514: #if AGA_CHIPSET == 1
2515: {
1.1.1.2 root 2516: /* XXX Broken */
1.1.1.3 ! root 2517: uae_u32 cval;
1.1.1.2 root 2518: colreg = ((bplcon3 >> 13) & 7) * 32 + num;
1.1 root 2519: r = (v & 0xF00) >> 8;
2520: g = (v & 0xF0) >> 4;
2521: b = (v & 0xF) >> 0;
1.1.1.2 root 2522: cr = color_regs[colreg] >> 16;
2523: cg = (color_regs[colreg] >> 8) & 0xFF;
2524: cb = color_regs[colreg] & 0xFF;
1.1 root 2525:
1.1.1.2 root 2526: if (bplcon3 & 0x200) {
1.1 root 2527: cr &= 0xF0; cr |= r;
2528: cg &= 0xF0; cg |= g;
2529: cb &= 0xF0; cb |= b;
2530: } else {
2531: cr = r + (r << 4);
2532: cg = g + (g << 4);
2533: cb = b + (b << 4);
2534: }
2535: cval = (cr << 16) | (cg << 8) | cb;
1.1.1.2 root 2536: if (cval == color_regs[colreg])
1.1 root 2537: return;
1.1.1.2 root 2538: color_regs[colreg] = cval;
1.1 root 2539: pfield_may_need_update(1);
2540: }
1.1.1.3 ! root 2541: #else
1.1 root 2542: {
1.1.1.2 root 2543: if (current_colors.color_regs[num] == v)
1.1 root 2544: return;
1.1.1.2 root 2545: /* Call this with the old table still intact. */
2546: record_color_change (num, v);
2547: remembered_color_entry = -1;
2548: current_colors.color_regs[num] = v;
2549: current_colors.acolors[num] = xcolors[v];
1.1 root 2550: }
2551: #endif
2552: }
2553:
1.1.1.3 ! root 2554: static void DSKSYNC(uae_u16 v) { dsksync = v; }
! 2555: static void DSKDAT(uae_u16 v) { write_log ("DSKDAT written. Not good.\n"); }
! 2556: static void DSKPTH(uae_u16 v) { dskpt = (dskpt & 0xffff) | ((uae_u32)v << 16); }
! 2557: static void DSKPTL(uae_u16 v) { dskpt = (dskpt & ~0xffff) | (v); }
1.1 root 2558:
1.1.1.3 ! root 2559: static void DSKLEN(uae_u16 v)
1.1 root 2560: {
2561: if (v & 0x8000) {
2562: dskdmaen = dskdmaen == 1 ? 2 : 1;
1.1.1.3 ! root 2563: } else {
1.1 root 2564: dskdmaen = 0;
2565: if (eventtab[ev_diskblk].active)
1.1.1.3 ! root 2566: write_log ("warning: Disk DMA aborted!\n");
1.1 root 2567: eventtab[ev_diskblk].active = 0;
2568: events_schedule();
1.1.1.3 ! root 2569:
1.1 root 2570: }
2571: dsklen = dsklength = v; dsklength &= 0x3fff;
2572: if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) {
1.1.1.3 ! root 2573: sprintf (warning_buffer, "Non-standard sync: %04x len: %x\n", dsksync, dsklength);
! 2574: write_log (warning_buffer);
1.1 root 2575: }
2576: if (dskdmaen > 1) {
2577: if (dsklen & 0x4000) {
2578: eventtab[ev_diskblk].active = 1;
2579: eventtab[ev_diskblk].oldcycles = cycles;
2580: eventtab[ev_diskblk].evtime = 40 + cycles; /* ??? */
2581: events_schedule();
2582: } else {
2583: int result = DISK_PrepareReadMFM(dsklength, dsksync, adkcon & 0x400);
2584: if (result) {
2585: eventtab[ev_diskblk].active = 1;
2586: eventtab[ev_diskblk].oldcycles = cycles;
2587: eventtab[ev_diskblk].evtime = result + cycles;
2588: events_schedule();
2589: }
2590: }
2591: }
2592: }
2593:
1.1.1.3 ! root 2594: static uae_u16 DSKBYTR(void)
1.1 root 2595: {
1.1.1.3 ! root 2596: uae_u16 v = (dsklen >> 1) & 0x6000;
! 2597: uae_u16 mfm, byte;
1.1 root 2598: if (DISK_GetData(&mfm, &byte))
2599: v |= 0x8000;
2600: v |= byte;
2601: if (dsksync == mfm) v |= 0x1000;
2602: return v;
2603: }
2604:
1.1.1.3 ! root 2605: static uae_u16 DSKDATR(void)
1.1 root 2606: {
1.1.1.3 ! root 2607: uae_u16 mfm, byte;
1.1 root 2608: DISK_GetData(&mfm, &byte);
1.1.1.3 ! root 2609: return mfm;
1.1 root 2610: }
1.1.1.3 ! root 2611:
! 2612: static uae_u16 potgo_value;
! 2613:
! 2614: static void POTGO(uae_u16 v)
1.1 root 2615: {
1.1.1.3 ! root 2616: potgo_value = v;
! 2617: }
! 2618:
! 2619: static uae_u16 POTGOR(void)
! 2620: {
! 2621: uae_u16 v = (potgo_value | (potgo_value << 1)) & 0xAA00;
! 2622: v |= v >> 1;
! 2623:
! 2624: if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
! 2625: if (buttonstate[2])
! 2626: v &= 0xFBFF;
! 2627:
! 2628: if (buttonstate[1])
! 2629: v &= 0xFEFF;
! 2630: }
! 2631: else if (JSEM_ISJOY0(0, currprefs.fake_joystick) || JSEM_ISJOY1(0, currprefs.fake_joystick)) {
! 2632: if (joy0button & 2) v &= 0xfbff;
! 2633: if (joy0button & 4) v &= 0xfeff;
! 2634: }
! 2635:
! 2636: if (JSEM_ISJOY0(1, currprefs.fake_joystick) || JSEM_ISJOY1(1, currprefs.fake_joystick)) {
! 2637: if (joy1button & 2) v &= 0xbfff;
! 2638: if (joy1button & 4) v &= 0xefff;
! 2639: }
1.1 root 2640:
2641: return v;
2642: }
1.1.1.3 ! root 2643: static uae_u16 POT0DAT(void)
1.1 root 2644: {
1.1.1.3 ! root 2645: static uae_u16 cnt = 0;
! 2646: if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
! 2647: if (buttonstate[2])
! 2648: cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00);
! 2649: if (buttonstate[1])
! 2650: cnt += 0x100;
! 2651: }
! 2652:
1.1 root 2653: return cnt;
2654: }
1.1.1.3 ! root 2655: static uae_u16 JOY0DAT(void)
1.1 root 2656: {
1.1.1.3 ! root 2657: if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
! 2658: do_mouse_hack();
! 2659: return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
! 2660: }
1.1 root 2661: return joy0dir;
2662: }
1.1.1.3 ! root 2663: static uae_u16 JOY1DAT(void)
1.1 root 2664: {
1.1.1.3 ! root 2665: if (JSEM_ISMOUSE (1, currprefs.fake_joystick)) {
! 2666: do_mouse_hack();
! 2667: return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
! 2668: }
! 2669: return joy1dir;
1.1 root 2670: }
1.1.1.3 ! root 2671: static void JOYTEST(uae_u16 v)
1.1 root 2672: {
1.1.1.3 ! root 2673: if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
! 2674: mouse_x = v & 0xFC;
! 2675: mouse_y = (v >> 8) & 0xFC;
1.1 root 2676: }
2677: }
2678:
1.1.1.2 root 2679: /*
2680: * Here starts the copper code. It should be rewritten.
2681: */
2682:
1.1.1.3 ! root 2683: #define COPPER_ALTERNATIVE 1
1.1 root 2684: /*
2685: * Calculate the minimum number of cycles after which the
2686: * copper comparison becomes true. This is quite tricky. I hope it works.
2687: */
2688: static int calc_copcomp_true(int currvpos, int currhpos)
1.1.1.3 ! root 2689: {
! 2690: uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
! 2691: uae_u16 hp = currhpos & (copi2 & 0xFE);
! 2692: uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8);
! 2693: uae_u16 hcmp = (copi1 & copi2 & 0xFE);
1.1 root 2694: int copper_time_hpos;
2695: int cycleadd = maxhpos - currhpos;
2696: int coptime = 0;
1.1.1.3 ! root 2697: int maxwait = 32767;
1.1 root 2698:
1.1.1.3 ! root 2699: #if COPPER_ALTERNATIVE == 0
1.1.1.2 root 2700: /* This is a kludge... the problem is that there are programs that wait for
2701: * FFDDFFFE and then for a line in the second display half, and this doesn't
2702: * work without this. I _think_ the reason why it works on the Amiga is that
2703: * the last cycle in the line isn't available for the copper, but I'm not sure.
2704: * OTOH, I'm pretty convinced that the copper timings are correct otherwise, so
2705: * I added this rather than changing something else. */
2706: if (hcmp == 0xDC)
2707: hcmp += 2;
1.1.1.3 ! root 2708: #endif
! 2709: decide_line();
! 2710: /* Copper DMA is turned off in Hires 4 bitplane mode */
! 2711: if (vp == vcmp
! 2712: && decided_nr_planes == 4 /* -1 if before plfstrt */
! 2713: && decided_hires
! 2714: && currhpos >= thisline_decision.plfstrt
! 2715: && currhpos < thisline_decision.plfstrt + thisline_decision.plflinelen)
! 2716: coptime += thisline_decision.plfstrt + thisline_decision.plflinelen - currhpos;
! 2717:
1.1 root 2718: if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
1.1.1.3 ! root 2719: return coptime;
1.1 root 2720:
2721: try_again:
2722:
2723: while (vp < vcmp) {
2724: currvpos++;
2725: if (currvpos > maxvpos + 1)
2726: return -1;
2727: currhpos = 0;
2728: coptime += cycleadd;
2729: cycleadd = maxhpos;
2730: vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
2731: }
1.1.1.3 ! root 2732: if ((bplcon0 & 0xF000) == 0xC000) {
! 2733: if (coptime > 0)
! 2734: return coptime;
! 2735: maxwait = plfstrt - current_hpos();
! 2736: if (maxwait < 0)
! 2737: maxwait = 32767;
! 2738: }
1.1 root 2739: copper_time_hpos = currhpos;
2740: hp = copper_time_hpos & (copi2 & 0xFE);
1.1.1.3 ! root 2741: if (!(vp > vcmp)) {
1.1.1.2 root 2742: while ((int)hp < ((int)hcmp)) {
1.1 root 2743: currhpos++;
2744: /* Copper DMA is turned off in Hires 4 bitplane mode */
1.1.1.2 root 2745: if (decided_nr_planes != 4 /* -1 if before plfstrt */
2746: || !decided_hires
2747: || current_hpos () >= (thisline_decision.plfstrt + thisline_decision.plflinelen))
1.1 root 2748: copper_time_hpos++;
1.1.1.3 ! root 2749:
1.1.1.2 root 2750: if (currhpos > maxhpos) {
1.1 root 2751: /* Now, what? There might be a good position on the
2752: * next line. But it can also be the FFFF FFFE
2753: * case.
2754: */
2755: currhpos = 0;
2756: currvpos++;
2757: vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
2758: goto try_again;
2759: }
2760: coptime++;
1.1.1.3 ! root 2761: if (coptime >= maxwait)
! 2762: return coptime;
1.1 root 2763: hp = copper_time_hpos & (copi2 & 0xFE);
2764: }
2765: }
1.1.1.2 root 2766: if (coptime == 0) /* waiting for the blitter */
1.1.1.3 ! root 2767: return 1;
1.1.1.2 root 2768:
2769: return coptime;
2770: }
2771:
2772: /*
2773: * Simple version of the above which only tries to get vpos correct.
2774: */
2775: static int calc_copcomp_true_vpos(int currvpos, int currhpos)
1.1.1.3 ! root 2776: {
! 2777: uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
! 2778: uae_u16 hp = currhpos & (copi2 & 0xFE);
! 2779: uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8);
! 2780: uae_u16 hcmp = (copi1 & copi2 & 0xFE);
1.1.1.2 root 2781: int copper_time_hpos;
2782: int cycleadd = maxhpos - currhpos;
2783: int coptime = 0;
1.1.1.3 ! root 2784: #if COPPER_ALTERNATIVE == 0
1.1.1.2 root 2785: /* see above */
2786: if (hcmp == 0xDC)
2787: hcmp += 2;
1.1.1.3 ! root 2788: #endif
1.1.1.2 root 2789: if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
1.1.1.3 ! root 2790: return 0;
1.1.1.2 root 2791:
2792: while (vp < vcmp) {
2793: currvpos++;
2794: if (currvpos > maxvpos + 1)
2795: return -1;
2796: currhpos = 0;
2797: coptime += cycleadd;
2798: cycleadd = maxhpos;
2799: vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
2800: }
2801: return coptime;
2802: }
2803:
2804: static enum copper_states cop_cmds[4] = { COP_move, COP_wait, COP_move, COP_skip };
2805:
2806: /* This function is not always correct, but it's the best we can do. */
2807: static int copper_memory_cycles (int n)
2808: {
2809: int current_cycle = current_hpos ();
2810: int n_needed = 0;
1.1.1.3 ! root 2811: int planes = corrected_nr_planes_from_bplcon0;
! 2812:
1.1.1.2 root 2813: while (n) {
2814: /* This sucks. The DIW may end vertically at exactly this point. Therefore,
2815: * we must call decide_line(). If we're vertically outside the DIW,
2816: * copper_cycle_time will be != -1 after this call [Sanity Interference] */
2817: decide_line ();
1.1.1.3 ! root 2818: #if COPPER_ALTERNATIVE == 1
! 2819: if (current_cycle >= (maxhpos-3)) {
! 2820: n_needed += maxhpos - current_cycle;
! 2821: current_cycle = 0;
! 2822: continue;
! 2823: }
! 2824: #endif
! 2825: if (copper_cycle_time == -1 && current_cycle >= 0x14
! 2826: && current_cycle >= plfstrt && current_cycle < plfstrt + plflinelen
! 2827: && (planes == 6 || (planes == 5 && (current_cycle % 8) < 4)))
1.1.1.2 root 2828: {
2829: n_needed += 4;
2830: current_cycle += 4;
2831: } else {
2832: n_needed += 2;
1.1.1.3 ! root 2833: current_cycle += 2;
1.1.1.2 root 2834: }
1.1.1.3 ! root 2835: if (current_cycle >= maxhpos)
! 2836: current_cycle -= maxhpos;
1.1.1.2 root 2837: n--;
2838: }
2839: return n_needed;
2840: }
1.1 root 2841:
1.1.1.2 root 2842: static __inline__ int calc_copper_cycles (int n_cycles)
2843: {
1.1.1.3 ! root 2844: return /*copper_cycle_time != -1 ? copper_cycle_time * n_cycles : */copper_memory_cycles (n_cycles);
1.1 root 2845: }
2846:
1.1.1.2 root 2847: static __inline__ int copper_init_read (int n_cycles)
1.1 root 2848: {
2849: if (dmaen(DMA_COPPER)){
1.1.1.2 root 2850: int t = calc_copper_cycles (n_cycles);
2851:
2852: eventtab[ev_copper].evtime = t + cycles;
2853: return 1;
1.1 root 2854: } else {
2855: copstate = COP_read;
2856: eventtab[ev_copper].active = 0;
1.1.1.2 root 2857: return 0;
2858: }
2859: }
2860:
2861: static __inline__ void copper_read (void)
2862: {
2863: int cmd;
1.1.1.3 ! root 2864:
! 2865: copi1 = chipmem_bank.wget(coplc);
1.1.1.2 root 2866: copi2 = chipmem_bank.wget(coplc+2);
2867: coplc += 4;
2868: eventtab[ev_copper].oldcycles = cycles;
1.1.1.3 ! root 2869:
1.1.1.2 root 2870: cmd = (copi1 & 1) | ((copi2 & 1) << 1);
2871: copstate = cop_cmds[cmd];
2872: eventtab[ev_copper].oldcycles = cycles;
2873: }
2874:
2875: static __inline__ void handle_bltfinish_wait (void)
2876: {
2877: if (bltstate == BLT_done) {
2878: copstate = COP_read;
2879: /* Don't need to wait. Experimental: No copper wakeup time in this case. */
2880: } else {
2881: eventtab[ev_copper].active = 0;
2882: copstate = COP_morewait;
2883: copper_waiting_for_blitter = 1;
2884: }
2885: }
2886:
2887: void blitter_done_notify (void)
2888: {
2889: if (copper_waiting_for_blitter) {
2890: copper_waiting_for_blitter = 0;
2891: eventtab[ev_copper].active = 1;
2892: eventtab[ev_copper].oldcycles = cycles;
2893: eventtab[ev_copper].evtime = 1 + cycles;
2894: events_schedule ();
1.1 root 2895: }
2896: }
2897:
1.1.1.3 ! root 2898: #if 0
! 2899: static void do_copper_cheat(void)
! 2900: {
! 2901: int coptime, t;
! 2902: int nmoves = 100; /*??*/
! 2903: int nextcycles = eventtab[ev_hsync].evtime + currprefs.copper_pos;
! 2904:
! 2905: eventtab[ev_copper].evtime = nextcycles;
! 2906: eventtab[ev_copper].oldcycles = cycles;
! 2907: nextcycles -= cycles;
! 2908:
! 2909: if (!dmaen(DMA_COPPER)) {
! 2910: eventtab[ev_copper].active = 0;
! 2911: return;
! 2912: }
! 2913: for (; nmoves; nmoves--)
! 2914: switch(copstate){
! 2915: case COP_read:
! 2916: copper_read ();
! 2917: break;
! 2918:
! 2919: case COP_read_ignore:
! 2920: copper_read ();
! 2921: copstate = COP_read;
! 2922: break;
! 2923:
! 2924: case COP_move:
! 2925: if (copi1 >= (copcon & 2 ? 0x40u : 0x80u)) {
! 2926: custom_bank.wput(copi1,copi2);
! 2927: copstate = COP_read;
! 2928: } else {
! 2929: copstate = COP_stop;
! 2930: eventtab[ev_copper].active = 0;
! 2931: copper_active = 0;
! 2932: return;
! 2933: }
! 2934: break;
! 2935:
! 2936: case COP_skip:
! 2937: copstate = COP_read;
! 2938: if (calc_copcomp_true(vpos, current_hpos()) == 0)
! 2939: copstate = COP_read_ignore;
! 2940: break;
! 2941:
! 2942: case COP_wait:
! 2943: coptime = calc_copcomp_true(vpos, current_hpos());
! 2944: if (coptime < 0) {
! 2945: copstate = COP_stop;
! 2946: eventtab[ev_copper].active = 0;
! 2947: copper_active = 0;
! 2948: return;
! 2949: }
! 2950: if (coptime == 0) {
! 2951: copper_read();
! 2952: if (vpos != 255)
! 2953: break;
! 2954: eventtab[ev_copper].evtime = cycles + 6;
! 2955: return;
! 2956: }
! 2957: if (coptime >= nextcycles)
! 2958: return;
! 2959: if (vpos == 255)
! 2960: eventtab[ev_copper].evtime = cycles + coptime;
! 2961: /*else
! 2962: copstate = COP_read;*/
! 2963: return;
! 2964:
! 2965: case COP_stop:
! 2966: eventtab[ev_copper].active = 0;
! 2967: copper_active = 0;
! 2968: return;
! 2969:
! 2970: case COP_morewait:
! 2971: case COP_do_read:
! 2972: case COP_do_read_ignore:
! 2973: abort();
! 2974: }
! 2975: }
! 2976: #endif
! 2977:
1.1 root 2978: static void do_copper(void)
1.1.1.2 root 2979: {
2980: int coptime, t;
2981: for (;;)
2982: switch(copstate){
2983: case COP_read:
2984: eventtab[ev_copper].oldcycles = cycles;
2985: if (!copper_init_read (2))
2986: return;
2987: copstate = COP_do_read;
2988: return;
1.1.1.3 ! root 2989:
1.1.1.2 root 2990: case COP_do_read:
2991: copper_read ();
2992: break;
2993:
2994: case COP_read_ignore:
2995: eventtab[ev_copper].oldcycles = cycles;
2996: if (!copper_init_read (2))
2997: return;
2998: copstate = COP_do_read_ignore;
2999: return;
3000:
3001: case COP_do_read_ignore:
3002: copper_read ();
3003: copstate = COP_read;
3004: break;
3005:
3006: case COP_move:
1.1.1.3 ! root 3007: if (copi1 >= (copcon & 2 ? 0x40u : 0x80u)) {
1.1.1.2 root 3008: custom_bank.wput(copi1,copi2);
3009: copstate = COP_read;
3010: break;
3011: } else {
3012: copstate = COP_stop;
3013: eventtab[ev_copper].active = 0;
3014: copper_active = 0;
3015: }
3016: return;
3017:
3018: case COP_skip:
3019: copstate = COP_read;
3020: if (calc_copcomp_true(vpos, current_hpos()) == 0)
3021: copstate = COP_read_ignore;
3022: break;
3023:
3024: case COP_wait:
3025: /* Recognize blitter wait statements. This is a speed optimization
3026: * only.*/
3027: if (copi1 == 1 && copi2 == 0) {
3028: handle_bltfinish_wait ();
3029: if (!eventtab[ev_copper].active)
3030: return;
3031: break;
3032: }
3033: coptime = calc_copcomp_true_vpos(vpos, current_hpos());
3034: if (coptime > 0) {
3035: copstate = COP_morewait;
3036: eventtab[ev_copper].oldcycles = cycles;
3037: eventtab[ev_copper].evtime = coptime + cycles;
3038: return;
3039: }
3040: coptime = calc_copcomp_true(vpos, current_hpos());
3041: if (coptime < 0) {
3042: copstate = COP_stop;
3043: eventtab[ev_copper].active = 0;
3044: copper_active = 0;
3045: return;
3046: }
3047: if (coptime) {
3048: copstate = COP_morewait;
3049: eventtab[ev_copper].evtime = coptime + cycles;
3050: return;
3051: }
3052: copstate = COP_read;
3053: /* Experimental: no copper wakeup time in this case. The HRM says
3054: * nothing about this. */
3055: break;
3056:
3057: case COP_morewait:
3058: coptime = calc_copcomp_true(vpos, current_hpos());
3059: if (coptime < 0) {
3060: copstate = COP_stop;
3061: eventtab[ev_copper].active = 0;
3062: copper_active = 0;
3063: return;
3064: }
3065: if (coptime) {
3066: eventtab[ev_copper].evtime = coptime + cycles;
3067: return;
3068: }
3069: /* Copper wakeup time: 1 memory cycle, plus 2 for the next read */
3070: eventtab[ev_copper].oldcycles = cycles;
3071: if (!copper_init_read (3))
3072: return;
3073: copstate = COP_do_read;
3074: return;
3075:
3076: case COP_stop:
1.1 root 3077: eventtab[ev_copper].active = 0;
3078: copper_active = 0;
1.1.1.2 root 3079: return;
1.1 root 3080: }
3081: }
3082:
3083: static void diskblk_handler(void)
3084: {
3085: regs.spcflags |= SPCFLAG_DISK;
3086: eventtab[ev_diskblk].active = 0;
3087: }
3088:
3089: void do_disk(void)
3090: {
3091: if (dskdmaen != 2 && (regs.spcflags & SPCFLAG_DISK)) {
1.1.1.3 ! root 3092: static int warned = 0;
! 3093: if (!warned)
! 3094: warned++, write_log ("BUG!\n");
1.1 root 3095: return;
3096: }
3097: if (dmaen(0x10)){
3098: if (dsklen & 0x4000) {
3099: if (!chipmem_bank.check (dskpt, 2*dsklength)) {
1.1.1.3 ! root 3100: write_log ("warning: Bad disk write DMA pointer\n");
1.1 root 3101: } else {
1.1.1.3 ! root 3102: uae_u8 *mfmp = get_real_address (dskpt);
1.1 root 3103: int i;
3104: DISK_InitWrite();
3105:
3106: for (i = 0; i < dsklength; i++) {
1.1.1.3 ! root 3107: uae_u16 d = (*mfmp << 8) + *(mfmp+1);
1.1 root 3108: mfmwrite[i] = d;
3109: mfmp += 2;
3110: }
3111: DISK_WriteData(dsklength);
3112: }
3113: } else {
3114: int result = DISK_ReadMFM (dskpt);
3115: }
3116: regs.spcflags &= ~SPCFLAG_DISK;
3117: INTREQ(0x9002);
3118: dskdmaen = -1;
3119: }
3120: }
3121:
3122: static void gen_pfield_tables(void)
3123: {
3124: int i;
3125: union {
3126: struct {
1.1.1.3 ! root 3127: uae_u8 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
1.1 root 3128: } foo;
3129: struct {
1.1.1.3 ! root 3130: uae_u32 a, b, c, d;
1.1 root 3131: } bar;
3132: } baz;
1.1.1.3 ! root 3133:
1.1 root 3134: for (i = 0; i < 256; i++) {
3135: /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */
3136: baz.foo.a = i & 64 ? 1 : 0;
3137: baz.foo.b = i & 16 ? 1 : 0;
3138: baz.foo.c = i & 4 ? 1 : 0;
3139: baz.foo.d = i & 1 ? 1 : 0;
3140: hirestab_l[i][0] = baz.bar.a;
1.1.1.3 ! root 3141:
1.1 root 3142: baz.foo.a = i & 128 ? 1 : 0;
3143: baz.foo.b = i & 64 ? 1 : 0;
3144: baz.foo.c = i & 32 ? 1 : 0;
3145: baz.foo.d = i & 16 ? 1 : 0;
3146: baz.foo.e = i & 8 ? 1 : 0;
3147: baz.foo.f = i & 4 ? 1 : 0;
3148: baz.foo.g = i & 2 ? 1 : 0;
3149: baz.foo.h = i & 1 ? 1 : 0;
3150: lorestab_l[i][0] = baz.bar.a;
3151: lorestab_l[i][1] = baz.bar.b;
1.1.1.3 ! root 3152: sprtaba[i] = ((((i >> 7) & 1) << 0)
! 3153: | (((i >> 6) & 1) << 2)
! 3154: | (((i >> 5) & 1) << 4)
! 3155: | (((i >> 4) & 1) << 6)
! 3156: | (((i >> 3) & 1) << 8)
! 3157: | (((i >> 2) & 1) << 10)
! 3158: | (((i >> 1) & 1) << 12)
! 3159: | (((i >> 0) & 1) << 14));
! 3160: sprtabb[i] = sprtaba[i] * 2;
! 3161: clxtab[i] = ((((i & 3) && (i & 12)) << 9)
! 3162: | (((i & 3) && (i & 48)) << 10)
! 3163: | (((i & 3) && (i & 192)) << 11)
! 3164: | (((i & 12) && (i & 48)) << 12)
! 3165: | (((i & 12) && (i & 192)) << 13)
! 3166: | (((i & 48) && (i & 192)) << 14));
1.1 root 3167: }
1.1.1.3 ! root 3168:
1.1 root 3169: for (i = 0; i < 256; i++) {
3170: baz.foo.a = i & 128 ? 1 : 0;
3171: baz.foo.b = i & 64 ? 1 : 0;
3172: baz.foo.c = i & 32 ? 1 : 0;
3173: baz.foo.d = i & 16 ? 1 : 0;
3174: baz.foo.e = i & 8 ? 1 : 0;
3175: baz.foo.f = i & 4 ? 1 : 0;
3176: baz.foo.g = i & 2 ? 1 : 0;
3177: baz.foo.h = i & 1 ? 1 : 0;
3178: hirestab_h[i][0] = baz.bar.a;
3179: hirestab_h[i][1] = baz.bar.b;
1.1.1.3 ! root 3180:
1.1 root 3181: baz.foo.a = i & 128 ? 1 : 0;
3182: baz.foo.b = i & 128 ? 1 : 0;
3183: baz.foo.c = i & 64 ? 1 : 0;
3184: baz.foo.d = i & 64 ? 1 : 0;
3185: baz.foo.e = i & 32 ? 1 : 0;
3186: baz.foo.f = i & 32 ? 1 : 0;
3187: baz.foo.g = i & 16 ? 1 : 0;
3188: baz.foo.h = i & 16 ? 1 : 0;
3189: baz.foo.i = i & 8 ? 1 : 0;
3190: baz.foo.j = i & 8 ? 1 : 0;
3191: baz.foo.k = i & 4 ? 1 : 0;
3192: baz.foo.l = i & 4 ? 1 : 0;
3193: baz.foo.m = i & 2 ? 1 : 0;
3194: baz.foo.n = i & 2 ? 1 : 0;
3195: baz.foo.o = i & 1 ? 1 : 0;
3196: baz.foo.p = i & 1 ? 1 : 0;
3197: lorestab_h[i][0] = baz.bar.a;
3198: lorestab_h[i][1] = baz.bar.b;
3199: lorestab_h[i][2] = baz.bar.c;
3200: lorestab_h[i][3] = baz.bar.d;
3201: }
3202: }
3203:
1.1.1.3 ! root 3204: static void do_sprites(int currvp, int currhp)
1.1.1.2 root 3205: {
3206: int i;
1.1.1.3 ! root 3207: /* The graph in the HRM, p. 195 seems to indicate that sprite 0 is
! 3208: * fetched at cycle 0x14 and thus can't be disabled by bitplane DMA. */
! 3209: int maxspr = currhp/4 - 0x14/4;
! 3210: #if 0
! 3211: if (currvp == 0)
! 3212: return;
! 3213: #else
! 3214: /* I don't know whether this is right. Some programs write the sprite pointers
! 3215: * directly at the start of the copper list. With the currvp==0 check, the
! 3216: * first two words of data are read on the second line in the frame. The problem
! 3217: * occurs when the program jumps to another copperlist a few lines further down
! 3218: * which _also_ writes the sprite pointer registers. This means that a) writing
! 3219: * to the sprite pointers sets the state to SPR_restart; or b) that sprite DMA
! 3220: * is disabled until the end of the vertical blanking interval. The HRM
! 3221: * isn't clear - it says that the vertical sprite position can be set to any
! 3222: * value, but this wouldn't be the first mistake... */
! 3223: /* Update: I modified one of the programs to write the sprite pointers the
! 3224: * second time only _after_ the VBlank interval, and it showed the same behaviour
! 3225: * as it did unmodified under UAE with the above check. This indicates that the
! 3226: * solution below is correct. */
! 3227: if (currvp < vblank_endline)
! 3228: return;
! 3229: #endif
! 3230: if (maxspr < 0)
! 3231: return;
! 3232: if (maxspr > 8)
! 3233: maxspr = 8;
1.1.1.2 root 3234:
1.1.1.3 ! root 3235: for (i = 0; i < maxspr; i++) {
! 3236: int fetch = 0;
1.1.1.2 root 3237:
1.1.1.3 ! root 3238: if (spron[i] == 0)
! 3239: continue;
! 3240:
! 3241: if (sprst[i] == SPR_restart) {
! 3242: fetch = 2;
! 3243: spron[i] = 1;
! 3244: } else if ((sprst[i] == SPR_waiting_start && sprvstart[i] == vpos) || sprst[i] == SPR_waiting_stop) {
! 3245: fetch = 1;
! 3246: sprst[i] = SPR_waiting_stop;
! 3247: }
! 3248: if (sprst[i] == SPR_waiting_stop && sprvstop[i] == vpos) {
! 3249: fetch = 2;
! 3250: sprst[i] = SPR_waiting_start;
1.1.1.2 root 3251: }
3252:
1.1.1.3 ! root 3253: if (fetch && dmaen(DMA_SPRITE)) {
! 3254: uae_u16 data1 = chipmem_bank.wget(sprpt[i]);
! 3255: uae_u16 data2 = chipmem_bank.wget(sprpt[i]+2);
! 3256: sprpt[i] += 4;
! 3257:
! 3258: if (fetch == 1) {
! 3259: /* Hack for X mouse auto-calibration */
! 3260: if (i == 0 && !sprvbfl && ((sprpos[0] & 0xff) << 2) > 2 * DISPLAY_LEFT_SHIFT) {
! 3261: spr0ctl=sprctl[0];
! 3262: spr0pos=sprpos[0];
! 3263: sprvbfl=2;
! 3264: }
! 3265: SPRxDATB_1(data2, i);
! 3266: SPRxDATA_1(data1, i);
! 3267: } else {
! 3268: SPRxPOS_1(data1, i);
! 3269: SPRxCTL_1(data2, i);
! 3270: }
1.1.1.2 root 3271: }
3272: }
3273: }
3274:
1.1.1.3 ! root 3275: static uae_u32 attach_2nd;
1.1.1.2 root 3276:
1.1.1.3 ! root 3277: static uae_u32 do_sprite_collisions (struct sprite_draw *spd, int prev_overlap, int i, int nr_spr)
! 3278: {
! 3279: int j;
! 3280: int sprxp = spd[i].linepos;
! 3281: uae_u32 datab = spd[i].datab;
! 3282: uae_u32 mask2 = 0;
! 3283: int sbit = 1 << spd[i].num;
! 3284: int sprx_shift = 1;
! 3285: int attach_compare = -1;
! 3286: if (currprefs.gfx_lores != 1)
! 3287: sprx_shift = 0;
! 3288:
! 3289: attach_2nd = 0;
! 3290: if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80)
! 3291: attach_compare = spd[i].num - 1;
! 3292:
! 3293: for (j = prev_overlap; j < i; j++) {
! 3294: uae_u32 mask1;
! 3295: int off;
1.1.1.2 root 3296:
1.1.1.3 ! root 3297: if (spd[i].num < spd[j].num)
! 3298: continue;
1.1.1.2 root 3299:
1.1.1.3 ! root 3300: off = sprxp - spd[j].linepos;
! 3301: off <<= sprx_shift;
! 3302: mask1 = spd[j].datab >> off;
! 3303:
! 3304: /* If j is an attachment for i, then j doesn't block i */
! 3305: if (spd[j].num == attach_compare) {
! 3306: attach_2nd |= mask1;
! 3307: } else {
! 3308: mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
! 3309: mask1 |= (mask1 & 0x55555555) << 1;
! 3310: if (datab & mask1)
! 3311: clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
! 3312: mask2 |= mask1;
1.1.1.2 root 3313: }
1.1.1.3 ! root 3314: }
! 3315: for (j = i+1; j < nr_spr; j++) {
! 3316: uae_u32 mask1;
! 3317: int off = spd[j].linepos - sprxp;
1.1.1.2 root 3318:
1.1.1.3 ! root 3319: if (off >= sprite_width || spd[i].num < spd[j].num)
! 3320: break;
1.1.1.2 root 3321:
1.1.1.3 ! root 3322: off <<= sprx_shift;
! 3323: mask1 = spd[j].datab << off;
1.1.1.2 root 3324:
1.1.1.3 ! root 3325: /* If j is an attachment for i, then j doesn't block i */
! 3326: if (spd[j].num == attach_compare) {
! 3327: attach_2nd |= mask1;
! 3328: } else {
! 3329: mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
! 3330: mask1 |= (mask1 & 0x55555555) << 1;
! 3331: if (datab & mask1)
! 3332: clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
! 3333: mask2 |= mask1;
1.1.1.2 root 3334: }
3335: }
1.1.1.3 ! root 3336: datab &= ~mask2;
! 3337: return datab;
1.1.1.2 root 3338: }
3339:
1.1.1.3 ! root 3340: static __inline__ void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc)
1.1.1.2 root 3341: {
1.1.1.3 ! root 3342: uae_u32 datcd;
! 3343: int basecol = 16;
! 3344: if (!attch)
! 3345: basecol += (spr & ~1)*2;
! 3346: if (bpldualpf)
! 3347: basecol |= 128;
! 3348: if (attch)
! 3349: datcd = attach_2nd;
1.1.1.2 root 3350:
1.1.1.3 ! root 3351: for(; attch ? datab | datcd : datab; sprxp += sprx_inc) {
! 3352: int col;
1.1.1.2 root 3353:
1.1.1.3 ! root 3354: if (attch) {
! 3355: col = ((datab & 3) << 2) | (datcd & 3);
! 3356: datcd >>= 2;
! 3357: } else
! 3358: col = datab & 3;
! 3359: datab >>= 2;
! 3360: if (col) {
! 3361: col |= basecol;
! 3362: if (ham) {
! 3363: col = colors_for_drawing.color_regs[col];
! 3364: ham_linebuf[sprxp] = col;
! 3365: if (sprx_inc == 2) {
! 3366: ham_linebuf[sprxp+1] = col;
! 3367: }
! 3368: } else {
! 3369: pixdata.apixels[sprxp] = col;
! 3370: if (sprx_inc == 2) {
! 3371: pixdata.apixels[sprxp+1] = col;
! 3372: }
! 3373: }
1.1.1.2 root 3374: }
3375: }
3376: }
3377:
1.1.1.3 ! root 3378: static void walk_sprites (struct sprite_draw *spd, int nr_spr)
1.1.1.2 root 3379: {
1.1.1.3 ! root 3380: int i, prev_overlap;
! 3381: int last_sprite_pos = -64;
! 3382: uae_u32 plane1 = 0, plane2 = 0;
! 3383: int sprx_inc = 1, sprx_shift = 1;
! 3384:
! 3385: if (currprefs.gfx_lores == 0)
! 3386: sprx_inc = 2, sprx_shift = 0;
! 3387:
! 3388: prev_overlap = 0;
! 3389: for (i = 0; i < nr_spr; i++) {
! 3390: int sprxp = spd[i].linepos;
! 3391: int m = 1 << spd[i].num;
! 3392: uae_u32 datab;
! 3393: while (prev_overlap < i && spd[prev_overlap].linepos + sprite_width <= sprxp)
! 3394: prev_overlap++;
1.1.1.2 root 3395:
1.1.1.3 ! root 3396: datab = do_sprite_collisions (spd, prev_overlap, i, nr_spr);
! 3397: #ifdef LORES_HACK
! 3398: if (currprefs.gfx_lores == 2)
! 3399: sprxp >>= 1;
! 3400: #endif
! 3401: if ((bpldualpf && plfpri[1] < 256) || (plfpri[2] < 256)) {
! 3402: if (sprxp != last_sprite_pos) {
! 3403: int ok = last_sprite_pos-sprxp+16;
! 3404: int ok2;
! 3405: if (ok <= 0) {
! 3406: ok = ok2 = 0;
! 3407: plane1 = 0;
! 3408: plane2 = 0;
! 3409: } else {
! 3410: ok2 = ok << sprx_shift;
! 3411: plane1 >>= 32 - ok2;
! 3412: plane2 >>= 32 - ok2;
! 3413: }
! 3414: last_sprite_pos = sprxp;
1.1.1.2 root 3415:
1.1.1.3 ! root 3416: if (bpldualpf) {
! 3417: uae_u32 mask = 3 << ok2;
! 3418: int p = sprxp+ok;
! 3419:
! 3420: for (; mask; mask <<= 2, p += sprx_inc) {
! 3421: int data = pixdata.apixels[p];
! 3422: if (dblpf_2nd2[data] == 2)
! 3423: plane2 |= mask;
! 3424: if (dblpf_2nd1[data] == 1)
! 3425: plane1 |= mask;
! 3426: }
! 3427: } else {
! 3428: uae_u32 mask = 3 << ok2;
! 3429: int p = sprxp+ok;
1.1.1.2 root 3430:
1.1.1.3 ! root 3431: for (; mask; mask <<= 2, p += sprx_inc) {
! 3432: if (pixdata.apixels[p])
! 3433: plane2 |= mask;
! 3434: }
! 3435: }
! 3436: }
! 3437: if (bpldualpf && m >= plfpri[1]) {
! 3438: datab &= ~plane1;
! 3439: attach_2nd &= ~plane1;
! 3440: }
! 3441: if (m >= plfpri[2]) {
! 3442: datab &= ~plane2;
! 3443: attach_2nd &= ~plane2;
! 3444: }
1.1.1.2 root 3445: }
1.1.1.3 ! root 3446: if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) {
! 3447: /* Attached sprite */
! 3448: if (bplham) {
! 3449: if (sprx_inc == 1) {
! 3450: render_sprite (spd[i].num, sprxp, datab, 1, 1, 1);
! 3451: } else {
! 3452: render_sprite (spd[i].num, sprxp, datab, 1, 1, 2);
! 3453: }
! 3454: } else {
! 3455: if (sprx_inc == 1) {
! 3456: render_sprite (spd[i].num, sprxp, datab, 0, 1, 1);
! 3457: } else {
! 3458: render_sprite (spd[i].num, sprxp, datab, 0, 1, 2);
! 3459: }
! 3460: }
! 3461: /* This still leaves one attached sprite bug, but at the moment I'm too lazy */
! 3462: if (i + 1 < nr_spr && spd[i+1].num == spd[i].num - 1 && spd[i+1].linepos == spd[i].linepos)
! 3463: i++;
! 3464: } else {
! 3465: if (bplham) {
! 3466: if (sprx_inc == 1) {
! 3467: render_sprite (spd[i].num, sprxp, datab, 1, 0, 1);
! 3468: } else {
! 3469: render_sprite (spd[i].num, sprxp, datab, 1, 0, 2);
! 3470: }
! 3471: } else {
! 3472: if (sprx_inc == 1) {
! 3473: render_sprite (spd[i].num, sprxp, datab, 0, 0, 1);
! 3474: } else {
! 3475: render_sprite (spd[i].num, sprxp, datab, 0, 0, 2);
! 3476: }
! 3477: }
1.1.1.2 root 3478: }
3479: }
3480: }
3481:
1.1.1.3 ! root 3482: #ifndef SMART_UPDATE
! 3483: #undef UNALIGNED_PROFITABLE
! 3484: #endif
! 3485:
! 3486: #ifdef UNALIGNED_PROFITABLE
! 3487:
1.1.1.2 root 3488: static void pfield_doline_unaligned_h (int lineno)
3489: {
3490: int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
1.1.1.3 ! root 3491:
1.1.1.2 root 3492: if (bplhires) {
3493: int xpos1 = xpos + 16 + bpldelay1*2;
3494: int xpos2;
1.1.1.3 ! root 3495: uae_u8 *dataptr = line_data[lineno];
! 3496: int len = dp_for_drawing->plflinelen >> 1;
! 3497:
! 3498: if (len <= 0)
! 3499: return;
! 3500:
1.1.1.2 root 3501: if (bpldelay1 == bpldelay2) {
3502: switch (bplplanecnt) {
1.1.1.3 ! root 3503: case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3504: case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3505: case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3506: case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3507: case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3508: case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3509: case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3510: case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2 root 3511: }
3512: } else {
3513: switch (bplplanecnt) {
1.1.1.3 ! root 3514: case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3515: case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3516: case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3517: case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2 root 3518: }
3519:
3520: xpos2 = xpos + 16 + bpldelay2*2;
3521: switch (bplplanecnt) {
1.1.1.3 ! root 3522: case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3523: case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3524: case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3525: case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1.1.1.2 root 3526: }
3527: }
3528: } else {
3529: int xpos1 = xpos + 32 + bpldelay1*2;
3530: int xpos2;
1.1.1.3 ! root 3531: uae_u8 *dataptr = line_data[lineno];
! 3532: int len = dp_for_drawing->plflinelen >> 2;
! 3533:
! 3534: if (len <= 0)
! 3535: return;
1.1.1.2 root 3536:
3537: if (bpldelay1 == bpldelay2) {
3538: switch (bplplanecnt) {
1.1.1.3 ! root 3539: case 1: set_lores_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3540: case 2: set_lores_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3541: case 3: set_lores_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3542: case 4: set_lores_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3543: case 5: set_lores_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3544: case 6: set_lores_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3545: case 7: set_lores_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3546: case 8: set_lores_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2 root 3547: }
3548: } else {
3549: switch (bplplanecnt) {
1.1.1.3 ! root 3550: case 1: case 2: set_lores_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3551: case 3: case 4: set_lores_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3552: case 5: case 6: set_lores_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3553: case 7: case 8: set_lores_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2 root 3554: }
1.1.1.3 ! root 3555:
1.1.1.2 root 3556: xpos2 = xpos + 32 + bpldelay2*2;
3557: switch (bplplanecnt) {
1.1.1.3 ! root 3558: case 2: case 3: set_lores_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3559: case 4: case 5: set_lores_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3560: case 6: case 7: set_lores_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3561: case 8: set_lores_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1.1.1.2 root 3562: }
3563: }
3564: }
3565: }
3566:
3567: static void pfield_doline_unaligned_l (int lineno)
3568: {
3569: int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
1.1.1.3 ! root 3570:
1.1.1.2 root 3571: if (bplhires) {
3572: int xpos1 = xpos + 8 + bpldelay1;
3573: int xpos2;
1.1.1.3 ! root 3574: uae_u8 *dataptr = line_data[lineno];
! 3575: int len = dp_for_drawing->plflinelen >> 1;
! 3576:
! 3577: if (len <= 0)
! 3578: return;
1.1.1.2 root 3579:
3580: if (bpldelay1 == bpldelay2) {
3581: switch (bplplanecnt) {
1.1.1.3 ! root 3582: case 1: set_hires_l_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3583: case 2: set_hires_l_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3584: case 3: set_hires_l_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3585: case 4: set_hires_l_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3586: case 5: set_hires_l_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3587: case 6: set_hires_l_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3588: case 7: set_hires_l_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3589: case 8: set_hires_l_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2 root 3590: }
3591: } else {
3592: switch (bplplanecnt) {
1.1.1.3 ! root 3593: case 1: case 2: set_hires_l_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3594: case 3: case 4: set_hires_l_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3595: case 5: case 6: set_hires_l_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3596: case 7: case 8: set_hires_l_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2 root 3597: }
3598:
3599: xpos2 = xpos + 8 + bpldelay2;
3600: switch (bplplanecnt) {
1.1.1.3 ! root 3601: case 2: case 3: set_hires_l_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3602: case 4: case 5: set_hires_l_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3603: case 6: case 7: set_hires_l_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3604: case 8: set_hires_l_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1.1.1.2 root 3605: }
3606: }
3607: } else {
3608: int xpos1 = xpos + 16 + bpldelay1;
3609: int xpos2;
1.1.1.3 ! root 3610: uae_u8 *dataptr = line_data[lineno];
! 3611: int len = dp_for_drawing->plflinelen >> 2;
! 3612:
! 3613: if (len <= 0)
! 3614: return;
1.1.1.2 root 3615:
3616: if (bpldelay1 == bpldelay2) {
3617: switch (bplplanecnt) {
1.1.1.3 ! root 3618: case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3619: case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3620: case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3621: case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3622: case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3623: case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3624: case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3625: case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2 root 3626: }
3627: } else {
3628: switch (bplplanecnt) {
1.1.1.3 ! root 3629: case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3630: case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3631: case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
! 3632: case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1.1.1.2 root 3633: }
1.1.1.3 ! root 3634:
1.1.1.2 root 3635: xpos2 = xpos + 16 + bpldelay2;
3636: switch (bplplanecnt) {
1.1.1.3 ! root 3637: case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3638: case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3639: case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
! 3640: case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1.1.1.2 root 3641: }
3642: }
3643: }
3644: }
3645:
3646: #define pfield_doline_h pfield_doline_unaligned_h
3647: #define pfield_doline_l pfield_doline_unaligned_l
3648:
3649: #else /* not UNALIGNED_PROFITABLE */
3650:
3651:
1.1 root 3652: static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit)
3653: {
1.1.1.3 ! root 3654: uae_u32 *pixptr = (uae_u32 *)dp;
1.1 root 3655:
3656: *pixptr |= hirestab_h[data >> 8][0] << bit;
3657: *(pixptr+1) |= hirestab_h[data >> 8][1] << bit;
3658: *(pixptr+2) |= hirestab_h[data & 255][0] << bit;
3659: *(pixptr+3) |= hirestab_h[data & 255][1] << bit;
3660: }
3661:
3662: static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit)
3663: {
1.1.1.3 ! root 3664: uae_u32 *pixptr = (uae_u32 *)dp;
! 3665:
1.1 root 3666: *pixptr |= lorestab_h[data >> 8][0] << bit;
3667: *(pixptr+1) |= lorestab_h[data >> 8][1] << bit;
3668: *(pixptr+2) |= lorestab_h[data >> 8][2] << bit;
3669: *(pixptr+3) |= lorestab_h[data >> 8][3] << bit;
3670: *(pixptr+4) |= lorestab_h[data & 255][0] << bit;
3671: *(pixptr+5) |= lorestab_h[data & 255][1] << bit;
3672: *(pixptr+6) |= lorestab_h[data & 255][2] << bit;
3673: *(pixptr+7) |= lorestab_h[data & 255][3] << bit;
3674: }
3675:
3676: static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit)
3677: {
1.1.1.3 ! root 3678: uae_u32 *pixptr = (uae_u32 *)dp;
1.1 root 3679:
3680: *pixptr = hirestab_h[data >> 8][0] << bit;
3681: *(pixptr+1) = hirestab_h[data >> 8][1] << bit;
3682: *(pixptr+2) = hirestab_h[data & 255][0] << bit;
3683: *(pixptr+3) = hirestab_h[data & 255][1] << bit;
3684: }
3685:
3686: static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit)
3687: {
1.1.1.3 ! root 3688: uae_u32 *pixptr = (uae_u32 *)dp;
! 3689:
1.1 root 3690: *pixptr = lorestab_h[data >> 8][0] << bit;
3691: *(pixptr+1) = lorestab_h[data >> 8][1] << bit;
3692: *(pixptr+2) = lorestab_h[data >> 8][2] << bit;
3693: *(pixptr+3) = lorestab_h[data >> 8][3] << bit;
3694: *(pixptr+4) = lorestab_h[data & 255][0] << bit;
3695: *(pixptr+5) = lorestab_h[data & 255][1] << bit;
3696: *(pixptr+6) = lorestab_h[data & 255][2] << bit;
3697: *(pixptr+7) = lorestab_h[data & 255][3] << bit;
3698: }
3699:
3700: static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit)
3701: {
1.1.1.3 ! root 3702: uae_u32 *pixptr = (uae_u32 *)dp;
1.1 root 3703:
3704: *pixptr |= hirestab_l[data >> 8][0] << bit;
3705: *(pixptr+1) |= hirestab_l[data & 255][0] << bit;
3706: }
3707:
3708: static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit)
3709: {
1.1.1.3 ! root 3710: uae_u32 *pixptr = (uae_u32 *)dp;
! 3711:
1.1 root 3712: *pixptr |= lorestab_l[data >> 8][0] << bit;
3713: *(pixptr+1) |= lorestab_l[data >> 8][1] << bit;
3714: *(pixptr+2) |= lorestab_l[data & 255][0] << bit;
3715: *(pixptr+3) |= lorestab_l[data & 255][1] << bit;
3716: }
3717:
3718: static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit)
3719: {
1.1.1.3 ! root 3720: uae_u32 *pixptr = (uae_u32 *)dp;
1.1 root 3721:
3722: *pixptr = hirestab_l[data >> 8][0] << bit;
3723: *(pixptr+1) = hirestab_l[data & 255][0] << bit;
3724: }
3725:
3726: static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit)
3727: {
1.1.1.3 ! root 3728: uae_u32 *pixptr = (uae_u32 *)dp;
! 3729:
1.1 root 3730: *pixptr = lorestab_l[data >> 8][0] << bit;
3731: *(pixptr+1) = lorestab_l[data >> 8][1] << bit;
3732: *(pixptr+2) = lorestab_l[data & 255][0] << bit;
3733: *(pixptr+3) = lorestab_l[data & 255][1] << bit;
3734: }
3735:
3736: #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \
3737: int i; \
3738: unsigned int bpldat1; \
1.1.1.3 ! root 3739: uae_u16 data; \
1.1 root 3740: unsigned int bpldat2 = 0; \
1.1.1.3 ! root 3741: uae_u8 *ptr = (POINTER); \
1.1.1.2 root 3742: for (i = dp_for_drawing->plflinelen; i > 0; i -= LL_SUB) { \
1.1.1.3 ! root 3743: bpldat1 = bpldat2; \
! 3744: bpldat2 = do_get_mem_word ((uae_u16 *)ptr); \
! 3745: ptr+=2; \
1.1 root 3746: data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \
3747: FUNC(data, app, MULT); \
3748: app += P_ADD; \
3749: } \
3750: data = bpldat2 << (16 - DELAY); \
3751: FUNC(data, app, MULT); \
3752: }
3753:
1.1.1.2 root 3754: #ifdef SMART_UPDATE
3755: #define DATA_POINTER(n) (dataptr + (n)*MAX_WORDS_PER_LINE*2)
3756: #else
3757: #define DATA_POINTER(n) (real_bplpt[n])
3758: #endif
1.1 root 3759:
1.1.1.2 root 3760: static void pfield_doline_aligned_h (int lineno)
3761: {
3762: int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
1.1.1.3 ! root 3763:
1.1 root 3764: if (bplhires) {
3765: if (bplplanecnt > 0) {
3766: int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0);
3767: int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0);
3768: int delay1 = 2*(bpldelay1 & 7);
3769: int delay2 = 2*(bpldelay2 & 7);
3770: unsigned char *app = pixdata.apixels + xpos1;
1.1.1.3 ! root 3771: uae_u8 *dataptr = line_data[lineno];
1.1 root 3772:
1.1.1.2 root 3773: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_h, delay1, 4, 16);
1.1 root 3774: if (bplplanecnt > 2) {
3775: app = pixdata.apixels + xpos1;
1.1.1.2 root 3776: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_h, delay1, 4, 16);
1.1 root 3777: }
3778: #if AGA_CHIPSET == 1
3779: if (bplplanecnt > 4) {
3780: app = pixdata.apixels + xpos1;
1.1.1.2 root 3781: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_h, delay1, 4, 16);
1.1 root 3782: }
3783: if (bplplanecnt > 6) {
3784: app = pixdata.apixels + xpos1;
1.1.1.2 root 3785: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_h, delay1, 4, 16);
1.1 root 3786: }
3787: #endif
3788: if (bplplanecnt > 1) {
3789: app = pixdata.apixels + xpos2;
1.1.1.2 root 3790: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_h, delay2, 4, 16);
1.1 root 3791: }
3792: if (bplplanecnt > 3) {
3793: app = pixdata.apixels + xpos2;
1.1.1.2 root 3794: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_h, delay2, 4, 16);
1.1 root 3795: }
3796: #if AGA_CHIPSET == 1
3797: if (bplplanecnt > 5) {
3798: app = pixdata.apixels + xpos2;
1.1.1.2 root 3799: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_h, delay2, 4, 16);
1.1 root 3800: }
3801: if (bplplanecnt > 7) {
3802: app = pixdata.apixels + xpos2;
1.1.1.2 root 3803: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_h, delay2, 4, 16);
1.1 root 3804: }
3805: #endif
3806: } else {
3807: memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
3808: }
3809: } else {
3810: if (bplplanecnt > 0) {
3811: int x = xpos + 32;
3812: unsigned char *app = pixdata.apixels + x;
1.1.1.3 ! root 3813: uae_u8 *dataptr = line_data[lineno];
! 3814:
1.1.1.2 root 3815: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_h, bpldelay1, 8, 32);
1.1 root 3816: if (bplplanecnt > 2) {
3817: app = pixdata.apixels + x;
1.1.1.2 root 3818: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_h, bpldelay1, 8, 32);
1.1 root 3819: }
3820: if (bplplanecnt > 4) {
3821: app = pixdata.apixels + x;
1.1.1.2 root 3822: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_h, bpldelay1, 8, 32);
1.1 root 3823: }
3824: #if AGA_CHIPSET == 1
3825: if (bplplanecnt > 6) {
3826: app = pixdata.apixels + x;
1.1.1.2 root 3827: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_h, bpldelay1, 8, 32);
1.1 root 3828: }
3829: #endif
3830: if (bplplanecnt > 1) {
3831: app = pixdata.apixels + x;
1.1.1.2 root 3832: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_h, bpldelay2, 8, 32);
1.1 root 3833: }
3834: if (bplplanecnt > 3) {
3835: app = pixdata.apixels + x;
1.1.1.2 root 3836: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_h, bpldelay2, 8, 32);
1.1 root 3837: }
3838: if (bplplanecnt > 5) {
3839: app = pixdata.apixels + x;
1.1.1.2 root 3840: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_h, bpldelay2, 8, 32);
1.1 root 3841: }
3842: #if AGA_CHIPSET == 1
3843: if (bplplanecnt > 7) {
3844: app = pixdata.apixels + x;
1.1.1.2 root 3845: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_h, bpldelay2, 8, 32);
1.1 root 3846: }
3847: #endif
3848: } else {
3849: memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
3850: }
3851: }
3852: }
1.1.1.2 root 3853:
3854: static void pfield_doline_aligned_l (int lineno)
1.1 root 3855: {
1.1.1.2 root 3856: int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
1.1.1.3 ! root 3857:
1.1 root 3858: if (bplhires) {
3859: if (bplplanecnt > 0) {
3860: int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0);
3861: int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0);
3862: int delay1 = (bpldelay1 & 7) * 2;
3863: int delay2 = (bpldelay2 & 7) * 2;
3864: unsigned char *app = pixdata.apixels + xpos1;
1.1.1.3 ! root 3865: uae_u8 *dataptr = line_data[lineno];
! 3866:
1.1.1.2 root 3867: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_l, delay1, 4, 8);
1.1 root 3868: if (bplplanecnt > 2) {
3869: app = pixdata.apixels + xpos1;
1.1.1.2 root 3870: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_l, delay1, 4, 8);
1.1 root 3871: }
3872: #if AGA_CHIPSET == 1
3873: if (bplplanecnt > 4) {
3874: app = pixdata.apixels + xpos1;
1.1.1.2 root 3875: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_l, delay1, 4, 8);
1.1 root 3876: }
3877: if (bplplanecnt > 6) {
3878: app = pixdata.apixels + xpos1;
1.1.1.2 root 3879: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_l, delay1, 4, 8);
1.1 root 3880: }
3881: #endif
3882: if (bplplanecnt > 1) {
3883: app = pixdata.apixels + xpos2;
1.1.1.2 root 3884: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_l, delay2, 4, 8);
1.1 root 3885: }
3886: if (bplplanecnt > 3) {
3887: app = pixdata.apixels + xpos2;
1.1.1.2 root 3888: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_l, delay2, 4, 8);
1.1 root 3889: }
3890: #if AGA_CHIPSET == 1
3891: if (bplplanecnt > 5) {
3892: app = pixdata.apixels + xpos2;
1.1.1.2 root 3893: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_l, delay2, 4, 8);
1.1 root 3894: }
3895: if (bplplanecnt > 7) {
3896: app = pixdata.apixels + xpos2;
1.1.1.2 root 3897: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_l, delay2, 4, 8);
1.1 root 3898: }
3899: #endif
3900: } else {
3901: memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
3902: }
3903: } else {
3904: if (bplplanecnt > 0) {
3905: int x = xpos + 16;
3906: int delay1 = bpldelay1;
3907: int delay2 = bpldelay2;
3908: unsigned char *app = pixdata.apixels + x;
1.1.1.3 ! root 3909: uae_u8 *dataptr = line_data[lineno];
! 3910:
1.1.1.2 root 3911: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_l, delay1, 8, 16);
1.1 root 3912: if (bplplanecnt > 2) {
3913: app = pixdata.apixels + x;
1.1.1.2 root 3914: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_l, delay1, 8, 16);
1.1 root 3915: }
3916: if (bplplanecnt > 4) {
3917: app = pixdata.apixels + x;
1.1.1.2 root 3918: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_l, delay1, 8, 16);
1.1 root 3919: }
3920: #if AGA_CHIPSET == 1
3921: if (bplplanecnt > 6) {
3922: app = pixdata.apixels + x;
1.1.1.2 root 3923: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_l, delay1, 8, 16);
1.1 root 3924: }
3925: #endif
3926: if (bplplanecnt > 1) {
3927: app = pixdata.apixels + x;
1.1.1.2 root 3928: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_l, delay2, 8, 16);
1.1 root 3929: }
3930: if (bplplanecnt > 3) {
3931: app = pixdata.apixels + x;
1.1.1.2 root 3932: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_l, delay2, 8, 16);
1.1 root 3933: }
3934: if (bplplanecnt > 5) {
3935: app = pixdata.apixels + x;
1.1.1.2 root 3936: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_l, delay2, 8, 16);
1.1 root 3937: }
3938: #if AGA_CHIPSET == 1
3939: if (bplplanecnt > 7) {
3940: app = pixdata.apixels + x;
1.1.1.2 root 3941: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_l, delay2, 8, 16);
1.1 root 3942: }
3943: #endif
3944: } else {
3945: memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
3946: }
3947: }
1.1.1.2 root 3948: }
1.1 root 3949:
1.1.1.2 root 3950: #define pfield_doline_h pfield_doline_aligned_h
3951: #define pfield_doline_l pfield_doline_aligned_l
1.1 root 3952:
1.1.1.2 root 3953: #endif /* UNALIGNED_PROFITABLE */
1.1 root 3954:
1.1.1.2 root 3955: static void pfield_adjust_delay (void)
3956: {
3957: int ddf_left = dp_for_drawing->plfstrt;
3958: int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen;
3959: int i;
3960:
1.1.1.3 ! root 3961: for (i = dip_for_drawing->last_delay_change-1; i >= dip_for_drawing->first_delay_change-1; i--) {
! 3962: int delayreg = i < dip_for_drawing->first_delay_change ? dp_for_drawing->bplcon1 : delay_changes[i].value;
! 3963: int delay1 = delayreg & 0xF;
! 3964: int delay2 = (delayreg >> 4) & 0xF;
! 3965: int startpos = i == dip_for_drawing->last_delay_change - 1 ? ddf_right + 8 : delay_changes[i+1].linepos;
! 3966: int stoppos = i < dip_for_drawing->first_delay_change ? ddf_left : delay_changes[i].linepos;
! 3967: int j;
! 3968: startpos = PIXEL_XPOS (startpos + (bplhires ? 4 : 8));
! 3969: stoppos = PIXEL_XPOS (stoppos + (bplhires ? 4 : 8));
! 3970: if (currprefs.gfx_lores == 0)
! 3971: delay1 <<= 1, delay2 <<= 1;
! 3972: else if (currprefs.gfx_lores == 2)
! 3973: startpos >>= 1, stoppos >>= 1;
! 3974: for (j = startpos-1; j >= stoppos; j--) {
! 3975: pixdata.apixels [j] = (pixdata.apixels[j-delay1] & 0x55) | (pixdata.apixels[j-delay2] & 0xAA);
1.1.1.2 root 3976: }
3977: }
3978: }
3979:
1.1.1.3 ! root 3980: static void init_sprites (void)
! 3981: {
! 3982: int i;
! 3983:
! 3984: for (i = 0; i < 8; i++) {
! 3985: /* ???? */
! 3986: sprst[i] = SPR_stop;
! 3987: spron[i] = 0;
! 3988: }
! 3989:
! 3990: memset(sprpos, 0, sizeof sprpos);
! 3991: memset(sprctl, 0, sizeof sprctl);
! 3992: }
! 3993:
! 3994: static void init_hardware_frame (void)
! 3995: {
! 3996: next_lineno = 0;
! 3997: nln_how = 0;
! 3998: diwstate = DIW_waiting_start;
! 3999: hdiwstate = DIW_waiting_start;
! 4000: }
! 4001:
! 4002: void init_row_map(void)
! 4003: {
! 4004: int i;
! 4005: if (gfxvidinfo.height > 2048) {
! 4006: write_log ("Resolution too high, aborting\n");
! 4007: }
! 4008: for (i = 0; i < gfxvidinfo.height + 1; i++)
! 4009: row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i;
! 4010: }
1.1.1.2 root 4011:
4012: /*
4013: * A raster line has been built in the graphics buffer. Tell the graphics code
4014: * to do anything necessary to display it.
4015: */
1.1.1.3 ! root 4016: static void do_flush_line_1 (int lineno)
1.1.1.2 root 4017: {
4018: if (lineno < first_drawn_line)
4019: first_drawn_line = lineno;
4020: if (lineno > last_drawn_line)
4021: last_drawn_line = lineno;
4022:
4023: if (gfxvidinfo.maxblocklines == 0)
4024: flush_line(lineno);
4025: else {
4026: if ((last_block_line+1) != lineno) {
4027: if (first_block_line != -2)
4028: flush_block (first_block_line, last_block_line);
4029: first_block_line = lineno;
4030: }
4031: last_block_line = lineno;
4032: if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
4033: flush_block (first_block_line, last_block_line);
4034: first_block_line = last_block_line = -2;
4035: }
4036: }
4037: }
4038:
1.1.1.3 ! root 4039: static __inline__ void do_flush_line (int lineno)
1.1.1.2 root 4040: {
4041: /* We don't want to call X libraries from the second thread right now. */
4042: #ifndef SUPPORT_PENGUINS
4043: do_flush_line_1 (lineno);
1.1 root 4044: #else
1.1.1.2 root 4045: line_drawn[lineno] = 1;
1.1 root 4046: #endif
4047: }
4048:
1.1.1.2 root 4049: /*
1.1.1.3 ! root 4050: * One drawing frame has been finished. Tell the graphics code about it.
1.1.1.2 root 4051: * Note that the actual flush_screen() call is a no-op for all reasonable
4052: * systems.
4053: */
4054:
1.1.1.3 ! root 4055: static __inline__ void do_flush_screen (int start, int stop)
1.1 root 4056: {
4057: int i;
1.1.1.2 root 4058: #ifdef SUPPORT_PENGUINS
1.1.1.3 ! root 4059: for (i = 0; i < gfxvidinfo.height; i++) {
1.1.1.2 root 4060: if (line_drawn[i])
4061: do_flush_line_1 (i);
4062: }
4063: #endif
4064: if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
4065: flush_block (first_block_line, last_block_line);
4066: }
4067: if (start <= stop)
4068: flush_screen (start, stop);
4069: }
4070:
4071: static void adjust_drawing_colors (int ctable, int bplham)
4072: {
4073: if (drawing_color_matches != ctable) {
4074: if (bplham) {
4075: memcpy (&colors_for_drawing, curr_color_tables + ctable,
4076: sizeof colors_for_drawing);
4077: color_match_type = color_match_full;
4078: } else {
4079: memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
4080: sizeof colors_for_drawing.acolors);
4081: color_match_type = color_match_acolors;
4082: }
4083: drawing_color_matches = ctable;
4084: } else if (bplham && color_match_type != color_match_full) {
4085: memcpy (colors_for_drawing.color_regs, curr_color_tables[ctable].color_regs,
4086: sizeof colors_for_drawing.color_regs);
4087: color_match_type = color_match_full;
4088: }
4089: }
4090:
4091: static __inline__ void adjust_color0_for_color_change (void)
4092: {
4093: drawing_color_matches = -1;
4094: if (dp_for_drawing->color0 != 0xFFFFFFFFul) {
4095: colors_for_drawing.color_regs[0] = dp_for_drawing->color0;
4096: colors_for_drawing.acolors[0] = xcolors[dp_for_drawing->color0];
4097: }
4098: }
4099:
4100: static __inline__ void do_color_changes (line_draw_func worker)
4101: {
4102: int lastpos = 0, nextpos, i;
4103: struct color_change *cc = curr_color_changes + dip_for_drawing->first_color_change;
1.1.1.3 ! root 4104:
1.1.1.2 root 4105: for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++, cc++) {
4106: if (i == dip_for_drawing->last_color_change)
4107: nextpos = max_diwlastword;
4108: else
4109: nextpos = PIXEL_XPOS (cc->linepos) + (COPPER_MAGIC_FUDGE << lores_shift);
4110: worker (lastpos, nextpos);
4111: if (i != dip_for_drawing->last_color_change) {
4112: colors_for_drawing.color_regs[cc->regno] = cc->value;
4113: colors_for_drawing.acolors[cc->regno] = xcolors[cc->value];
4114: }
4115: if (nextpos > lastpos) {
4116: lastpos = nextpos;
4117: if (lastpos >= linetoscr_right_x)
4118: break;
4119: }
4120: }
4121: }
4122:
1.1.1.3 ! root 4123: /* We only save hardware registers during the hardware frame. Now, when
! 4124: * drawing the frame, we expand the data into a slightly more useful
! 4125: * form. */
1.1.1.2 root 4126: static void pfield_expand_dp_bplcon (void)
4127: {
4128: bplhires = (dp_for_drawing->bplcon0 & 0x8000) == 0x8000;
4129: bplplanecnt = (dp_for_drawing->bplcon0 & 0x7000) >> 12;
4130: bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800;
4131: #if AGA_CHIPSET == 1 /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock
1.1.1.3 ! root 4132: * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */
1.1.1.2 root 4133: bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200));
4134: #else
4135: bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000;
4136: #endif
1.1.1.3 ! root 4137: bpldelay1 = dp_for_drawing->bplcon1 & 0xF;
! 4138: bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF;
1.1.1.2 root 4139: plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7);
4140: plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7);
4141: bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
4142: bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
4143: }
4144:
4145: static __inline__ void pfield_draw_line(int lineno, int gfx_ypos, int follow_ypos)
4146: {
4147: int border = 0;
4148: int to_screen = 0;
4149: int do_double = 0;
1.1.1.3 ! root 4150:
1.1.1.2 root 4151: dp_for_drawing = 0;
4152: dip_for_drawing = 0;
4153: switch (linestate[lineno]) {
4154: case LINE_AS_PREVIOUS:
4155: case LINE_REMEMBERED_AS_PREVIOUS:
4156: {
4157: static int warned = 0;
4158: if (!warned)
1.1.1.3 ! root 4159: write_log ("Shouldn't get here... this is a bug.\n"), warned++;
1.1.1.2 root 4160: }
4161: line_decisions[lineno].which = -2;
4162: return;
4163:
4164: case LINE_BORDER_PREV:
4165: border = 1;
4166: dp_for_drawing = line_decisions + lineno - 1;
4167: dip_for_drawing = curr_drawinfo + lineno - 1;
4168: break;
4169:
4170: case LINE_BORDER_NEXT:
4171: border = 1;
4172: dp_for_drawing = line_decisions + lineno + 1;
4173: dip_for_drawing = curr_drawinfo + lineno + 1;
4174: break;
4175:
4176: case LINE_DONE_AS_PREVIOUS:
4177: line_decisions[lineno].which = -2;
4178: /* fall through */
4179: case LINE_DONE:
4180: return;
4181:
4182: case LINE_DECIDED_DOUBLE:
4183: line_decisions[lineno+1].which = -2;
4184: if (follow_ypos != -1) {
4185: do_double = 1;
4186: linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos);
4187: }
1.1.1.3 ! root 4188:
1.1.1.2 root 4189: /* fall through */
4190: default:
4191: dip_for_drawing = curr_drawinfo + lineno;
4192: dp_for_drawing = line_decisions + lineno;
4193: if (dp_for_drawing->which != 1)
4194: border = 1;
4195: break;
4196: }
1.1.1.3 ! root 4197:
1.1.1.2 root 4198: if (!line_changed[lineno] && !frame_redraw_necessary) {
1.1.1.3 ! root 4199: /* The case where we can skip redrawing this line. If this line
1.1.1.2 root 4200: * is supposed to be doubled, and the next line is remembered as
4201: * having been doubled, then the next line is done as well. */
4202: if (do_double) {
4203: if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS) {
1.1.1.3 ! root 4204: if (gfxvidinfo.linemem == NULL)
! 4205: memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
1.1.1.2 root 4206: line_decisions[lineno + 1].which = -2;
4207: do_flush_line (follow_ypos);
4208: }
4209: linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
4210: }
4211: linestate[lineno] = LINE_DONE;
4212: return;
4213: }
4214:
4215: if (!border) {
1.1.1.3 ! root 4216: xlinebuffer = gfxvidinfo.linemem;
! 4217: if (xlinebuffer == NULL)
! 4218: xlinebuffer = row_map[gfx_ypos];
! 4219: xlinebuffer -= linetoscr_x_adjust_bytes;
1.1.1.2 root 4220: aga_lbufptr = aga_linebuf;
1.1.1.3 ! root 4221:
1.1.1.2 root 4222: pfield_expand_dp_bplcon ();
4223:
4224: #ifdef LORES_HACK
1.1.1.3 ! root 4225: if (gfxvidinfo.can_double && !bplhires && !currprefs.gfx_lores
! 4226: && dip_for_drawing->nr_color_changes == 0 && !bplham)
! 4227: currprefs.gfx_lores = 2;
1.1.1.2 root 4228: #endif
4229: pfield_init_linetoscr ();
4230: if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) {
4231: bpldelay1 = bpldelay2 = 0;
1.1.1.3 ! root 4232: if (currprefs.gfx_lores)
1.1.1.2 root 4233: pfield_doline_l (lineno);
4234: else
4235: pfield_doline_h (lineno);
4236: pfield_adjust_delay ();
4237: } else {
1.1.1.3 ! root 4238: if (currprefs.gfx_lores)
1.1.1.2 root 4239: pfield_doline_l (lineno);
4240: else
4241: pfield_doline_h (lineno);
4242: }
1.1.1.3 ! root 4243:
1.1.1.2 root 4244: /* Check color0 adjust only if we have color changes - shouldn't happen
4245: * otherwise. */
4246: adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
4247:
4248: /* The problem is that we must call decode_ham6() BEFORE we do the
4249: * sprites. */
4250: if (bplham) {
1.1.1.3 ! root 4251: init_ham_decoding(linetoscr_x_adjust);
1.1.1.2 root 4252: if (dip_for_drawing->nr_color_changes == 0) {
4253: /* The easy case: need to do HAM decoding only once for the
4254: * full line. */
4255: decode_ham6 (linetoscr_x_adjust, linetoscr_right_x);
1.1.1.3 ! root 4256: } else /* Argh. */ {
1.1.1.2 root 4257: adjust_color0_for_color_change ();
4258: do_color_changes (decode_ham6);
4259: adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
4260: }
4261: }
4262:
4263: if (dip_for_drawing->nr_sprites != 0) {
4264: int spr;
1.1.1.3 ! root 4265: walk_sprites (curr_sprite_positions + dip_for_drawing->first_sprite_draw, dip_for_drawing->nr_sprites);
1.1.1.2 root 4266: }
4267: if (dip_for_drawing->nr_color_changes == 0) {
1.1.1.3 ! root 4268: pfield_do_linetoscr_full (gfxvidinfo.linemem == NULL ? do_double : 0);
1.1.1.2 root 4269: do_flush_line (gfx_ypos);
4270: linestate[lineno] = LINE_DONE;
4271:
4272: if (do_double) {
4273: linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
4274: do_flush_line (follow_ypos);
4275: }
4276: } else {
4277: int lastpos = 0, nextpos, i;
4278:
4279: adjust_color0_for_color_change ();
4280: do_color_changes (pfield_do_linetoscr);
4281:
4282: linestate[lineno] = LINE_DONE;
4283: do_flush_line (gfx_ypos);
4284: if (do_double) {
1.1.1.3 ! root 4285: if (gfxvidinfo.linemem == NULL)
! 4286: memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
1.1.1.2 root 4287: linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
4288: line_decisions[lineno + 1].which = -2;
4289: do_flush_line (follow_ypos);
4290: }
4291: }
4292: #ifdef LORES_HACK
1.1.1.3 ! root 4293: if (currprefs.gfx_lores == 2)
! 4294: currprefs.gfx_lores = 0;
1.1.1.2 root 4295: #endif
4296: } else {
4297: /* Border. */
4298: int i, lastpos = 0, nextpos;
4299: struct color_change *cc;
1.1 root 4300:
1.1.1.3 ! root 4301: xlinebuffer = gfxvidinfo.linemem;
! 4302: if (xlinebuffer == NULL)
! 4303: xlinebuffer = row_map[gfx_ypos];
! 4304: xlinebuffer -= linetoscr_x_adjust_bytes;
! 4305:
1.1.1.2 root 4306: adjust_drawing_colors (dp_for_drawing->ctable, 0);
4307: /* Check color0 adjust only if we have color changes - shouldn't happen
4308: * otherwise. */
4309:
4310: if (dip_for_drawing->nr_color_changes == 0) {
4311: fill_line ();
4312: do_flush_line (gfx_ypos);
4313: linestate[lineno] = LINE_DONE;
4314: if (do_double) {
1.1.1.3 ! root 4315: if (gfxvidinfo.linemem == NULL) {
! 4316: xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
! 4317: fill_line ();
! 4318: }
1.1.1.2 root 4319: do_flush_line (follow_ypos);
4320: linestate[lineno+1] = LINE_DONE_AS_PREVIOUS;
4321: }
1.1 root 4322: return;
1.1.1.2 root 4323: }
4324:
4325: adjust_color0_for_color_change ();
4326: do_color_changes (pfield_do_fill_line);
1.1.1.3 ! root 4327:
1.1.1.2 root 4328: do_flush_line (gfx_ypos);
4329: linestate[lineno] = LINE_DONE;
4330: if (do_double) {
1.1.1.3 ! root 4331: if (gfxvidinfo.linemem == NULL)
! 4332: memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
1.1.1.2 root 4333: linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
4334: line_decisions[lineno + 1].which = -2;
4335: do_flush_line (follow_ypos);
4336: }
1.1 root 4337: }
4338: }
4339:
1.1.1.2 root 4340: #ifdef SUPPORT_PENGUINS
1.1.1.3 ! root 4341: static smp_comm_pipe drawing_pipe;
! 4342: static uae_sem_t drawing_lock;
! 4343:
! 4344: static void *drawing_penguin (void *cruxmedo)
1.1.1.2 root 4345: {
4346: int l;
1.1.1.3 ! root 4347: fprintf(stderr, "Hello, world!\n");
1.1.1.2 root 4348:
4349: for (;;) {
4350: /* Start of a frame. */
1.1.1.3 ! root 4351: int k;
! 4352: new_frame:
! 4353: k = read_comm_pipe_int_blocking (&drawing_pipe);
! 4354:
! 4355: switch (k) {
! 4356: case -2:
! 4357: /* Hoopy */
! 4358: break;
! 4359:
! 4360: default:
! 4361: write_log ("Penguin got out of sync.\n");
! 4362: /* what can we do? Try to reduce the damage */
! 4363: for (;;) {
! 4364: k = read_comm_pipe_int_blocking (&drawing_pipe);
! 4365: if (k == -3)
! 4366: break;
! 4367: if (k == -1) {
! 4368: uae_sem_post (&drawing_lock);
! 4369: goto new_frame;
! 4370: }
! 4371: }
! 4372: case -3:
! 4373: UAE_PENGUIN_EXIT;
! 4374: /* Can't happen */
! 4375: return 0;
1.1.1.2 root 4376: }
4377:
4378: for (;;) {
4379: int i, where;
4380: int l = read_comm_pipe_int_blocking (&drawing_pipe);
1.1.1.3 ! root 4381: switch (l) {
! 4382: case -1:
1.1.1.2 root 4383: /* End-of-frame synchronization. */
1.1.1.3 ! root 4384: uae_sem_post (&drawing_lock);
! 4385: goto new_frame;
! 4386: case -2:
! 4387: /* customreset called a bit too often. That's harmless. */
! 4388: continue;
! 4389: case -3:
! 4390: write_log ("Penguin got out of sync.\n");
! 4391: UAE_PENGUIN_EXIT;
! 4392: return 0;
1.1.1.2 root 4393: }
1.1.1.3 ! root 4394:
1.1.1.2 root 4395: /* l is the line that has been finished for drawing. */
4396: i = l - thisframe_y_adjust_real;
4397: if (i < 0 || i >= max_ypos_thisframe)
4398: continue;
1.1 root 4399:
1.1.1.2 root 4400: if (linestate[l] == LINE_UNDECIDED) {
4401: fprintf (stderr, "Line scheduled for drawing, but undecided %d!?\n", l);
4402: continue;
4403: }
1.1.1.3 ! root 4404: if (inhibit_frame != 0)
! 4405: continue;
1.1.1.2 root 4406: where = amiga2aspect_line_map[i+min_ypos_for_screen];
1.1.1.3 ! root 4407: if (where >= gfxvidinfo.height || where == -1)
1.1.1.2 root 4408: continue;
1.1 root 4409:
1.1.1.2 root 4410: pfield_draw_line (l, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
1.1 root 4411: }
4412: }
4413: }
4414:
1.1.1.2 root 4415: static penguin_id our_penguin;
1.1 root 4416:
1.1.1.2 root 4417: static void kill_drawing_penguin (void)
1.1 root 4418: {
1.1.1.3 ! root 4419: /* ??? does libpthread do that for us? */
1.1.1.2 root 4420: }
4421:
4422: #endif
4423:
4424: static int penguins_enabled_thisframe;
4425:
1.1.1.3 ! root 4426: static void adjust_array_sizes (void)
1.1.1.2 root 4427: {
4428: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1.1.1.3 ! root 4429: if (delta_sprite_draw) {
! 4430: void *p1,*p2;
! 4431: int mcc = max_sprite_draw + 200 + delta_sprite_draw;
! 4432: delta_sprite_draw = 0;
! 4433: p1 = realloc (sprite_positions[0], mcc * sizeof (struct sprite_draw));
! 4434: p2 = realloc (sprite_positions[1], mcc * sizeof (struct sprite_draw));
! 4435: if (p1) sprite_positions[0] = p1;
! 4436: if (p2) sprite_positions[1] = p2;
! 4437: if (p1 && p2) {
! 4438: fprintf (stderr, "new max_sprite_draw=%d\n",mcc);
1.1.1.2 root 4439: max_sprite_draw = mcc;
4440: }
4441: }
1.1.1.3 ! root 4442: if (delta_color_change) {
! 4443: void *p1,*p2;
! 4444: int mcc = max_color_change + 200 + delta_color_change;
! 4445: delta_color_change = 0;
! 4446: p1 = realloc (color_changes[0], mcc * sizeof (struct color_change));
! 4447: p2 = realloc (color_changes[1], mcc * sizeof (struct color_change));
! 4448: if (p1) color_changes[0] = p1;
! 4449: if (p2) color_changes[1] = p2;
! 4450: if (p1 && p2) {
! 4451: fprintf (stderr, "new max_color_change=%d\n",mcc);
1.1.1.2 root 4452: max_color_change = mcc;
1.1.1.3 ! root 4453: }
! 4454: }
! 4455: if (delta_delay_change) {
! 4456: void *p;
! 4457: int mcc = max_delay_change + 200 + delta_delay_change;
! 4458: delta_delay_change = 0;
! 4459: p = realloc (delay_changes, mcc * sizeof (struct delay_change));
! 4460: if (p) {
! 4461: fprintf (stderr, "new max_delay_change=%d\n",mcc);
! 4462: delay_changes = p;
! 4463: max_delay_change = mcc;
! 4464: }
1.1.1.2 root 4465: }
4466: #endif
1.1.1.3 ! root 4467: }
! 4468:
! 4469: static void init_drawing_frame (void)
! 4470: {
! 4471: int i, maxline;
1.1.1.2 root 4472:
1.1.1.3 ! root 4473: adjust_array_sizes ();
! 4474:
! 4475: check_prefs_changed_custom ();
! 4476: check_prefs_changed_cpu ();
! 4477:
1.1 root 4478: if (max_diwstop == 0)
4479: max_diwstop = diwlastword;
1.1.1.2 root 4480: if (min_diwstart > max_diwstop)
4481: min_diwstart = 0;
1.1 root 4482:
1.1.1.2 root 4483: if (thisframe_first_drawn_line == -1)
4484: thisframe_first_drawn_line = minfirstline;
4485: if (thisframe_first_drawn_line > thisframe_last_drawn_line)
4486: thisframe_last_drawn_line = thisframe_first_drawn_line;
4487:
4488: next_color_change = 0;
4489: next_delay_change = 0;
4490: next_sprite_draw = 0;
1.1.1.3 ! root 4491: maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1;
1.1.1.2 root 4492: #ifdef SMART_UPDATE
4493: for (i = 0; i < maxline; i++)
4494: linestate[i] = linestate[i] == LINE_DONE_AS_PREVIOUS ? LINE_REMEMBERED_AS_PREVIOUS : LINE_UNDECIDED;
4495: #else
4496: memset (linestate, LINE_UNDECIDED, maxline);
4497: #endif
1.1 root 4498: last_drawn_line = 0;
4499: first_drawn_line = 32767;
4500:
4501: first_block_line = last_block_line = -2;
1.1.1.3 ! root 4502: if (currprefs.test_drawing_speed)
1.1.1.2 root 4503: frame_redraw_necessary = 1;
4504: else if (frame_redraw_necessary)
1.1 root 4505: frame_redraw_necessary--;
1.1.1.3 ! root 4506:
1.1.1.2 root 4507: next_color_entry = 0;
4508: remembered_color_entry = -1;
4509: prev_sprite_positions = sprite_positions[current_change_set];
4510: curr_sprite_positions = sprite_positions[current_change_set ^ 1];
4511: prev_color_changes = color_changes[current_change_set];
4512: curr_color_changes = color_changes[current_change_set ^ 1];
4513: prev_color_tables = color_tables[current_change_set];
4514: curr_color_tables = color_tables[current_change_set ^ 1];
1.1.1.3 ! root 4515:
1.1.1.2 root 4516: prev_drawinfo = line_drawinfo[current_change_set];
4517: curr_drawinfo = line_drawinfo[current_change_set ^= 1];
4518: drawing_color_matches = -1;
4519: color_src_match = color_dest_match = -1;
4520:
4521: prev_x_adjust = linetoscr_x_adjust;
4522: prev_y_adjust = thisframe_y_adjust;
4523:
1.1.1.3 ! root 4524: if (currprefs.gfx_xcenter) {
! 4525: if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2)
1.1.1.2 root 4526: /* Try to center. */
1.1.1.3 ! root 4527: linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1;
1.1.1.2 root 4528: else
1.1.1.3 ! root 4529: linetoscr_x_adjust = max_diwstop - gfxvidinfo.width;
1.1.1.2 root 4530:
1.1.1.3 ! root 4531: /* Would the old value be good enough? If so, leave it as it is if we want to
! 4532: * be clever. */
! 4533: if (currprefs.gfx_xcenter == 2) {
1.1.1.2 root 4534: if (linetoscr_x_adjust < prev_x_adjust && prev_x_adjust < min_diwstart)
4535: linetoscr_x_adjust = prev_x_adjust;
1.1 root 4536: }
1.1.1.2 root 4537: } else
1.1.1.3 ! root 4538: linetoscr_x_adjust = max_diwlastword - gfxvidinfo.width;
1.1.1.2 root 4539: if (linetoscr_x_adjust < 0)
4540: linetoscr_x_adjust = 0;
1.1.1.3 ! root 4541:
! 4542: linetoscr_x_adjust_bytes = linetoscr_x_adjust * gfxvidinfo.pixbytes;
! 4543:
! 4544: linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.width;
1.1.1.2 root 4545: if (linetoscr_right_x > max_diwlastword)
4546: linetoscr_right_x = max_diwlastword;
1.1.1.3 ! root 4547:
1.1.1.2 root 4548: thisframe_y_adjust = minfirstline;
1.1.1.3 ! root 4549: if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) {
! 4550: if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2)
1.1.1.2 root 4551: thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
4552: else
4553: thisframe_y_adjust = thisframe_first_drawn_line;
1.1.1.3 ! root 4554: /* Would the old value be good enough? If so, leave it as it is if we want to
! 4555: * be clever. */
! 4556: if (currprefs.gfx_ycenter == 2) {
1.1.1.2 root 4557: if (thisframe_y_adjust != prev_y_adjust
4558: && prev_y_adjust <= thisframe_first_drawn_line
4559: && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)
4560: thisframe_y_adjust = prev_y_adjust;
4561: }
1.1.1.3 ! root 4562: /* Make sure the value makes sense */
1.1.1.2 root 4563: if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos)
4564: thisframe_y_adjust = maxvpos - max_drawn_amiga_line;
4565: if (thisframe_y_adjust < minfirstline)
4566: thisframe_y_adjust = minfirstline;
1.1 root 4567: }
1.1.1.3 ! root 4568: thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0);
! 4569: max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0);
1.1 root 4570:
1.1.1.2 root 4571: if (prev_x_adjust != linetoscr_x_adjust || prev_y_adjust != thisframe_y_adjust)
1.1.1.3 ! root 4572: frame_redraw_necessary |= (bplcon0 & 4) && currprefs.gfx_linedbl ? 2 : 1;
1.1 root 4573:
1.1.1.2 root 4574: max_diwstop = 0;
4575: min_diwstart = 10000;
4576: thisframe_first_drawn_line = -1;
4577: thisframe_last_drawn_line = -1;
4578: #ifdef SUPPORT_PENGUINS
4579: penguins_enabled_thisframe = 1;
4580: /* Tell the other thread that it can now expect data from us. */
1.1.1.3 ! root 4581: write_comm_pipe_int (&drawing_pipe, -2, 1);
1.1.1.2 root 4582: memset (line_drawn, 0, sizeof line_drawn);
4583: #endif
1.1 root 4584: }
4585:
1.1.1.2 root 4586: static void finish_drawing_frame (void)
1.1 root 4587: {
1.1.1.2 root 4588: int i;
1.1 root 4589:
1.1.1.2 root 4590: #ifdef SUPPORT_PENGUINS
4591: /* Synchronize with other thread, then see whether there's something left for
4592: * us to draw. @@@ This is probably a big waste of cycles if the two threads
1.1.1.3 ! root 4593: * run at very different speeds - this one could draw stuff as well. */
! 4594: write_comm_pipe_int (&drawing_pipe, -1, 1);
! 4595: uae_sem_wait (&drawing_lock);
! 4596: #else
1.1 root 4597:
1.1.1.2 root 4598: #ifndef SMART_UPDATE
4599: /* @@@ This isn't exactly right yet. FIXME */
4600: if (!interlace_seen) {
4601: do_flush_screen (first_drawn_line, last_drawn_line);
4602: return;
1.1 root 4603: }
1.1.1.2 root 4604: #endif
4605: for (i = 0; i < max_ypos_thisframe; i++) {
4606: int where;
4607: int line = i + thisframe_y_adjust_real;
4608:
4609: if (linestate[line] == LINE_UNDECIDED)
4610: break;
4611:
4612: where = amiga2aspect_line_map[i+min_ypos_for_screen];
1.1.1.3 ! root 4613: if (where >= gfxvidinfo.height)
1.1.1.2 root 4614: break;
4615: if (where == -1)
4616: continue;
1.1 root 4617:
1.1.1.2 root 4618: pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
1.1 root 4619: }
1.1.1.3 ! root 4620: #endif
1.1.1.2 root 4621: do_flush_screen (first_drawn_line, last_drawn_line);
1.1 root 4622: }
4623:
1.1.1.3 ! root 4624: static __inline__ void check_picasso (void)
! 4625: {
! 4626: #ifdef PICASSO96
! 4627: if (picasso_requested_on == picasso_on)
! 4628: return;
! 4629:
! 4630: picasso_on = picasso_requested_on;
! 4631:
! 4632: if (!picasso_on)
! 4633: clear_inhibit_frame (2);
! 4634: else
! 4635: set_inhibit_frame (2);
! 4636:
! 4637: gfx_set_picasso_state (picasso_on);
! 4638: picasso_enablescreen (picasso_requested_on);
! 4639:
! 4640: notice_screen_contents_lost ();
! 4641: #endif
! 4642: }
! 4643:
1.1.1.2 root 4644: static void vsync_handler (void)
1.1 root 4645: {
1.1.1.3 ! root 4646: #ifdef FRAME_RATE_HACK /* put this here or at the end of the function? */
! 4647: {
! 4648: frame_time_t curr_time = read_processor_time();
! 4649: vsyncmintime += vsynctime;
! 4650: /* @@@ Mathias? How do you think we should do this? */
! 4651: /* If we are too far behind, or we just did a reset, adjust the
! 4652: * needed time. */
! 4653: if ((long int)(curr_time - vsyncmintime) > 0 || did_reset)
! 4654: vsyncmintime = curr_time + vsynctime;
! 4655: did_reset = 0;
! 4656: }
! 4657: #endif
! 4658: handle_events ();
1.1 root 4659:
1.1.1.3 ! root 4660: getjoystate (0, &joy0dir, &joy0button);
! 4661: getjoystate (1, &joy1dir, &joy1button);
1.1 root 4662:
4663: INTREQ(0x8020);
1.1.1.3 ! root 4664: if (bplcon0 & 4)
1.1.1.2 root 4665: lof ^= 0x8000;
1.1.1.3 ! root 4666:
! 4667: if (quit_program < 0) {
! 4668: quit_program = -quit_program;
! 4669: set_inhibit_frame (1);
! 4670: regs.spcflags |= SPCFLAG_BRK;
! 4671: if (framecnt == 0)
! 4672: finish_drawing_frame ();
! 4673: filesys_prepare_reset ();
! 4674: #ifdef SUPPORT_PENGUINS
! 4675: if (quit_program == 1)
! 4676: /* Stop eating herring */
! 4677: write_comm_pipe_int (&drawing_pipe, -3, 1);
! 4678: #endif
! 4679: return;
! 4680: }
! 4681:
1.1.1.2 root 4682: last_redraw_point++;
4683: if (lof_changed || !interlace_seen || last_redraw_point >= 2 || lof) {
1.1.1.3 ! root 4684: static int cnt = 0;
! 4685:
1.1.1.2 root 4686: if (framecnt == 0)
4687: finish_drawing_frame ();
4688: count_frame ();
4689: last_redraw_point = 0;
1.1.1.3 ! root 4690:
! 4691: check_picasso ();
! 4692:
! 4693: uae_sem_wait (&ihf_sem);
! 4694: if (inhibit_frame != 0)
! 4695: framecnt = 1;
! 4696: if (frame_do_semup)
! 4697: uae_sem_post (&frame_sem);
! 4698: frame_do_semup = 0;
! 4699: uae_sem_post (&ihf_sem);
! 4700:
! 4701: if (cnt == 0) {
! 4702: /* resolution_check_change (); */
! 4703: DISK_check_change ();
! 4704: cnt = 5;
! 4705: }
! 4706: cnt--;
1.1.1.2 root 4707: if (framecnt == 0)
4708: init_drawing_frame ();
4709: }
1.1.1.3 ! root 4710:
1.1.1.2 root 4711: lof_changed = 0;
4712: interlace_seen = 0;
1.1 root 4713: COPJMP1(0);
1.1.1.3 ! root 4714:
1.1.1.2 root 4715: init_hardware_frame();
1.1 root 4716: #ifdef HAVE_GETTIMEOFDAY
4717: {
4718: struct timeval tv;
4719: unsigned long int newtime;
1.1.1.3 ! root 4720:
! 4721: gettimeofday(&tv,NULL);
1.1 root 4722: newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
1.1.1.3 ! root 4723:
! 4724: if (!bogusframe) {
1.1 root 4725: frametime += newtime - msecs;
4726: timeframes++;
4727: }
4728: msecs = newtime;
4729: bogusframe = 0;
4730: }
4731: #endif
1.1.1.3 ! root 4732: if (ievent_alive > 0)
! 4733: ievent_alive--;
1.1 root 4734: CIA_vsync_handler();
4735: }
4736:
4737: static void hsync_handler(void)
4738: {
1.1.1.2 root 4739: int lineno = next_lineno;
1.1 root 4740: int lineisdouble = 0;
4741: int line_was_doubled = 0;
1.1.1.3 ! root 4742:
1.1.1.2 root 4743: finish_decisions ();
4744: do_modulos ();
4745:
4746: if (framecnt == 0) {
4747: switch (nln_how) {
4748: case 0:
4749: linestate[lineno] = LINE_DECIDED;
4750: break;
4751: case 1:
4752: linestate[lineno] = LINE_DECIDED_DOUBLE;
4753: if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS)
4754: linestate[lineno+1] = LINE_AS_PREVIOUS;
4755: break;
4756: case 2:
4757: if (linestate[lineno-1] == LINE_UNDECIDED)
4758: linestate[lineno-1] = LINE_BORDER_NEXT;
4759: linestate[lineno] = LINE_DECIDED;
4760: break;
4761: case 3:
4762: linestate[lineno] = LINE_DECIDED;
4763: if (linestate[lineno+1] == LINE_UNDECIDED
4764: || linestate[lineno+1] == LINE_REMEMBERED_AS_PREVIOUS
4765: || linestate[lineno+1] == LINE_AS_PREVIOUS)
4766: linestate[lineno+1] = LINE_BORDER_PREV;
4767: break;
1.1 root 4768: }
4769: }
4770:
4771: eventtab[ev_hsync].evtime += cycles - eventtab[ev_hsync].oldcycles;
4772: eventtab[ev_hsync].oldcycles = cycles;
4773: CIA_hsync_handler();
1.1.1.3 ! root 4774:
! 4775: if (currprefs.produce_sound > 0) {
1.1 root 4776: int nr;
4777: /* Sound data is fetched at the beginning of each line */
4778: for (nr = 0; nr < 4; nr++) {
4779: struct audio_channel_data *cdp = audio_channel + nr;
1.1.1.3 ! root 4780:
1.1 root 4781: if (cdp->data_written == 2) {
4782: cdp->data_written = 0;
4783: cdp->nextdat = chipmem_bank.wget(cdp->pt);
4784: cdp->pt += 2;
4785: if (cdp->state == 2 || cdp->state == 3) {
4786: if (cdp->wlen == 1) {
4787: cdp->pt = cdp->lc;
4788: cdp->wlen = cdp->len;
4789: cdp->intreq2 = 1;
4790: } else
4791: cdp->wlen--;
4792: }
4793: }
4794: }
4795: }
1.1.1.2 root 4796: #ifdef SUPPORT_PENGUINS
4797: if (framecnt == 0 && penguins_enabled_thisframe) {
1.1.1.3 ! root 4798: write_comm_pipe_int (&drawing_pipe, next_lineno, 0);
1.1.1.2 root 4799: }
1.1 root 4800: #endif
1.1.1.2 root 4801: #ifndef SMART_UPDATE
4802: {
4803: int i, where;
4804: /* l is the line that has been finished for drawing. */
4805: i = next_lineno - thisframe_y_adjust_real;
4806: if (i >= 0 && i < max_ypos_thisframe) {
4807: where = amiga2aspect_line_map[i+min_ypos_for_screen];
1.1.1.3 ! root 4808: if (where < gfxvidinfo.height && where != -1)
1.1.1.2 root 4809: pfield_draw_line (next_lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
1.1 root 4810: }
4811: }
1.1.1.2 root 4812: #endif
1.1 root 4813: if (++vpos == (maxvpos + (lof != 0))) {
4814: vpos = 0;
4815: vsync_handler();
4816: }
1.1.1.2 root 4817:
1.1.1.3 ! root 4818: is_lastline = vpos + 1 == maxvpos + (lof != 0);
! 4819:
! 4820: if ((bplcon0 & 4) && currprefs.gfx_linedbl) {
1.1.1.2 root 4821: interlace_seen = 1, penguins_enabled_thisframe = 0;
4822: }
4823:
4824: if (framecnt == 0) {
4825: lineno = vpos;
4826: nln_how = 0;
1.1.1.3 ! root 4827: if (currprefs.gfx_linedbl) {
1.1 root 4828: lineno *= 2;
1.1.1.2 root 4829: nln_how = 1;
4830: if (bplcon0 & 4) {
4831: if (!lof) {
4832: lineno++;
4833: nln_how = 2;
4834: } else {
4835: nln_how = 3;
4836: }
1.1 root 4837: }
4838: }
4839: next_lineno = lineno;
1.1.1.2 root 4840: reset_decisions ();
1.1 root 4841: }
1.1.1.3 ! root 4842: if (uae_int_requested) {
! 4843: set_uae_int_flag ();
! 4844: INTREQ (0xA000);
! 4845: }
! 4846: }
! 4847:
! 4848: static void init_eventtab (void)
! 4849: {
! 4850: int i;
! 4851:
! 4852: for(i = 0; i < ev_max; i++) {
! 4853: eventtab[i].active = 0;
! 4854: eventtab[i].oldcycles = 0;
! 4855: }
! 4856: copper_active = 0;
! 4857: eventtab[ev_cia].handler = CIA_handler;
! 4858: eventtab[ev_copper].handler = /* currprefs.copper_pos >= 0 ? do_copper_cheat : */ do_copper;
! 4859: eventtab[ev_hsync].handler = hsync_handler;
! 4860: eventtab[ev_hsync].evtime = maxhpos + cycles;
! 4861: eventtab[ev_hsync].active = 1;
! 4862:
! 4863: eventtab[ev_blitter].handler = blitter_handler;
! 4864: eventtab[ev_blitter].active = 0;
! 4865: eventtab[ev_diskblk].handler = diskblk_handler;
! 4866: eventtab[ev_diskblk].active = 0;
! 4867: eventtab[ev_diskindex].handler = diskindex_handler;
! 4868: eventtab[ev_diskindex].active = 0;
! 4869: #ifndef DONT_WANT_SOUND
! 4870: eventtab[ev_aud0].handler = aud0_handler;
! 4871: eventtab[ev_aud0].active = 0;
! 4872: eventtab[ev_aud1].handler = aud1_handler;
! 4873: eventtab[ev_aud1].active = 0;
! 4874: eventtab[ev_aud2].handler = aud2_handler;
! 4875: eventtab[ev_aud2].active = 0;
! 4876: eventtab[ev_aud3].handler = aud3_handler;
! 4877: eventtab[ev_aud3].active = 0;
! 4878: if (sound_available && currprefs.produce_sound >= 2) {
! 4879: eventtab[ev_sample].active = 1;
! 4880: eventtab[ev_sample].evtime = sample_evtime;
! 4881: } else {
! 4882: eventtab[ev_sample].active = 0;
! 4883: }
! 4884: #endif
! 4885: events_schedule ();
1.1 root 4886: }
4887:
1.1.1.3 ! root 4888: void customreset (void)
1.1 root 4889: {
1.1.1.2 root 4890: int i, maxl;
4891: double native_lines_per_amiga_line;
1.1 root 4892: #ifdef HAVE_GETTIMEOFDAY
4893: struct timeval tv;
4894: #endif
1.1.1.2 root 4895:
1.1.1.3 ! root 4896: for (i = 0; i < sizeof current_colors.color_regs / sizeof *current_colors.color_regs; i++)
! 4897: current_colors.color_regs[i] = -1;
! 4898:
! 4899: #ifdef FRAME_RATE_HACK
! 4900: did_reset = 1;
! 4901: vsyncmintime = read_processor_time() + vsynctime;
! 4902: #endif
1.1 root 4903: inhibit_frame = 0;
1.1.1.3 ! root 4904: frame_do_semup = 0;
! 4905: uae_sem_init (&frame_sem, 0, 0);
! 4906: uae_sem_init (&gui_sem, 0, 1);
! 4907: uae_sem_init (&ihf_sem, 0, 1);
! 4908: expamem_reset ();
! 4909: filesys_reset ();
! 4910: CIA_reset ();
! 4911: #ifdef PICASSO96
! 4912: InitPicasso96 ();
! 4913: picasso_on = 0;
! 4914: picasso_requested_on = 0;
! 4915: gfx_set_picasso_state (0);
! 4916: #endif
! 4917: cycles = 0;
1.1 root 4918: regs.spcflags &= SPCFLAG_BRK;
1.1.1.3 ! root 4919:
! 4920: lores_factor = currprefs.gfx_lores ? 1 : 2;
! 4921: lores_shift = currprefs.gfx_lores ? 0 : 1;
! 4922: sprite_width = currprefs.gfx_lores ? 16 : 32;
! 4923:
1.1.1.2 root 4924: vpos = 0;
1.1.1.3 ! root 4925: is_lastline = 0;
1.1 root 4926: lof = 0;
4927: max_diwstop = 0;
1.1.1.3 ! root 4928:
1.1 root 4929: if (needmousehack()) {
1.1.1.3 ! root 4930: #if 0
! 4931: if (mousestate != follow_mouse) setfollow();
! 4932: #else
! 4933: if (mousestate != dont_care_mouse) setdontcare();
! 4934: #endif
1.1 root 4935: } else {
4936: mousestate = normal_mouse;
4937: }
1.1.1.3 ! root 4938: ievent_alive = 0;
! 4939:
! 4940: clx_sprmask = 0xFF;
! 4941: clxdat = 0;
! 4942:
! 4943: memset(sprarmed, 0, sizeof sprarmed);
! 4944: nr_armed = 0;
1.1 root 4945:
4946: /*memset(blitcount, 0, sizeof(blitcount)); blitter debug */
1.1.1.2 root 4947: for (i = 0; i < (maxvpos+1)*2 + 1; i++) {
4948: linestate[i] = LINE_UNDECIDED;
1.1 root 4949: }
4950: xlinebuffer = gfxvidinfo.bufmem;
4951:
4952: dmacon = intena = 0;
4953: bltstate = BLT_done;
4954: copstate = COP_stop;
1.1.1.2 root 4955: diwstate = DIW_waiting_start;
1.1.1.3 ! root 4956: hdiwstate = DIW_waiting_start;
1.1 root 4957: copcon = 0;
4958: dskdmaen = 0;
4959: cycles = 0;
1.1.1.3 ! root 4960:
! 4961: audio_reset ();
1.1 root 4962:
1.1.1.2 root 4963: bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */
4964: bplcon3 = 0xC00;
1.1 root 4965:
1.1.1.3 ! root 4966: init_eventtab ();
1.1.1.2 root 4967:
4968: if (native2amiga_line_map)
4969: free (native2amiga_line_map);
4970: if (amiga2aspect_line_map)
4971: free (amiga2aspect_line_map);
4972:
1.1.1.3 ! root 4973: /* At least for this array the +1 is necessary. */
1.1.1.2 root 4974: amiga2aspect_line_map = (int *)malloc (sizeof (int) * (maxvpos+1)*2 + 1);
1.1.1.3 ! root 4975: native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height);
1.1.1.2 root 4976:
1.1.1.3 ! root 4977: if (currprefs.gfx_correct_aspect)
! 4978: native_lines_per_amiga_line = ((double)gfxvidinfo.height
! 4979: * (currprefs.gfx_lores ? 320 : 640)
! 4980: / (currprefs.gfx_linedbl ? 512 : 256)
! 4981: / gfxvidinfo.width);
1.1.1.2 root 4982: else
4983: native_lines_per_amiga_line = 1;
4984:
1.1.1.3 ! root 4985: maxl = (maxvpos+1) * (currprefs.gfx_linedbl ? 2 : 1);
! 4986: min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0);
1.1.1.2 root 4987: max_drawn_amiga_line = -1;
4988: for (i = 0; i < maxl; i++) {
4989: int v = (i - min_ypos_for_screen) * native_lines_per_amiga_line;
1.1.1.3 ! root 4990: if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1)
1.1.1.2 root 4991: max_drawn_amiga_line = i-min_ypos_for_screen;
1.1.1.3 ! root 4992: if (i < min_ypos_for_screen || v >= gfxvidinfo.height)
1.1.1.2 root 4993: v = -1;
4994: amiga2aspect_line_map[i] = v;
4995: }
1.1.1.3 ! root 4996: if (currprefs.gfx_linedbl)
1.1.1.2 root 4997: max_drawn_amiga_line >>= 1;
4998:
1.1.1.3 ! root 4999: if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) {
! 5000: extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1;
! 5001: if (extra_y_adjust < 0)
! 5002: extra_y_adjust = 0;
! 5003: }
! 5004:
! 5005: for (i = 0; i < gfxvidinfo.height; i++)
1.1.1.2 root 5006: native2amiga_line_map[i] = -1;
5007:
5008: if (native_lines_per_amiga_line < 1) {
5009: /* Must omit drawing some lines. */
5010: for (i = maxl-1; i > min_ypos_for_screen; i--) {
5011: if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) {
1.1.1.3 ! root 5012: if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) {
1.1.1.2 root 5013: /* If only the first line of a line pair would be omitted,
5014: * omit the second one instead to avoid problems with line
5015: * doubling. */
5016: amiga2aspect_line_map[i] = amiga2aspect_line_map[i+1];
5017: amiga2aspect_line_map[i+1] = -1;
5018: } else
5019: amiga2aspect_line_map[i] = -1;
5020: }
5021: }
5022: }
5023:
5024: for (i = maxl-1; i >= min_ypos_for_screen; i--) {
5025: int j;
5026: if (amiga2aspect_line_map[i] == -1)
5027: continue;
1.1.1.3 ! root 5028: for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++)
! 5029: native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0);
1.1.1.2 root 5030: }
1.1.1.3 ! root 5031:
! 5032: if (line_drawn == 0)
! 5033: line_drawn = (char *)malloc (gfxvidinfo.height);
! 5034: init_row_map();
! 5035:
! 5036: init_sprites ();
! 5037:
1.1.1.2 root 5038: init_hardware_frame ();
5039: init_drawing_frame ();
5040: last_redraw_point = 0;
5041: reset_decisions ();
1.1.1.3 ! root 5042:
1.1 root 5043: #ifdef HAVE_GETTIMEOFDAY
5044: gettimeofday(&tv,NULL);
5045: seconds_base = tv.tv_sec;
5046: bogusframe = 1;
5047: #endif
5048: }
5049:
1.1.1.3 ! root 5050: void dumpcustom (void)
1.1 root 5051: {
5052: int i;
5053: fprintf(stderr, "DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
5054: intena, intreq, vpos, current_hpos());
1.1.1.3 ! root 5055: if (timeframes) {
! 5056: fprintf(stderr, "Average frame time: %d ms [frames: %d time: %d]\n",
1.1 root 5057: frametime/timeframes, timeframes, frametime);
5058: }
1.1.1.3 ! root 5059: dump_audio_bench ();
1.1 root 5060: /*for (i=0; i<256; i++) if (blitcount[i]) fprintf(stderr, "minterm %x = %d\n",i,blitcount[i]); blitter debug */
5061: }
5062:
1.1.1.3 ! root 5063: int intlev (void)
1.1 root 5064: {
1.1.1.3 ! root 5065: uae_u16 imask = intreq & intena;
1.1 root 5066: if (imask && (intena & 0x4000)){
5067: if (imask & 0x2000) return 6;
5068: if (imask & 0x1800) return 5;
5069: if (imask & 0x0780) return 4;
5070: if (imask & 0x0070) return 3;
5071: if (imask & 0x0008) return 2;
5072: if (imask & 0x0007) return 1;
5073: }
5074: return -1;
5075: }
5076:
1.1.1.3 ! root 5077: void custom_init (void)
1.1 root 5078: {
5079: int num;
1.1.1.2 root 5080:
5081: #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
5082: for(num=0;num<2;++num) {
1.1.1.3 ! root 5083: sprite_positions[num] = xmalloc(max_sprite_draw * sizeof(struct sprite_draw));
! 5084: color_changes[num] = xmalloc(max_color_change * sizeof(struct color_change));
1.1.1.2 root 5085: }
1.1.1.3 ! root 5086: delay_changes = xmalloc(max_delay_change * sizeof(struct delay_change));
1.1.1.2 root 5087: #endif
1.1.1.3 ! root 5088:
1.1 root 5089: if (needmousehack())
5090: setfollow();
1.1.1.2 root 5091: init_regchanges ();
5092: init_decisions ();
5093:
1.1.1.3 ! root 5094: /* For now, the AGA stuff is broken in the dual playfield case. We encode
! 5095: * sprites in dpf mode by ORing the pixel value with 0x80. To make dual
! 5096: * playfield rendering easy, the lookup tables contain are made linear for
! 5097: * values >= 128. That only works for OCS/ECS, though. */
! 5098:
! 5099: for (num = 0; num < 256; num++) {
1.1 root 5100: int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4) | ((num >> 3) & 8);
5101: int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4) | ((num >> 4) & 8);
5102: dblpf_2nd1[num] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
5103: dblpf_2nd2[num] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
5104: if (plane2 > 0) plane2 += 8;
1.1.1.3 ! root 5105: dblpf_ind1[num] = num >= 128 ? num & 0x7F : (plane1 == 0 ? plane2 : plane1);
! 5106: dblpf_ind2[num] = num >= 128 ? num & 0x7F : (plane2 == 0 ? plane1 : plane2);
! 5107:
1.1 root 5108: lots_of_twos[num] = num == 0 ? 0 : 2;
5109: linear_map_256[num] = num;
5110: }
5111: build_blitfilltable();
5112: gen_pfield_tables();
1.1.1.2 root 5113: native2amiga_line_map = 0;
5114: amiga2aspect_line_map = 0;
5115: line_drawn = 0;
1.1.1.3 ! root 5116:
1.1.1.2 root 5117: #ifdef SUPPORT_PENGUINS
1.1.1.3 ! root 5118: init_comm_pipe (&drawing_pipe, 800, 5);
! 5119: uae_sem_init (&drawing_lock, 0, 0);
! 5120: start_penguin (drawing_penguin, 0, &our_penguin);
! 5121: /*atexit(kill_drawing_penguin);*/
1.1.1.2 root 5122: #endif
1.1 root 5123: }
5124:
5125: /* Custom chip memory bank */
5126:
1.1.1.3 ! root 5127: static uae_u32 custom_lget(uaecptr) REGPARAM;
! 5128: static uae_u32 custom_wget(uaecptr) REGPARAM;
! 5129: static uae_u32 custom_bget(uaecptr) REGPARAM;
! 5130: static void custom_lput(uaecptr, uae_u32) REGPARAM;
! 5131: static void custom_wput(uaecptr, uae_u32) REGPARAM;
! 5132: static void custom_bput(uaecptr, uae_u32) REGPARAM;
1.1 root 5133:
5134: addrbank custom_bank = {
5135: custom_lget, custom_wget, custom_bget,
5136: custom_lput, custom_wput, custom_bput,
5137: default_xlate, default_check
5138: };
5139:
1.1.1.3 ! root 5140: uae_u32 REGPARAM2 custom_wget (uaecptr addr)
1.1 root 5141: {
5142: switch(addr & 0x1FE) {
5143: case 0x002: return DMACONR();
5144: case 0x004: return VPOSR();
5145: case 0x006: return VHPOSR();
1.1.1.3 ! root 5146:
1.1 root 5147: case 0x008: return DSKDATR();
5148:
5149: case 0x00A: return JOY0DAT();
5150: case 0x00C: return JOY1DAT();
1.1.1.3 ! root 5151: case 0x00E: return CLXDAT();
1.1 root 5152: case 0x010: return ADKCONR();
5153:
5154: case 0x012: return POT0DAT();
5155: case 0x016: return POTGOR();
5156: case 0x018: return SERDATR();
5157: case 0x01A: return DSKBYTR();
5158: case 0x01C: return INTENAR();
5159: case 0x01E: return INTREQR();
5160: #if AGA_CHIPSET == 1
5161: case 0x07C: return 0xF8;
5162: #elif defined ECS_DENISE
5163: case 0x07C: return 0xFC;
5164: #endif
5165: default:
5166: custom_wput(addr,0);
5167: return 0xffff;
5168: }
5169: }
5170:
1.1.1.3 ! root 5171: uae_u32 REGPARAM2 custom_bget (uaecptr addr)
1.1 root 5172: {
5173: return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
5174: }
5175:
1.1.1.3 ! root 5176: uae_u32 REGPARAM2 custom_lget (uaecptr addr)
1.1 root 5177: {
1.1.1.3 ! root 5178: return ((uae_u32)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe);
1.1 root 5179: }
5180:
1.1.1.3 ! root 5181: void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value)
1.1 root 5182: {
5183: addr &= 0x1FE;
5184: cregs[addr>>1] = value;
1.1.1.3 ! root 5185: switch (addr) {
! 5186: case 0x020: DSKPTH (value); break;
! 5187: case 0x022: DSKPTL (value); break;
! 5188: case 0x024: DSKLEN (value); break;
! 5189: case 0x026: DSKDAT (value); break;
! 5190:
! 5191: case 0x02A: VPOSW (value); break;
! 5192: case 0x2E: COPCON (value); break;
! 5193: case 0x030: SERDAT (value); break;
! 5194: case 0x032: SERPER (value); break;
! 5195: case 0x34: POTGO (value); break;
! 5196: case 0x040: BLTCON0 (value); break;
! 5197: case 0x042: BLTCON1 (value); break;
! 5198:
! 5199: case 0x044: BLTAFWM (value); break;
! 5200: case 0x046: BLTALWM (value); break;
! 5201:
! 5202: case 0x050: BLTAPTH (value); break;
! 5203: case 0x052: BLTAPTL (value); break;
! 5204: case 0x04C: BLTBPTH (value); break;
! 5205: case 0x04E: BLTBPTL (value); break;
! 5206: case 0x048: BLTCPTH (value); break;
! 5207: case 0x04A: BLTCPTL (value); break;
! 5208: case 0x054: BLTDPTH (value); break;
! 5209: case 0x056: BLTDPTL (value); break;
! 5210:
! 5211: case 0x058: BLTSIZE (value); break;
! 5212:
! 5213: case 0x064: BLTAMOD (value); break;
! 5214: case 0x062: BLTBMOD (value); break;
! 5215: case 0x060: BLTCMOD (value); break;
! 5216: case 0x066: BLTDMOD (value); break;
! 5217:
! 5218: case 0x070: BLTCDAT (value); break;
! 5219: case 0x072: BLTBDAT (value); break;
! 5220: case 0x074: BLTADAT (value); break;
! 5221:
! 5222: case 0x07E: DSKSYNC (value); break;
! 5223:
! 5224: case 0x080: COP1LCH (value); break;
! 5225: case 0x082: COP1LCL (value); break;
! 5226: case 0x084: COP2LCH (value); break;
! 5227: case 0x086: COP2LCL (value); break;
! 5228:
! 5229: case 0x088: COPJMP1 (value); break;
! 5230: case 0x08A: COPJMP2 (value); break;
! 5231:
! 5232: case 0x08E: DIWSTRT (value); break;
! 5233: case 0x090: DIWSTOP (value); break;
! 5234: case 0x092: DDFSTRT (value); break;
! 5235: case 0x094: DDFSTOP (value); break;
! 5236:
! 5237: case 0x096: DMACON (value); break;
! 5238: case 0x098: CLXCON (value); break;
! 5239: case 0x09A: INTENA (value); break;
! 5240: case 0x09C: INTREQ (value); break;
! 5241: case 0x09E: ADKCON (value); break;
! 5242:
! 5243: case 0x0A0: AUDxLCH (0, value); break;
! 5244: case 0x0A2: AUDxLCL (0, value); break;
! 5245: case 0x0A4: AUDxLEN (0, value); break;
! 5246: case 0x0A6: AUDxPER (0, value); break;
! 5247: case 0x0A8: AUDxVOL (0, value); break;
! 5248: case 0x0AA: AUDxDAT (0, value); break;
! 5249:
! 5250: case 0x0B0: AUDxLCH (1, value); break;
! 5251: case 0x0B2: AUDxLCL (1, value); break;
! 5252: case 0x0B4: AUDxLEN (1, value); break;
! 5253: case 0x0B6: AUDxPER (1, value); break;
! 5254: case 0x0B8: AUDxVOL (1, value); break;
! 5255: case 0x0BA: AUDxDAT (1, value); break;
! 5256:
! 5257: case 0x0C0: AUDxLCH (2, value); break;
! 5258: case 0x0C2: AUDxLCL (2, value); break;
! 5259: case 0x0C4: AUDxLEN (2, value); break;
! 5260: case 0x0C6: AUDxPER (2, value); break;
! 5261: case 0x0C8: AUDxVOL (2, value); break;
! 5262: case 0x0CA: AUDxDAT (2, value); break;
! 5263:
! 5264: case 0x0D0: AUDxLCH (3, value); break;
! 5265: case 0x0D2: AUDxLCL (3, value); break;
! 5266: case 0x0D4: AUDxLEN (3, value); break;
! 5267: case 0x0D6: AUDxPER (3, value); break;
! 5268: case 0x0D8: AUDxVOL (3, value); break;
! 5269: case 0x0DA: AUDxDAT (3, value); break;
! 5270:
! 5271: case 0x0E0: BPLPTH (value, 0); break;
! 5272: case 0x0E2: BPLPTL (value, 0); break;
! 5273: case 0x0E4: BPLPTH (value, 1); break;
! 5274: case 0x0E6: BPLPTL (value, 1); break;
! 5275: case 0x0E8: BPLPTH (value, 2); break;
! 5276: case 0x0EA: BPLPTL (value, 2); break;
! 5277: case 0x0EC: BPLPTH (value, 3); break;
! 5278: case 0x0EE: BPLPTL (value, 3); break;
! 5279: case 0x0F0: BPLPTH (value, 4); break;
! 5280: case 0x0F2: BPLPTL (value, 4); break;
! 5281: case 0x0F4: BPLPTH (value, 5); break;
! 5282: case 0x0F6: BPLPTL (value, 5); break;
! 5283:
! 5284: case 0x100: BPLCON0 (value); break;
! 5285: case 0x102: BPLCON1 (value); break;
! 5286: case 0x104: BPLCON2 (value); break;
! 5287: case 0x106: BPLCON3 (value); break;
! 5288:
! 5289: case 0x108: BPL1MOD (value); break;
! 5290: case 0x10A: BPL2MOD (value); break;
! 5291:
! 5292: case 0x110: BPL1DAT (value); break;
! 5293: case 0x112: BPL2DAT (value); break;
! 5294: case 0x114: BPL3DAT (value); break;
! 5295: case 0x116: BPL4DAT (value); break;
! 5296: case 0x118: BPL5DAT (value); break;
! 5297: case 0x11A: BPL6DAT (value); break;
1.1 root 5298:
5299: case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
5300: case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
5301: case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
5302: case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
5303: case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
1.1.1.2 root 5304: case 0x1BC: case 0x1BE:
1.1.1.3 ! root 5305: COLOR (value & 0xFFF, (addr & 0x3E) / 2);
1.1.1.2 root 5306: break;
5307: case 0x120: case 0x124: case 0x128: case 0x12C:
1.1 root 5308: case 0x130: case 0x134: case 0x138: case 0x13C:
1.1.1.3 ! root 5309: SPRxPTH (value, (addr - 0x120) / 4);
1.1 root 5310: break;
1.1.1.2 root 5311: case 0x122: case 0x126: case 0x12A: case 0x12E:
1.1 root 5312: case 0x132: case 0x136: case 0x13A: case 0x13E:
1.1.1.3 ! root 5313: SPRxPTL (value, (addr - 0x122) / 4);
1.1 root 5314: break;
1.1.1.2 root 5315: case 0x140: case 0x148: case 0x150: case 0x158:
1.1 root 5316: case 0x160: case 0x168: case 0x170: case 0x178:
1.1.1.3 ! root 5317: SPRxPOS (value, (addr - 0x140) / 8);
1.1 root 5318: break;
1.1.1.2 root 5319: case 0x142: case 0x14A: case 0x152: case 0x15A:
1.1 root 5320: case 0x162: case 0x16A: case 0x172: case 0x17A:
1.1.1.3 ! root 5321: SPRxCTL (value, (addr - 0x142) / 8);
1.1 root 5322: break;
5323: case 0x144: case 0x14C: case 0x154: case 0x15C:
5324: case 0x164: case 0x16C: case 0x174: case 0x17C:
1.1.1.3 ! root 5325: SPRxDATA (value, (addr - 0x144) / 8);
1.1 root 5326: break;
1.1.1.2 root 5327: case 0x146: case 0x14E: case 0x156: case 0x15E:
1.1 root 5328: case 0x166: case 0x16E: case 0x176: case 0x17E:
1.1.1.3 ! root 5329: SPRxDATB (value, (addr - 0x146) / 8);
1.1 root 5330: break;
1.1.1.3 ! root 5331:
! 5332: case 0x36: JOYTEST (value); break;
! 5333: #if defined (ECS_AGNUS) || (AGA_CHIPSET == 1)
1.1 root 5334: case 0x5A: BLTCON0L(value); break;
1.1.1.3 ! root 5335: case 0x5C: BLTSIZV (value); break;
! 5336: case 0x5E: BLTSIZH (value); break;
1.1 root 5337: #endif
5338: #if AGA_CHIPSET == 1
1.1.1.3 ! root 5339: case 0x10C: BPLCON4 (value); break;
1.1 root 5340: case 0x1FC: fmode = value; break;
5341: #endif
5342: }
5343: }
5344:
1.1.1.3 ! root 5345: void REGPARAM2 custom_bput(uaecptr addr, uae_u32 value)
1.1 root 5346: {
1.1.1.2 root 5347: static int warned = 0;
5348: /* Is this correct now? (There are people who bput things to the upper byte of AUDxVOL). */
1.1.1.3 ! root 5349: uae_u16 rval = (value << 8) | (value & 0xFF);
1.1.1.2 root 5350: custom_wput(addr, rval);
5351: if (!warned)
1.1.1.3 ! root 5352: write_log ("Byte put to custom register.\n"), warned++;
1.1 root 5353: }
5354:
1.1.1.3 ! root 5355: void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value)
1.1 root 5356: {
5357: custom_wput(addr & 0xfffe, value >> 16);
1.1.1.3 ! root 5358: custom_wput((addr+2) & 0xfffe, (uae_u16)value);
1.1 root 5359: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.