--- uae/src/custom.c 2018/04/24 16:39:15 1.1.1.2 +++ uae/src/custom.c 2018/04/24 16:40:07 1.1.1.3 @@ -1,12 +1,20 @@ /* * UAE - The Un*x Amiga Emulator - * + * * Custom chip emulation - * + * * Copyright 1995, 1996, 1997 Bernd Schmidt * Copyright 1995 Alessandro Bissacco */ + /* + * This file should be split into two parts. There are two concepts of a + * "frame" here: a hardware frame which emulates the display hardware of + * the A500, and a "drawing" frame, which renders data on the screen. You + * can have multiple hardware frames for one drawing frame, or completely + * inhibit drawing while hardware frames continue to be emulated. There + * should be a separate file "drawing.c" or something. + */ #include "sysconfig.h" #include "sysdeps.h" @@ -15,6 +23,10 @@ #include "config.h" #include "options.h" +#include "threaddep/penguin.h" +#include "uae.h" +#include "gensound.h" +#include "sounddep/sound.h" #include "events.h" #include "memory.h" #include "custom.h" @@ -24,15 +36,20 @@ #include "disk.h" #include "blitter.h" #include "xwin.h" -#include "os.h" +#include "joystick.h" +#include "audio.h" #include "keybuf.h" #include "serial.h" #include "osemu.h" -#include "machdep/penguin.h" +#include "autoconf.h" +#include "gui.h" +#include "picasso96.h" +#include "p2c.h" #ifdef X86_ASSEMBLY #define LORES_HACK #endif +#define SPRITE_COLLISIONS /* * Several people have tried this define, with not much success. Turning on @@ -40,7 +57,7 @@ * function - the AGA timing parameters are different, and apparently I * haven't figured out the correct formula yet. Pity, the current one looks * logical. - * + * * @@@ Probably won't compile in this version. */ @@ -56,7 +73,7 @@ #ifdef SUPPORT_PENGUINS #undef SMART_UPDATE -#define SMART_UDPATE 1 +#define SMART_UPDATE 1 #endif #if AGA_CHIPSET == 1 @@ -79,34 +96,45 @@ static int lores_factor, lores_shift, sp /* @@@ Is maxhpos + 4 - 1 correct? (4 less isn't enough) */ #define max_diwlastword (PIXEL_XPOS(maxhpos + 4 -1)) -/* These are default values for mouse calibration. - * The first two are default values for mstepx and mstepy. - * The second line set the horizontal and vertical offset for amiga and X - * pointer matching - */ +/* Mouse and joystick emulation */ #define defstepx (1<<16) #define defstepy (1<<16) #define defxoffs 0 #define defyoffs 0 - -/* Values below define mouse auto calibration process. - * They are not critical, change them if you want. - * The most important is calweight, which sets mouse adjustement rate */ static const int docal = 60, xcaloff = 40, ycaloff = 20; static const int calweight = 3; static int lastsampledmx, lastsampledmy; - /* - * Events - */ +int buttonstate[3]; +int lastmx, lastmy; +int newmousecounters; +int ievent_alive = 0; -unsigned long int cycles, nextevent; +static enum { normal_mouse, dont_care_mouse, follow_mouse } mousestate; + +static int mouse_x, mouse_y; +int joy0button, joy1button; +unsigned int joy0dir, joy1dir; +static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl; +static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs; +static int sprvbfl; + +/* Video buffer description structure. Filled in by the graphics system + * dependent code. */ + +struct vidbuf_description gfxvidinfo; + +/* Events */ + +unsigned long int cycles, nextevent, is_lastline, did_reset; struct ev eventtab[ev_max]; +frame_time_t vsynctime, vsyncmintime; + int vpos; -UWORD lof; +uae_u16 lof; static int lof_changed = 0, interlace_seen = 0; static int copper_waiting_for_blitter, copper_active; @@ -117,31 +145,47 @@ static int dblpf_aga1[256], dblpf_aga2[2 static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 }; +/* Big lookup tables for planar to chunky conversion. */ + +uae_u32 hirestab_h[256][2]; +uae_u32 lorestab_h[256][4]; + +uae_u32 hirestab_l[256][1]; +uae_u32 lorestab_l[256][2]; + +static uae_u32 sprtaba[256],sprtabb[256]; +static uae_u32 clxtab[256]; + +/* The color lookup table. */ + +xcolnr xcolors[4096]; + /* * Hardware registers of all sorts. */ static int fmode; -static UWORD cregs[256]; +static uae_u16 cregs[256]; -UWORD intena,intreq; -UWORD dmacon; -UWORD adkcon; /* used by audio code */ +uae_u16 intena,intreq; +uae_u16 dmacon; +uae_u16 adkcon; /* used by audio code */ -static ULONG cop1lc,cop2lc,copcon; +static uae_u32 cop1lc,cop2lc,copcon; /* This is but an educated guess. It seems to be correct, but this stuff * isn't documented well. */ -enum sprstate { SPR_vtop, SPR_restart, SPR_waiting_start, SPR_waiting_stop, SPR_stop }; -static enum sprstate spron[8]; -static CPTR sprpt[8]; +enum sprstate { SPR_stop, SPR_restart, SPR_waiting_start, SPR_waiting_stop }; +static enum sprstate sprst[8]; +static int spron[8]; +static uaecptr sprpt[8]; static int sprxpos[8], sprvstart[8], sprvstop[8]; -static ULONG bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat,bpl7dat,bpl8dat; -static WORD bpl1mod,bpl2mod; +static uae_u32 bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat,bpl7dat,bpl8dat; +static uae_s16 bpl1mod,bpl2mod; -static CPTR bplpt[8]; +static uaecptr bplpt[8]; #ifndef SMART_UPDATE static char *real_bplpt[8]; #endif @@ -152,31 +196,26 @@ struct color_entry { #if AGA_CHIPSET == 0 /* X86.S expects this at the start of the structure. */ xcolnr acolors[32]; - UWORD color_regs[32]; + uae_u16 color_regs[32]; #else - ULONG color_regs[256]; + uae_u32 color_regs[256]; #endif }; static struct color_entry current_colors; struct color_entry colors_for_drawing; static unsigned int bplcon0,bplcon1,bplcon2,bplcon3,bplcon4; +static int nr_planes_from_bplcon0, corrected_nr_planes_from_bplcon0; static unsigned int diwstrt,diwstop,ddfstrt,ddfstop; static unsigned int sprdata[8], sprdatb[8], sprctl[8], sprpos[8]; static int sprarmed[8], sprite_last_drawn_at[8]; -static ULONG dskpt; -static UWORD dsklen,dsksync; - -static int joy0x, joy1x, joy0y, joy1y; -int joy0button; -UWORD joy0dir; -static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl; -static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs; -static int sprvbfl; - -static enum { normal_mouse, dont_care_mouse, follow_mouse } mousestate; +static int last_sprite_point, nr_armed; +static uae_u16 clxdat, clxcon; +static int clx_sprmask; +static uae_u32 dskpt; +static uae_u16 dsklen,dsksync; -static ULONG coplc; +static uae_u32 coplc; static unsigned int copi1,copi2; static enum copper_states { @@ -190,7 +229,7 @@ static int dsklength; static int plffirstline,plflastline,plfstrt,plfstop,plflinelen; static int diwfirstword,diwlastword; -static enum { DIW_waiting_start, DIW_waiting_stop } diwstate; +static enum { DIW_waiting_start, DIW_waiting_stop } diwstate, hdiwstate; int dskdmaen; /* used in cia.c */ @@ -204,17 +243,15 @@ union { unsigned char apixels[880]; } pixdata; -char spixels[880]; /* for sprites */ -char spixstate[880]; /* more sprites */ - -ULONG ham_linebuf[880]; -ULONG aga_linebuf[880], *aga_lbufptr; +uae_u32 ham_linebuf[880]; +uae_u32 aga_linebuf[880], *aga_lbufptr; char *xlinebuffer; int next_lineno; static int nln_how; static int *amiga2aspect_line_map, *native2amiga_line_map; +static char *row_map[2049]; static int max_drawn_amiga_line; /* @@ -230,21 +267,37 @@ int bogusframe; * helper functions */ -int inhibit_frame; +int picasso_requested_on; +int picasso_on; + +uae_sem_t frame_sem, gui_sem, ihf_sem; +volatile int frame_do_semup; +volatile int inhibit_frame; + static int framecnt = 0; +static int frame_redraw_necessary; -static __inline__ void count_frame(void) +static __inline__ void count_frame (void) { - if (inhibit_frame) - framecnt = 1; - else { - framecnt++; - if (framecnt >= framerate) - framecnt = 0; + framecnt++; + if (framecnt >= currprefs.framerate) + framecnt = 0; +} + +void check_prefs_changed_custom (void) +{ + currprefs.framerate = changed_prefs.framerate; + /* Not really the right place... */ + if (currprefs.fake_joystick != changed_prefs.fake_joystick) { + currprefs.fake_joystick = changed_prefs.fake_joystick; + joystick_setting_changed (); } + currprefs.immediate_blits = changed_prefs.immediate_blits; + currprefs.blits_32bit_enabled = changed_prefs.blits_32bit_enabled; + } -static __inline__ void setclr(UWORD *p, UWORD val) +static __inline__ void setclr (uae_u16 *p, uae_u16 val) { if (val & 0x8000) { *p |= val & 0x7FFF; @@ -253,21 +306,17 @@ static __inline__ void setclr(UWORD *p, } } -__inline__ int current_hpos(void) +__inline__ int current_hpos (void) { return cycles - eventtab[ev_hsync].oldcycles; } -static __inline__ UBYTE *pfield_xlateptr(CPTR plpt, int bytecount) +static __inline__ uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount) { if (!chipmem_bank.check(plpt,bytecount)) { static int count = 0; - if (count < 5) { - count++; - fprintf(stderr, "Warning: Bad playfield pointer"); - if (count == 5) fprintf(stderr, " (no further warnings)"); - fprintf(stderr, "\n"); - } + if (!count) + count++, write_log ("Warning: Bad playfield pointer\n"); return NULL; } return chipmem_bank.xlateaddr(plpt); @@ -275,16 +324,11 @@ static __inline__ UBYTE *pfield_xlateptr static void calculate_copper_cycle_time (void) { - int bplplanes; - if (diwstate == DIW_waiting_start || !dmaen (DMA_BITPLANE)) { copper_cycle_time = 2; return; } - bplplanes = (bplcon0 & 0x7000) >> 12; - if (bplcon0 & 0x8000) - bplplanes *= 2; - copper_cycle_time = bplplanes <= 4 ? 2 : -1; + copper_cycle_time = corrected_nr_planes_from_bplcon0 <= 4 ? 2 : -1; } /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham6 */ @@ -303,23 +347,21 @@ typedef void (*line_draw_func)(int, int) static char *line_drawn; static char linestate[(maxvpos + 1)*2 + 1]; -static int frame_redraw_necessary; static int min_diwstart, max_diwstop, prev_x_adjust, linetoscr_x_adjust, linetoscr_right_x; +static int linetoscr_x_adjust_bytes; static int thisframe_y_adjust, prev_y_adjust, thisframe_first_drawn_line, thisframe_last_drawn_line; static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen; +static int extra_y_adjust; -/* 50 words give you 800 horizontal pixels. An A500 can't do that, so it ought - * to be enough. */ -#define MAX_WORDS_PER_LINE 50 -static UBYTE line_data[(maxvpos+1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2]; +static uae_u8 line_data[(maxvpos+1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2]; /* * The idea behind this code is that at some point during each horizontal * line, we decide how to draw this line. There are many more-or-less * independent decisions, each of which can be taken at a different horizontal * position. - * Sprites, color changes and bitplane delay changes are handled specially: - * There isn't a single decision, but a list of structures containing + * Sprites, color changes and bitplane delay changes are handled specially: + * There isn't a single decision, but a list of structures containing * information on how to draw the line. */ @@ -333,7 +375,7 @@ struct sprite_draw { int linepos; int num; int ctl; - UWORD data, datb; + uae_u32 datab; }; struct delay_change { @@ -345,32 +387,28 @@ struct delay_change { #define MAX_REG_CHANGE ((maxvpos+1) * 2 * maxhpos) static int current_change_set; -/* Add others here (RISC OS, maybe Windows). Under Unix, these big arrays - * neither take up physical memory nor make the executable bigger so it's - * a very convenient way to get safety without overhead. */ -#ifdef AMIGA -#define OS_WITHOUT_MEMORY_MANAGEMENT -#endif - #ifdef OS_WITHOUT_MEMORY_MANAGEMENT -/* sam: Those arrays uses around 7Mb of BBS... That seems */ +/* sam: Those arrays uses around 7Mb of BSS... That seems */ /* too much for AmigaDOS (uae crashes as soon as one loads */ /* it. So I use a different strategy here (realloc the */ /* arrays when needed. That strategy might be usefull for */ /* computer with low memory. */ static struct sprite_draw *sprite_positions[2]; -static int max_sprite_draw = 800; -static int _max_sprite_draw = 0; +static int max_sprite_draw = 400; +static int delta_sprite_draw = 0; static struct color_change *color_changes[2]; -static int max_color_change = 800; -static int _max_color_change = 0; +static int max_color_change = 400; +static int delta_color_change = 0; +static struct delay_change *delay_changes; +static int max_delay_change = 100; +static int delta_delay_change = 0; #else static struct sprite_draw sprite_positions[2][MAX_REG_CHANGE]; static struct color_change color_changes[2][MAX_REG_CHANGE]; -#endif -/* We don't remember those across frames, that would be too much effort. +/* We don't remember those across frames, that would be too much effort. * We simply redraw the line whenever we see one of these. */ static struct delay_change delay_changes[MAX_REG_CHANGE]; +#endif static struct sprite_draw *curr_sprite_positions, *prev_sprite_positions; static struct color_change *curr_color_changes, *prev_color_changes; @@ -380,13 +418,43 @@ static struct color_entry color_tables[2 static struct color_entry *curr_color_tables, *prev_color_tables; static int next_color_entry, remembered_color_entry, drawing_color_matches; static enum { color_match_acolors, color_match_full } color_match_type; -static int color_src_match, color_dest_match; +static int color_src_match, color_dest_match, color_compare_result; static int last_redraw_point; static int first_drawn_line, last_drawn_line; static int first_block_line, last_block_line; +static __inline__ void docols(struct color_entry *colentry) +{ +#if AGA_CHIPSET == 0 + int i; + for (i = 0; i < 32; i++) { + int v = colentry->color_regs[i]; + if (v < 0 || v > 4095) + continue; + colentry->acolors[i] = xcolors[v]; + } +#endif +} + +void notice_new_xcolors (void) +{ + int i; + + docols(¤t_colors); + docols(&colors_for_drawing); + for (i = 0; i < (maxvpos+1)*2; i++) { + docols(color_tables[0]+i); + docols(color_tables[1]+i); + } +} + +void notice_screen_contents_lost (void) +{ + frame_redraw_necessary = 2; +} + static void init_regchanges (void) { size_t i; @@ -407,12 +475,12 @@ struct decision { int diwfirstword, diwlastword; int ctable; - UWORD bplcon0, bplcon1, bplcon2; + uae_u16 bplcon0, bplcon1, bplcon2; #if 0 /* We don't need this. */ - UWORD bplcon3; + uae_u16 bplcon3; #endif #if AGA_CHIPSET == 1 - UWORD bplcon4; + uae_u16 bplcon4; #endif }; @@ -441,7 +509,7 @@ static struct draw_info *curr_drawinfo, static struct decision *dp_for_drawing; static struct draw_info *dip_for_drawing; -static int line_changed[2 * (maxvpos+1)]; +static char line_changed[2 * (maxvpos+1)]; #ifdef SMART_UPDATE #define MARK_LINE_CHANGED(l) do { line_changed[l] = 1; } while (0) @@ -470,26 +538,79 @@ static void remember_ctable (void) int oldctable = line_decisions[next_lineno].ctable; int changed = 0; - if (oldctable == -1) + if (oldctable == -1) { changed = 1; - else if (fast_memcmp (&prev_color_tables[oldctable].color_regs, ¤t_colors.color_regs, - sizeof current_colors.color_regs) != 0) - changed = 1; - - if (changed) { color_src_match = color_dest_match = -1; - line_changed[next_lineno] = 1; } else { + color_compare_result = memcmp (&prev_color_tables[oldctable].color_regs, + ¤t_colors.color_regs, + sizeof current_colors.color_regs) != 0; + if (color_compare_result) + changed = 1; + color_src_match = oldctable; color_dest_match = remembered_color_entry; + } + if (changed) { + line_changed[next_lineno] = 1; + } + } else { + /* We know the result of the comparison */ + if (color_compare_result) + line_changed[next_lineno] = 1; + } +} + +static void remember_ctable_for_border (void) +{ + remember_ctable (); +#if 0 + if (remembered_color_entry == -1) { + /* The colors changed since we last recorded a color map. Record a + * new one. */ + memcpy (curr_color_tables + next_color_entry, ¤t_colors, sizeof current_colors); + remembered_color_entry = next_color_entry++; + } + thisline_decision.ctable = remembered_color_entry; + if (color_src_match == -1 || color_dest_match != remembered_color_entry + || line_decisions[next_lineno].ctable != color_src_match) + { + /* The remembered comparison didn't help us - need to compare again. */ + int oldctable = line_decisions[next_lineno].ctable; + int changed = 0; + + if (oldctable == -1) { + changed = 1; + color_src_match = color_dest_match = -1; + } else { + color_compare_result = memcmp (&prev_color_tables[oldctable].color_regs, + ¤t_colors.color_regs, + sizeof current_colors.color_regs) != 0; + if (color_compare_result) + changed = 1; color_src_match = oldctable; + color_dest_match = remembered_color_entry; + } + if (changed) { + line_changed[next_lineno] = 1; } + } else { + /* We know the result of the comparison */ + if (color_compare_result) + line_changed[next_lineno] = 1; } +#endif } +/* Called to determine the state of the horizontal display window state + * machine at the current position. It might have changed since we last + * checked. */ static void decide_diw (void) { - if (thisline_decision.diwfirstword == -1 && PIXEL_XPOS (current_hpos ()) >= diwfirstword) { + if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1 + && PIXEL_XPOS (current_hpos ()) >= diwfirstword) + { thisline_decision.diwfirstword = diwfirstword; + hdiwstate = DIW_waiting_stop; /* Decide playfield delays only at DIW start, because they don't matter before and * some programs change them after DDF start but before DIW start. */ thisline_decision.bplcon1 = bplcon1; @@ -497,57 +618,18 @@ static void decide_diw (void) MARK_LINE_CHANGED (next_lineno); thisline_decision.diwlastword = -1; } - if (thisline_decision.diwlastword == -1 && (current_hpos () >= maxhpos || PIXEL_XPOS (current_hpos ()) >= diwlastword)) { + if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1 + && PIXEL_XPOS (current_hpos ()) >= diwlastword) + { thisline_decision.diwlastword = diwlastword; + hdiwstate = DIW_waiting_start; if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword) MARK_LINE_CHANGED (next_lineno); } } -static void record_color_change (int regno, unsigned long value) -{ - /* Early positions don't appear on-screen. */ - if (framecnt != 0 || vpos < minfirstline || current_hpos () < 0x18) - return; - decide_diw (); - - /* See if we can record the color table, but have not done so yet. - * @@@ There might be a minimal performance loss in case someone changes - * a color exactly at the start of the DIW. I don't think it can actually - * fail to work even in this case, but I'm not 100% sure. - * @@@ There might be a slightly larger performance loss if we're drawing - * this line as border... especially if there are changes in colors != 0 - * we might end up setting line_changed for no reason. FIXME */ - if (thisline_decision.diwfirstword >= 0) { - if (thisline_decision.ctable == -1) - remember_ctable (); - } - - /* Changes outside the DIW can be ignored if the modified color is not the - * background color, or if the accuracy is 0. */ - if ((regno != 0 || emul_accuracy == 0) - && (thisline_decision.diwfirstword < 0 || thisline_decision.diwlastword >= 0)) - return; - - /* If the border is changed the first time before the DIW, record the - * original starting border value. */ - if (regno == 0 && thisline_decision.color0 == 0xFFFFFFFFul && thisline_decision.diwfirstword < 0) { - thisline_decision.color0 = current_colors.color_regs[0]; - if (line_decisions[next_lineno].color0 != value) - line_changed[next_lineno] = 1; - } - /* Anything else gets recorded in the color_changes table. */ -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT - if(next_color_change >= _max_color_change) { - _max_color_change = next_color_change; - return; - } -#endif - curr_color_changes[next_color_change].linepos = current_hpos (); - curr_color_changes[next_color_change].regno = regno; - curr_color_changes[next_color_change++].value = value; -} - +/* Called when we know that the line is not in the border and we want to it. + * The data fetch starting position and length are passed as parameters. */ static __inline__ void decide_as_playfield (int startpos, int len) { thisline_decision.which = 1; @@ -580,6 +662,9 @@ static __inline__ void decide_as_playfie line_changed[next_lineno] = 1; } +/* Called when we already decided whether the line is playfield or border, + * but are no longer sure that this was such a good idea. This can make a + * difference only for very badly written software. */ static __inline__ void post_decide_line (void) { static int warned = 0; @@ -597,19 +682,19 @@ static __inline__ void post_decide_line modulos_added = 1; return; } - + if (thisline_decision.which != -1 || diwstate == DIW_waiting_start || (bplcon0 & 0x7000) == 0 || !dmaen (DMA_BITPLANE) || current_hpos () >= thisline_decision.plfstrt + thisline_decision.plflinelen) return; #if 0 /* Can't warn because Kickstart 1.3 does it at reset time ;-) */ if (!warned) { - fprintf(stderr, "That program you are running is _really_ broken.\n"); + write_log ("That program you are running is _really_ broken.\n"); warned = 1; } #endif decided_hires = (bplcon0 & 0x8000) == 0x8000; - decided_nr_planes = ((bplcon0 & 0x7000) >> 12); + decided_nr_planes = nr_planes_from_bplcon0; /* Magic 12, Ray of Hope 2 demo does ugly things. Looks great from the * outside, rotten inside. */ @@ -643,17 +728,19 @@ static void decide_line_1 (void) /* thisline_decision.which = -2; This doesn't do anything but hurt, I think. */ return; } - - if (!dmaen(DMA_BITPLANE) || diwstate == DIW_waiting_start || (bplcon0 & 0x7000) == 0) { + + if (!dmaen(DMA_BITPLANE) || diwstate == DIW_waiting_start || nr_planes_from_bplcon0 == 0) { /* We don't want to draw this one. */ thisline_decision.which = -1; + thisline_decision.plfstrt = plfstrt; + thisline_decision.plflinelen = plflinelen; return; } decided_hires = (bplcon0 & 0x8000) == 0x8000; - decided_nr_planes = ((bplcon0 & 0x7000) >> 12); + decided_nr_planes = nr_planes_from_bplcon0; #if 0 - /* The blitter gets slower if there's high bitplane activity. + /* The blitter gets slower if there's high bitplane activity. * @@@ but the values must be different. FIXME */ if (bltstate != BLT_done && ((decided_hires && decided_nr_planes > 2) @@ -678,12 +765,69 @@ static void decide_line_1 (void) decide_as_playfield (plfstrt, plflinelen); } +/* Main entry point for deciding how to draw a line. May either do + * nothing, decide the line as border, or decide the line as playfield. */ static __inline__ void decide_line (void) { if (thisline_decision.which == 0 && current_hpos() >= plfstrt) decide_line_1 (); } +/* Called when a color is about to be changed (write to a color register), + * but the new color has not been entered into the table yet. */ +static void record_color_change (int regno, unsigned long value) +{ + /* Early positions don't appear on-screen. */ + if (framecnt != 0 || vpos < minfirstline || current_hpos () < 0x18 + /*|| currprefs.emul_accuracy == 0*/) + return; + + decide_diw (); + decide_line (); + + /* See if we can record the color table, but have not done so yet. + * @@@ There might be a minimal performance loss in case someone changes + * a color exactly at the start of the DIW. I don't think it can actually + * fail to work even in this case, but I'm not 100% sure. + * @@@ There might be a slightly larger performance loss if we're drawing + * this line as border... especially if there are changes in colors != 0 + * we might end up setting line_changed for no reason. FIXME */ + if (thisline_decision.diwfirstword >= 0 + && thisline_decision.which != 0) + { + if (thisline_decision.ctable == -1) + remember_ctable (); + } + + /* Changes outside the DIW can be ignored if the modified color is not the + * background color, or if the accuracy is < 2. */ + if ((regno != 0 || currprefs.emul_accuracy < 2) + && (diwstate == DIW_waiting_start || thisline_decision.diwfirstword < 0 + || thisline_decision.diwlastword >= 0 + || thisline_decision.which == 0 + || (thisline_decision.which == 1 && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen))) + return; + + /* If the border is changed the first time before the DIW, record the + * original starting border value. */ + if (regno == 0 && thisline_decision.color0 == 0xFFFFFFFFul && thisline_decision.diwfirstword < 0) { + thisline_decision.color0 = current_colors.color_regs[0]; + if (line_decisions[next_lineno].color0 != value) + line_changed[next_lineno] = 1; + } + /* Anything else gets recorded in the color_changes table. */ +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT + if(next_color_change >= max_color_change) { + ++delta_color_change; + return; + } +#endif + curr_color_changes[next_color_change].linepos = current_hpos (); + curr_color_changes[next_color_change].regno = regno; + curr_color_changes[next_color_change++].value = value; +} + +/* Stupid hack to get some Sanity demos working. */ static void decide_delay (void) { static int warned; @@ -699,12 +843,18 @@ static void decide_delay (void) return; } /* @@@ Could check here for DDF stopping earlier than DIW */ - + +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT + if(next_delay_change >= max_delay_change) { + ++delta_delay_change; + return; + } +#endif delay_changes[next_delay_change].linepos = current_hpos (); delay_changes[next_delay_change++].value = bplcon1; if (!warned) { warned = 1; - fprintf (stderr, "Program is torturing BPLCON1.\n"); + write_log ("Program is torturing BPLCON1.\n"); } } @@ -735,31 +885,33 @@ static void decide_plane (void) /* Can't happen. */ static int warned = 0; if (!warned) - fprintf (stderr, "Mysterious bug in decide_plane(). Please report.\n"); + write_log ("Mysterious bug in decide_plane(). Please report.\n"); bytecount = 0; } if (!very_broken_program) { - UBYTE *dataptr = line_data[next_lineno]; + uae_u8 *dataptr = line_data[next_lineno]; for (i = 0; i < decided_nr_planes; i++, dataptr += MAX_WORDS_PER_LINE*2) { - CPTR pt = bplpt[i]; - UBYTE *real_ptr = pfield_xlateptr(pt, bytecount); + uaecptr pt = bplpt[i]; + uae_u8 *real_ptr = pfield_xlateptr(pt, bytecount); if (real_ptr == NULL) real_ptr = pfield_xlateptr(0, 0); #ifdef SMART_UPDATE - if (!line_changed[next_lineno]) - line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount); - else +#if 1 + if (line_changed[next_lineno]) memcpy (dataptr, real_ptr, bytecount); + else +#endif + line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount); #else real_bplpt[i] = real_ptr; #endif } } else { - UBYTE *dataptr = line_data[next_lineno]; + uae_u8 *dataptr = line_data[next_lineno]; for (i = 0; i < decided_nr_planes; i++, dataptr += MAX_WORDS_PER_LINE*2) { - CPTR pt = bplpt[i]; - UBYTE *real_ptr; - + uaecptr pt = bplpt[i]; + uae_u8 *real_ptr; + if (decided_hires) { switch (i) { case 3: pt -= 2; @@ -808,12 +960,15 @@ static void decide_modulos (void) } /* - * Call decide_plane() before calling this. + * Add the modulos to the bitplane pointers if data fetch is already + * finished for the current line. + * Call decide_plane() before calling this, so that we won't use the + * new values of the plane pointers for the current line. */ static void do_modulos (void) { /* decided_nr_planes is != -1 if this line should be drawn by the - * display hardware, regardless of whether it fits on the emulated screen. + * display hardware, regardless of whether it fits on the emulated screen. */ if (decided_nr_planes != -1 && plane_decided && !modulos_added && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen) @@ -833,7 +988,7 @@ static void do_modulos (void) case 2: bplpt[1] += add2; case 1: bplpt[0] += add1; } - } else if (bplhires) { + } else if (decided_hires) { /* @@@ used to be bplhires which is clearly wrong */ switch (decided_nr_planes) { case 8: bplpt[7] += add2; case 7: bplpt[6] += add1; @@ -843,7 +998,7 @@ static void do_modulos (void) case 3: bplpt[2] += add1 - (very_broken_program >= 3 ? 2 : 0); case 2: bplpt[1] += add2 - (very_broken_program >= 2 ? 2 : 0); case 1: bplpt[0] += add1; - } + } } else { switch (decided_nr_planes) { case 8: bplpt[7] += add2; @@ -854,83 +1009,106 @@ static void do_modulos (void) case 3: bplpt[2] += add1 - (very_broken_program >= 6 ? 2 : 0); case 2: bplpt[1] += add2 - (very_broken_program >= 4 ? 2 : 0); case 1: bplpt[0] += add1; - } + } } modulos_added = 1; } } -static void decide_sprite (int spr) +static __inline__ void record_sprite (int spr, int sprxp) { - int sprxp; + int pos = next_sprite_draw; + unsigned int data, datb; - if (framecnt != 0) +#ifdef OS_WITHOUT_MEMORY_MANAGEMENT + if(pos >= max_sprite_draw) { + ++delta_sprite_draw; return; + } +#endif + data = sprdata[spr]; + datb = sprdatb[spr]; - decide_diw (); - decide_line (); + /* XXX FIXME, this isn't very clever, but it might do */ + for (;;) { + if (pos == curr_drawinfo[next_lineno].first_sprite_draw) + break; + if (curr_sprite_positions[pos-1].linepos < sprxp) + break; + if (curr_sprite_positions[pos-1].linepos == sprxp + && curr_sprite_positions[pos-1].num > spr) + break; + printf("Foo\n"); + pos--; + } + if (pos != next_sprite_draw) { + int pos2 = next_sprite_draw; + while (pos2 != pos) { + curr_sprite_positions[pos2] = curr_sprite_positions[pos2-1]; + pos2--; + } + } + curr_sprite_positions[pos].linepos = sprxp; + curr_sprite_positions[pos].num = spr; + curr_sprite_positions[pos].ctl = sprctl[spr]; + curr_sprite_positions[pos].datab = ((sprtaba[data & 0xFF] << 16) | sprtaba[data >> 8] + | (sprtabb[datb & 0xFF] << 16) | sprtabb[datb >> 8]); + next_sprite_draw++; +} - if (!sprarmed[spr] || thisline_decision.which != 1 || current_hpos () < 0x14) - return; +static void decide_sprites (void) +{ + int nrs[8], posns[8], count, i; + int point = PIXEL_XPOS (current_hpos ()); - sprxp = sprxpos[spr]; - /* We _must_ check at the start of the sprite - we might avoid some - * unnecessary redraws by testing at the end, but that doesn't always - * work. */ - if (sprxp > PIXEL_XPOS (current_hpos ()) || sprite_last_drawn_at[spr] >= sprxp) + if (framecnt != 0 || current_hpos() < 0x14 || nr_armed == 0 || point == last_sprite_point) return; - - sprite_last_drawn_at[spr] = sprxp; - /* Ignore sprites outside the DIW. There is a small problem here when - * we haven't decided diwstart yet - but that should be very rare and - * drawing one sprite too much doesn't hurt all that much. - * We don't draw sprites with zero data, unless they might be attached - * sprites. */ - if (sprxp < 0 - || (thisline_decision.diwfirstword >= 0 && sprxp + sprite_width < thisline_decision.diwfirstword) - || (thisline_decision.diwlastword >= 0 && sprxp > thisline_decision.diwlastword) - || (sprdata[spr] == 0 && sprdatb[spr] == 0 && (sprctl[(spr & ~1)+1] & 0x80) == 0)) + decide_diw (); + decide_line (); + + if (thisline_decision.which != 1) return; -#ifdef OS_WITHOUT_MEMORY_MANAGEMENT - if(next_sprite_draw >= _max_sprite_draw) { - _max_sprite_draw = next_sprite_draw; - return; - } -#endif - curr_sprite_positions[next_sprite_draw].linepos = sprxp; - curr_sprite_positions[next_sprite_draw].num = spr; - curr_sprite_positions[next_sprite_draw].ctl = sprctl[spr]; - curr_sprite_positions[next_sprite_draw].data = sprdata[spr]; - curr_sprite_positions[next_sprite_draw++].datb = sprdatb[spr]; -} -static __inline__ void decide_sprite_1 (int spr) -{ - int sprxp = sprxpos[spr]; + count = 0; + for (i = 0; i < 8; i++) { + int sprxp = sprxpos[i]; + int j, bestp; - if (sprxp > max_diwlastword || sprite_last_drawn_at[spr] >= sprxp - || sprxp < 0 - || (thisline_decision.diwfirstword >= 0 && sprxp + sprite_width < thisline_decision.diwfirstword) - || (thisline_decision.diwlastword >= 0 && sprxp > thisline_decision.diwlastword) - || (sprdata[spr] == 0 && sprdatb[spr] == 0 && (sprctl[(spr & ~1)+1] & 0x80) == 0)) - return; + if (!sprarmed[i] || sprxp < 0 || sprxp > point || last_sprite_point >= sprxp) + continue; + if ((thisline_decision.diwfirstword >= 0 && sprxp + sprite_width < thisline_decision.diwfirstword) + || (thisline_decision.diwlastword >= 0 && sprxp > thisline_decision.diwlastword)) + continue; - curr_sprite_positions[next_sprite_draw].linepos = sprxp; - curr_sprite_positions[next_sprite_draw].num = spr; - curr_sprite_positions[next_sprite_draw].ctl = sprctl[spr]; - curr_sprite_positions[next_sprite_draw].data = sprdata[spr]; - curr_sprite_positions[next_sprite_draw++].datb = sprdatb[spr]; + for (bestp = 0; bestp < count; bestp++) { + if (posns[bestp] > sprxp) + break; + if (posns[bestp] == sprxp && nrs[bestp] < i) + break; + } + for (j = count; j > bestp; j--) { + posns[j] = posns[j-1]; + nrs[j] = nrs[j-1]; + } + posns[j] = sprxp; + nrs[j] = i; + count++; + } + for (i = 0; i < count; i++) + record_sprite(nrs[i], posns[i]); + last_sprite_point = point; } +/* End of a horizontal scan line. Finish off all decisions that were not + * made yet. */ static void finish_decisions (void) { struct draw_info *dip; struct draw_info *dip_old; struct decision *dp; int changed; - int i; if (framecnt != 0) return; @@ -938,6 +1116,16 @@ static void finish_decisions (void) decide_diw (); if (thisline_decision.which == 0) decide_line_1 (); + + /* Large DIWSTOP values can cause the stop position never to be + * reached, so the state machine always stays in the same state and + * there's a more-or-less full-screen DIW. */ + if (hdiwstate == DIW_waiting_stop) { + thisline_decision.diwlastword = max_diwlastword; + if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword) + MARK_LINE_CHANGED (next_lineno); + } + if (line_decisions[next_lineno].which != thisline_decision.which) line_changed[next_lineno] = 1; decide_plane (); @@ -953,15 +1141,8 @@ static void finish_decisions (void) if (diwfirstword < min_diwstart) min_diwstart = diwfirstword; - if (sprarmed[0]) decide_sprite_1 (0); - if (sprarmed[1]) decide_sprite_1 (1); - if (sprarmed[2]) decide_sprite_1 (2); - if (sprarmed[3]) decide_sprite_1 (3); - if (sprarmed[4]) decide_sprite_1 (4); - if (sprarmed[5]) decide_sprite_1 (5); - if (sprarmed[6]) decide_sprite_1 (6); - if (sprarmed[7]) decide_sprite_1 (7); - + decide_sprites(); + if (thisline_decision.bplcon1 != line_decisions[next_lineno].bplcon1) changed = 1; } @@ -969,10 +1150,13 @@ static void finish_decisions (void) dip->last_color_change = next_color_change; dip->last_delay_change = next_delay_change; dip->last_sprite_draw = next_sprite_draw; - - /* Must do this for border also... this should be more clever. FIXME */ - if (/*thisline_decision.which == 1 && */thisline_decision.ctable == -1) - remember_ctable (); + + if (thisline_decision.ctable == -1) { + if (thisline_decision.which == 1) + remember_ctable (); + else + remember_ctable_for_border (); + } if (thisline_decision.which == -1 && thisline_decision.color0 == 0xFFFFFFFFul) thisline_decision.color0 = current_colors.color_regs[0]; @@ -983,17 +1167,17 @@ static void finish_decisions (void) changed = 1; if (!changed && (dip->nr_color_changes != dip_old->nr_color_changes - || (dip->nr_color_changes > 0 - && fast_memcmp (curr_color_changes + dip->first_color_change, - prev_color_changes + dip_old->first_color_change, - dip->nr_color_changes * sizeof *curr_color_changes) != 0))) + || (dip->nr_color_changes > 0 + && memcmp (curr_color_changes + dip->first_color_change, + prev_color_changes + dip_old->first_color_change, + dip->nr_color_changes * sizeof *curr_color_changes) != 0))) changed = 1; if (!changed && thisline_decision.which == 1 && (dip->nr_sprites != dip_old->nr_sprites || (dip->nr_sprites > 0 - && fast_memcmp (curr_sprite_positions + dip->first_sprite_draw, - prev_sprite_positions + dip_old->first_sprite_draw, - dip->nr_sprites * sizeof *curr_sprite_positions) != 0))) + && memcmp (curr_sprite_positions + dip->first_sprite_draw, + prev_sprite_positions + dip_old->first_sprite_draw, + dip->nr_sprites * sizeof *curr_sprite_positions) != 0))) changed = 1; if (changed) { @@ -1004,10 +1188,9 @@ static void finish_decisions (void) dp->ctable = thisline_decision.ctable; } +/* Set the state of all decisions to "undecided" for a new scanline. */ static void reset_decisions (void) { - int i; - if (framecnt != 0) return; thisline_decision.which = 0; @@ -1018,6 +1201,11 @@ static void reset_decisions (void) /* decided_hires shouldn't be touched before it's initialized by decide_line(). */ thisline_decision.diwfirstword = -1; thisline_decision.diwlastword = -2; + if (hdiwstate == DIW_waiting_stop) { + thisline_decision.diwfirstword = PIXEL_XPOS (DISPLAY_LEFT_SHIFT/2); + if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) + MARK_LINE_CHANGED (next_lineno); + } thisline_decision.ctable = -1; thisline_decision.color0 = 0xFFFFFFFFul; @@ -1026,13 +1214,15 @@ static void reset_decisions (void) curr_drawinfo[next_lineno].first_delay_change = next_delay_change; curr_drawinfo[next_lineno].first_sprite_draw = next_sprite_draw; - memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); + /* memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); */ + last_sprite_point = 0; modulos_added = 0; plane_decided = 0; color_decided = 0; very_broken_program = 0; } +/* Initialize the decision array, once before the emulator really starts. */ static void init_decisions (void) { size_t i; @@ -1041,6 +1231,8 @@ static void init_decisions (void) } } +/* Calculate display window and data fetch values from the corresponding + * hardware registers. */ static void calcdiw (void) { diwfirstword = ((diwstrt & 0xFF) - DISPLAY_LEFT_SHIFT - 1) << lores_shift; @@ -1052,7 +1244,7 @@ static void calcdiw (void) diwfirstword = 0; if (diwlastword < 0) diwlastword = 0; - + plffirstline = diwstrt >> 8; plflastline = diwstop >> 8; #if 0 @@ -1072,6 +1264,7 @@ static void calcdiw (void) plfstrt = ddfstrt; plfstop = ddfstop; if (plfstrt < 0x18) plfstrt = 0x18; + if (plfstop < 0x18) plfstop = 0x18; if (plfstop > 0xD8) plfstop = 0xD8; if (plfstrt > plfstop) plfstrt = plfstop; @@ -1093,45 +1286,62 @@ static void calcdiw (void) * Screen update macros/functions */ +static unsigned int ham_lastcolor; + +static void init_ham_decoding(int first) +{ + int pix = dp_for_drawing->diwfirstword; + ham_lastcolor = colors_for_drawing.color_regs[0]; + while (pix < first) { + int pv = pixdata.apixels[pix]; + switch(pv & 0x30) { + case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break; + case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; + case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; + case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; + } + pix++; + } +} + static void decode_ham6 (int pix, int stoppos) { - static UWORD lastcolor; - ULONG *buf = ham_linebuf; + uae_u32 *buf = ham_linebuf; if (!bplham || bplplanecnt != 6) return; - + if (stoppos > dp_for_drawing->diwlastword) stoppos = dp_for_drawing->diwlastword; if (pix < dp_for_drawing->diwfirstword) { - lastcolor = colors_for_drawing.color_regs[0]; + ham_lastcolor = colors_for_drawing.color_regs[0]; pix = dp_for_drawing->diwfirstword; } #ifdef LORES_HACK - if (gfx_requested_lores == 2) + if (currprefs.gfx_lores == 2) pix <<= 1, stoppos <<= 1; #endif while (pix < stoppos) { int pv = pixdata.apixels[pix]; switch(pv & 0x30) { - case 0x00: lastcolor = colors_for_drawing.color_regs[pv]; break; - case 0x10: lastcolor &= 0xFF0; lastcolor |= (pv & 0xF); break; - case 0x20: lastcolor &= 0x0FF; lastcolor |= (pv & 0xF) << 8; break; - case 0x30: lastcolor &= 0xF0F; lastcolor |= (pv & 0xF) << 4; break; + case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break; + case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; + case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; + case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; } - buf[pix++] = lastcolor; - } + buf[pix++] = ham_lastcolor; + } } #if 0 static void decode_ham_aga (int pix, int stoppos) { - static ULONG lastcolor; - ULONG *buf = ham_linebuf; + static uae_u32 lastcolor; + uae_u32 *buf = ham_linebuf; if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8)) return; - + if (pix <= dp_for_drawing->diwfirstword) { pix = dp_for_drawing->diwfirstword; lastcolor = colors_for_drawing.color_regs[0]; @@ -1146,7 +1356,7 @@ static void decode_ham_aga (int pix, int case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break; case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break; case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break; - } + } buf[pix++] = lastcolor; } } else if (dp_for_drawing->bplplanecnt == 8) { @@ -1170,22 +1380,22 @@ static void decode_ham_aga (int pix, int static void pfield_linetoscr_aga(int pix, int stoppos) { - ULONG *buf = aga_lbufptr; + uae_u32 *buf = aga_lbufptr; int i; - int xor = (UBYTE)(bplcon4 >> 8); + int xor = (uae_u8)(bplcon4 >> 8); int oldpix = pix; \ buf -= pix; \ for (i = 0; i < stoppos; i++) pixdata.apixels[i] ^= xor; - + while (pix < diwfirstword && pix < stoppos) { buf[pix++] = colors_for_drawing.color_regs[0]; } if (bplham) { while (pix < diwlastword && pix < stoppos) { - ULONG d = ham_linebuf[pix]; + uae_u32 d = ham_linebuf[pix]; buf[pix] = d; pix++; } @@ -1196,12 +1406,12 @@ static void pfield_linetoscr_aga(int pix while (pix < diwlastword && pix < stoppos) { int pixcol = pixdata.apixels[pix]; int pfno = lookup_no[pixcol]; - + if (spixstate[pix]) { - buf[pix] = colors_for_drawing.color_regs[pixcol]; + buf[pix] = colors_for_drawing.color_regs[pixcol]; } else { int val = lookup[pixdata.apixels[pix]]; - if (pfno == 2) + if (pfno == 2) val += dblpfofs[(bplcon2 >> 10) & 7]; buf[pix] = colors_for_drawing.color_regs[val]; } @@ -1209,8 +1419,8 @@ static void pfield_linetoscr_aga(int pix } } else if (bplehb) { while (pix < diwlastword && pix < stoppos) { - int pixcol = pixdata.apixels[pix]; - ULONG d = colors_for_drawing.color_regs[pixcol]; + int pixcol = pixdata.apixels[pix]; + uae_u32 d = colors_for_drawing.color_regs[pixcol]; /* What about sprites? */ if (pixcol & 0x20) d = (d & 0x777777) >> 1; @@ -1232,16 +1442,16 @@ static void pfield_linetoscr_aga(int pix static void aga_translate32(int start, int stop) { - memcpy (((ULONG *)xlinebuffer) + start, aga_linebuf + start, 4*(stop-start)); + memcpy (((uae_u32 *)xlinebuffer) + start, aga_linebuf + start, 4*(stop-start)); } static void aga_translate16(int start, int stop) { int i; for (i = start; i < stop; i++) { - ULONG d = aga_linebuf[i]; - UWORD v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12); - ((UWORD *)xlinebuffer)[i] = xcolors[v]; + uae_u32 d = aga_linebuf[i]; + uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12); + ((uae_u16 *)xlinebuffer)[i] = xcolors[v]; } } @@ -1249,16 +1459,16 @@ static void aga_translate8(int start, in { int i; for (i = start; i < stop; i++) { - ULONG d = aga_linebuf[i]; - UWORD v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12); - ((UBYTE *)xlinebuffer)[i] = xcolors[v]; + uae_u32 d = aga_linebuf[i]; + uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12); + ((uae_u8 *)xlinebuffer)[i] = xcolors[v]; } } #endif static int linetoscr_double_offset; -#define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE) \ +#define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE, CONVERT) \ static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \ { \ TYPE *buf = ((TYPE *)xlinebuffer); \ @@ -1269,7 +1479,7 @@ static void NAME(int pix, int lframe_end \ if (DO_DOUBLE) offset = linetoscr_double_offset / sizeof(TYPE); \ \ - d1 = colors_for_drawing.acolors[0]; \ + d1 = CONVERT(colors_for_drawing.acolors[0]); \ while (pix < lframe_end) { \ buf[pix] = d1; if (DO_DOUBLE) buf[pix+offset] = d1; \ pix++; \ @@ -1277,7 +1487,7 @@ static void NAME(int pix, int lframe_end if (bplham && bplplanecnt == 6) { \ /* HAM 6 */ \ while (pix < diw_end) { \ - TYPE d = xcolors[ham_linebuf[pix]]; \ + TYPE d = CONVERT(xcolors[ham_linebuf[pix]]); \ buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ pix++; \ } \ @@ -1287,66 +1497,150 @@ static void NAME(int pix, int lframe_end while (pix < diw_end) { \ int pixcol = pixdata.apixels[pix]; \ TYPE d; \ - if (spixstate[pix]) { \ - d = colors_for_drawing.acolors[pixcol]; \ - } else { \ - d = colors_for_drawing.acolors[lookup[pixcol]]; \ - } \ + d = CONVERT(colors_for_drawing.acolors[lookup[pixcol]]); \ buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ pix++; \ } \ } else if (bplehb) { \ while (pix < diw_end) { \ int p = pixdata.apixels[pix]; \ - TYPE d = colors_for_drawing.acolors[p]; \ - if (p > 32) d = xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]; \ + TYPE d = CONVERT (colors_for_drawing.acolors[p]); \ + if (p >= 32) d = CONVERT(xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]); \ buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ pix++; \ } \ } else { \ while (pix < diw_end) { \ - TYPE d = colors_for_drawing.acolors[pixdata.apixels[pix]]; \ + TYPE d = CONVERT (colors_for_drawing.acolors[pixdata.apixels[pix]]); \ buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ pix++; \ } \ } \ - d2 = colors_for_drawing.acolors[0]; \ + d2 = CONVERT (colors_for_drawing.acolors[0]); \ while (pix < stoppos) { \ buf[pix] = d2; if (DO_DOUBLE) buf[pix+offset] = d2; \ pix++; \ } \ } -#define FILL_LINE(NAME, TYPE) \ +#define FILL_LINE(NAME, TYPE, CONVERT) \ static void NAME(char *buf, int start, int stop) \ { \ TYPE *b = (TYPE *)buf; \ int i;\ xcolnr col = colors_for_drawing.acolors[0]; \ for (i = start; i < stop; i++) \ - b[i] = col; \ + b[i] = CONVERT (col); \ } -LINE_TO_SCR(pfield_linetoscr_8, UBYTE, 0) -LINE_TO_SCR(pfield_linetoscr_16, UWORD, 0) -LINE_TO_SCR(pfield_linetoscr_32, ULONG, 0) -LINE_TO_SCR(pfield_linetoscr_8_double_slow, UBYTE, 1) -LINE_TO_SCR(pfield_linetoscr_16_double_slow, UWORD, 1) -LINE_TO_SCR(pfield_linetoscr_32_double_slow, ULONG, 1) - -FILL_LINE(fill_line_8, UBYTE) -FILL_LINE(fill_line_16, UWORD) -FILL_LINE(fill_line_32, ULONG) +LINE_TO_SCR(pfield_linetoscr_8, uae_u8, 0,) +LINE_TO_SCR(pfield_linetoscr_16, uae_u16, 0,) +LINE_TO_SCR(pfield_linetoscr_32, uae_u32, 0,) +LINE_TO_SCR(pfield_linetoscr_8_double_slow, uae_u8, 1,) +LINE_TO_SCR(pfield_linetoscr_16_double_slow, uae_u16, 1,) +LINE_TO_SCR(pfield_linetoscr_32_double_slow, uae_u32, 1,) + +FILL_LINE(fill_line_8, uae_u8,) +FILL_LINE(fill_line_16, uae_u16,) +FILL_LINE(fill_line_32, uae_u32,) + +#ifdef HAVE_UAE_U24 +LINE_TO_SCR(pfield_linetoscr_24, uae_u24, 0, uae24_convert) +LINE_TO_SCR(pfield_linetoscr_24_double_slow, uae_u24, 1, uae24_convert) +FILL_LINE(fill_line_24, uae_u24, uae24_convert) +#else +/* Dummy versions */ +static void pfield_linetoscr_24 (int pix, int lframe_end, int diw_end, int stoppos) +{ +} +static void pfield_linetoscr_24_double_slow (int pix, int lframe_end, int diw_end, int stoppos) +{ +} +static void fill_line_24 (char *buf, int start, int stop) +{ +} +#endif + +static __inline__ void fill_line_full (void) +{ + switch (gfxvidinfo.pixbytes) { + case 1: fill_line_8(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; + case 2: fill_line_16(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; + case 3: fill_line_24(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; + case 4: fill_line_32(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; + } +} + +#define fill_line fill_line_full #define pfield_linetoscr_full8 pfield_linetoscr_8 #define pfield_linetoscr_full16 pfield_linetoscr_16 +#define pfield_linetoscr_full24 pfield_linetoscr_24 #define pfield_linetoscr_full32 pfield_linetoscr_32 #define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow #define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow +#define pfield_linetoscr_full24_double pfield_linetoscr_24_double_slow #define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow #if 1 && defined(X86_ASSEMBLY) +/* This version of fill_line is probably a win on all machines, but for + * now I'm cautious */ +#undef fill_line +static __inline__ void fill_line (void) +{ + int shift; + int nints, nrem; + int *start; + xcolnr val; + +#ifdef HAVE_UAE_U24 + if (gfxvidinfo.pixbytes == 3) { + fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); + return; + } +#endif + + shift = 0; + if (gfxvidinfo.pixbytes == 2) + shift = 1; + if (gfxvidinfo.pixbytes == 4) + shift = 2; + + nints = gfxvidinfo.width >> (2-shift); + nrem = nints & 7; + nints &= ~7; + start = (int *)(((char *)xlinebuffer) + (linetoscr_x_adjust << shift)); + val = colors_for_drawing.acolors[0]; + for (; nints > 0; nints -= 8, start+=8) { + *start = val; + *(start+1) = val; + *(start+2) = val; + *(start+3) = val; + *(start+4) = val; + *(start+5) = val; + *(start+6) = val; + *(start+7) = val; + } + + switch (nrem) { + case 7: + *start++ = val; + case 6: + *start++ = val; + case 5: + *start++ = val; + case 4: + *start++ = val; + case 3: + *start++ = val; + case 2: + *start++ = val; + case 1: + *start = val; + } +} + #undef pfield_linetoscr_full8 /* The types are lies, of course. */ extern void pfield_linetoscr_normal_asm8(void) __asm__("pfield_linetoscr_normal_asm8"); @@ -1354,6 +1648,8 @@ extern void pfield_linetoscr_ehb_asm8(vo extern void pfield_linetoscr_ham6_asm8(void) __asm__("pfield_linetoscr_ham6_asm8"); extern void pfield_linetoscr_dualpf_asm8(void) __asm__("pfield_linetoscr_dualpf_asm8"); extern void pfield_linetoscr_hdouble_asm8(void) __asm__("pfield_linetoscr_hdouble_asm8"); +extern void pfield_linetoscr_hdouble_dpf_asm8(void) __asm__("pfield_linetoscr_hdouble_dpf_asm8"); +extern void pfield_linetoscr_hdouble_ehb_asm8(void) __asm__("pfield_linetoscr_hdouble_ehb_asm8"); extern void pfield_linetoscr_asm8(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm8"); static void pfield_linetoscr_full8(int pix, int lframe_end, int diw_end, int stoppos) @@ -1366,18 +1662,30 @@ static void pfield_linetoscr_full8(int p if (bplham && bplplanecnt == 6) { pfield_linetoscr_asm8(pfield_linetoscr_ham6_asm8, pix, lframe_end_1, diw_end_1, stoppos); } else if (bpldualpf) { - pfield_linetoscr_asm8(pfield_linetoscr_dualpf_asm8, pix, lframe_end_1, diw_end_1, stoppos, - bpldualpfpri ? dblpf_ind2 : dblpf_ind1); +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm8(pfield_linetoscr_hdouble_dpf_asm8, pix, lframe_end_1, diw_end_1, stoppos, + bpldualpfpri ? dblpf_ind2 : dblpf_ind1); + else +#endif + pfield_linetoscr_asm8(pfield_linetoscr_dualpf_asm8, pix, lframe_end_1, diw_end_1, stoppos, + bpldualpfpri ? dblpf_ind2 : dblpf_ind1); } else if (bplehb) { - pfield_linetoscr_asm8(pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos); #ifdef LORES_HACK - } else if (gfx_requested_lores == 2) { - pfield_linetoscr_asm8(pfield_linetoscr_hdouble_asm8, pix, lframe_end_1, diw_end_1, stoppos); + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm8(pfield_linetoscr_hdouble_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos); + else #endif + pfield_linetoscr_asm8(pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos); } else { - pfield_linetoscr_asm8(pfield_linetoscr_normal_asm8, pix, lframe_end_1, diw_end_1, stoppos); +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm8(pfield_linetoscr_hdouble_asm8, pix, lframe_end_1, diw_end_1, stoppos); + else +#endif + pfield_linetoscr_asm8(pfield_linetoscr_normal_asm8, pix, lframe_end_1, diw_end_1, stoppos); } - + /* The assembly functions work on aligned data, so we may have to do some * additional work at the edges. */ if (lframe_end != lframe_end_1) { @@ -1398,6 +1706,8 @@ extern void pfield_linetoscr_ehb_asm16(v extern void pfield_linetoscr_ham6_asm16(void) __asm__("pfield_linetoscr_ham6_asm16"); extern void pfield_linetoscr_dualpf_asm16(void) __asm__("pfield_linetoscr_dualpf_asm16"); extern void pfield_linetoscr_hdouble_asm16(void) __asm__("pfield_linetoscr_hdouble_asm16"); +extern void pfield_linetoscr_hdouble_dpf_asm16(void) __asm__("pfield_linetoscr_hdouble_dpf_asm16"); +extern void pfield_linetoscr_hdouble_ehb_asm16(void) __asm__("pfield_linetoscr_hdouble_ehb_asm16"); extern void pfield_linetoscr_asm16(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm16"); static void pfield_linetoscr_full16(int pix, int lframe_end, int diw_end, int stoppos) @@ -1410,16 +1720,28 @@ static void pfield_linetoscr_full16(int if (bplham && bplplanecnt == 6) { pfield_linetoscr_asm16(pfield_linetoscr_ham6_asm16, pix, lframe_end_1, diw_end_1, stoppos); } else if (bpldualpf) { - pfield_linetoscr_asm16(pfield_linetoscr_dualpf_asm16, pix, lframe_end_1, diw_end_1, stoppos, - bpldualpfpri ? dblpf_ind2 : dblpf_ind1); +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm16(pfield_linetoscr_hdouble_dpf_asm16, pix, lframe_end_1, diw_end_1, stoppos, + bpldualpfpri ? dblpf_ind2 : dblpf_ind1); + else +#endif + pfield_linetoscr_asm16(pfield_linetoscr_dualpf_asm16, pix, lframe_end_1, diw_end_1, stoppos, + bpldualpfpri ? dblpf_ind2 : dblpf_ind1); } else if (bplehb) { - pfield_linetoscr_asm16(pfield_linetoscr_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos); #ifdef LORES_HACK - } else if (gfx_requested_lores == 2) { - pfield_linetoscr_asm16(pfield_linetoscr_hdouble_asm16, pix, lframe_end_1, diw_end_1, stoppos); + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm16(pfield_linetoscr_hdouble_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos); + else #endif + pfield_linetoscr_asm16(pfield_linetoscr_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos); } else { - pfield_linetoscr_asm16(pfield_linetoscr_normal_asm16, pix, lframe_end_1, diw_end_1, stoppos); +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + pfield_linetoscr_asm16(pfield_linetoscr_hdouble_asm16, pix, lframe_end_1, diw_end_1, stoppos); + else +#endif + pfield_linetoscr_asm16(pfield_linetoscr_normal_asm16, pix, lframe_end_1, diw_end_1, stoppos); } /* The assembly functions work on aligned data, so we may have to do some @@ -1427,12 +1749,12 @@ static void pfield_linetoscr_full16(int if (lframe_end != lframe_end_1) { int i, c = colors_for_drawing.acolors[0]; for (i = lframe_end_1; i < lframe_end; i++) - ((UWORD *)xlinebuffer)[i] = c; + ((uae_u16 *)xlinebuffer)[i] = c; } if (diw_end != diw_end_1) { int i, c = colors_for_drawing.acolors[0]; for (i = diw_end; i < diw_end_1; i++) - ((UWORD *)xlinebuffer)[i] = c; + ((uae_u16 *)xlinebuffer)[i] = c; } } @@ -1461,17 +1783,13 @@ static void pfield_linetoscr_full16_doub } #endif -static __inline__ void fill_line(void) -{ - switch (gfxvidinfo.pixbytes) { - case 1: fill_line_8(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.maxlinetoscr); break; - case 2: fill_line_16(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.maxlinetoscr); break; - case 4: fill_line_32(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.maxlinetoscr); break; - } -} - static int linetoscr_diw_end, linetoscr_diw_start; +/* Initialize the variables necessary for drawing a line. + * This involves setting up start/stop positions and display window + * borders. Also, since the drawing code may not fully overwrite all + * releveant areas in the pixdata.apixels array for speed reasons, parts of + * it must possibly be cleared here. */ static void pfield_init_linetoscr (void) { int ddf_left, ddf_right; @@ -1484,13 +1802,13 @@ static void pfield_init_linetoscr (void) /* We should really look at DDF also when calculating max_diwstop/min_diwstrt, * so that centering works better, but I'm afraid that might cost too many - * cycles. Plus it's dangerous, see the code below that handles the case + * cycles. Plus it's dangerous, see the code below that handles the case * with sprites. */ if (dip_for_drawing->nr_sprites == 0) { int hiresadjust = bplhires ? 4 : 8; ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift; ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift; - + if (linetoscr_diw_start < ddf_left) linetoscr_diw_start = ddf_left; if (linetoscr_diw_end > ddf_right) @@ -1502,7 +1820,10 @@ static void pfield_init_linetoscr (void) * cleared. We could do this exactly, but it would come out slower * because of the overhead. */ int strt = ddf_left; - if (gfx_requested_lores) { + if (currprefs.gfx_lores == 2) { + fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_left>>1), 15); + fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_right>>1) - 15, 15); + } else if (currprefs.gfx_lores) { fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 15); fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 15, 15); } else { @@ -1521,7 +1842,7 @@ static void pfield_init_linetoscr (void) int strt = linetoscr_diw_start; int stop = ddf_left; #ifdef LORES_HACK - if (gfx_requested_lores == 2) + if (currprefs.gfx_lores == 2) strt >>= 1, stop >>= 1; #endif if (strt < stop) @@ -1532,7 +1853,7 @@ static void pfield_init_linetoscr (void) int strt = ddf_right; int stop = linetoscr_diw_end; #ifdef LORES_HACK - if (gfx_requested_lores == 2) + if (currprefs.gfx_lores == 2) strt >>= 1, stop >>= 1; #endif if (strt < stop) @@ -1552,7 +1873,7 @@ static void pfield_do_linetoscr(int star stop = linetoscr_right_x; if (start < linetoscr_x_adjust) start = linetoscr_x_adjust; - + if (lframe_end < start) lframe_end = start; if (diw_end > stop) @@ -1566,12 +1887,14 @@ static void pfield_do_linetoscr(int star switch (gfxvidinfo.pixbytes) { case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break; case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break; + case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break; case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break; } } else { switch (gfxvidinfo.pixbytes) { case 1: pfield_linetoscr_8 (start, lframe_end, diw_end, stop); break; case 2: pfield_linetoscr_16 (start, lframe_end, diw_end, stop); break; + case 3: pfield_linetoscr_24 (start, lframe_end, diw_end, stop); break; case 4: pfield_linetoscr_32 (start, lframe_end, diw_end, stop); break; } } @@ -1593,13 +1916,14 @@ static void pfield_do_fill_line(int star switch (gfxvidinfo.pixbytes) { case 1: fill_line_8 (xlinebuffer, start, stop); break; case 2: fill_line_16 (xlinebuffer, start, stop); break; + case 3: fill_line_24 (xlinebuffer, start, stop); break; case 4: fill_line_32 (xlinebuffer, start, stop); break; } } static void pfield_do_linetoscr_full(int double_line) { - int start = linetoscr_x_adjust, stop = start + gfxvidinfo.maxlinetoscr; + int start = linetoscr_x_adjust, stop = start + gfxvidinfo.width; int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end; if (lframe_end < start) lframe_end = start; @@ -1611,12 +1935,14 @@ static void pfield_do_linetoscr_full(int switch (gfxvidinfo.pixbytes) { case 1: pfield_linetoscr_full8_double (start, lframe_end, diw_end, stop); break; case 2: pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); break; + case 3: pfield_linetoscr_full24_double (start, lframe_end, diw_end, stop); break; case 4: pfield_linetoscr_full32_double (start, lframe_end, diw_end, stop); break; } - } else + } else switch (gfxvidinfo.pixbytes) { case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break; case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break; + case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break; case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break; } #else @@ -1624,22 +1950,156 @@ static void pfield_do_linetoscr_full(int #endif } - /* +/* Mouse stuff */ +static void setdontcare(void) +{ + write_log ("Don't care mouse mode set\n"); + mousestate = dont_care_mouse; + lastspr0x = lastmx; lastspr0y = lastmy; + mstepx = defstepx; mstepy = defstepy; +} + +static void setfollow(void) +{ + write_log ("Follow sprite mode set\n"); + mousestate = follow_mouse; + lastdiffx = lastdiffy = 0; + sprvbfl = 0; + spr0ctl=spr0pos = 0; + mstepx = defstepx; mstepy = defstepy; +} + +uae_u32 mousehack_helper (void) +{ + int mousexpos, mouseypos; + +#ifdef PICASSO96 + if (picasso_on) { + mousexpos = lastmx + picasso96_state.XOffset; + mouseypos = lastmy + picasso96_state.YOffset; + } else +#endif + { + mousexpos = lastmx + linetoscr_x_adjust; + if (lastmy >= gfxvidinfo.height) + lastmy = gfxvidinfo.height-1; + mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline; + mouseypos <<= 1; + mousexpos <<= (1-lores_shift); + mousexpos += 2*DISPLAY_LEFT_SHIFT; + } + + switch (m68k_dreg (regs, 0)) { + case 0: + return ievent_alive ? -1 : needmousehack (); + case 1: + ievent_alive = 10; + return mousexpos; + case 2: + return mouseypos; + } + return 0; +} + +void togglemouse(void) +{ + switch(mousestate) { + case dont_care_mouse: setfollow(); break; + case follow_mouse: setdontcare(); break; + default: break; /* Nnnnnghh! */ + } +} + +static __inline__ int adjust(int val) +{ + if (val>127) + return 127; + else if (val<-127) + return -127; + return val; +} + +static void do_mouse_hack(void) +{ + int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1); + int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1; + int diffx, diffy; + + if (ievent_alive > 0) { + mouse_x = mouse_y = 0; + return; + } + switch (mousestate) { + case normal_mouse: + diffx = lastmx - lastsampledmx; + diffy = lastmy - lastsampledmy; + if (!newmousecounters) { + if (diffx > 127) diffx = 127; + if (diffx < -127) diffx = -127; + mouse_x += diffx; + if (diffy > 127) diffy = 127; + if (diffy < -127) diffy = -127; + mouse_y += diffy; + } + lastsampledmx += diffx; lastsampledmy += diffy; + break; + + case dont_care_mouse: + diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16); + diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16); + lastspr0x=lastmx; lastspr0y=lastmy; + mouse_x+=diffx; mouse_y+=diffy; + break; + + case follow_mouse: + if (sprvbfl && sprvbfl-- >1) { + int mousexpos, mouseypos; + + if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x + && spr0x > plfstrt*4 + 34 + xcaloff && spr0x < plfstop*4 - xcaloff) + { + int val = (lastdiffx << 16) / (spr0x - lastspr0x); + if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight; + } + if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y + && spr0y>plffirstline+ycaloff && spr0y=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight; + } + mousexpos = lastmx + linetoscr_x_adjust; + if (lastmy >= gfxvidinfo.height) + lastmy = gfxvidinfo.height-1; + mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline; + mouseypos <<= 1; + mousexpos <<= (1-lores_shift); + mousexpos += 2*DISPLAY_LEFT_SHIFT; + diffx = adjust ((((mousexpos + xoffs - spr0x) & ~1) * mstepx) >> 16); + diffy = adjust ((((mouseypos + yoffs - spr0y) & ~1) * mstepy) >> 16); + lastspr0x=spr0x; lastspr0y=spr0y; + lastdiffx=diffx; lastdiffy=diffy; + mouse_x+=diffx; mouse_y+=diffy; + } + break; + } +} + + /* * register functions */ -UWORD DMACONR(void) +__inline__ uae_u16 DMACONR(void) { return (dmacon | (bltstate==BLT_done ? 0 : 0x4000) | (blt_info.blitzero ? 0x2000 : 0)); } -static UWORD INTENAR(void) { return intena; } -UWORD INTREQR(void) +static __inline__ uae_u16 INTENAR(void) { return intena; } +uae_u16 INTREQR(void) { - return intreq | (use_serial ? 0x0001 : 0); + return intreq | (currprefs.use_serial ? 0x0001 : 0); } -static UWORD ADKCONR(void) { return adkcon; } -static UWORD VPOSR(void) +static __inline__ uae_u16 ADKCONR(void) { return adkcon; } +static __inline__ uae_u16 VPOSR(void) { #if AGA_CHIPSET == 1 return (vpos >> 8) | lof | 0x2300; @@ -1649,70 +2109,67 @@ static UWORD VPOSR(void) return (vpos >> 8) | lof; #endif } -static void VPOSW(UWORD v) +static void VPOSW(uae_u16 v) { if (lof != (v & 0x8000)) lof_changed = 1; lof = v & 0x8000; + /* + * This register is much more fun on a real Amiga. You can program + * refresh rates with it ;) But I won't emulate this... + */ } -static UWORD VHPOSR(void) { return (vpos << 8) | current_hpos(); } +static __inline__ uae_u16 VHPOSR(void) { return (vpos << 8) | current_hpos(); } -static void COP1LCH(UWORD v) { cop1lc= (cop1lc & 0xffff) | ((ULONG)v << 16); } -static void COP1LCL(UWORD v) { cop1lc= (cop1lc & ~0xffff) | v; } -static void COP2LCH(UWORD v) { cop2lc= (cop2lc & 0xffff) | ((ULONG)v << 16); } -static void COP2LCL(UWORD v) { cop2lc= (cop2lc & ~0xffff) | v; } +static __inline__ void COP1LCH(uae_u16 v) { cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16); } +static __inline__ void COP1LCL(uae_u16 v) { cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe); } +static __inline__ void COP2LCH(uae_u16 v) { cop2lc = (cop2lc & 0xffff) | ((uae_u32)v << 16); } +static __inline__ void COP2LCL(uae_u16 v) { cop2lc = (cop2lc & ~0xffff) | (v & 0xfffe); } -static void COPJMP1(UWORD a) +static void COPJMP1(uae_u16 a) { - coplc = cop1lc; copstate = COP_read; + coplc = cop1lc; copstate = COP_read; eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles; eventtab[ev_copper].evtime = 4 + cycles; events_schedule(); copper_active = 1; copper_waiting_for_blitter = 0; } -static void COPJMP2(UWORD a) +static void COPJMP2(uae_u16 a) { - coplc = cop2lc; copstate = COP_read; + coplc = cop2lc; copstate = COP_read; eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles; eventtab[ev_copper].evtime = 4 + cycles; events_schedule(); copper_active = 1; copper_waiting_for_blitter = 0; } -static void COPCON(UWORD a) { copcon = a; } -static void DMACON(UWORD v) +static __inline__ void COPCON(uae_u16 a) { copcon = a; } +static void DMACON(uae_u16 v) { int i, need_resched = 0; - UWORD oldcon = dmacon; - + uae_u16 oldcon = dmacon; + decide_line(); setclr(&dmacon,v); dmacon &= 0x1FFF; - post_decide_line (); - - /* FIXME? Maybe we need to think a bit more about the master DMA enable + /* ??? post_decide_line (); */ + + /* FIXME? Maybe we need to think a bit more about the master DMA enable * bit in these cases. */ - if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) { + if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) { COPJMP1(0); } -#if 0 /* @@@ ??? Is this right now? */ - if ((dmacon & DMA_SPRITE) < (oldcon & DMA_SPRITE)) { - int i; - for (i = 0; i < 8; i++) - spron[i] = SPR_restart; - } -#endif if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) { static int count = 0; if (!count) { count = 1; - fprintf(stderr, "warning: program is doing blitpri hacks.\n"); + write_log ("warning: program is doing blitpri hacks.\n"); } regs.spcflags |= SPCFLAG_BLTNASTY; } #ifndef DONT_WANT_SOUND for (i = 0; i < 4; i++) { struct audio_channel_data *cdp = audio_channel + i; - + cdp->dmaen = (dmacon & 0x200) && (dmacon & (1<dmaen) { if (cdp->state == 0) { @@ -1747,27 +2204,48 @@ static void DMACON(UWORD v) events_schedule(); } -static int trace_intena = 0; +/*static int trace_intena = 0;*/ -static void INTENA(UWORD v) +static __inline__ void INTENA (uae_u16 v) { - if (trace_intena) - fprintf(stderr, "INTENA: %04x\n", v); - setclr(&intena,v); regs.spcflags |= SPCFLAG_INT; +/* if (trace_intena) + fprintf(stderr, "INTENA: %04x\n", v);*/ + setclr(&intena,v); regs.spcflags |= SPCFLAG_INT; } -void INTREQ(UWORD v) +void INTREQ (uae_u16 v) { - setclr(&intreq,v); - regs.spcflags |= SPCFLAG_INT; - if ((v&0x8800)==0x0800) serdat&=0xbfff; - } + setclr(&intreq,v); + regs.spcflags |= SPCFLAG_INT; + if ((v&0x8800)==0x0800) serdat&=0xbfff; +} -static void ADKCON(UWORD v) { setclr(&adkcon,v); } +static void ADKCON (uae_u16 v) +{ + unsigned long t; + setclr (&adkcon,v); + t = adkcon | (adkcon >> 4); + audio_channel[0].adk_mask = (((t >> 0) & 1) - 1); + audio_channel[1].adk_mask = (((t >> 1) & 1) - 1); + audio_channel[2].adk_mask = (((t >> 2) & 1) - 1); + audio_channel[3].adk_mask = (((t >> 3) & 1) - 1); +} -static void BPLPTH(UWORD v, int num) { decide_line (); decide_plane(); do_modulos(); bplpt[num] = (bplpt[num] & 0xffff) | ((ULONG)v << 16); } -static void BPLPTL(UWORD v, int num) { decide_line (); decide_plane(); do_modulos(); bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xFFFE); } +static void BPLPTH (uae_u16 v, int num) +{ + decide_line (); + decide_plane(); + do_modulos(); + bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16); +} +static void BPLPTL (uae_u16 v, int num) +{ + decide_line (); + decide_plane(); + do_modulos(); + bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xfffe); +} -static void BPLCON0(UWORD v) +static void BPLCON0 (uae_u16 v) { #if AGA_CHIPSET == 0 v &= 0xFF0E; @@ -1783,13 +2261,15 @@ static void BPLCON0(UWORD v) return; decide_line (); bplcon0 = v; + nr_planes_from_bplcon0 = (bplcon0 >> 12) & 7; + corrected_nr_planes_from_bplcon0 = ((bplcon0 >> 12) & 7) << (bplcon0 & 0x8000 ? 1 : 0); post_decide_line (); calculate_copper_cycle_time (); #if 0 calcdiw(); /* This should go away. */ #endif } -static void BPLCON1(UWORD v) +static __inline__ void BPLCON1 (uae_u16 v) { if (bplcon1 == v) return; @@ -1797,77 +2277,77 @@ static void BPLCON1(UWORD v) bplcon1 = v; decide_delay (); } -static void BPLCON2(UWORD v) +static __inline__ void BPLCON2 (uae_u16 v) { if (bplcon2 != v) decide_line (); bplcon2 = v; } -static void BPLCON3(UWORD v) +static __inline__ void BPLCON3 (uae_u16 v) { if (bplcon3 != v) decide_line (); - bplcon3 = v; + bplcon3 = v; } -static void BPLCON4(UWORD v) +static __inline__ void BPLCON4 (uae_u16 v) { if (bplcon4 != v) decide_line (); - bplcon4 = v; + bplcon4 = v; } -static void BPL1MOD(UWORD v) +static void BPL1MOD (uae_u16 v) { v &= ~1; - if ((WORD)bpl1mod == (WORD)v) + if ((uae_s16)bpl1mod == (uae_s16)v) return; bpl1mod = v; decide_modulos (); } -static void BPL2MOD(UWORD v) -{ +static void BPL2MOD (uae_u16 v) +{ v &= ~1; - if ((WORD)bpl2mod == (WORD)v) + if ((uae_s16)bpl2mod == (uae_s16)v) return; bpl2mod = v; decide_modulos(); } /* We could do as well without those... */ -static void BPL1DAT(UWORD v) { bpl1dat = v; } -static void BPL2DAT(UWORD v) { bpl2dat = v; } -static void BPL3DAT(UWORD v) { bpl3dat = v; } -static void BPL4DAT(UWORD v) { bpl4dat = v; } -static void BPL5DAT(UWORD v) { bpl5dat = v; } -static void BPL6DAT(UWORD v) { bpl6dat = v; } +static __inline__ void BPL1DAT (uae_u16 v) { bpl1dat = v; } +static __inline__ void BPL2DAT (uae_u16 v) { bpl2dat = v; } +static __inline__ void BPL3DAT (uae_u16 v) { bpl3dat = v; } +static __inline__ void BPL4DAT (uae_u16 v) { bpl4dat = v; } +static __inline__ void BPL5DAT (uae_u16 v) { bpl5dat = v; } +static __inline__ void BPL6DAT (uae_u16 v) { bpl6dat = v; } -static void DIWSTRT(UWORD v) +static void DIWSTRT (uae_u16 v) { if (diwstrt == v) return; decide_line (); - diwstrt = v; + diwstrt = v; calcdiw(); } -static void DIWSTOP(UWORD v) +static void DIWSTOP (uae_u16 v) { if (diwstop == v) return; - diwstop = v; + diwstop = v; calcdiw(); } -static void DDFSTRT(UWORD v) -{ +static void DDFSTRT (uae_u16 v) +{ v &= 0xFF; if (ddfstrt == v) return; decide_line (); - ddfstrt = v; + ddfstrt = v; calcdiw(); } -static void DDFSTOP(UWORD v) -{ +static void DDFSTOP (uae_u16 v) +{ v &= 0xFF; if (ddfstop == v) return; @@ -1876,7 +2356,7 @@ static void DDFSTOP(UWORD v) calcdiw(); } -static void BLTADAT(UWORD v) +static void BLTADAT(uae_u16 v) { maybe_blit(); @@ -1887,9 +2367,9 @@ static void BLTADAT(UWORD v) * be true for BLTBDAT, but not for BLTADAT - it appears the A data must be * loaded for every word so that AFWM and ALWM can be applied. */ -static void BLTBDAT(UWORD v) +static void BLTBDAT(uae_u16 v) { - maybe_blit(); + maybe_blit(); if (bltcon1 & 2) blt_info.bltbhold = v << (bltcon1 >> 12); @@ -1897,50 +2377,50 @@ static void BLTBDAT(UWORD v) blt_info.bltbhold = v >> (bltcon1 >> 12); blt_info.bltbdat = v; } -static void BLTCDAT(UWORD v) { maybe_blit(); blt_info.bltcdat = v; } +static void BLTCDAT(uae_u16 v) { maybe_blit(); blt_info.bltcdat = v; } -static void BLTAMOD(UWORD v) { maybe_blit(); blt_info.bltamod = (WORD)(v & 0xFFFE); } -static void BLTBMOD(UWORD v) { maybe_blit(); blt_info.bltbmod = (WORD)(v & 0xFFFE); } -static void BLTCMOD(UWORD v) { maybe_blit(); blt_info.bltcmod = (WORD)(v & 0xFFFE); } -static void BLTDMOD(UWORD v) { maybe_blit(); blt_info.bltdmod = (WORD)(v & 0xFFFE); } +static void BLTAMOD(uae_u16 v) { maybe_blit(); blt_info.bltamod = (uae_s16)(v & 0xFFFE); } +static void BLTBMOD(uae_u16 v) { maybe_blit(); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); } +static void BLTCMOD(uae_u16 v) { maybe_blit(); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); } +static void BLTDMOD(uae_u16 v) { maybe_blit(); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); } -static void BLTCON0(UWORD v) { maybe_blit(); bltcon0 = v; blinea_shift = v >> 12; } -/* The next category is "Most useless hardware register". +static void BLTCON0(uae_u16 v) { maybe_blit(); bltcon0 = v; blinea_shift = v >> 12; } +/* The next category is "Most useless hardware register". * And the winner is... */ -static void BLTCON0L(UWORD v) { maybe_blit(); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); } -static void BLTCON1(UWORD v) { maybe_blit(); bltcon1 = v; } +static void BLTCON0L(uae_u16 v) { maybe_blit(); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); } +static void BLTCON1(uae_u16 v) { maybe_blit(); bltcon1 = v; } -static void BLTAFWM(UWORD v) { maybe_blit(); blt_info.bltafwm = v; } -static void BLTALWM(UWORD v) { maybe_blit(); blt_info.bltalwm = v; } +static void BLTAFWM(uae_u16 v) { maybe_blit(); blt_info.bltafwm = v; } +static void BLTALWM(uae_u16 v) { maybe_blit(); blt_info.bltalwm = v; } -static void BLTAPTH(UWORD v) { maybe_blit(); bltapt= (bltapt & 0xffff) | ((ULONG)v << 16); } -static void BLTAPTL(UWORD v) { maybe_blit(); bltapt= (bltapt & ~0xffff) | (v & 0xFFFE); } -static void BLTBPTH(UWORD v) { maybe_blit(); bltbpt= (bltbpt & 0xffff) | ((ULONG)v << 16); } -static void BLTBPTL(UWORD v) { maybe_blit(); bltbpt= (bltbpt & ~0xffff) | (v & 0xFFFE); } -static void BLTCPTH(UWORD v) { maybe_blit(); bltcpt= (bltcpt & 0xffff) | ((ULONG)v << 16); } -static void BLTCPTL(UWORD v) { maybe_blit(); bltcpt= (bltcpt & ~0xffff) | (v & 0xFFFE); } -static void BLTDPTH(UWORD v) { maybe_blit(); bltdpt= (bltdpt & 0xffff) | ((ULONG)v << 16); } -static void BLTDPTL(UWORD v) { maybe_blit(); bltdpt= (bltdpt & ~0xffff) | (v & 0xFFFE); } -static void BLTSIZE(UWORD v) +static void BLTAPTH(uae_u16 v) { maybe_blit(); bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); } +static void BLTAPTL(uae_u16 v) { maybe_blit(); bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); } +static void BLTBPTH(uae_u16 v) { maybe_blit(); bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); } +static void BLTBPTL(uae_u16 v) { maybe_blit(); bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); } +static void BLTCPTH(uae_u16 v) { maybe_blit(); bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); } +static void BLTCPTL(uae_u16 v) { maybe_blit(); bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); } +static void BLTDPTH(uae_u16 v) { maybe_blit(); bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); } +static void BLTDPTL(uae_u16 v) { maybe_blit(); bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); } +static void BLTSIZE(uae_u16 v) { bltsize = v; - - maybe_blit(); + + maybe_blit(); blt_info.vblitsize = bltsize >> 6; blt_info.hblitsize = bltsize & 0x3F; if (!blt_info.vblitsize) blt_info.vblitsize = 1024; if (!blt_info.hblitsize) blt_info.hblitsize = 64; - - bltstate = BLT_init; + + bltstate = BLT_init; do_blitter(); } -static void BLTSIZV(UWORD v) +static void BLTSIZV(uae_u16 v) { - maybe_blit(); + maybe_blit(); oldvblts = v & 0x7FFF; } -static void BLTSIZH(UWORD v) +static void BLTSIZH(uae_u16 v) { maybe_blit(); blt_info.hblitsize = v & 0x7FF; @@ -1950,76 +2430,91 @@ static void BLTSIZH(UWORD v) bltstate = BLT_init; do_blitter(); } -static void SPRxCTL_1(UWORD v, int num) +static __inline__ void SPRxCTL_1(uae_u16 v, int num) { int sprxp; sprctl[num] = v; + nr_armed -= sprarmed[num]; sprarmed[num] = 0; - if (sprpos[num] == 0 && v == 0) - spron[num] = SPR_stop; + if (sprpos[num] == 0 && v == 0) { + sprst[num] = SPR_stop; + spron[num] = 0; + } else + sprst[num] = SPR_waiting_start; sprxp = ((sprpos[num] & 0xFF) * 2) + (v & 1) - DISPLAY_LEFT_SHIFT; - if (!gfx_requested_lores) + if (!currprefs.gfx_lores) sprxp *= 2; sprxpos[num] = sprxp; sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); sprvstop[num] = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100); } -static void SPRxPOS_1(UWORD v, int num) +static __inline__ void SPRxPOS_1(uae_u16 v, int num) { int sprxp; sprpos[num] = v; sprxp = ((v & 0xFF) * 2) + (sprctl[num] & 1) - DISPLAY_LEFT_SHIFT; - if (!gfx_requested_lores) + if (!currprefs.gfx_lores) sprxp *= 2; sprxpos[num] = sprxp; sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); } -static void SPRxDATA_1(UWORD v, int num) +static __inline__ void SPRxDATA_1(uae_u16 v, int num) { sprdata[num] = v; + nr_armed += 1 - sprarmed[num]; sprarmed[num] = 1; } -static void SPRxDATB_1(UWORD v, int num) +static __inline__ void SPRxDATB_1(uae_u16 v, int num) { sprdatb[num] = v; } -static void SPRxDATA(UWORD v, int num) { decide_sprite (num); SPRxDATA_1 (v, num); } -static void SPRxDATB(UWORD v, int num) { decide_sprite (num); SPRxDATB_1 (v, num); } -static void SPRxCTL(UWORD v, int num) { decide_sprite (num); SPRxCTL_1 (v, num); } -static void SPRxPOS(UWORD v, int num) { decide_sprite (num); SPRxPOS_1 (v, num); } -static void SPRxPTH(UWORD v, int num) +static void SPRxDATA(uae_u16 v, int num) { decide_sprites (); SPRxDATA_1 (v, num); } +static void SPRxDATB(uae_u16 v, int num) { decide_sprites (); SPRxDATB_1 (v, num); } +static void SPRxCTL(uae_u16 v, int num) { decide_sprites (); SPRxCTL_1 (v, num); } +static void SPRxPOS(uae_u16 v, int num) { decide_sprites (); SPRxPOS_1 (v, num); } +static void SPRxPTH(uae_u16 v, int num) { - sprpt[num] &= 0xffff; - sprpt[num] |= (ULONG)v << 16; -#if 1 - /* I don't like these, I'd prefer to set sprite state to SPR_restart on - * a vsync, but the Majic 12 Ray of Hope 2 demo doesn't like that. */ - if (spron[num] == SPR_vtop) -#endif - spron[num] = SPR_restart; + decide_line (); + sprpt[num] &= 0xffff; + sprpt[num] |= (uae_u32)v << 16; + + if (sprst[num] == SPR_stop || vpos < vblank_endline) + sprst[num] = SPR_restart; + spron[num] = 1; } -static void SPRxPTL(UWORD v, int num) +static void SPRxPTL(uae_u16 v, int num) { - sprpt[num] &= ~0xffff; + decide_line (); + sprpt[num] &= ~0xffff; sprpt[num] |= v; -#if 1 - if (spron[num] == SPR_vtop) -#endif - spron[num] = SPR_restart; -} -static void COLOR(UWORD v, int num) + if (sprst[num] == SPR_stop || vpos < vblank_endline) + sprst[num] = SPR_restart; + spron[num] = 1; +} +static void CLXCON(uae_u16 v) +{ + clxcon = v; + clx_sprmask = (((v >> 15) << 7) | ((v >> 14) << 5) | ((v >> 13) << 3) | ((v >> 12) << 1) | 0x55); +} +static uae_u16 CLXDAT(void) +{ + uae_u16 v = clxdat; + clxdat = 0; + return v; +} +static void COLOR(uae_u16 v, int num) { int r,g,b; int cr,cg,cb; int colreg; - + v &= 0xFFF; #if AGA_CHIPSET == 1 { /* XXX Broken */ - ULONG cval; + uae_u32 cval; colreg = ((bplcon3 >> 13) & 7) * 32 + num; r = (v & 0xF00) >> 8; g = (v & 0xF0) >> 4; @@ -2043,7 +2538,7 @@ static void COLOR(UWORD v, int num) color_regs[colreg] = cval; pfield_may_need_update(1); } -#else +#else { if (current_colors.color_regs[num] == v) return; @@ -2056,26 +2551,27 @@ static void COLOR(UWORD v, int num) #endif } -static void DSKSYNC(UWORD v) { dsksync = v; } -static void DSKDAT(UWORD v) { fprintf(stderr, "DSKDAT written. Not good.\n"); } -static void DSKPTH(UWORD v) { dskpt = (dskpt & 0xffff) | ((ULONG)v << 16); } -static void DSKPTL(UWORD v) { dskpt = (dskpt & ~0xffff) | (v); } +static void DSKSYNC(uae_u16 v) { dsksync = v; } +static void DSKDAT(uae_u16 v) { write_log ("DSKDAT written. Not good.\n"); } +static void DSKPTH(uae_u16 v) { dskpt = (dskpt & 0xffff) | ((uae_u32)v << 16); } +static void DSKPTL(uae_u16 v) { dskpt = (dskpt & ~0xffff) | (v); } -static void DSKLEN(UWORD v) +static void DSKLEN(uae_u16 v) { if (v & 0x8000) { dskdmaen = dskdmaen == 1 ? 2 : 1; - } else { + } else { dskdmaen = 0; if (eventtab[ev_diskblk].active) - fprintf(stderr, "warning: Disk DMA aborted!\n"); + write_log ("warning: Disk DMA aborted!\n"); eventtab[ev_diskblk].active = 0; events_schedule(); - + } dsklen = dsklength = v; dsklength &= 0x3fff; if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) { - fprintf(stderr, "Non-standard sync: %04x len: %x\n", dsksync, dsklength); + sprintf (warning_buffer, "Non-standard sync: %04x len: %x\n", dsksync, dsklength); + write_log (warning_buffer); } if (dskdmaen > 1) { if (dsklen & 0x4000) { @@ -2095,10 +2591,10 @@ static void DSKLEN(UWORD v) } } -static UWORD DSKBYTR(void) +static uae_u16 DSKBYTR(void) { - UWORD v = (dsklen >> 1) & 0x6000; - UWORD mfm, byte; + uae_u16 v = (dsklen >> 1) & 0x6000; + uae_u16 mfm, byte; if (DISK_GetData(&mfm, &byte)) v |= 0x8000; v |= byte; @@ -2106,91 +2602,101 @@ static UWORD DSKBYTR(void) return v; } -static UWORD DSKDATR(void) +static uae_u16 DSKDATR(void) { - UWORD mfm, byte; + uae_u16 mfm, byte; DISK_GetData(&mfm, &byte); - return mfm; + return mfm; } -static UWORD POTGOR(void) + +static uae_u16 potgo_value; + +static void POTGO(uae_u16 v) { - UWORD v = 0xFF00; - if (buttonstate[2]) - v &= 0xFBFF; + potgo_value = v; +} + +static uae_u16 POTGOR(void) +{ + uae_u16 v = (potgo_value | (potgo_value << 1)) & 0xAA00; + v |= v >> 1; + + if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) { + if (buttonstate[2]) + v &= 0xFBFF; + + if (buttonstate[1]) + v &= 0xFEFF; + } + else if (JSEM_ISJOY0(0, currprefs.fake_joystick) || JSEM_ISJOY1(0, currprefs.fake_joystick)) { + if (joy0button & 2) v &= 0xfbff; + if (joy0button & 4) v &= 0xfeff; + } + + if (JSEM_ISJOY0(1, currprefs.fake_joystick) || JSEM_ISJOY1(1, currprefs.fake_joystick)) { + if (joy1button & 2) v &= 0xbfff; + if (joy1button & 4) v &= 0xefff; + } - if (buttonstate[1]) - v &= 0xFEFF; - return v; } -static UWORD POT0DAT(void) +static uae_u16 POT0DAT(void) { - static UWORD cnt = 0; - if (buttonstate[2]) - cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00); - if (buttonstate[1]) - cnt += 0x100; - + static uae_u16 cnt = 0; + if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) { + if (buttonstate[2]) + cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00); + if (buttonstate[1]) + cnt += 0x100; + } + return cnt; } -static UWORD JOY0DAT(void) { return ((UBYTE)joy0x) + ((UWORD)joy0y << 8); } -static UWORD JOY1DAT(void) +static uae_u16 JOY0DAT(void) { + if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) { + do_mouse_hack(); + return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8); + } return joy0dir; } -static void JOYTEST(UWORD v) +static uae_u16 JOY1DAT(void) { - joy0x = joy1x = v & 0xFC; - joy0y = joy1y = (v >> 8) & 0xFC; + if (JSEM_ISMOUSE (1, currprefs.fake_joystick)) { + do_mouse_hack(); + return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8); + } + return joy1dir; } -static void AUDxLCH(int nr, UWORD v) { audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((ULONG)v << 16); } -static void AUDxLCL(int nr, UWORD v) { audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE); } -static void AUDxPER(int nr, UWORD v) +static void JOYTEST(uae_u16 v) { - if (v <= 0) { -#if 0 /* v == 0 is rather common, and harmless, and the value isn't signed anyway */ - static int warned = 0; - if (!warned) - fprintf(stderr, "Broken program accessing the sound hardware\n"), warned++; -#endif - v = 65535; + if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) { + mouse_x = v & 0xFC; + mouse_y = (v >> 8) & 0xFC; } - if (v < maxhpos/2 && produce_sound < 3) - v = maxhpos/2; - - audio_channel[nr].per = v; } -static void AUDxVOL(int nr, UWORD v) { audio_channel[nr].vol = v & 64 ? 63 : v & 63; } -static void AUDxLEN(int nr, UWORD v) { audio_channel[nr].len = v; } - /* * Here starts the copper code. It should be rewritten. */ -static int copcomp(void) -{ - UWORD vp = vpos & (((copi2 >> 8) & 0x7F) | 0x80); - UWORD hp = current_hpos() & (copi2 & 0xFE); - UWORD vcmp = copi1 >> 8; - UWORD hcmp = copi1 & 0xFE; - return (vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)); -} - +#define COPPER_ALTERNATIVE 1 /* * Calculate the minimum number of cycles after which the * copper comparison becomes true. This is quite tricky. I hope it works. */ static int calc_copcomp_true(int currvpos, int currhpos) -{ - UWORD vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80); - UWORD hp = currhpos & (copi2 & 0xFE); - UWORD vcmp = ((copi1 & (copi2 | 0x8000)) >> 8); - UWORD hcmp = (copi1 & copi2 & 0xFE); +{ + uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80); + uae_u16 hp = currhpos & (copi2 & 0xFE); + uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8); + uae_u16 hcmp = (copi1 & copi2 & 0xFE); int copper_time_hpos; int cycleadd = maxhpos - currhpos; int coptime = 0; + int maxwait = 32767; +#if COPPER_ALTERNATIVE == 0 /* This is a kludge... the problem is that there are programs that wait for * FFDDFFFE and then for a line in the second display half, and this doesn't * work without this. I _think_ the reason why it works on the Amiga is that @@ -2199,9 +2705,18 @@ static int calc_copcomp_true(int currvpo * I added this rather than changing something else. */ if (hcmp == 0xDC) hcmp += 2; - +#endif + decide_line(); + /* Copper DMA is turned off in Hires 4 bitplane mode */ + if (vp == vcmp + && decided_nr_planes == 4 /* -1 if before plfstrt */ + && decided_hires + && currhpos >= thisline_decision.plfstrt + && currhpos < thisline_decision.plfstrt + thisline_decision.plflinelen) + coptime += thisline_decision.plfstrt + thisline_decision.plflinelen - currhpos; + if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000))) - return 0; + return coptime; try_again: @@ -2214,11 +2729,16 @@ static int calc_copcomp_true(int currvpo cycleadd = maxhpos; vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80); } - if (coptime > 0 && (bplcon0 & 0xF000) == 0xC000) - return coptime; + if ((bplcon0 & 0xF000) == 0xC000) { + if (coptime > 0) + return coptime; + maxwait = plfstrt - current_hpos(); + if (maxwait < 0) + maxwait = 32767; + } copper_time_hpos = currhpos; hp = copper_time_hpos & (copi2 & 0xFE); - if (!(vp > vcmp)) { + if (!(vp > vcmp)) { while ((int)hp < ((int)hcmp)) { currhpos++; /* Copper DMA is turned off in Hires 4 bitplane mode */ @@ -2226,7 +2746,7 @@ static int calc_copcomp_true(int currvpo || !decided_hires || current_hpos () >= (thisline_decision.plfstrt + thisline_decision.plflinelen)) copper_time_hpos++; - + if (currhpos > maxhpos) { /* Now, what? There might be a good position on the * next line. But it can also be the FFFF FFFE @@ -2238,11 +2758,13 @@ static int calc_copcomp_true(int currvpo goto try_again; } coptime++; + if (coptime >= maxwait) + return coptime; hp = copper_time_hpos & (copi2 & 0xFE); } } if (coptime == 0) /* waiting for the blitter */ - return 1; + return 1; return coptime; } @@ -2251,21 +2773,21 @@ static int calc_copcomp_true(int currvpo * Simple version of the above which only tries to get vpos correct. */ static int calc_copcomp_true_vpos(int currvpos, int currhpos) -{ - UWORD vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80); - UWORD hp = currhpos & (copi2 & 0xFE); - UWORD vcmp = ((copi1 & (copi2 | 0x8000)) >> 8); - UWORD hcmp = (copi1 & copi2 & 0xFE); +{ + uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80); + uae_u16 hp = currhpos & (copi2 & 0xFE); + uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8); + uae_u16 hcmp = (copi1 & copi2 & 0xFE); int copper_time_hpos; int cycleadd = maxhpos - currhpos; int coptime = 0; - +#if COPPER_ALTERNATIVE == 0 /* see above */ if (hcmp == 0xDC) hcmp += 2; - +#endif if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000))) - return 0; + return 0; while (vp < vcmp) { currvpos++; @@ -2286,15 +2808,21 @@ static int copper_memory_cycles (int n) { int current_cycle = current_hpos (); int n_needed = 0; - int planes = ((bplcon0 >> 12) & 7) * (bplcon0 & 0x8000 ? 2 : 1); - + int planes = corrected_nr_planes_from_bplcon0; + while (n) { /* This sucks. The DIW may end vertically at exactly this point. Therefore, * we must call decide_line(). If we're vertically outside the DIW, * copper_cycle_time will be != -1 after this call [Sanity Interference] */ decide_line (); - - if (copper_cycle_time == -1 && current_cycle >= 0x14 +#if COPPER_ALTERNATIVE == 1 + if (current_cycle >= (maxhpos-3)) { + n_needed += maxhpos - current_cycle; + current_cycle = 0; + continue; + } +#endif + if (copper_cycle_time == -1 && current_cycle >= 0x14 && current_cycle >= plfstrt && current_cycle < plfstrt + plflinelen && (planes == 6 || (planes == 5 && (current_cycle % 8) < 4))) { @@ -2302,8 +2830,10 @@ static int copper_memory_cycles (int n) current_cycle += 4; } else { n_needed += 2; - current_cycle += 2; + current_cycle += 2; } + if (current_cycle >= maxhpos) + current_cycle -= maxhpos; n--; } return n_needed; @@ -2311,7 +2841,7 @@ static int copper_memory_cycles (int n) static __inline__ int calc_copper_cycles (int n_cycles) { - return copper_cycle_time != -1 ? copper_cycle_time * n_cycles : copper_memory_cycles (n_cycles); + return /*copper_cycle_time != -1 ? copper_cycle_time * n_cycles : */copper_memory_cycles (n_cycles); } static __inline__ int copper_init_read (int n_cycles) @@ -2331,12 +2861,12 @@ static __inline__ int copper_init_read ( static __inline__ void copper_read (void) { int cmd; - - copi1 = chipmem_bank.wget(coplc); + + copi1 = chipmem_bank.wget(coplc); copi2 = chipmem_bank.wget(coplc+2); coplc += 4; eventtab[ev_copper].oldcycles = cycles; - + cmd = (copi1 & 1) | ((copi2 & 1) << 1); copstate = cop_cmds[cmd]; eventtab[ev_copper].oldcycles = cycles; @@ -2365,6 +2895,86 @@ void blitter_done_notify (void) } } +#if 0 +static void do_copper_cheat(void) +{ + int coptime, t; + int nmoves = 100; /*??*/ + int nextcycles = eventtab[ev_hsync].evtime + currprefs.copper_pos; + + eventtab[ev_copper].evtime = nextcycles; + eventtab[ev_copper].oldcycles = cycles; + nextcycles -= cycles; + + if (!dmaen(DMA_COPPER)) { + eventtab[ev_copper].active = 0; + return; + } + for (; nmoves; nmoves--) + switch(copstate){ + case COP_read: + copper_read (); + break; + + case COP_read_ignore: + copper_read (); + copstate = COP_read; + break; + + case COP_move: + if (copi1 >= (copcon & 2 ? 0x40u : 0x80u)) { + custom_bank.wput(copi1,copi2); + copstate = COP_read; + } else { + copstate = COP_stop; + eventtab[ev_copper].active = 0; + copper_active = 0; + return; + } + break; + + case COP_skip: + copstate = COP_read; + if (calc_copcomp_true(vpos, current_hpos()) == 0) + copstate = COP_read_ignore; + break; + + case COP_wait: + coptime = calc_copcomp_true(vpos, current_hpos()); + if (coptime < 0) { + copstate = COP_stop; + eventtab[ev_copper].active = 0; + copper_active = 0; + return; + } + if (coptime == 0) { + copper_read(); + if (vpos != 255) + break; + eventtab[ev_copper].evtime = cycles + 6; + return; + } + if (coptime >= nextcycles) + return; + if (vpos == 255) + eventtab[ev_copper].evtime = cycles + coptime; + /*else + copstate = COP_read;*/ + return; + + case COP_stop: + eventtab[ev_copper].active = 0; + copper_active = 0; + return; + + case COP_morewait: + case COP_do_read: + case COP_do_read_ignore: + abort(); + } +} +#endif + static void do_copper(void) { int coptime, t; @@ -2376,7 +2986,7 @@ static void do_copper(void) return; copstate = COP_do_read; return; - + case COP_do_read: copper_read (); break; @@ -2394,7 +3004,7 @@ static void do_copper(void) break; case COP_move: - if (copi1 >= (copcon & 2 ? 0x40 : 0x80)) { + if (copi1 >= (copcon & 2 ? 0x40u : 0x80u)) { custom_bank.wput(copi1,copi2); copstate = COP_read; break; @@ -2479,20 +3089,22 @@ static void diskblk_handler(void) void do_disk(void) { if (dskdmaen != 2 && (regs.spcflags & SPCFLAG_DISK)) { - fprintf(stderr, "BUG!\n"); + static int warned = 0; + if (!warned) + warned++, write_log ("BUG!\n"); return; } if (dmaen(0x10)){ if (dsklen & 0x4000) { if (!chipmem_bank.check (dskpt, 2*dsklength)) { - fprintf(stderr, "warning: Bad disk write DMA pointer\n"); + write_log ("warning: Bad disk write DMA pointer\n"); } else { - UBYTE *mfmp = get_real_address (dskpt); + uae_u8 *mfmp = get_real_address (dskpt); int i; DISK_InitWrite(); for (i = 0; i < dsklength; i++) { - UWORD d = (*mfmp << 8) + *(mfmp+1); + uae_u16 d = (*mfmp << 8) + *(mfmp+1); mfmwrite[i] = d; mfmp += 2; } @@ -2507,226 +3119,18 @@ void do_disk(void) } } -static void do_sprites(int currvp, int currhp) -{ - int i; - /* The graph in the HRM, p. 195 seems to indicate that sprite 0 is - * fetched at cycle 0x14 and thus can't be disabled by bitplane DMA. */ - int maxspr = currhp/4 - 0x14/4; -#if 0 - if (currvp == 0) - return; -#else - /* I don't know whether this is right. Some programs write the sprite pointers - * directly at the start of the copper list. With the currvp==0 check, the - * first two words of data are read on the second line in the frame. The problem - * occurs when the program jumps to another copperlist a few lines further down - * which _also_ writes the sprite pointer registers. This means that a) writing - * to the sprite pointers sets the state to SPR_restart; or b) that sprite DMA - * is disabled until the end of the vertical blanking interval. The HRM - * isn't clear - it says that the vertical sprite position can be set to any - * value, but this wouldn't be the first mistake... */ - /* Update: I modified one of the programs to write the sprite pointers the - * second time only _after_ the VBlank interval, and it showed the same behaviour - * as it did unmodified under UAE with the above check. This indicates that the - * solution below is correct. */ - if (currvp < vblank_endline) - return; -#endif - if (maxspr < 0) - return; - if (maxspr > 8) - maxspr = 8; - - for (i = 0; i < maxspr; i++) { - int fetch = 0; - - if (spron[i] == SPR_restart) { - fetch = 2; - spron[i] = SPR_waiting_start; - } else if ((spron[i] == SPR_waiting_start && sprvstart[i] == vpos) || spron[i] == SPR_waiting_stop) { - fetch = 1; - spron[i] = SPR_waiting_stop; - } - if (spron[i] == SPR_waiting_stop && sprvstop[i] == vpos) { - fetch = 2; - spron[i] = SPR_waiting_start; - } - - if (fetch && dmaen(DMA_SPRITE)) { - UWORD data1 = chipmem_bank.wget(sprpt[i]); - UWORD data2 = chipmem_bank.wget(sprpt[i]+2); - sprpt[i] += 4; - - if (fetch == 1) { - /* Hack for X mouse auto-calibration */ - if (i == 0 && !sprvbfl && ((sprpos[0] & 0xff) << 2) > 2 * DISPLAY_LEFT_SHIFT) { - spr0ctl=sprctl[0]; - spr0pos=sprpos[0]; - sprvbfl=2; - } - SPRxDATB_1(data2, i); - SPRxDATA_1(data1, i); - } else { - SPRxPOS_1(data1, i); - SPRxCTL_1(data2, i); - } - } - } -} - -#if AGA_CHIPSET == 0 -static void pfield_sprite (int num, int sprxp, UWORD data, UWORD datb, int ctl) -{ - int i; - int sprx_inc; - int *lookup = bpldualpf ? (bpldualpfpri ? dblpf_ind2 : dblpf_ind1) : linear_map_256; - int *lookup_no = bpldualpf ? (bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1) : lots_of_twos; - - sprx_inc = 1; - if (!gfx_requested_lores) - sprx_inc = 2; -#ifdef LORES_HACK - else if (gfx_requested_lores == 2) - sprxp >>= 1; -#endif - sprxp += sprx_inc * 16 - sprx_inc; - for(i = 15; i >= 0; i--, data >>= 1, datb >>= 1, sprxp -= sprx_inc) { - int plno; - int col; - - /* Check the priority, but only if we did not already put a sprite - * pixel at this position. If there's already a sprite pixel here, - * the priority was previously tested. */ - if (!spixstate[sprxp]) { - /* ??? What about hires mode when one hires pixel is 0, enabling the - * sprite, and the other is != 0, blocking it? */ - plno = lookup_no[pixdata.apixels[sprxp]]; - if (plno != 0 && (1 << num) >= plfpri[plno]) - continue; - } - - if ((ctl & 0x80) && (num & 1)) { - /* Attached sprite */ - col = ((data << 2) & 4) + ((datb << 3) & 8); - spixstate[sprxp] |= 1 << (num-1); - spixels[sprxp] = col; - } else { - col = (data & 1) | ((datb << 1) & 2); - if (spixstate[sprxp] & (1 << num)) { - /* Finish attached sprite */ - /* Did the upper half of the sprite have any bits set? */ - if (spixstate[sprxp] & (1 << (num+1))) - col += spixels[sprxp]; - /* Is there any sprite pixel at this position at all? */ - if (!col) { - spixstate[sprxp] &= ~(3 << num); - } else - col += 16; - } else { - if (col) { - col |= 16 | ((num & 6) << 1); - } - } - } - if (col) { - pixdata.apixels[sprxp] = col; - spixstate[sprxp] |= 1 << num; - - if (!gfx_requested_lores) { - pixdata.apixels[sprxp+1] = col; - spixstate[sprxp+1] |= 1 << num; - } - if (bplham && bplplanecnt == 6) { - ham_linebuf[sprxp] = colors_for_drawing.color_regs[col]; - if (!gfx_requested_lores) - ham_linebuf[sprxp+1] = colors_for_drawing.color_regs[col]; - } - } - } -} -#else /* AGA version */ -static void pfield_sprite (int num, int sprxp, UWORD data, UWORD datb) -{ - int i; - - int *lookup = bpldualpf ? (bpldualpfpri ? dblpf_ind2 : dblpf_ind1) : linear_map_256; - int *lookup_no = bpldualpf ? (bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1) : lots_of_twos; - - for(i = 15; i >= 0; i--, data >>= 1, datb >>= 1) { - int sprxpos = sprxp + (i << lores_shift); - int plno; - int col; - - /* Check the priority, but only if we did not already put a sprite - * pixel at this position. If there's already a sprite pixel here, - * the priority was previously tested. */ - if (!spixstate[sprxpos]) { - /* ??? What about hires mode when one hires pixel is 0, enabling the - * sprite, and the other is != 0, blocking it? */ - plno = lookup_no[pixdata.apixels[sprxpos]]; - if (plno != 0 && (1 << num) >= plfpri[plno]) - continue; - } - - if ((sprctl[num] & 0x80) && (num & 1)) { - /* Attached sprite */ - col = ((data << 2) & 4) + ((datb << 3) & 8); - spixstate[sprxpos] |= 1 << (num-1); - spixels[sprxpos] = col; - } else { - col = (data & 1) | ((datb << 1) & 2); - if (spixstate[sprxpos] & (1 << num)) { - /* Finish attached sprite */ - /* Did the upper half of the sprite have any bits set? */ - if (spixstate[sprxpos] & (1 << (num+1))) - col += spixels[sprxpos]; - /* Is there any sprite pixel at this position at all? */ - if (!col) { - spixstate[sprxpos] &= ~(3 << num); - } else - col += ((bplcon4 << (num & 1 ? 4 : 0)) & 240); - } else { - if (col) { - col |= ((bplcon4 << (num & 1 ? 4 : 0)) & 240) | ((num & 6) << 1); - } - } - } - if (col) { - pixdata.apixels[sprxpos] = col; - spixstate[sprxpos] |= 1<> 7) & 1) << 0) + | (((i >> 6) & 1) << 2) + | (((i >> 5) & 1) << 4) + | (((i >> 4) & 1) << 6) + | (((i >> 3) & 1) << 8) + | (((i >> 2) & 1) << 10) + | (((i >> 1) & 1) << 12) + | (((i >> 0) & 1) << 14)); + sprtabb[i] = sprtaba[i] * 2; + clxtab[i] = ((((i & 3) && (i & 12)) << 9) + | (((i & 3) && (i & 48)) << 10) + | (((i & 3) && (i & 192)) << 11) + | (((i & 12) && (i & 48)) << 12) + | (((i & 12) && (i & 192)) << 13) + | (((i & 48) && (i & 192)) << 14)); } - + for (i = 0; i < 256; i++) { baz.foo.a = i & 128 ? 1 : 0; baz.foo.b = i & 64 ? 1 : 0; @@ -2758,7 +3177,7 @@ static void gen_pfield_tables(void) baz.foo.h = i & 1 ? 1 : 0; hirestab_h[i][0] = baz.bar.a; hirestab_h[i][1] = baz.bar.b; - + baz.foo.a = i & 128 ? 1 : 0; baz.foo.b = i & 128 ? 1 : 0; baz.foo.c = i & 64 ? 1 : 0; @@ -2782,472 +3201,364 @@ static void gen_pfield_tables(void) } } -#ifndef SMART_UPDATE -#undef UNALIGNED_PROFITABLE -#endif - -#ifdef UNALIGNED_PROFITABLE -/* - * Be sure to pass a constant for the third and fourth parameters to get proper optimization. - */ -static __inline__ void doop_planes_hires_unaligned_h (ULONG *app, UBYTE *ptr, int nplanes, int do_or) +static void do_sprites(int currvp, int currhp) { int i; - int len = dp_for_drawing->plflinelen >> 1; - for (i = 0; i < len; i++) { - unsigned int data1; - ULONG v1, v2; - - data1 = *(ptr + i); - v1 = hirestab_h[data1][0]; - v2 = hirestab_h[data1][1]; - - if (nplanes > 1) { - unsigned int data2 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2); - v1 |= hirestab_h[data2][0] << 2; - v2 |= hirestab_h[data2][1] << 2; - } - if (nplanes > 2) { - unsigned int data3 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2); - v1 |= hirestab_h[data3][0] << 4; - v2 |= hirestab_h[data3][1] << 4; - } - if (nplanes > 3) { - unsigned int data4 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2); - v1 |= hirestab_h[data4][0] << 6; - v2 |= hirestab_h[data4][1] << 6; - } - if (do_or) { - app[i*2] |= v1 << 1; - app[i*2 + 1] |= v2 << 1; - } else { - app[i*2] = v1; - app[i*2 + 1] = v2; - } - } -} + /* The graph in the HRM, p. 195 seems to indicate that sprite 0 is + * fetched at cycle 0x14 and thus can't be disabled by bitplane DMA. */ + int maxspr = currhp/4 - 0x14/4; +#if 0 + if (currvp == 0) + return; +#else + /* I don't know whether this is right. Some programs write the sprite pointers + * directly at the start of the copper list. With the currvp==0 check, the + * first two words of data are read on the second line in the frame. The problem + * occurs when the program jumps to another copperlist a few lines further down + * which _also_ writes the sprite pointer registers. This means that a) writing + * to the sprite pointers sets the state to SPR_restart; or b) that sprite DMA + * is disabled until the end of the vertical blanking interval. The HRM + * isn't clear - it says that the vertical sprite position can be set to any + * value, but this wouldn't be the first mistake... */ + /* Update: I modified one of the programs to write the sprite pointers the + * second time only _after_ the VBlank interval, and it showed the same behaviour + * as it did unmodified under UAE with the above check. This indicates that the + * solution below is correct. */ + if (currvp < vblank_endline) + return; +#endif + if (maxspr < 0) + return; + if (maxspr > 8) + maxspr = 8; -static __inline__ void doop_planes_lores_unaligned_h (ULONG *app, UBYTE *ptr, int nplanes, int do_or) -{ - int i; - int len = dp_for_drawing->plflinelen >> 2; - for (i = 0; i < len; i++) { - unsigned int data1; - ULONG v1, v2, v3, v4; - - data1 = *(ptr + i); - v1 = lorestab_h[data1][0]; - v2 = lorestab_h[data1][1]; - v3 = lorestab_h[data1][2]; - v4 = lorestab_h[data1][3]; - - if (nplanes > 1) { - unsigned int data2 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_h[data2][0] << 2; - v2 |= lorestab_h[data2][1] << 2; - v3 |= lorestab_h[data2][2] << 2; - v4 |= lorestab_h[data2][3] << 2; - } - - if (nplanes > 2) { - unsigned int data3 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_h[data3][0] << 4; - v2 |= lorestab_h[data3][1] << 4; - v3 |= lorestab_h[data3][2] << 4; - v4 |= lorestab_h[data3][3] << 4; - } - - if (nplanes > 3) { - unsigned int data4 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_h[data4][0] << 6; - v2 |= lorestab_h[data4][1] << 6; - v3 |= lorestab_h[data4][2] << 6; - v4 |= lorestab_h[data4][3] << 6; - } - if (do_or) { - app[i*4] |= v1 << 1; - app[i*4 + 1] |= v2 << 1; - app[i*4 + 2] |= v3 << 1; - app[i*4 + 3] |= v4 << 1; - } else { - app[i*4] = v1; - app[i*4 + 1] = v2; - app[i*4 + 2] = v3; - app[i*4 + 3] = v4; - } - } -} + for (i = 0; i < maxspr; i++) { + int fetch = 0; -static __inline__ void doop_planes_hires_unaligned_l (ULONG *app, UBYTE *ptr, int nplanes, int do_or) -{ - int i; - int len = dp_for_drawing->plflinelen >> 1; - for (i = 0; i < len; i++) { - unsigned int data1; - ULONG v; - - data1 = *(ptr + i); - v = hirestab_l[data1][0]; - if (nplanes > 1) { - unsigned int data2 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2); - v |= hirestab_l[data2][0] << 2; - } - if (nplanes > 2) { - unsigned int data3 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2); - v |= hirestab_l[data3][0] << 4; - } - if (nplanes > 3) { - unsigned int data4 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2); - v |= hirestab_l[data4][0] << 6; + if (spron[i] == 0) + continue; + + if (sprst[i] == SPR_restart) { + fetch = 2; + spron[i] = 1; + } else if ((sprst[i] == SPR_waiting_start && sprvstart[i] == vpos) || sprst[i] == SPR_waiting_stop) { + fetch = 1; + sprst[i] = SPR_waiting_stop; + } + if (sprst[i] == SPR_waiting_stop && sprvstop[i] == vpos) { + fetch = 2; + sprst[i] = SPR_waiting_start; } - if (do_or) - app[i] |= v << 1; - else - app[i] = v; - } -} -static __inline__ void doop_planes_lores_unaligned_l (ULONG *app, UBYTE *ptr, int nplanes, int do_or) -{ - int i; - int len = dp_for_drawing->plflinelen >> 2; - for (i = 0; i < len; i++) { - unsigned int data1; - ULONG v1, v2; - - data1 = *(ptr + i); - v1 = lorestab_l[data1][0]; - v2 = lorestab_l[data1][1]; - - if (nplanes > 1) { - unsigned int data2 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_l[data2][0] << 2; - v2 |= lorestab_l[data2][1] << 2; - } - if (nplanes > 2) { - unsigned int data3 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_l[data3][0] << 4; - v2 |= lorestab_l[data3][1] << 4; - } - if (nplanes > 3) { - unsigned int data4 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_l[data4][0] << 6; - v2 |= lorestab_l[data4][1] << 6; - } - if (do_or) { - app[i*2] |= v1 << 1; - app[i*2 + 1] |= v2 << 1; - } else { - app[i*2] = v1; - app[i*2 + 1] = v2; + if (fetch && dmaen(DMA_SPRITE)) { + uae_u16 data1 = chipmem_bank.wget(sprpt[i]); + uae_u16 data2 = chipmem_bank.wget(sprpt[i]+2); + sprpt[i] += 4; + + if (fetch == 1) { + /* Hack for X mouse auto-calibration */ + if (i == 0 && !sprvbfl && ((sprpos[0] & 0xff) << 2) > 2 * DISPLAY_LEFT_SHIFT) { + spr0ctl=sprctl[0]; + spr0pos=sprpos[0]; + sprvbfl=2; + } + SPRxDATB_1(data2, i); + SPRxDATA_1(data1, i); + } else { + SPRxPOS_1(data1, i); + SPRxCTL_1(data2, i); + } } } } -static __inline__ void set_planes_hires_unaligned_h (ULONG *app, UBYTE *ptr, int nplanes) -{ - int i; - int len = dp_for_drawing->plflinelen >> 1; - for (i = 0; i < len; i++) { - unsigned int data1; - ULONG v1, v2; - - data1 = *(ptr + i); - v1 = hirestab_h[data1][0]; - v2 = hirestab_h[data1][1]; +static uae_u32 attach_2nd; - if (nplanes > 1) { - unsigned int data2 = *(ptr + i + 1*MAX_WORDS_PER_LINE*2); - v1 |= hirestab_h[data2][0] << 1; - v2 |= hirestab_h[data2][1] << 1; - } - - if (nplanes > 2) { - unsigned int data3 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2); - v1 |= hirestab_h[data3][0] << 2; - v2 |= hirestab_h[data3][1] << 2; - } +static uae_u32 do_sprite_collisions (struct sprite_draw *spd, int prev_overlap, int i, int nr_spr) +{ + int j; + int sprxp = spd[i].linepos; + uae_u32 datab = spd[i].datab; + uae_u32 mask2 = 0; + int sbit = 1 << spd[i].num; + int sprx_shift = 1; + int attach_compare = -1; + if (currprefs.gfx_lores != 1) + sprx_shift = 0; + + attach_2nd = 0; + if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) + attach_compare = spd[i].num - 1; + + for (j = prev_overlap; j < i; j++) { + uae_u32 mask1; + int off; - if (nplanes > 3) { - unsigned int data4 = *(ptr + i + 3*MAX_WORDS_PER_LINE*2); - v1 |= hirestab_h[data4][0] << 3; - v2 |= hirestab_h[data4][1] << 3; - } + if (spd[i].num < spd[j].num) + continue; - if (nplanes > 4) { - unsigned int data5 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2); - v1 |= hirestab_h[data5][0] << 4; - v2 |= hirestab_h[data5][1] << 4; + off = sprxp - spd[j].linepos; + off <<= sprx_shift; + mask1 = spd[j].datab >> off; + + /* If j is an attachment for i, then j doesn't block i */ + if (spd[j].num == attach_compare) { + attach_2nd |= mask1; + } else { + mask1 |= (mask1 & 0xAAAAAAAA) >> 1; + mask1 |= (mask1 & 0x55555555) << 1; + if (datab & mask1) + clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask]; + mask2 |= mask1; } + } + for (j = i+1; j < nr_spr; j++) { + uae_u32 mask1; + int off = spd[j].linepos - sprxp; - if (nplanes > 5) { - unsigned int data6 = *(ptr + i + 5*MAX_WORDS_PER_LINE*2); - v1 |= hirestab_h[data6][0] << 5; - v2 |= hirestab_h[data6][1] << 5; - } + if (off >= sprite_width || spd[i].num < spd[j].num) + break; - if (nplanes > 6) { - unsigned int data7 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2); - v1 |= hirestab_h[data7][0] << 6; - v2 |= hirestab_h[data7][1] << 6; - } + off <<= sprx_shift; + mask1 = spd[j].datab << off; - if (nplanes > 7) { - unsigned int data8 = *(ptr + i + 7*MAX_WORDS_PER_LINE*2); - v1 |= hirestab_h[data8][0] << 7; - v2 |= hirestab_h[data8][1] << 7; + /* If j is an attachment for i, then j doesn't block i */ + if (spd[j].num == attach_compare) { + attach_2nd |= mask1; + } else { + mask1 |= (mask1 & 0xAAAAAAAA) >> 1; + mask1 |= (mask1 & 0x55555555) << 1; + if (datab & mask1) + clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask]; + mask2 |= mask1; } - app[i*2] = v1; - app[i*2 + 1] = v2; } + datab &= ~mask2; + return datab; } -static __inline__ void set_planes_lores_unaligned_h (ULONG *app, UBYTE *ptr, int nplanes) +static __inline__ void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc) { - int i; - int len = dp_for_drawing->plflinelen >> 2; - for (i = 0; i < len; i++) { - unsigned int data1; - ULONG v1, v2, v3, v4; - - data1 = *(ptr + i); - v1 = lorestab_h[data1][0]; - v2 = lorestab_h[data1][1]; - v3 = lorestab_h[data1][2]; - v4 = lorestab_h[data1][3]; - - if (nplanes > 1) { - unsigned int data2 = *(ptr + i + 1*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_h[data2][0] << 1; - v2 |= lorestab_h[data2][1] << 1; - v3 |= lorestab_h[data2][2] << 1; - v4 |= lorestab_h[data2][3] << 1; - } - - if (nplanes > 2) { - unsigned int data3 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_h[data3][0] << 2; - v2 |= lorestab_h[data3][1] << 2; - v3 |= lorestab_h[data3][2] << 2; - v4 |= lorestab_h[data3][3] << 2; - } - - if (nplanes > 3) { - unsigned int data4 = *(ptr + i + 3*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_h[data4][0] << 3; - v2 |= lorestab_h[data4][1] << 3; - v3 |= lorestab_h[data4][2] << 3; - v4 |= lorestab_h[data4][3] << 3; - } - - if (nplanes > 4) { - unsigned int data5 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_h[data5][0] << 4; - v2 |= lorestab_h[data5][1] << 4; - v3 |= lorestab_h[data5][2] << 4; - v4 |= lorestab_h[data5][3] << 4; - } - - if (nplanes > 5) { - unsigned int data6 = *(ptr + i + 5*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_h[data6][0] << 5; - v2 |= lorestab_h[data6][1] << 5; - v3 |= lorestab_h[data6][2] << 5; - v4 |= lorestab_h[data6][3] << 5; - } - - if (nplanes > 6) { - unsigned int data7 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_h[data7][0] << 6; - v2 |= lorestab_h[data7][1] << 6; - v3 |= lorestab_h[data7][2] << 6; - v4 |= lorestab_h[data7][3] << 6; - } - - if (nplanes > 7) { - unsigned int data8 = *(ptr + i + 7*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_h[data8][0] << 7; - v2 |= lorestab_h[data8][1] << 7; - v3 |= lorestab_h[data8][2] << 7; - v4 |= lorestab_h[data8][3] << 7; - } - app[i*4] = v1; - app[i*4 + 1] = v2; - app[i*4 + 2] = v3; - app[i*4 + 3] = v4; - } -} + uae_u32 datcd; + int basecol = 16; + if (!attch) + basecol += (spr & ~1)*2; + if (bpldualpf) + basecol |= 128; + if (attch) + datcd = attach_2nd; -static __inline__ void set_planes_hires_unaligned_l (ULONG *app, UBYTE *ptr, int nplanes) -{ - int i; - int len = dp_for_drawing->plflinelen >> 1; - for (i = 0; i < len; i++) { - unsigned int data1; - ULONG v; + for(; attch ? datab | datcd : datab; sprxp += sprx_inc) { + int col; - data1 = *(ptr + i); - - v = hirestab_l[data1][0]; - if (nplanes > 1) { - unsigned int data2 = *(ptr + i + 1*MAX_WORDS_PER_LINE*2); - v |= hirestab_l[data2][0] << 1; - } - if (nplanes > 2) { - unsigned int data3 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2); - v |= hirestab_l[data3][0] << 2; - } - if (nplanes > 3) { - unsigned int data4 = *(ptr + i + 3*MAX_WORDS_PER_LINE*2); - v |= hirestab_l[data4][0] << 3; - } - if (nplanes > 4) { - unsigned int data5 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2); - v |= hirestab_l[data5][0] << 4; - } - if (nplanes > 5) { - unsigned int data6 = *(ptr + i + 5*MAX_WORDS_PER_LINE*2); - v |= hirestab_l[data6][0] << 5; - } - if (nplanes > 6) { - unsigned int data7 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2); - v |= hirestab_l[data7][0] << 6; - } - if (nplanes > 7) { - unsigned int data8 = *(ptr + i + 7*MAX_WORDS_PER_LINE*2); - v |= hirestab_l[data8][0] << 7; + if (attch) { + col = ((datab & 3) << 2) | (datcd & 3); + datcd >>= 2; + } else + col = datab & 3; + datab >>= 2; + if (col) { + col |= basecol; + if (ham) { + col = colors_for_drawing.color_regs[col]; + ham_linebuf[sprxp] = col; + if (sprx_inc == 2) { + ham_linebuf[sprxp+1] = col; + } + } else { + pixdata.apixels[sprxp] = col; + if (sprx_inc == 2) { + pixdata.apixels[sprxp+1] = col; + } + } } - app[i] = v; } } -static __inline__ void set_planes_lores_unaligned_l (ULONG *app, UBYTE *ptr, int nplanes) +static void walk_sprites (struct sprite_draw *spd, int nr_spr) { - int i; - int len = dp_for_drawing->plflinelen >> 2; - for (i = 0; i < len; i++) { - unsigned int data1; - ULONG v1, v2; - - data1 = *(ptr + i); - v1 = lorestab_l[data1][0]; - v2 = lorestab_l[data1][1]; - - if (nplanes > 1) { - unsigned int data2 = *(ptr + i + 1*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_l[data2][0] << 1; - v2 |= lorestab_l[data2][1] << 1; - } - - if (nplanes > 2) { - unsigned int data3 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_l[data3][0] << 2; - v2 |= lorestab_l[data3][1] << 2; - } - - if (nplanes > 3) { - unsigned int data4 = *(ptr + i + 3*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_l[data4][0] << 3; - v2 |= lorestab_l[data4][1] << 3; - } + int i, prev_overlap; + int last_sprite_pos = -64; + uae_u32 plane1 = 0, plane2 = 0; + int sprx_inc = 1, sprx_shift = 1; + + if (currprefs.gfx_lores == 0) + sprx_inc = 2, sprx_shift = 0; + + prev_overlap = 0; + for (i = 0; i < nr_spr; i++) { + int sprxp = spd[i].linepos; + int m = 1 << spd[i].num; + uae_u32 datab; + while (prev_overlap < i && spd[prev_overlap].linepos + sprite_width <= sprxp) + prev_overlap++; - if (nplanes > 4) { - unsigned int data5 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_l[data5][0] << 4; - v2 |= lorestab_l[data5][1] << 4; - } + datab = do_sprite_collisions (spd, prev_overlap, i, nr_spr); +#ifdef LORES_HACK + if (currprefs.gfx_lores == 2) + sprxp >>= 1; +#endif + if ((bpldualpf && plfpri[1] < 256) || (plfpri[2] < 256)) { + if (sprxp != last_sprite_pos) { + int ok = last_sprite_pos-sprxp+16; + int ok2; + if (ok <= 0) { + ok = ok2 = 0; + plane1 = 0; + plane2 = 0; + } else { + ok2 = ok << sprx_shift; + plane1 >>= 32 - ok2; + plane2 >>= 32 - ok2; + } + last_sprite_pos = sprxp; - if (nplanes > 5) { - unsigned int data6 = *(ptr + i + 5*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_l[data6][0] << 5; - v2 |= lorestab_l[data6][1] << 5; - } + if (bpldualpf) { + uae_u32 mask = 3 << ok2; + int p = sprxp+ok; + + for (; mask; mask <<= 2, p += sprx_inc) { + int data = pixdata.apixels[p]; + if (dblpf_2nd2[data] == 2) + plane2 |= mask; + if (dblpf_2nd1[data] == 1) + plane1 |= mask; + } + } else { + uae_u32 mask = 3 << ok2; + int p = sprxp+ok; - if (nplanes > 6) { - unsigned int data7 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_l[data7][0] << 6; - v2 |= lorestab_l[data7][1] << 6; + for (; mask; mask <<= 2, p += sprx_inc) { + if (pixdata.apixels[p]) + plane2 |= mask; + } + } + } + if (bpldualpf && m >= plfpri[1]) { + datab &= ~plane1; + attach_2nd &= ~plane1; + } + if (m >= plfpri[2]) { + datab &= ~plane2; + attach_2nd &= ~plane2; + } } - - if (nplanes > 7) { - unsigned int data8 = *(ptr + i + 7*MAX_WORDS_PER_LINE*2); - v1 |= lorestab_l[data8][0] << 7; - v2 |= lorestab_l[data8][1] << 7; + if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) { + /* Attached sprite */ + if (bplham) { + if (sprx_inc == 1) { + render_sprite (spd[i].num, sprxp, datab, 1, 1, 1); + } else { + render_sprite (spd[i].num, sprxp, datab, 1, 1, 2); + } + } else { + if (sprx_inc == 1) { + render_sprite (spd[i].num, sprxp, datab, 0, 1, 1); + } else { + render_sprite (spd[i].num, sprxp, datab, 0, 1, 2); + } + } + /* This still leaves one attached sprite bug, but at the moment I'm too lazy */ + if (i + 1 < nr_spr && spd[i+1].num == spd[i].num - 1 && spd[i+1].linepos == spd[i].linepos) + i++; + } else { + if (bplham) { + if (sprx_inc == 1) { + render_sprite (spd[i].num, sprxp, datab, 1, 0, 1); + } else { + render_sprite (spd[i].num, sprxp, datab, 1, 0, 2); + } + } else { + if (sprx_inc == 1) { + render_sprite (spd[i].num, sprxp, datab, 0, 0, 1); + } else { + render_sprite (spd[i].num, sprxp, datab, 0, 0, 2); + } + } } - - app[i*2] = v1; - app[i*2 + 1] = v2; } } +#ifndef SMART_UPDATE +#undef UNALIGNED_PROFITABLE +#endif + +#ifdef UNALIGNED_PROFITABLE + static void pfield_doline_unaligned_h (int lineno) { int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2; - + if (bplhires) { int xpos1 = xpos + 16 + bpldelay1*2; int xpos2; - UBYTE *dataptr = line_data[lineno]; - + uae_u8 *dataptr = line_data[lineno]; + int len = dp_for_drawing->plflinelen >> 1; + + if (len <= 0) + return; + if (bpldelay1 == bpldelay2) { switch (bplplanecnt) { - case 1: set_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 1); break; - case 2: set_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 2); break; - case 3: set_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 3); break; - case 4: set_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 4); break; - case 5: set_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 5); break; - case 6: set_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 6); break; - case 7: set_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 7); break; - case 8: set_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 8); break; + case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; } } else { switch (bplplanecnt) { - case 1: case 2: doop_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 1, 0); break; - case 3: case 4: doop_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 2, 0); break; - case 5: case 6: doop_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 3, 0); break; - case 7: case 8: doop_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 4, 0); break; + case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; } - dataptr += MAX_WORDS_PER_LINE*2; xpos2 = xpos + 16 + bpldelay2*2; switch (bplplanecnt) { - case 2: case 3: doop_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos2), dataptr, 1, 1); break; - case 4: case 5: doop_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos2), dataptr, 2, 1); break; - case 6: case 7: doop_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos2), dataptr, 3, 1); break; - case 8: doop_planes_hires_unaligned_h ((ULONG *)(pixdata.apixels + xpos2), dataptr, 4, 1); break; + case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; } } } else { int xpos1 = xpos + 32 + bpldelay1*2; int xpos2; - UBYTE *dataptr = line_data[lineno]; + uae_u8 *dataptr = line_data[lineno]; + int len = dp_for_drawing->plflinelen >> 2; + + if (len <= 0) + return; if (bpldelay1 == bpldelay2) { switch (bplplanecnt) { - case 1: set_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 1); break; - case 2: set_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 2); break; - case 3: set_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 3); break; - case 4: set_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 4); break; - case 5: set_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 5); break; - case 6: set_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 6); break; - case 7: set_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 7); break; - case 8: set_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 8); break; + case 1: set_lores_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 2: set_lores_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: set_lores_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 4: set_lores_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: set_lores_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 6: set_lores_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: set_lores_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 8: set_lores_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; } } else { switch (bplplanecnt) { - case 1: case 2: doop_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 1, 0); break; - case 3: case 4: doop_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 2, 0); break; - case 5: case 6: doop_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 3, 0); break; - case 7: case 8: doop_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos1), dataptr, 4, 0); break; + case 1: case 2: set_lores_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: case 4: set_lores_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: case 6: set_lores_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: case 8: set_lores_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; } - - dataptr += MAX_WORDS_PER_LINE*2; + xpos2 = xpos + 32 + bpldelay2*2; switch (bplplanecnt) { - case 2: case 3: doop_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos2), dataptr, 1, 1); break; - case 4: case 5: doop_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos2), dataptr, 2, 1); break; - case 6: case 7: doop_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos2), dataptr, 3, 1); break; - case 8: doop_planes_lores_unaligned_h ((ULONG *)(pixdata.apixels + xpos2), dataptr, 4, 1); break; + case 2: case 3: set_lores_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 4: case 5: set_lores_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 6: case 7: set_lores_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 8: set_lores_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; } } } @@ -3256,71 +3567,77 @@ static void pfield_doline_unaligned_h (i static void pfield_doline_unaligned_l (int lineno) { int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT; - + if (bplhires) { int xpos1 = xpos + 8 + bpldelay1; int xpos2; - UBYTE *dataptr = line_data[lineno]; + uae_u8 *dataptr = line_data[lineno]; + int len = dp_for_drawing->plflinelen >> 1; + + if (len <= 0) + return; if (bpldelay1 == bpldelay2) { switch (bplplanecnt) { - case 1: set_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 1); break; - case 2: set_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 2); break; - case 3: set_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 3); break; - case 4: set_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 4); break; - case 5: set_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 5); break; - case 6: set_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 6); break; - case 7: set_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 7); break; - case 8: set_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 8); break; + case 1: set_hires_l_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 2: set_hires_l_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: set_hires_l_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 4: set_hires_l_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: set_hires_l_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 6: set_hires_l_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: set_hires_l_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 8: set_hires_l_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; } } else { switch (bplplanecnt) { - case 1: case 2: doop_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 1, 0); break; - case 3: case 4: doop_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 2, 0); break; - case 5: case 6: doop_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 3, 0); break; - case 7: case 8: doop_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 4, 0); break; + case 1: case 2: set_hires_l_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: case 4: set_hires_l_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: case 6: set_hires_l_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: case 8: set_hires_l_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; } - dataptr += MAX_WORDS_PER_LINE*2; xpos2 = xpos + 8 + bpldelay2; switch (bplplanecnt) { - case 2: case 3: doop_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos2), dataptr, 1, 1); break; - case 4: case 5: doop_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos2), dataptr, 2, 1); break; - case 6: case 7: doop_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos2), dataptr, 3, 1); break; - case 8: doop_planes_hires_unaligned_l ((ULONG *)(pixdata.apixels + xpos2), dataptr, 4, 1); break; + case 2: case 3: set_hires_l_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 4: case 5: set_hires_l_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 6: case 7: set_hires_l_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 8: set_hires_l_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; } } } else { int xpos1 = xpos + 16 + bpldelay1; int xpos2; - UBYTE *dataptr = line_data[lineno]; + uae_u8 *dataptr = line_data[lineno]; + int len = dp_for_drawing->plflinelen >> 2; + + if (len <= 0) + return; if (bpldelay1 == bpldelay2) { switch (bplplanecnt) { - case 1: set_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 1); break; - case 2: set_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 2); break; - case 3: set_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 3); break; - case 4: set_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 4); break; - case 5: set_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 5); break; - case 6: set_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 6); break; - case 7: set_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 7); break; - case 8: set_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 8); break; + case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; } } else { switch (bplplanecnt) { - case 1: case 2: doop_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 1, 0); break; - case 3: case 4: doop_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 2, 0); break; - case 5: case 6: doop_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 3, 0); break; - case 7: case 8: doop_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos1), dataptr, 4, 0); break; + case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; + case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; } - - dataptr += MAX_WORDS_PER_LINE*2; + xpos2 = xpos + 16 + bpldelay2; switch (bplplanecnt) { - case 2: case 3: doop_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos2), dataptr, 1, 1); break; - case 4: case 5: doop_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos2), dataptr, 2, 1); break; - case 6: case 7: doop_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos2), dataptr, 3, 1); break; - case 8: doop_planes_lores_unaligned_l ((ULONG *)(pixdata.apixels + xpos2), dataptr, 4, 1); break; + case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; + case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; } } } @@ -3334,7 +3651,7 @@ static void pfield_doline_unaligned_l (i static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit) { - ULONG *pixptr = (ULONG *)dp; + uae_u32 *pixptr = (uae_u32 *)dp; *pixptr |= hirestab_h[data >> 8][0] << bit; *(pixptr+1) |= hirestab_h[data >> 8][1] << bit; @@ -3344,8 +3661,8 @@ static __inline__ void pfield_orword_hir static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit) { - ULONG *pixptr = (ULONG *)dp; - + uae_u32 *pixptr = (uae_u32 *)dp; + *pixptr |= lorestab_h[data >> 8][0] << bit; *(pixptr+1) |= lorestab_h[data >> 8][1] << bit; *(pixptr+2) |= lorestab_h[data >> 8][2] << bit; @@ -3358,7 +3675,7 @@ static __inline__ void pfield_orword_lor static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit) { - ULONG *pixptr = (ULONG *)dp; + uae_u32 *pixptr = (uae_u32 *)dp; *pixptr = hirestab_h[data >> 8][0] << bit; *(pixptr+1) = hirestab_h[data >> 8][1] << bit; @@ -3368,8 +3685,8 @@ static __inline__ void pfield_setword_hi static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit) { - ULONG *pixptr = (ULONG *)dp; - + uae_u32 *pixptr = (uae_u32 *)dp; + *pixptr = lorestab_h[data >> 8][0] << bit; *(pixptr+1) = lorestab_h[data >> 8][1] << bit; *(pixptr+2) = lorestab_h[data >> 8][2] << bit; @@ -3382,7 +3699,7 @@ static __inline__ void pfield_setword_lo static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit) { - ULONG *pixptr = (ULONG *)dp; + uae_u32 *pixptr = (uae_u32 *)dp; *pixptr |= hirestab_l[data >> 8][0] << bit; *(pixptr+1) |= hirestab_l[data & 255][0] << bit; @@ -3390,8 +3707,8 @@ static __inline__ void pfield_orword_hir static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit) { - ULONG *pixptr = (ULONG *)dp; - + uae_u32 *pixptr = (uae_u32 *)dp; + *pixptr |= lorestab_l[data >> 8][0] << bit; *(pixptr+1) |= lorestab_l[data >> 8][1] << bit; *(pixptr+2) |= lorestab_l[data & 255][0] << bit; @@ -3400,7 +3717,7 @@ static __inline__ void pfield_orword_lor static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit) { - ULONG *pixptr = (ULONG *)dp; + uae_u32 *pixptr = (uae_u32 *)dp; *pixptr = hirestab_l[data >> 8][0] << bit; *(pixptr+1) = hirestab_l[data & 255][0] << bit; @@ -3408,8 +3725,8 @@ static __inline__ void pfield_setword_hi static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit) { - ULONG *pixptr = (ULONG *)dp; - + uae_u32 *pixptr = (uae_u32 *)dp; + *pixptr = lorestab_l[data >> 8][0] << bit; *(pixptr+1) = lorestab_l[data >> 8][1] << bit; *(pixptr+2) = lorestab_l[data & 255][0] << bit; @@ -3419,13 +3736,13 @@ static __inline__ void pfield_setword_lo #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \ int i; \ unsigned int bpldat1; \ - UWORD data; \ + uae_u16 data; \ unsigned int bpldat2 = 0; \ - UBYTE *ptr = (POINTER); \ + uae_u8 *ptr = (POINTER); \ for (i = dp_for_drawing->plflinelen; i > 0; i -= LL_SUB) { \ - bpldat1 = bpldat2; \ - bpldat2 = do_get_mem_word ((UWORD *)ptr); \ - ptr+=2; \ + bpldat1 = bpldat2; \ + bpldat2 = do_get_mem_word ((uae_u16 *)ptr); \ + ptr+=2; \ data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \ FUNC(data, app, MULT); \ app += P_ADD; \ @@ -3443,7 +3760,7 @@ static __inline__ void pfield_setword_lo static void pfield_doline_aligned_h (int lineno) { int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2; - + if (bplhires) { if (bplplanecnt > 0) { int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0); @@ -3451,7 +3768,7 @@ static void pfield_doline_aligned_h (int int delay1 = 2*(bpldelay1 & 7); int delay2 = 2*(bpldelay2 & 7); unsigned char *app = pixdata.apixels + xpos1; - UBYTE *dataptr = line_data[lineno]; + uae_u8 *dataptr = line_data[lineno]; DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_h, delay1, 4, 16); if (bplplanecnt > 2) { @@ -3493,8 +3810,8 @@ static void pfield_doline_aligned_h (int if (bplplanecnt > 0) { int x = xpos + 32; unsigned char *app = pixdata.apixels + x; - UBYTE *dataptr = line_data[lineno]; - + uae_u8 *dataptr = line_data[lineno]; + DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_h, bpldelay1, 8, 32); if (bplplanecnt > 2) { app = pixdata.apixels + x; @@ -3537,7 +3854,7 @@ static void pfield_doline_aligned_h (int static void pfield_doline_aligned_l (int lineno) { int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT; - + if (bplhires) { if (bplplanecnt > 0) { int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0); @@ -3545,8 +3862,8 @@ static void pfield_doline_aligned_l (int int delay1 = (bpldelay1 & 7) * 2; int delay2 = (bpldelay2 & 7) * 2; unsigned char *app = pixdata.apixels + xpos1; - UBYTE *dataptr = line_data[lineno]; - + uae_u8 *dataptr = line_data[lineno]; + DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_l, delay1, 4, 8); if (bplplanecnt > 2) { app = pixdata.apixels + xpos1; @@ -3589,8 +3906,8 @@ static void pfield_doline_aligned_l (int int delay1 = bpldelay1; int delay2 = bpldelay2; unsigned char *app = pixdata.apixels + x; - UBYTE *dataptr = line_data[lineno]; - + uae_u8 *dataptr = line_data[lineno]; + DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_l, delay1, 8, 16); if (bplplanecnt > 2) { app = pixdata.apixels + x; @@ -3640,7 +3957,7 @@ static void pfield_adjust_delay (void) int ddf_left = dp_for_drawing->plfstrt; int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen; int i; - + for (i = dip_for_drawing->last_delay_change-1; i >= dip_for_drawing->first_delay_change-1; i--) { int delayreg = i < dip_for_drawing->first_delay_change ? dp_for_drawing->bplcon1 : delay_changes[i].value; int delay1 = delayreg & 0xF; @@ -3650,9 +3967,9 @@ static void pfield_adjust_delay (void) int j; startpos = PIXEL_XPOS (startpos + (bplhires ? 4 : 8)); stoppos = PIXEL_XPOS (stoppos + (bplhires ? 4 : 8)); - if (gfx_requested_lores == 0) + if (currprefs.gfx_lores == 0) delay1 <<= 1, delay2 <<= 1; - else if (gfx_requested_lores == 2) + else if (currprefs.gfx_lores == 2) startpos >>= 1, stoppos >>= 1; for (j = startpos-1; j >= stoppos; j--) { pixdata.apixels [j] = (pixdata.apixels[j-delay1] & 0x55) | (pixdata.apixels[j-delay2] & 0xAA); @@ -3660,126 +3977,43 @@ static void pfield_adjust_delay (void) } } -static void init_hardware_frame (void) +static void init_sprites (void) { int i; - for (i = 0; i < 8; i++) - spron[i] = SPR_vtop; -#if 0 + for (i = 0; i < 8; i++) { + /* ???? */ + sprst[i] = SPR_stop; + spron[i] = 0; + } + memset(sprpos, 0, sizeof sprpos); memset(sprctl, 0, sizeof sprctl); -#endif +} +static void init_hardware_frame (void) +{ next_lineno = 0; nln_how = 0; diwstate = DIW_waiting_start; + hdiwstate = DIW_waiting_start; } -static void setdontcare(void) -{ - fprintf(stderr, "Don't care mouse mode set\n"); - mousestate = dont_care_mouse; - lastspr0x = lastmx; lastspr0y = lastmy; - mstepx = defstepx; mstepy = defstepy; -} - -static void setfollow(void) -{ - fprintf(stderr, "Follow sprite mode set\n"); - mousestate = follow_mouse; - lastdiffx = lastdiffy = 0; - sprvbfl = 0; - spr0ctl=spr0pos = 0; - mstepx = defstepx; mstepy = defstepy; -} - -void togglemouse(void) +void init_row_map(void) { - switch(mousestate) { - case dont_care_mouse: setfollow(); break; - case follow_mouse: setdontcare(); break; - default: break; /* Nnnnnghh! */ - } -} - -static __inline__ int adjust(int val) -{ - if (val>127) - return 127; - else if (val<-127) - return -127; - return val; -} - -static void do_mouse_hack(void) -{ - int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1); - int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1; - int diffx, diffy; - - switch (mousestate) { - case normal_mouse: - diffx = lastmx - lastsampledmx; - diffy = lastmy - lastsampledmy; - if (!newmousecounters) { - if (diffx > 127) diffx = 127; - if (diffx < -127) diffx = -127; - joy0x += diffx; - if (diffy > 127) diffy = 127; - if (diffy < -127) diffy = -127; - joy0y += diffy; - } - lastsampledmx += diffx; lastsampledmy += diffy; - break; - - case dont_care_mouse: - diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16); - diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16); - lastspr0x=lastmx; lastspr0y=lastmy; - joy0x+=diffx; joy0y+=diffy; - break; - - case follow_mouse: - if (sprvbfl && sprvbfl-- >1) { - int mousexpos, mouseypos; - - if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x - && spr0x > plfstrt*4 + 34 + xcaloff && spr0x < plfstop*4 - xcaloff) - { - int val = (lastdiffx << 16) / (spr0x - lastspr0x); - if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight; - } - if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y - && spr0y>plffirstline+ycaloff && spr0y=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight; - } - mousexpos = lastmx + linetoscr_x_adjust; - if (lastmy >= gfxvidinfo.maxline) - lastmy = gfxvidinfo.maxline-1; - mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline; - mouseypos <<= 1; - mousexpos <<= (1-lores_shift); - mousexpos += 2*DISPLAY_LEFT_SHIFT; - diffx = adjust ((((mousexpos + xoffs - spr0x) & ~1) * mstepx) >> 16); - diffy = adjust ((((mouseypos + yoffs - spr0y) & ~1) * mstepy) >> 16); - lastspr0x=spr0x; lastspr0y=spr0y; - lastdiffx=diffx; lastdiffy=diffy; - joy0x+=diffx; joy0y+=diffy; - } - break; + int i; + if (gfxvidinfo.height > 2048) { + write_log ("Resolution too high, aborting\n"); } + for (i = 0; i < gfxvidinfo.height + 1; i++) + row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i; } -/* @@@ Are those still useful? */ - /* * A raster line has been built in the graphics buffer. Tell the graphics code * to do anything necessary to display it. */ -static __inline__ void do_flush_line_1 (int lineno) +static void do_flush_line_1 (int lineno) { if (lineno < first_drawn_line) first_drawn_line = lineno; @@ -3802,7 +4036,7 @@ static __inline__ void do_flush_line_1 ( } } -static void do_flush_line (int lineno) +static __inline__ void do_flush_line (int lineno) { /* We don't want to call X libraries from the second thread right now. */ #ifndef SUPPORT_PENGUINS @@ -3813,16 +4047,16 @@ static void do_flush_line (int lineno) } /* - * One Amiga frame has been finished. Tell the graphics code about it. + * One drawing frame has been finished. Tell the graphics code about it. * Note that the actual flush_screen() call is a no-op for all reasonable * systems. */ -static void do_flush_screen (int start, int stop) +static __inline__ void do_flush_screen (int start, int stop) { int i; #ifdef SUPPORT_PENGUINS - for (i = 0; i < gfxvidinfo.maxline; i++) { + for (i = 0; i < gfxvidinfo.height; i++) { if (line_drawn[i]) do_flush_line_1 (i); } @@ -3867,7 +4101,7 @@ static __inline__ void do_color_changes { int lastpos = 0, nextpos, i; struct color_change *cc = curr_color_changes + dip_for_drawing->first_color_change; - + for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++, cc++) { if (i == dip_for_drawing->last_color_change) nextpos = max_diwlastword; @@ -3886,19 +4120,22 @@ static __inline__ void do_color_changes } } +/* We only save hardware registers during the hardware frame. Now, when + * drawing the frame, we expand the data into a slightly more useful + * form. */ static void pfield_expand_dp_bplcon (void) { bplhires = (dp_for_drawing->bplcon0 & 0x8000) == 0x8000; bplplanecnt = (dp_for_drawing->bplcon0 & 0x7000) >> 12; bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800; #if AGA_CHIPSET == 1 /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock - * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */ + * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */ bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200)); #else bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000; #endif - bpldelay1 = dp_for_drawing->bplcon1 & 0xF; - bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF; + bpldelay1 = dp_for_drawing->bplcon1 & 0xF; + bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF; plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7); plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7); bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400; @@ -3910,7 +4147,7 @@ static __inline__ void pfield_draw_line( int border = 0; int to_screen = 0; int do_double = 0; - + dp_for_drawing = 0; dip_for_drawing = 0; switch (linestate[lineno]) { @@ -3919,7 +4156,7 @@ static __inline__ void pfield_draw_line( { static int warned = 0; if (!warned) - fprintf(stderr, "Shouldn't get here... this is a bug.\n"), warned++; + write_log ("Shouldn't get here... this is a bug.\n"), warned++; } line_decisions[lineno].which = -2; return; @@ -3948,7 +4185,7 @@ static __inline__ void pfield_draw_line( do_double = 1; linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos); } - + /* fall through */ default: dip_for_drawing = curr_drawinfo + lineno; @@ -3957,16 +4194,15 @@ static __inline__ void pfield_draw_line( border = 1; break; } - + if (!line_changed[lineno] && !frame_redraw_necessary) { - /* The case where we can skip redrawing this line. If this line + /* The case where we can skip redrawing this line. If this line * is supposed to be doubled, and the next line is remembered as * having been doubled, then the next line is done as well. */ if (do_double) { if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS) { - memcpy (gfxvidinfo.bufmem + gfxvidinfo.rowbytes * follow_ypos, - gfxvidinfo.bufmem + gfxvidinfo.rowbytes * gfx_ypos, - gfxvidinfo.rowbytes); + if (gfxvidinfo.linemem == NULL) + memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); line_decisions[lineno + 1].which = -2; do_flush_line (follow_ypos); } @@ -3977,31 +4213,34 @@ static __inline__ void pfield_draw_line( } if (!border) { - xlinebuffer = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * gfx_ypos - gfxvidinfo.pixbytes * linetoscr_x_adjust; + xlinebuffer = gfxvidinfo.linemem; + if (xlinebuffer == NULL) + xlinebuffer = row_map[gfx_ypos]; + xlinebuffer -= linetoscr_x_adjust_bytes; aga_lbufptr = aga_linebuf; - + pfield_expand_dp_bplcon (); #ifdef LORES_HACK - if (!bplhires && !gfx_requested_lores && dip_for_drawing->nr_color_changes == 0 - && !bplham && !bplehb && !bpldualpf) - gfx_requested_lores = 2; + if (gfxvidinfo.can_double && !bplhires && !currprefs.gfx_lores + && dip_for_drawing->nr_color_changes == 0 && !bplham) + currprefs.gfx_lores = 2; #endif pfield_init_linetoscr (); if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) { bpldelay1 = bpldelay2 = 0; - if (gfx_requested_lores) + if (currprefs.gfx_lores) pfield_doline_l (lineno); else pfield_doline_h (lineno); pfield_adjust_delay (); } else { - if (gfx_requested_lores) + if (currprefs.gfx_lores) pfield_doline_l (lineno); else pfield_doline_h (lineno); } - + /* Check color0 adjust only if we have color changes - shouldn't happen * otherwise. */ adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb); @@ -4009,11 +4248,12 @@ static __inline__ void pfield_draw_line( /* The problem is that we must call decode_ham6() BEFORE we do the * sprites. */ if (bplham) { + init_ham_decoding(linetoscr_x_adjust); if (dip_for_drawing->nr_color_changes == 0) { /* The easy case: need to do HAM decoding only once for the * full line. */ decode_ham6 (linetoscr_x_adjust, linetoscr_right_x); - } else /* Argh. */ { + } else /* Argh. */ { adjust_color0_for_color_change (); do_color_changes (decode_ham6); adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb); @@ -4022,19 +4262,10 @@ static __inline__ void pfield_draw_line( if (dip_for_drawing->nr_sprites != 0) { int spr; - for(spr = 7; spr >= 0; spr--) { - struct sprite_draw *spd = curr_sprite_positions + dip_for_drawing->first_sprite_draw; - int i; - - for (i = dip_for_drawing->first_sprite_draw; i < dip_for_drawing->last_sprite_draw; i++, spd++) { - if (spd->num != spr) - continue; - pfield_sprite (spr, spd->linepos, spd->data, spd->datb, spd->ctl); - } - } + walk_sprites (curr_sprite_positions + dip_for_drawing->first_sprite_draw, dip_for_drawing->nr_sprites); } if (dip_for_drawing->nr_color_changes == 0) { - pfield_do_linetoscr_full (do_double); + pfield_do_linetoscr_full (gfxvidinfo.linemem == NULL ? do_double : 0); do_flush_line (gfx_ypos); linestate[lineno] = LINE_DONE; @@ -4051,44 +4282,27 @@ static __inline__ void pfield_draw_line( linestate[lineno] = LINE_DONE; do_flush_line (gfx_ypos); if (do_double) { - memcpy (gfxvidinfo.bufmem + gfxvidinfo.rowbytes * follow_ypos, - gfxvidinfo.bufmem + gfxvidinfo.rowbytes * gfx_ypos, - gfxvidinfo.rowbytes); + if (gfxvidinfo.linemem == NULL) + memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; line_decisions[lineno + 1].which = -2; do_flush_line (follow_ypos); } } - /* Clean up the spixstate array. */ - { - struct sprite_draw *spd = curr_sprite_positions + dip_for_drawing->first_sprite_draw; - int i; - #ifdef LORES_HACK - if (gfx_requested_lores == 2) { - for (i = dip_for_drawing->first_sprite_draw; i < dip_for_drawing->last_sprite_draw; i++, spd++) - fuzzy_memset_le32 (spixstate, 0, (spd->linepos >> 1), 16*sizeof *spixstate); - } else -#endif - if (gfx_requested_lores) { - for (i = dip_for_drawing->first_sprite_draw; i < dip_for_drawing->last_sprite_draw; i++, spd++) - fuzzy_memset_le32 (spixstate, 0, spd->linepos, 16*sizeof *spixstate); - } else { - for (i = dip_for_drawing->first_sprite_draw; i < dip_for_drawing->last_sprite_draw; i++, spd++) - fuzzy_memset_le32 (spixstate, 0, spd->linepos, 32*sizeof *spixstate); - } - } -#ifdef LORES_HACK - if (gfx_requested_lores == 2) - gfx_requested_lores = 0; + if (currprefs.gfx_lores == 2) + currprefs.gfx_lores = 0; #endif } else { /* Border. */ int i, lastpos = 0, nextpos; struct color_change *cc; - xlinebuffer = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * gfx_ypos - gfxvidinfo.pixbytes * linetoscr_x_adjust; - + xlinebuffer = gfxvidinfo.linemem; + if (xlinebuffer == NULL) + xlinebuffer = row_map[gfx_ypos]; + xlinebuffer -= linetoscr_x_adjust_bytes; + adjust_drawing_colors (dp_for_drawing->ctable, 0); /* Check color0 adjust only if we have color changes - shouldn't happen * otherwise. */ @@ -4098,8 +4312,10 @@ static __inline__ void pfield_draw_line( do_flush_line (gfx_ypos); linestate[lineno] = LINE_DONE; if (do_double) { - xlinebuffer = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * follow_ypos - gfxvidinfo.pixbytes * linetoscr_x_adjust; - fill_line (); + if (gfxvidinfo.linemem == NULL) { + xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes; + fill_line (); + } do_flush_line (follow_ypos); linestate[lineno+1] = LINE_DONE_AS_PREVIOUS; } @@ -4108,13 +4324,12 @@ static __inline__ void pfield_draw_line( adjust_color0_for_color_change (); do_color_changes (pfield_do_fill_line); - + do_flush_line (gfx_ypos); linestate[lineno] = LINE_DONE; if (do_double) { - memcpy (gfxvidinfo.bufmem + gfxvidinfo.rowbytes * follow_ypos, - gfxvidinfo.bufmem + gfxvidinfo.rowbytes * gfx_ypos, - gfxvidinfo.rowbytes); + if (gfxvidinfo.linemem == NULL) + memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; line_decisions[lineno + 1].which = -2; do_flush_line (follow_ypos); @@ -4123,30 +4338,60 @@ static __inline__ void pfield_draw_line( } #ifdef SUPPORT_PENGUINS -static smp_comm_pipe drawing_pipe, drawing_lock_pipe; -#include -static void drawing_penguin (void) +static smp_comm_pipe drawing_pipe; +static uae_sem_t drawing_lock; + +static void *drawing_penguin (void *cruxmedo) { int l; - /* fprintf(stderr, "Hello, world!\n"); */ - signal (SIGINT, SIG_IGN); + fprintf(stderr, "Hello, world!\n"); for (;;) { /* Start of a frame. */ - int k = read_comm_pipe_int_blocking (&drawing_pipe); - if (k != -2) { - fprintf (stderr, "Penguin got out of sync.\n"); - return; /* what can we do? */ + int k; + new_frame: + k = read_comm_pipe_int_blocking (&drawing_pipe); + + switch (k) { + case -2: + /* Hoopy */ + break; + + default: + write_log ("Penguin got out of sync.\n"); + /* what can we do? Try to reduce the damage */ + for (;;) { + k = read_comm_pipe_int_blocking (&drawing_pipe); + if (k == -3) + break; + if (k == -1) { + uae_sem_post (&drawing_lock); + goto new_frame; + } + } + case -3: + UAE_PENGUIN_EXIT; + /* Can't happen */ + return 0; } for (;;) { int i, where; int l = read_comm_pipe_int_blocking (&drawing_pipe); - if (l == -1) { + switch (l) { + case -1: /* End-of-frame synchronization. */ - write_comm_pipe_int (&drawing_lock_pipe, -1); - break; + uae_sem_post (&drawing_lock); + goto new_frame; + case -2: + /* customreset called a bit too often. That's harmless. */ + continue; + case -3: + write_log ("Penguin got out of sync.\n"); + UAE_PENGUIN_EXIT; + return 0; } + /* l is the line that has been finished for drawing. */ i = l - thisframe_y_adjust_real; if (i < 0 || i >= max_ypos_thisframe) @@ -4156,8 +4401,10 @@ static void drawing_penguin (void) fprintf (stderr, "Line scheduled for drawing, but undecided %d!?\n", l); continue; } + if (inhibit_frame != 0) + continue; where = amiga2aspect_line_map[i+min_ypos_for_screen]; - if (where >= gfxvidinfo.maxline || where == -1) + if (where >= gfxvidinfo.height || where == -1) continue; pfield_draw_line (l, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]); @@ -4169,46 +4416,65 @@ static penguin_id our_penguin; static void kill_drawing_penguin (void) { - kill (our_penguin, SIGQUIT); + /* ??? does libpthread do that for us? */ } #endif static int penguins_enabled_thisframe; -static void init_drawing_frame (void) +static void adjust_array_sizes (void) { - int i, maxline; - #ifdef OS_WITHOUT_MEMORY_MANAGEMENT - if(_max_sprite_draw > max_sprite_draw) { - void *p1,*p2; - int mcc = _max_sprite_draw + 128; - _max_sprite_draw = 0; - p1 = realloc(sprite_positions[0], mcc*sizeof(struct sprite_draw)); - p2 = realloc(sprite_positions[1], mcc*sizeof(struct sprite_draw)); - if(p1) sprite_positions[0] = p1; - if(p2) sprite_positions[1] = p2; - if(p1 && p2) { + if (delta_sprite_draw) { + void *p1,*p2; + int mcc = max_sprite_draw + 200 + delta_sprite_draw; + delta_sprite_draw = 0; + p1 = realloc (sprite_positions[0], mcc * sizeof (struct sprite_draw)); + p2 = realloc (sprite_positions[1], mcc * sizeof (struct sprite_draw)); + if (p1) sprite_positions[0] = p1; + if (p2) sprite_positions[1] = p2; + if (p1 && p2) { + fprintf (stderr, "new max_sprite_draw=%d\n",mcc); max_sprite_draw = mcc; - printf("sam: sprite: %s\n", mcc); } } - if(_max_color_change > max_color_change) { - void *p1,*p2; - int mcc = _max_color_change + 128; - _max_color_change = 0; - p1 = realloc(color_changes[0], mcc*sizeof(struct color_change)); - p2 = realloc(color_changes[1], mcc*sizeof(struct color_change)); - if(p1) color_changes[0] = p1; - if(p2) color_changes[1] = p2; - if(p1 && p2) { + if (delta_color_change) { + void *p1,*p2; + int mcc = max_color_change + 200 + delta_color_change; + delta_color_change = 0; + p1 = realloc (color_changes[0], mcc * sizeof (struct color_change)); + p2 = realloc (color_changes[1], mcc * sizeof (struct color_change)); + if (p1) color_changes[0] = p1; + if (p2) color_changes[1] = p2; + if (p1 && p2) { + fprintf (stderr, "new max_color_change=%d\n",mcc); max_color_change = mcc; - printf("sam: color: %s\n", mcc); - } + } + } + if (delta_delay_change) { + void *p; + int mcc = max_delay_change + 200 + delta_delay_change; + delta_delay_change = 0; + p = realloc (delay_changes, mcc * sizeof (struct delay_change)); + if (p) { + fprintf (stderr, "new max_delay_change=%d\n",mcc); + delay_changes = p; + max_delay_change = mcc; + } } #endif +} + +static void init_drawing_frame (void) +{ + int i, maxline; + adjust_array_sizes (); + + check_prefs_changed_custom (); + check_prefs_changed_cpu (); + if (max_diwstop == 0) max_diwstop = diwlastword; if (min_diwstart > max_diwstop) @@ -4222,7 +4488,7 @@ static void init_drawing_frame (void) next_color_change = 0; next_delay_change = 0; next_sprite_draw = 0; - maxline = gfx_requested_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1; + maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1; #ifdef SMART_UPDATE for (i = 0; i < maxline; i++) linestate[i] = linestate[i] == LINE_DONE_AS_PREVIOUS ? LINE_REMEMBERED_AS_PREVIOUS : LINE_UNDECIDED; @@ -4233,11 +4499,11 @@ static void init_drawing_frame (void) first_drawn_line = 32767; first_block_line = last_block_line = -2; - if (test_drawing_speed) + if (currprefs.test_drawing_speed) frame_redraw_necessary = 1; else if (frame_redraw_necessary) frame_redraw_necessary--; - + next_color_entry = 0; remembered_color_entry = -1; prev_sprite_positions = sprite_positions[current_change_set]; @@ -4246,7 +4512,7 @@ static void init_drawing_frame (void) curr_color_changes = color_changes[current_change_set ^ 1]; prev_color_tables = color_tables[current_change_set]; curr_color_tables = color_tables[current_change_set ^ 1]; - + prev_drawinfo = line_drawinfo[current_change_set]; curr_drawinfo = line_drawinfo[current_change_set ^= 1]; drawing_color_matches = -1; @@ -4255,50 +4521,55 @@ static void init_drawing_frame (void) prev_x_adjust = linetoscr_x_adjust; prev_y_adjust = thisframe_y_adjust; - if (gfx_requested_xcenter) { - if (max_diwstop - min_diwstart < gfxvidinfo.maxlinetoscr && gfx_requested_xcenter == 2) + if (currprefs.gfx_xcenter) { + if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2) /* Try to center. */ - linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.maxlinetoscr) / 2 + min_diwstart) & ~1; + linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1; else - linetoscr_x_adjust = max_diwstop - gfxvidinfo.maxlinetoscr; + linetoscr_x_adjust = max_diwstop - gfxvidinfo.width; - /* Should we try to be clever? */ - if (gfx_requested_xcenter == 2) { - /* Don't change x_adjust if wthe new display will fit in the old range. */ + /* Would the old value be good enough? If so, leave it as it is if we want to + * be clever. */ + if (currprefs.gfx_xcenter == 2) { if (linetoscr_x_adjust < prev_x_adjust && prev_x_adjust < min_diwstart) linetoscr_x_adjust = prev_x_adjust; } } else - linetoscr_x_adjust = max_diwlastword - gfxvidinfo.maxlinetoscr; + linetoscr_x_adjust = max_diwlastword - gfxvidinfo.width; if (linetoscr_x_adjust < 0) linetoscr_x_adjust = 0; - - linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.maxlinetoscr; + + linetoscr_x_adjust_bytes = linetoscr_x_adjust * gfxvidinfo.pixbytes; + + linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.width; if (linetoscr_right_x > max_diwlastword) linetoscr_right_x = max_diwlastword; - + thisframe_y_adjust = minfirstline; - if (gfx_requested_ycenter && thisframe_first_drawn_line != -1) { - if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && gfx_requested_ycenter == 2) + if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) { + if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2) thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line; else thisframe_y_adjust = thisframe_first_drawn_line; - if (gfx_requested_ycenter == 2) { + /* Would the old value be good enough? If so, leave it as it is if we want to + * be clever. */ + if (currprefs.gfx_ycenter == 2) { if (thisframe_y_adjust != prev_y_adjust && prev_y_adjust <= thisframe_first_drawn_line && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line) thisframe_y_adjust = prev_y_adjust; } + /* Make sure the value makes sense */ if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos) thisframe_y_adjust = maxvpos - max_drawn_amiga_line; if (thisframe_y_adjust < minfirstline) thisframe_y_adjust = minfirstline; } - thisframe_y_adjust_real = thisframe_y_adjust << (gfx_requested_linedbl ? 1 : 0); - max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (gfx_requested_linedbl ? 1 : 0); + thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0); + max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0); if (prev_x_adjust != linetoscr_x_adjust || prev_y_adjust != thisframe_y_adjust) - frame_redraw_necessary |= (bplcon0 & 4) && gfx_requested_linedbl ? 2 : 1; + frame_redraw_necessary |= (bplcon0 & 4) && currprefs.gfx_linedbl ? 2 : 1; max_diwstop = 0; min_diwstart = 10000; @@ -4307,7 +4578,7 @@ static void init_drawing_frame (void) #ifdef SUPPORT_PENGUINS penguins_enabled_thisframe = 1; /* Tell the other thread that it can now expect data from us. */ - write_comm_pipe_int (&drawing_pipe, -2); + write_comm_pipe_int (&drawing_pipe, -2, 1); memset (line_drawn, 0, sizeof line_drawn); #endif } @@ -4319,10 +4590,10 @@ static void finish_drawing_frame (void) #ifdef SUPPORT_PENGUINS /* Synchronize with other thread, then see whether there's something left for * us to draw. @@@ This is probably a big waste of cycles if the two threads - * run at very different speeds. */ - write_comm_pipe_int (&drawing_pipe, -1); - read_comm_pipe_int_blocking (&drawing_lock_pipe); -#endif + * run at very different speeds - this one could draw stuff as well. */ + write_comm_pipe_int (&drawing_pipe, -1, 1); + uae_sem_wait (&drawing_lock); +#else #ifndef SMART_UPDATE /* @@@ This isn't exactly right yet. FIXME */ @@ -4339,54 +4610,118 @@ static void finish_drawing_frame (void) break; where = amiga2aspect_line_map[i+min_ypos_for_screen]; - if (where >= gfxvidinfo.maxline) + if (where >= gfxvidinfo.height) break; if (where == -1) continue; pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]); } +#endif do_flush_screen (first_drawn_line, last_drawn_line); } +static __inline__ void check_picasso (void) +{ +#ifdef PICASSO96 + if (picasso_requested_on == picasso_on) + return; + + picasso_on = picasso_requested_on; + + if (!picasso_on) + clear_inhibit_frame (2); + else + set_inhibit_frame (2); + + gfx_set_picasso_state (picasso_on); + picasso_enablescreen (picasso_requested_on); + + notice_screen_contents_lost (); +#endif +} + static void vsync_handler (void) { - UWORD dir; - int button; +#ifdef FRAME_RATE_HACK /* put this here or at the end of the function? */ + { + frame_time_t curr_time = read_processor_time(); + vsyncmintime += vsynctime; + /* @@@ Mathias? How do you think we should do this? */ + /* If we are too far behind, or we just did a reset, adjust the + * needed time. */ + if ((long int)(curr_time - vsyncmintime) > 0 || did_reset) + vsyncmintime = curr_time + vsynctime; + did_reset = 0; + } +#endif + handle_events (); - handle_events(); - getjoystate(&joy0dir, &joy0button); + getjoystate (0, &joy0dir, &joy0button); + getjoystate (1, &joy1dir, &joy1button); - do_mouse_hack(); - INTREQ(0x8020); - if (bplcon0 & 4) + if (bplcon0 & 4) lof ^= 0x8000; - + + if (quit_program < 0) { + quit_program = -quit_program; + set_inhibit_frame (1); + regs.spcflags |= SPCFLAG_BRK; + if (framecnt == 0) + finish_drawing_frame (); + filesys_prepare_reset (); +#ifdef SUPPORT_PENGUINS + if (quit_program == 1) + /* Stop eating herring */ + write_comm_pipe_int (&drawing_pipe, -3, 1); +#endif + return; + } + last_redraw_point++; if (lof_changed || !interlace_seen || last_redraw_point >= 2 || lof) { + static int cnt = 0; + if (framecnt == 0) finish_drawing_frame (); count_frame (); last_redraw_point = 0; + + check_picasso (); + + uae_sem_wait (&ihf_sem); + if (inhibit_frame != 0) + framecnt = 1; + if (frame_do_semup) + uae_sem_post (&frame_sem); + frame_do_semup = 0; + uae_sem_post (&ihf_sem); + + if (cnt == 0) { + /* resolution_check_change (); */ + DISK_check_change (); + cnt = 5; + } + cnt--; if (framecnt == 0) init_drawing_frame (); } - + lof_changed = 0; interlace_seen = 0; COPJMP1(0); - + init_hardware_frame(); #ifdef HAVE_GETTIMEOFDAY { struct timeval tv; unsigned long int newtime; - - gettimeofday(&tv,NULL); + + gettimeofday(&tv,NULL); newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000; - - if (!bogusframe) { + + if (!bogusframe) { frametime += newtime - msecs; timeframes++; } @@ -4394,6 +4729,8 @@ static void vsync_handler (void) bogusframe = 0; } #endif + if (ievent_alive > 0) + ievent_alive--; CIA_vsync_handler(); } @@ -4402,7 +4739,7 @@ static void hsync_handler(void) int lineno = next_lineno; int lineisdouble = 0; int line_was_doubled = 0; - + finish_decisions (); do_modulos (); @@ -4434,13 +4771,13 @@ static void hsync_handler(void) eventtab[ev_hsync].evtime += cycles - eventtab[ev_hsync].oldcycles; eventtab[ev_hsync].oldcycles = cycles; CIA_hsync_handler(); - - if (produce_sound > 0) { + + if (currprefs.produce_sound > 0) { int nr; /* Sound data is fetched at the beginning of each line */ for (nr = 0; nr < 4; nr++) { struct audio_channel_data *cdp = audio_channel + nr; - + if (cdp->data_written == 2) { cdp->data_written = 0; cdp->nextdat = chipmem_bank.wget(cdp->pt); @@ -4458,11 +4795,7 @@ static void hsync_handler(void) } #ifdef SUPPORT_PENGUINS if (framecnt == 0 && penguins_enabled_thisframe) { - /* This is awfully bad. Just think about how many syscalls this does - * in one second and you'll be ill. But before I change it I want to - * hear from someone who has an SMP machine just exactly how bad this - * is. */ - write_comm_pipe_int (&drawing_pipe, next_lineno); + write_comm_pipe_int (&drawing_pipe, next_lineno, 0); } #endif #ifndef SMART_UPDATE @@ -4472,7 +4805,7 @@ static void hsync_handler(void) i = next_lineno - thisframe_y_adjust_real; if (i >= 0 && i < max_ypos_thisframe) { where = amiga2aspect_line_map[i+min_ypos_for_screen]; - if (where < gfxvidinfo.maxline && where != -1) + if (where < gfxvidinfo.height && where != -1) pfield_draw_line (next_lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]); } } @@ -4482,14 +4815,16 @@ static void hsync_handler(void) vsync_handler(); } - if ((bplcon0 & 4) && gfx_requested_linedbl) { + is_lastline = vpos + 1 == maxvpos + (lof != 0); + + if ((bplcon0 & 4) && currprefs.gfx_linedbl) { interlace_seen = 1, penguins_enabled_thisframe = 0; } if (framecnt == 0) { lineno = vpos; nln_how = 0; - if (gfx_requested_linedbl) { + if (currprefs.gfx_linedbl) { lineno *= 2; nln_how = 1; if (bplcon0 & 4) { @@ -4504,9 +4839,53 @@ static void hsync_handler(void) next_lineno = lineno; reset_decisions (); } + if (uae_int_requested) { + set_uae_int_flag (); + INTREQ (0xA000); + } +} + +static void init_eventtab (void) +{ + int i; + + for(i = 0; i < ev_max; i++) { + eventtab[i].active = 0; + eventtab[i].oldcycles = 0; + } + copper_active = 0; + eventtab[ev_cia].handler = CIA_handler; + eventtab[ev_copper].handler = /* currprefs.copper_pos >= 0 ? do_copper_cheat : */ do_copper; + eventtab[ev_hsync].handler = hsync_handler; + eventtab[ev_hsync].evtime = maxhpos + cycles; + eventtab[ev_hsync].active = 1; + + eventtab[ev_blitter].handler = blitter_handler; + eventtab[ev_blitter].active = 0; + eventtab[ev_diskblk].handler = diskblk_handler; + eventtab[ev_diskblk].active = 0; + eventtab[ev_diskindex].handler = diskindex_handler; + eventtab[ev_diskindex].active = 0; +#ifndef DONT_WANT_SOUND + eventtab[ev_aud0].handler = aud0_handler; + eventtab[ev_aud0].active = 0; + eventtab[ev_aud1].handler = aud1_handler; + eventtab[ev_aud1].active = 0; + eventtab[ev_aud2].handler = aud2_handler; + eventtab[ev_aud2].active = 0; + eventtab[ev_aud3].handler = aud3_handler; + eventtab[ev_aud3].active = 0; + if (sound_available && currprefs.produce_sound >= 2) { + eventtab[ev_sample].active = 1; + eventtab[ev_sample].evtime = sample_evtime; + } else { + eventtab[ev_sample].active = 0; + } +#endif + events_schedule (); } -void customreset(void) +void customreset (void) { int i, maxl; double native_lines_per_amiga_line; @@ -4514,28 +4893,56 @@ void customreset(void) struct timeval tv; #endif + for (i = 0; i < sizeof current_colors.color_regs / sizeof *current_colors.color_regs; i++) + current_colors.color_regs[i] = -1; + +#ifdef FRAME_RATE_HACK + did_reset = 1; + vsyncmintime = read_processor_time() + vsynctime; +#endif inhibit_frame = 0; - expamem_reset(); - CIA_reset(); - cycles = 0; + frame_do_semup = 0; + uae_sem_init (&frame_sem, 0, 0); + uae_sem_init (&gui_sem, 0, 1); + uae_sem_init (&ihf_sem, 0, 1); + expamem_reset (); + filesys_reset (); + CIA_reset (); +#ifdef PICASSO96 + InitPicasso96 (); + picasso_on = 0; + picasso_requested_on = 0; + gfx_set_picasso_state (0); +#endif + cycles = 0; regs.spcflags &= SPCFLAG_BRK; - - lores_factor = gfx_requested_lores ? 1 : 2; - lores_shift = gfx_requested_lores ? 0 : 1; - sprite_width = gfx_requested_lores ? 16 : 32; - + + lores_factor = currprefs.gfx_lores ? 1 : 2; + lores_shift = currprefs.gfx_lores ? 0 : 1; + sprite_width = currprefs.gfx_lores ? 16 : 32; + vpos = 0; + is_lastline = 0; lof = 0; max_diwstop = 0; - + if (needmousehack()) { - if (mousestate != follow_mouse) setfollow(); +#if 0 + if (mousestate != follow_mouse) setfollow(); +#else + if (mousestate != dont_care_mouse) setdontcare(); +#endif } else { mousestate = normal_mouse; } + ievent_alive = 0; + + clx_sprmask = 0xFF; + clxdat = 0; + + memset(sprarmed, 0, sizeof sprarmed); + nr_armed = 0; - memset(spixstate, 0, sizeof(spixstate)); - /*memset(blitcount, 0, sizeof(blitcount)); blitter debug */ for (i = 0; i < (maxvpos+1)*2 + 1; i++) { linestate[i] = LINE_UNDECIDED; @@ -4546,89 +4953,63 @@ void customreset(void) bltstate = BLT_done; copstate = COP_stop; diwstate = DIW_waiting_start; + hdiwstate = DIW_waiting_start; copcon = 0; dskdmaen = 0; cycles = 0; - - memset(audio_channel, 0, sizeof audio_channel); + + audio_reset (); bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */ bplcon3 = 0xC00; - for(i = 0; i < ev_max; i++) { - eventtab[i].active = 0; - eventtab[i].oldcycles = 0; - } - copper_active = 0; - eventtab[ev_cia].handler = CIA_handler; - eventtab[ev_copper].handler = do_copper; - eventtab[ev_hsync].handler = hsync_handler; - eventtab[ev_hsync].evtime = maxhpos + cycles; - eventtab[ev_hsync].active = 1; - eventtab[ev_blitter].handler = blitter_handler; - eventtab[ev_blitter].active = 0; - eventtab[ev_diskblk].handler = diskblk_handler; - eventtab[ev_diskblk].active = 0; - eventtab[ev_diskindex].handler = diskindex_handler; - eventtab[ev_diskindex].active = 0; -#ifndef DONT_WANT_SOUND - eventtab[ev_aud0].handler = aud0_handler; - eventtab[ev_aud0].active = 0; - eventtab[ev_aud1].handler = aud1_handler; - eventtab[ev_aud1].active = 0; - eventtab[ev_aud2].handler = aud2_handler; - eventtab[ev_aud2].active = 0; - eventtab[ev_aud3].handler = aud3_handler; - eventtab[ev_aud3].active = 0; - if (sound_available) { - eventtab[ev_sample].active = 1; - eventtab[ev_sample].evtime += cycles; - eventtab[ev_sample].oldcycles = cycles; - } else { - eventtab[ev_sample].active = 0; - } -#endif - events_schedule (); + init_eventtab (); if (native2amiga_line_map) free (native2amiga_line_map); if (amiga2aspect_line_map) free (amiga2aspect_line_map); - /* At least for this array the +1 is necessary. */ + /* At least for this array the +1 is necessary. */ amiga2aspect_line_map = (int *)malloc (sizeof (int) * (maxvpos+1)*2 + 1); - native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.maxline); + native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height); - if (gfx_requested_correct_aspect) - native_lines_per_amiga_line = ((double)gfxvidinfo.maxline - * (gfx_requested_lores ? 320 : 640) - / (gfx_requested_linedbl ? 512 : 256) - / gfxvidinfo.maxlinetoscr); + if (currprefs.gfx_correct_aspect) + native_lines_per_amiga_line = ((double)gfxvidinfo.height + * (currprefs.gfx_lores ? 320 : 640) + / (currprefs.gfx_linedbl ? 512 : 256) + / gfxvidinfo.width); else native_lines_per_amiga_line = 1; - maxl = (maxvpos+1) * (gfx_requested_linedbl ? 2 : 1); - min_ypos_for_screen = minfirstline << (gfx_requested_linedbl ? 1 : 0); + maxl = (maxvpos+1) * (currprefs.gfx_linedbl ? 2 : 1); + min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0); max_drawn_amiga_line = -1; for (i = 0; i < maxl; i++) { int v = (i - min_ypos_for_screen) * native_lines_per_amiga_line; - if (v >= gfxvidinfo.maxline && max_drawn_amiga_line == -1) + if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1) max_drawn_amiga_line = i-min_ypos_for_screen; - if (i < min_ypos_for_screen || v >= gfxvidinfo.maxline) + if (i < min_ypos_for_screen || v >= gfxvidinfo.height) v = -1; amiga2aspect_line_map[i] = v; } - if (gfx_requested_linedbl) + if (currprefs.gfx_linedbl) max_drawn_amiga_line >>= 1; - for (i = 0; i < gfxvidinfo.maxline; i++) + if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) { + extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1; + if (extra_y_adjust < 0) + extra_y_adjust = 0; + } + + for (i = 0; i < gfxvidinfo.height; i++) native2amiga_line_map[i] = -1; if (native_lines_per_amiga_line < 1) { /* Must omit drawing some lines. */ for (i = maxl-1; i > min_ypos_for_screen; i--) { if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) { - if (gfx_requested_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) { + if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) { /* If only the first line of a line pair would be omitted, * omit the second one instead to avoid problems with line * doubling. */ @@ -4644,17 +5025,21 @@ void customreset(void) int j; if (amiga2aspect_line_map[i] == -1) continue; - for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.maxline && native2amiga_line_map[j] == -1; j++) - native2amiga_line_map[j] = i >> (gfx_requested_linedbl ? 1 : 0); + for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++) + native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0); } - - line_drawn = (char *)malloc (gfxvidinfo.maxline); - + + if (line_drawn == 0) + line_drawn = (char *)malloc (gfxvidinfo.height); + init_row_map(); + + init_sprites (); + init_hardware_frame (); init_drawing_frame (); last_redraw_point = 0; reset_decisions (); - + #ifdef HAVE_GETTIMEOFDAY gettimeofday(&tv,NULL); seconds_base = tv.tv_sec; @@ -4662,21 +5047,22 @@ void customreset(void) #endif } -void dumpcustom(void) +void dumpcustom (void) { int i; fprintf(stderr, "DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(), intena, intreq, vpos, current_hpos()); - if (timeframes) { - fprintf(stderr, "Average frame time: %d ms [frames: %d time: %d]\n", + if (timeframes) { + fprintf(stderr, "Average frame time: %d ms [frames: %d time: %d]\n", frametime/timeframes, timeframes, frametime); } + dump_audio_bench (); /*for (i=0; i<256; i++) if (blitcount[i]) fprintf(stderr, "minterm %x = %d\n",i,blitcount[i]); blitter debug */ } -int intlev(void) +int intlev (void) { - UWORD imask = intreq & intena; + uae_u16 imask = intreq & intena; if (imask && (intena & 0x4000)){ if (imask & 0x2000) return 6; if (imask & 0x1800) return 5; @@ -4684,43 +5070,41 @@ int intlev(void) if (imask & 0x0070) return 3; if (imask & 0x0008) return 2; if (imask & 0x0007) return 1; - if (regs.spcflags & SPCFLAG_TIMER) - return 7; } return -1; } -void custom_init(void) +void custom_init (void) { int num; #ifdef OS_WITHOUT_MEMORY_MANAGEMENT for(num=0;num<2;++num) { - sprite_positions[num] = malloc(max_sprite_draw * sizeof(struct sprite_draw)); - color_changes[num] = malloc(max_color_change * sizeof(struct color_change)); - if(!sprite_positions[num] || !color_changes[num]) { - printf("Out of mem int %s %d!\n",__FILE__,__LINE__); - abort(); - } + sprite_positions[num] = xmalloc(max_sprite_draw * sizeof(struct sprite_draw)); + color_changes[num] = xmalloc(max_color_change * sizeof(struct color_change)); } + delay_changes = xmalloc(max_delay_change * sizeof(struct delay_change)); #endif - + if (needmousehack()) setfollow(); init_regchanges (); init_decisions (); - for (num = 0; num < 256; num++) { + /* For now, the AGA stuff is broken in the dual playfield case. We encode + * sprites in dpf mode by ORing the pixel value with 0x80. To make dual + * playfield rendering easy, the lookup tables contain are made linear for + * values >= 128. That only works for OCS/ECS, though. */ + + for (num = 0; num < 256; num++) { int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4) | ((num >> 3) & 8); int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4) | ((num >> 4) & 8); dblpf_2nd1[num] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1; dblpf_2nd2[num] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2; - dblpf_aga1[num] = plane1 == 0 ? plane2 : plane1; - dblpf_aga2[num] = plane2 == 0 ? plane1 : plane2; if (plane2 > 0) plane2 += 8; - dblpf_ind1[num] = plane1 == 0 ? plane2 : plane1; - dblpf_ind2[num] = plane2 == 0 ? plane1 : plane2; - + dblpf_ind1[num] = num >= 128 ? num & 0x7F : (plane1 == 0 ? plane2 : plane1); + dblpf_ind2[num] = num >= 128 ? num & 0x7F : (plane2 == 0 ? plane1 : plane2); + lots_of_twos[num] = num == 0 ? 0 : 2; linear_map_256[num] = num; } @@ -4729,42 +5113,42 @@ void custom_init(void) native2amiga_line_map = 0; amiga2aspect_line_map = 0; line_drawn = 0; + #ifdef SUPPORT_PENGUINS - init_comm_pipe (&drawing_pipe); - init_comm_pipe (&drawing_lock_pipe); - our_penguin = start_penguin (drawing_penguin); - atexit(kill_drawing_penguin); + init_comm_pipe (&drawing_pipe, 800, 5); + uae_sem_init (&drawing_lock, 0, 0); + start_penguin (drawing_penguin, 0, &our_penguin); + /*atexit(kill_drawing_penguin);*/ #endif } /* Custom chip memory bank */ -static ULONG custom_lget(CPTR) REGPARAM; -static ULONG custom_wget(CPTR) REGPARAM; -static ULONG custom_bget(CPTR) REGPARAM; -static void custom_lput(CPTR, ULONG) REGPARAM; -static void custom_wput(CPTR, ULONG) REGPARAM; -static void custom_bput(CPTR, ULONG) REGPARAM; +static uae_u32 custom_lget(uaecptr) REGPARAM; +static uae_u32 custom_wget(uaecptr) REGPARAM; +static uae_u32 custom_bget(uaecptr) REGPARAM; +static void custom_lput(uaecptr, uae_u32) REGPARAM; +static void custom_wput(uaecptr, uae_u32) REGPARAM; +static void custom_bput(uaecptr, uae_u32) REGPARAM; addrbank custom_bank = { - default_alget, default_awget, custom_lget, custom_wget, custom_bget, custom_lput, custom_wput, custom_bput, default_xlate, default_check }; -ULONG REGPARAM2 custom_wget(CPTR addr) +uae_u32 REGPARAM2 custom_wget (uaecptr addr) { switch(addr & 0x1FE) { case 0x002: return DMACONR(); case 0x004: return VPOSR(); case 0x006: return VHPOSR(); - + case 0x008: return DSKDATR(); case 0x00A: return JOY0DAT(); case 0x00C: return JOY1DAT(); - case 0x00E: return 0; /* CLXDAT */ + case 0x00E: return CLXDAT(); case 0x010: return ADKCONR(); case 0x012: return POT0DAT(); @@ -4784,191 +5168,192 @@ ULONG REGPARAM2 custom_wget(CPTR addr) } } -ULONG REGPARAM2 custom_bget(CPTR addr) +uae_u32 REGPARAM2 custom_bget (uaecptr addr) { return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8); } -ULONG REGPARAM2 custom_lget(CPTR addr) +uae_u32 REGPARAM2 custom_lget (uaecptr addr) { - return ((ULONG)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe); + return ((uae_u32)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe); } -void REGPARAM2 custom_wput(CPTR addr, ULONG value) +void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value) { addr &= 0x1FE; cregs[addr>>1] = value; - switch(addr) { - case 0x020: DSKPTH(value); break; - case 0x022: DSKPTL(value); break; - case 0x024: DSKLEN(value); break; - case 0x026: DSKDAT(value); break; - - case 0x02A: VPOSW(value); break; - case 0x2E: COPCON(value); break; - case 0x030: SERDAT(value); break; - case 0x032: SERPER(value); break; - - case 0x040: BLTCON0(value); break; - case 0x042: BLTCON1(value); break; - - case 0x044: BLTAFWM(value); break; - case 0x046: BLTALWM(value); break; - - case 0x050: BLTAPTH(value); break; - case 0x052: BLTAPTL(value); break; - case 0x04C: BLTBPTH(value); break; - case 0x04E: BLTBPTL(value); break; - case 0x048: BLTCPTH(value); break; - case 0x04A: BLTCPTL(value); break; - case 0x054: BLTDPTH(value); break; - case 0x056: BLTDPTL(value); break; - - case 0x058: BLTSIZE(value); break; - - case 0x064: BLTAMOD(value); break; - case 0x062: BLTBMOD(value); break; - case 0x060: BLTCMOD(value); break; - case 0x066: BLTDMOD(value); break; - - case 0x070: BLTCDAT(value); break; - case 0x072: BLTBDAT(value); break; - case 0x074: BLTADAT(value); break; - - case 0x07E: DSKSYNC(value); break; - - case 0x080: COP1LCH(value); break; - case 0x082: COP1LCL(value); break; - case 0x084: COP2LCH(value); break; - case 0x086: COP2LCL(value); break; - - case 0x088: COPJMP1(value); break; - case 0x08A: COPJMP2(value); break; - - case 0x08E: DIWSTRT(value); break; - case 0x090: DIWSTOP(value); break; - case 0x092: DDFSTRT(value); break; - case 0x094: DDFSTOP(value); break; - - case 0x096: DMACON(value); break; - case 0x09A: INTENA(value); break; - case 0x09C: INTREQ(value); break; - case 0x09E: ADKCON(value); break; - - case 0x0A0: AUDxLCH(0, value); break; - case 0x0A2: AUDxLCL(0, value); break; - case 0x0A4: AUDxLEN(0, value); break; - case 0x0A6: AUDxPER(0, value); break; - case 0x0A8: AUDxVOL(0, value); break; - case 0x0AA: AUDxDAT(0, value); break; - - case 0x0B0: AUDxLCH(1, value); break; - case 0x0B2: AUDxLCL(1, value); break; - case 0x0B4: AUDxLEN(1, value); break; - case 0x0B6: AUDxPER(1, value); break; - case 0x0B8: AUDxVOL(1, value); break; - case 0x0BA: AUDxDAT(1, value); break; - - case 0x0C0: AUDxLCH(2, value); break; - case 0x0C2: AUDxLCL(2, value); break; - case 0x0C4: AUDxLEN(2, value); break; - case 0x0C6: AUDxPER(2, value); break; - case 0x0C8: AUDxVOL(2, value); break; - case 0x0CA: AUDxDAT(2, value); break; - - case 0x0D0: AUDxLCH(3, value); break; - case 0x0D2: AUDxLCL(3, value); break; - case 0x0D4: AUDxLEN(3, value); break; - case 0x0D6: AUDxPER(3, value); break; - case 0x0D8: AUDxVOL(3, value); break; - case 0x0DA: AUDxDAT(3, value); break; - - case 0x0E0: BPLPTH(value, 0); break; - case 0x0E2: BPLPTL(value, 0); break; - case 0x0E4: BPLPTH(value, 1); break; - case 0x0E6: BPLPTL(value, 1); break; - case 0x0E8: BPLPTH(value, 2); break; - case 0x0EA: BPLPTL(value, 2); break; - case 0x0EC: BPLPTH(value, 3); break; - case 0x0EE: BPLPTL(value, 3); break; - case 0x0F0: BPLPTH(value, 4); break; - case 0x0F2: BPLPTL(value, 4); break; - case 0x0F4: BPLPTH(value, 5); break; - case 0x0F6: BPLPTL(value, 5); break; - - case 0x100: BPLCON0(value); break; - case 0x102: BPLCON1(value); break; - case 0x104: BPLCON2(value); break; - case 0x106: BPLCON3(value); break; - - case 0x108: BPL1MOD(value); break; - case 0x10A: BPL2MOD(value); break; + switch (addr) { + case 0x020: DSKPTH (value); break; + case 0x022: DSKPTL (value); break; + case 0x024: DSKLEN (value); break; + case 0x026: DSKDAT (value); break; + + case 0x02A: VPOSW (value); break; + case 0x2E: COPCON (value); break; + case 0x030: SERDAT (value); break; + case 0x032: SERPER (value); break; + case 0x34: POTGO (value); break; + case 0x040: BLTCON0 (value); break; + case 0x042: BLTCON1 (value); break; + + case 0x044: BLTAFWM (value); break; + case 0x046: BLTALWM (value); break; + + case 0x050: BLTAPTH (value); break; + case 0x052: BLTAPTL (value); break; + case 0x04C: BLTBPTH (value); break; + case 0x04E: BLTBPTL (value); break; + case 0x048: BLTCPTH (value); break; + case 0x04A: BLTCPTL (value); break; + case 0x054: BLTDPTH (value); break; + case 0x056: BLTDPTL (value); break; + + case 0x058: BLTSIZE (value); break; + + case 0x064: BLTAMOD (value); break; + case 0x062: BLTBMOD (value); break; + case 0x060: BLTCMOD (value); break; + case 0x066: BLTDMOD (value); break; + + case 0x070: BLTCDAT (value); break; + case 0x072: BLTBDAT (value); break; + case 0x074: BLTADAT (value); break; + + case 0x07E: DSKSYNC (value); break; + + case 0x080: COP1LCH (value); break; + case 0x082: COP1LCL (value); break; + case 0x084: COP2LCH (value); break; + case 0x086: COP2LCL (value); break; + + case 0x088: COPJMP1 (value); break; + case 0x08A: COPJMP2 (value); break; + + case 0x08E: DIWSTRT (value); break; + case 0x090: DIWSTOP (value); break; + case 0x092: DDFSTRT (value); break; + case 0x094: DDFSTOP (value); break; + + case 0x096: DMACON (value); break; + case 0x098: CLXCON (value); break; + case 0x09A: INTENA (value); break; + case 0x09C: INTREQ (value); break; + case 0x09E: ADKCON (value); break; + + case 0x0A0: AUDxLCH (0, value); break; + case 0x0A2: AUDxLCL (0, value); break; + case 0x0A4: AUDxLEN (0, value); break; + case 0x0A6: AUDxPER (0, value); break; + case 0x0A8: AUDxVOL (0, value); break; + case 0x0AA: AUDxDAT (0, value); break; + + case 0x0B0: AUDxLCH (1, value); break; + case 0x0B2: AUDxLCL (1, value); break; + case 0x0B4: AUDxLEN (1, value); break; + case 0x0B6: AUDxPER (1, value); break; + case 0x0B8: AUDxVOL (1, value); break; + case 0x0BA: AUDxDAT (1, value); break; + + case 0x0C0: AUDxLCH (2, value); break; + case 0x0C2: AUDxLCL (2, value); break; + case 0x0C4: AUDxLEN (2, value); break; + case 0x0C6: AUDxPER (2, value); break; + case 0x0C8: AUDxVOL (2, value); break; + case 0x0CA: AUDxDAT (2, value); break; + + case 0x0D0: AUDxLCH (3, value); break; + case 0x0D2: AUDxLCL (3, value); break; + case 0x0D4: AUDxLEN (3, value); break; + case 0x0D6: AUDxPER (3, value); break; + case 0x0D8: AUDxVOL (3, value); break; + case 0x0DA: AUDxDAT (3, value); break; + + case 0x0E0: BPLPTH (value, 0); break; + case 0x0E2: BPLPTL (value, 0); break; + case 0x0E4: BPLPTH (value, 1); break; + case 0x0E6: BPLPTL (value, 1); break; + case 0x0E8: BPLPTH (value, 2); break; + case 0x0EA: BPLPTL (value, 2); break; + case 0x0EC: BPLPTH (value, 3); break; + case 0x0EE: BPLPTL (value, 3); break; + case 0x0F0: BPLPTH (value, 4); break; + case 0x0F2: BPLPTL (value, 4); break; + case 0x0F4: BPLPTH (value, 5); break; + case 0x0F6: BPLPTL (value, 5); break; + + case 0x100: BPLCON0 (value); break; + case 0x102: BPLCON1 (value); break; + case 0x104: BPLCON2 (value); break; + case 0x106: BPLCON3 (value); break; + + case 0x108: BPL1MOD (value); break; + case 0x10A: BPL2MOD (value); break; + + case 0x110: BPL1DAT (value); break; + case 0x112: BPL2DAT (value); break; + case 0x114: BPL3DAT (value); break; + case 0x116: BPL4DAT (value); break; + case 0x118: BPL5DAT (value); break; + case 0x11A: BPL6DAT (value); break; - case 0x110: BPL1DAT(value); break; - case 0x112: BPL2DAT(value); break; - case 0x114: BPL3DAT(value); break; - case 0x116: BPL4DAT(value); break; - case 0x118: BPL5DAT(value); break; - case 0x11A: BPL6DAT(value); break; - case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A: case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196: case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2: case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE: case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA: case 0x1BC: case 0x1BE: - COLOR(value & 0xFFF, (addr & 0x3E) / 2); + COLOR (value & 0xFFF, (addr & 0x3E) / 2); break; case 0x120: case 0x124: case 0x128: case 0x12C: case 0x130: case 0x134: case 0x138: case 0x13C: - SPRxPTH(value, (addr - 0x120) / 4); + SPRxPTH (value, (addr - 0x120) / 4); break; case 0x122: case 0x126: case 0x12A: case 0x12E: case 0x132: case 0x136: case 0x13A: case 0x13E: - SPRxPTL(value, (addr - 0x122) / 4); + SPRxPTL (value, (addr - 0x122) / 4); break; case 0x140: case 0x148: case 0x150: case 0x158: case 0x160: case 0x168: case 0x170: case 0x178: - SPRxPOS(value, (addr - 0x140) / 8); + SPRxPOS (value, (addr - 0x140) / 8); break; case 0x142: case 0x14A: case 0x152: case 0x15A: case 0x162: case 0x16A: case 0x172: case 0x17A: - SPRxCTL(value, (addr - 0x142) / 8); + SPRxCTL (value, (addr - 0x142) / 8); break; case 0x144: case 0x14C: case 0x154: case 0x15C: case 0x164: case 0x16C: case 0x174: case 0x17C: - SPRxDATA(value, (addr - 0x144) / 8); + SPRxDATA (value, (addr - 0x144) / 8); break; case 0x146: case 0x14E: case 0x156: case 0x15E: case 0x166: case 0x16E: case 0x176: case 0x17E: - SPRxDATB(value, (addr - 0x146) / 8); + SPRxDATB (value, (addr - 0x146) / 8); break; - - case 0x36: JOYTEST(value); break; -#if defined(ECS_AGNUS) || (AGA_CHIPSET == 1) + + case 0x36: JOYTEST (value); break; +#if defined (ECS_AGNUS) || (AGA_CHIPSET == 1) case 0x5A: BLTCON0L(value); break; - case 0x5C: BLTSIZV(value); break; - case 0x5E: BLTSIZH(value); break; + case 0x5C: BLTSIZV (value); break; + case 0x5E: BLTSIZH (value); break; #endif #if AGA_CHIPSET == 1 - case 0x10C: BPLCON4(value); break; + case 0x10C: BPLCON4 (value); break; case 0x1FC: fmode = value; break; #endif } } -void REGPARAM2 custom_bput(CPTR addr, ULONG value) +void REGPARAM2 custom_bput(uaecptr addr, uae_u32 value) { static int warned = 0; /* Is this correct now? (There are people who bput things to the upper byte of AUDxVOL). */ - UWORD rval = (value << 8) | (value & 0xFF); + uae_u16 rval = (value << 8) | (value & 0xFF); custom_wput(addr, rval); if (!warned) - fprintf(stderr, "Byte put to custom register.\n"), warned++; + write_log ("Byte put to custom register.\n"), warned++; } -void REGPARAM2 custom_lput(CPTR addr, ULONG value) +void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value) { custom_wput(addr & 0xfffe, value >> 16); - custom_wput((addr+2) & 0xfffe, (UWORD)value); + custom_wput((addr+2) & 0xfffe, (uae_u16)value); }