]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
2600b15
authorToni Wilen <twilen@winuae.net>
Sat, 6 Apr 2013 13:55:45 +0000 (16:55 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 6 Apr 2013 13:55:45 +0000 (16:55 +0300)
blitter.cpp
custom.cpp
drawing.cpp
gayle.cpp
gencpu.cpp
od-win32/hardfile_win32.cpp
od-win32/rp.cpp
od-win32/win32.cpp
od-win32/win32.h
od-win32/winuaechangelog.txt

index d9fdf071b4a3c4eba7cadfcabdef2069ee7a6896..896064c75de19eb259f4fce7bf9f818a01e1caeb 100644 (file)
@@ -269,6 +269,7 @@ STATIC_INLINE void record_dma_blit (uae_u16 reg, uae_u16 dat, uae_u32 addr, int
 
 static void blitter_dump (void)
 {
+       int chipsize = currprefs.chipmem_size;
        write_log (_T("PT A=%08X B=%08X C=%08X D=%08X\n"), bltapt, bltbpt, bltcpt, bltdpt);
        write_log (_T("CON0=%04X CON1=%04X DAT A=%04X B=%04X C=%04X\n"),
                bltcon0, bltcon1, blt_info.bltadat, blt_info.bltbdat, blt_info.bltcdat);
@@ -276,6 +277,10 @@ static void blitter_dump (void)
                blt_info.bltafwm, blt_info.bltalwm,
                blt_info.bltamod & 0xffff, blt_info.bltbmod & 0xffff, blt_info.bltcmod & 0xffff, blt_info.bltdmod & 0xffff);
        write_log (_T("PC=%08X DMA=%d\n"), m68k_getpc (), dmaen (DMA_BLITTER));
+
+       if (((bltcon0 & 0x800) && bltapt >= chipsize) || ((bltcon0 & 0x400) && bltbpt >= chipsize) ||
+               ((bltcon0 & 0x200) && bltcpt >= chipsize) || ((bltcon0 & 0x100) && bltdpt >= chipsize))
+               write_log (_T("PT outside of chipram\n"));
 }
 
 STATIC_INLINE const int *get_ch (void)
index f80137fcb6233d5768aac235b9667c406cfc5b17..082bde276124648c4ab483521b4183b9bc188e8a 100644 (file)
@@ -901,7 +901,7 @@ int is_bitplane_dma (int hpos)
 {
        if (fetch_state == fetch_not_started || hpos < plfstrt)
                return 0;
-       if ((plf_state == plf_end && hpos >= thisline_decision.plfright)
+       if ((plf_state >= plf_end && hpos >= thisline_decision.plfright)
                || hpos >= estimated_last_fetch_cycle)
                return 0;
        return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask];
@@ -911,7 +911,7 @@ STATIC_INLINE int is_bitplane_dma_inline (int hpos)
 {
        if (fetch_state == fetch_not_started || hpos < plfstrt)
                return 0;
-       if ((plf_state == plf_end && hpos >= thisline_decision.plfright)
+       if ((plf_state >= plf_end && hpos >= thisline_decision.plfright)
                || hpos >= estimated_last_fetch_cycle)
                return 0;
        return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask];
@@ -1582,14 +1582,11 @@ static void do_long_fetch (int hpos, int nwords, int dma, int fm)
 #endif
 
 /* make sure fetch that goes beyond maxhpos is finished */
-static void finish_final_fetch (int fm)
+static void finish_final_fetch (void)
 {
-       int pos = maxhpos;
        if (plf_state != plf_end)
                return;
-       pos += flush_plane_data (fm);
-       thisline_decision.plfright = pos;
-       thisline_decision.plflinelen = out_offs;
+       plf_state = plf_finished;
        finish_playfield_line ();
 }
 
@@ -1597,14 +1594,16 @@ static void finish_last_fetch (int pos, int fm)
 {
        if (thisline_decision.plfleft < 0)
                return;
-       if (plf_state == plf_end)
+       if (plf_state >= plf_end)
                return;
        plf_state = plf_end;
-       if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) {
-               finish_final_fetch (fm);
-       } else {
+
+       pos += flush_plane_data (fm);
+       thisline_decision.plfright = pos;
+       thisline_decision.plflinelen = out_offs;
+
+       if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
                bpl1dat_early = true;
-               pos += flush_plane_data (fm);
                ddfstate = DIW_waiting_start;
                fetch_state = fetch_not_started;
        }
@@ -1625,7 +1624,6 @@ STATIC_INLINE int one_fetch_cycle_0 (int pos, int ddfstop_to_test, int dma, int
                } else if (plf_state == plf_passed_stop2) {
                        plf_state = plf_end;
                }
-
        }
 
        maybe_check (pos);
@@ -1754,7 +1752,7 @@ STATIC_INLINE void update_fetch (int until, int fm)
 
        int ddfstop_to_test;
 
-       if (nodraw () || plf_state == plf_end)
+       if (nodraw () || plf_state >= plf_end)
                return;
 
        /* We need an explicit test against HARD_DDF_STOP here to guard against
@@ -1928,6 +1926,12 @@ static void start_bpl_dma (int hpos, int hstart)
 
                bpldmawasactive = true;
 
+       } else {
+               
+               // this is a hack, something weird happens without this
+               // (Subtle Shades)
+               thisline_decision.plfright++;
+               thisline_decision.plflinelen = ++out_offs;
        }
 
        last_fetch_hpos = hstart;
@@ -2093,10 +2097,10 @@ static bool issprbrd (int hpos, uae_u16 bplcon0, uae_u16 bplcon3)
                record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (current_colors.borderblank ? 1 : 0) | (brdsprt ? 2 : 0));
                current_colors.bordersprite = brdsprt;
                remembered_color_entry = -1;
-               if (brdsprt)
+               if (brdsprt && !current_colors.borderblank)
                        thisline_decision.bordersprite_seen = true;
        }
-       return brdsprt;
+       return brdsprt && !current_colors.borderblank;
 }
 
 static void record_register_change (int hpos, int regno, uae_u16 value)
@@ -2422,7 +2426,7 @@ static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16
                unsigned int da = *data;
                unsigned int db = *datb;
                uae_u32 datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8]
-               | (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]);
+                       | (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]);
                int off = (i << dbl) >> half;
                uae_u16 *buf = spixels + word_offs + off;
                if (currprefs.collision_level > 0 && collision_mask)
@@ -2481,7 +2485,7 @@ static int tospritexdiw (int diw)
 }
 static int tospritexddf (int ddf)
 {
-       return (ddf * 2) << sprite_buffer_res;
+       return (ddf * 2 - DIW_DDF_OFFSET) << sprite_buffer_res;
 }
 static int fromspritexdiw (int ddf)
 {
@@ -2509,7 +2513,7 @@ static void calcsprite (void)
                        }
                }
                /* sprites are visible from first BPL1DAT write to end of line
-                * ECS Denise/AGA: not limits
+                * ECS Denise/AGA: no limits
                 * OCS Denise: BPL1DAT write only enables sprite if hpos >= 0x28 or so.
                 * (undocumented feature)
                 */
@@ -2660,7 +2664,7 @@ static void finish_decisions (void)
        decide_diw (hpos);
        decide_line (hpos);
        decide_fetch (hpos);
-       finish_final_fetch (fetchmode);
+       finish_final_fetch ();
 
        record_color_change2 (hsyncstartpos, 0xffff, 0);
        if (thisline_decision.plfleft >= 0 && thisline_decision.plflinelen < 0) {
@@ -3295,7 +3299,7 @@ static void calcdiw (void)
                                plfstrt = HARD_DDF_START;
                        plfstrt_start = plfstrt - 4;
                } else {
-                       plfstrt_start = plfstrt - 4;
+                       plfstrt_start = plfstrt;
                }
        } else {
                if (!bpldmawasactive) {
@@ -3441,8 +3445,10 @@ static uae_u16 VPOSR (void)
                csbit |= (currprefs.chipset_mask & CSMASK_AGA) ? 0x2300 : 0;
 #endif
                csbit |= (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0;
+#if 0 /* apparently "8372 (Fat-hr) (agnushr),rev 5" does not exist */
                if (currprefs.chipmem_size > 1024 * 1024 && (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
                        csbit |= 0x2100;
+#endif
                if (currprefs.ntscmode)
                        csbit |= 0x1000;
        }
@@ -4108,7 +4114,7 @@ static void BPLxDAT (int hpos, int num, uae_u16 v)
                bpl1dat_written = true;
                bpl1dat_written_at_least_once = true;
                if (thisline_decision.plfleft < 0) {
-                       thisline_decision.plfleft = hpos & ~3;
+                       thisline_decision.plfleft = (hpos + 3) & ~3;
                        reset_bpl_vars ();
                        compute_delay_offset ();
                }
index efd8805dfb941c30e2435615e76c91883970ff4a..c0cca803b04c56fea833c208701ccb2e26c3bbce 100644 (file)
@@ -219,7 +219,8 @@ static int first_block_line, last_block_line;
 /* These are generated by the drawing code from the line_decisions array for
 each line that needs to be drawn.  These are basically extracted out of
 bit fields in the hardware registers.  */
-static int bplehb, bplham, bpldualpf, bpldualpfpri, bpldualpf2of, bplplanecnt, ecsshres, issprites;
+static int bplehb, bplham, bpldualpf, bpldualpfpri, bpldualpf2of, bplplanecnt, ecsshres;
+static bool issprites;
 static int bplres;
 static int plf1pri, plf2pri, bplxor;
 static uae_u32 plf_sprite_mask;
@@ -694,6 +695,7 @@ static int playfield_start, playfield_end;
 static int real_playfield_start, real_playfield_end;
 static int linetoscr_diw_start, linetoscr_diw_end;
 static int native_ddf_left, native_ddf_right;
+static bool can_have_bordersprite;
 
 static int pixels_offset;
 static int src_pixel, ham_src_pixel;
@@ -764,6 +766,22 @@ static void pfield_init_linetoscr (void)
        real_playfield_end = playfield_end;
        real_playfield_start = playfield_start;
 
+       // Sprite hpos don't include DIW_DDF_OFFSET and can appear 1 lores pixel
+       // before first bitplane pixel appears.
+       // This means "bordersprite" conditions is possible under OCS/ECS too. Argh!
+       if (dip_for_drawing->nr_sprites) {
+               /* bordersprite off or not supported: sprites are visible until diw_end */
+               if (playfield_end < linetoscr_diw_end)
+                       playfield_end = linetoscr_diw_end;
+               int end = coord_hw_to_window_x (dp_for_drawing->plfleft * 2);
+               if (end < playfield_start && end > linetoscr_diw_start) {
+                       playfield_start = end;
+                       can_have_bordersprite = true;
+               }
+       } else {
+               can_have_bordersprite = dp_for_drawing->bordersprite_seen;
+       }
+
 #ifdef AGA
        if (dp_for_drawing->bordersprite_seen && dip_for_drawing->nr_sprites) {
                int min = visible_right_border, max = visible_left_border, i;
@@ -1268,6 +1286,7 @@ static int NOINLINE linetoscr_16_shrink2f_sh (int spix, int dpix, int stoppos, i
 static void pfield_do_linetoscr (int start, int stop, bool blank)
 {
        xlinecheck(start, stop);
+#ifdef AGA
        if (issprites && (currprefs.chipset_mask & CSMASK_AGA)) {
                if (res_shift == 0) {
                        switch (gfxvidinfo.drawbuffer.pixbytes) {
@@ -1310,7 +1329,6 @@ static void pfield_do_linetoscr (int start, int stop, bool blank)
                        }
                }
        } else
-#ifdef AGA
                if (currprefs.chipset_mask & CSMASK_AGA) {
                        if (res_shift == 0) {
                                switch (gfxvidinfo.drawbuffer.pixbytes) {
@@ -1450,6 +1468,15 @@ static void pfield_do_linetoscr (int start, int stop, bool blank)
 
 }
 
+// left or right border sprite
+static void pfield_do_linetoscr_border (int start, int stop, bool blank)
+{
+       bool old = issprites;
+       issprites = colors_for_drawing.bordersprite != 0;
+       pfield_do_linetoscr (start, stop, blank);
+       issprites = old;
+}
+
 static void dummy_worker (int start, int stop, bool blank)
 {
 }
@@ -1681,9 +1708,8 @@ STATIC_INLINE void draw_sprites_ecs (struct sprite_entry *e)
        }
 }
 
-#ifdef AGA
 /* clear possible bitplane data outside DIW area */
-static void clear_bitplane_border_aga (void)
+static void clear_bitplane_border (void)
 {
        int len, shift = res_shift;
        uae_u8 v = 0;
@@ -1701,7 +1727,6 @@ static void clear_bitplane_border_aga (void)
                memset (pixdata.apixels + pixels_offset + (real_playfield_end >> shift), v, len);
        }
 }
-#endif
 
 /* emulate OCS/ECS only undocumented "SWIV" hardware feature */
 static void weird_bitplane_fix (void)
@@ -1994,7 +2019,7 @@ static void pfield_expand_dp_bplcon (void)
        bplehb = dp_for_drawing->ehb_seen;
        if ((currprefs.chipset_mask & CSMASK_AGA) && (dp_for_drawing->bplcon2 & 0x0200))
                bplehb = 0;
-       issprites = dip_for_drawing->nr_sprites;
+       issprites = dip_for_drawing->nr_sprites > 0;
 #ifdef ECS_DENISE
        ecsshres = bplres == RES_SUPERHIRES && (currprefs.chipset_mask & CSMASK_ECS_DENISE) && !(currprefs.chipset_mask & CSMASK_AGA);
 #endif
@@ -2081,6 +2106,7 @@ static void adjust_drawing_colors (int ctable, int need_full)
                        memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
                                sizeof colors_for_drawing.acolors);
                        colors_for_drawing.borderblank = curr_color_tables[ctable].borderblank;
+                       colors_for_drawing.bordersprite = curr_color_tables[ctable].bordersprite;
                        color_match_type = color_match_acolors;
                }
                drawing_color_matches = ctable;
@@ -2191,7 +2217,7 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in
 
        case LINE_BLACK:
                linestate[lineno] = LINE_REMEMBERED_AS_BLACK;
-               border = 2;
+               border = -1;
                break;
 
        case LINE_REMEMBERED_AS_BLACK:
@@ -2261,10 +2287,9 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in
 
                if (dip_for_drawing->nr_sprites) {
                        int i;
-#ifdef AGA
-                       if (dp_for_drawing->bordersprite_seen)
-                               clear_bitplane_border_aga ();
-#endif
+                       if (can_have_bordersprite)
+                               clear_bitplane_border ();
+
                        for (i = 0; i < dip_for_drawing->nr_sprites; i++) {
 #ifdef AGA
                                if (currprefs.chipset_mask & CSMASK_AGA)
@@ -2289,13 +2314,14 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in
                        do_flush_line (vb, follow_ypos);
                }
 
-       } else if (border == 1) {
+       } else if (border > 0) {
+               // border > 0: top or bottom border
                bool dosprites = false;
 
                adjust_drawing_colors (dp_for_drawing->ctable, 0);
 
 #ifdef AGA /* this makes things complex.. */
-               if (dp_for_drawing->bordersprite_seen && dip_for_drawing->nr_sprites > 0) {
+               if (dp_for_drawing->bordersprite_seen && dip_for_drawing->nr_sprites) {
                        dosprites = true;
                        pfield_expand_dp_bplcon ();
                        pfield_init_linetoscr ();
@@ -2327,7 +2353,7 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in
                        uae_u16 oxor = bplxor;
                        memset (pixdata.apixels, 0, sizeof pixdata);
                        bplxor = 0;
-                       do_color_changes (pfield_do_fill_line, pfield_do_linetoscr, lineno);
+                       do_color_changes (pfield_do_fill_line, pfield_do_linetoscr_border, lineno);
                        bplxor = oxor;
 
                } else {
index a4c00a914a097ee278ae9f13c063276092208313..15a6dbc27794599451c3f28fd7f817ad8622efbb 100644 (file)
--- a/gayle.cpp
+++ b/gayle.cpp
@@ -110,7 +110,7 @@ read 1 byte to stop reset */
 /*
 *  These are at different offsets from the base
 */
-#define GAYLE_IRQ_4000  0x3020    /* MSB = 1, Harddisk is source of interrupt */
+#define GAYLE_IRQ_4000  0x3020    /* WORD register MSB = 1, Harddisk is source of interrupt */
 #define GAYLE_CS_1200  0x8000
 #define GAYLE_IRQ_1200  0x9000
 #define GAYLE_INT_1200  0xA000
@@ -228,19 +228,17 @@ static int pcmcia_configured;
 
 static int gayle_id_cnt;
 static uae_u8 gayle_irq, gayle_int, gayle_cs, gayle_cs_mask, gayle_cfg;
-static int ide2, ide_splitter;
-
-static struct ide_hdf *ide;
+static int ide_splitter;
 
 static smp_comm_pipe requests;
 static volatile int gayle_thread_running;
 
-STATIC_INLINE void pw (int offset, uae_u16 w)
+STATIC_INLINE void pw (struct ide_hdf *ide, int offset, uae_u16 w)
 {
        ide->secbuf[offset * 2 + 0] = (uae_u8)w;
        ide->secbuf[offset * 2 + 1] = w >> 8;
 }
-static void ps (int offset, const TCHAR *src, int max)
+static void ps (struct ide_hdf *ide, int offset, const TCHAR *src, int max)
 {
        int i, len;
        char *s;
@@ -277,9 +275,9 @@ static uae_u8 checkpcmciaideirq (void)
        return 0;
 }
 
-static bool isdrive (struct ide_hdf *drv)
+static bool isdrive (struct ide_hdf *ide)
 {
-       return drv->hdhfd.size != 0 || drv->atapi;
+       return ide && (ide->hdhfd.size != 0 || ide->atapi);
 }
 
 static uae_u8 checkgayleideirq (void)
@@ -434,11 +432,11 @@ static uae_u8 read_gayle_cs (void)
        return v;
 }
 
-static void ide_interrupt (void)
+static void ide_interrupt (struct ide_hdf *ide)
 {
        ide->irq_delay = 2;
 }
-static void ide_fast_interrupt (void)
+static void ide_fast_interrupt (struct ide_hdf *ide)
 {
        ide->irq_delay = 1;
 }
@@ -446,6 +444,8 @@ static void ide_fast_interrupt (void)
 static void ide_interrupt_do (struct ide_hdf *ide)
 {
        ide->regs.ide_status &= ~IDE_STATUS_BSY;
+       if (ide->direction)
+               ide->regs.ide_status |= IDE_STATUS_DRQ;
        ide->irq_delay = 0;
        if (ide->regs.ide_devcon & 2)
                return;
@@ -453,37 +453,37 @@ static void ide_interrupt_do (struct ide_hdf *ide)
        rethink_gayle ();
 }
 
-static void ide_fail_err (uae_u8 err)
+static void ide_fail_err (struct ide_hdf *ide, uae_u8 err)
 {
        ide->regs.ide_error |= err;
-       if (ide->ide_drv == 1 && !isdrive (ide + 1))
-               idedrive[ide2]->regs.ide_status |= IDE_STATUS_ERR;
+       if (ide->ide_drv == 1 && !isdrive (ide->pair))
+               idedrive[ide->ide_drv >= 2 ? 2 : 0]->regs.ide_status |= IDE_STATUS_ERR;
        ide->regs.ide_status |= IDE_STATUS_ERR;
-       ide_interrupt ();
+       ide_interrupt (ide);
 }
-static void ide_fail (void)
+static void ide_fail (struct ide_hdf *ide)
 {
-       ide_fail_err (IDE_ERR_ABRT);
+       ide_fail_err (ide, IDE_ERR_ABRT);
 }
 
-static void ide_data_ready (void)
+static void ide_data_ready (struct ide_hdf *ide)
 {
        memset (ide->secbuf, 0, ide->blocksize);
        ide->data_offset = 0;
        ide->regs.ide_status |= IDE_STATUS_DRQ;
        ide->data_size = ide->blocksize;
        ide->data_multi = 1;
-       ide_interrupt ();
+       ide_interrupt (ide);
 }
 
-static void ide_recalibrate (void)
+static void ide_recalibrate (struct ide_hdf *ide)
 {
        write_log (_T("IDE%d recalibrate\n"), ide->num);
        ide->regs.ide_sector = 0;
        ide->regs.ide_lcyl = ide->regs.ide_hcyl = 0;
-       ide_interrupt ();
+       ide_interrupt (ide);
 }
-static void ide_identify_drive (void)
+static void ide_identify_drive (struct ide_hdf *ide)
 {
        uae_u64 totalsecs;
        int v;
@@ -492,73 +492,73 @@ static void ide_identify_drive (void)
        bool atapi = ide->atapi;
 
        if (!isdrive (ide)) {
-               ide_fail ();
+               ide_fail (ide);
                return;
        }
        memset (buf, 0, ide->blocksize);
        if (IDE_LOG > 0)
                write_log (_T("IDE%d identify drive\n"), ide->num);
-       ide_data_ready ();
+       ide_data_ready (ide);
        ide->direction = 0;
-       pw (0, atapi ? 0x85c0 : 1 << 6);
-       pw (1, ide->hdhfd.cyls_def);
-       pw (2, 0xc837);
-       pw (3, ide->hdhfd.heads_def);
-       pw (4, ide->blocksize * ide->hdhfd.secspertrack_def);
-       pw (5, ide->blocksize);
-       pw (6, ide->hdhfd.secspertrack_def);
-       ps (10, _T("68000"), 20); /* serial */
-       pw (20, 3);
-       pw (21, ide->blocksize);
-       pw (22, 4);
-       ps (23, _T("0.5"), 8); /* firmware revision */
+       pw (ide, 0, atapi ? 0x85c0 : 1 << 6);
+       pw (ide, 1, ide->hdhfd.cyls_def);
+       pw (ide, 2, 0xc837);
+       pw (ide, 3, ide->hdhfd.heads_def);
+       pw (ide, 4, ide->blocksize * ide->hdhfd.secspertrack_def);
+       pw (ide, 5, ide->blocksize);
+       pw (ide, 6, ide->hdhfd.secspertrack_def);
+       ps (ide, 10, _T("68000"), 20); /* serial */
+       pw (ide, 20, 3);
+       pw (ide, 21, ide->blocksize);
+       pw (ide, 22, 4);
+       ps (ide, 23, _T("0.5"), 8); /* firmware revision */
        if (ide->atapi)
                _tcscpy (tmp, _T("UAE-ATAPI"));
        else
                _stprintf (tmp, _T("UAE-IDE %s"), ide->hdhfd.hfd.product_id);
-       ps (27, tmp, 40); /* model */
-       pw (47, MAX_IDE_MULTIPLE_SECTORS >> (ide->blocksize / 512 - 1)); /* max sectors in multiple mode */
-       pw (48, 1);
-       pw (49, (1 << 9) | (1 << 8)); /* LBA and DMA supported */
-       pw (51, 0x200); /* PIO cycles */
-       pw (52, 0x200); /* DMA cycles */
-       pw (53, 1 | 2 | 4);
-       pw (54, ide->hdhfd.cyls);
-       pw (55, ide->hdhfd.heads);
-       pw (56, ide->hdhfd.secspertrack);
+       ps (ide, 27, tmp, 40); /* model */
+       pw (ide, 47, MAX_IDE_MULTIPLE_SECTORS >> (ide->blocksize / 512 - 1)); /* max sectors in multiple mode */
+       pw (ide, 48, 1);
+       pw (ide, 49, (1 << 9) | (1 << 8)); /* LBA and DMA supported */
+       pw (ide, 51, 0x200); /* PIO cycles */
+       pw (ide, 52, 0x200); /* DMA cycles */
+       pw (ide, 53, 1 | 2 | 4);
+       pw (ide, 54, ide->hdhfd.cyls);
+       pw (ide, 55, ide->hdhfd.heads);
+       pw (ide, 56, ide->hdhfd.secspertrack);
        totalsecs = ide->hdhfd.cyls * ide->hdhfd.heads * ide->hdhfd.secspertrack;
-       pw (57, (uae_u16)totalsecs);
-       pw (58, (uae_u16)(totalsecs >> 16));
+       pw (ide, 57, (uae_u16)totalsecs);
+       pw (ide, 58, (uae_u16)(totalsecs >> 16));
        v = idedrive[ide->ide_drv]->multiple_mode;
-       pw (59, (v > 0 ? 0x100 : 0) | v);
+       pw (ide, 59, (v > 0 ? 0x100 : 0) | v);
        totalsecs = ide->blocksize ? ide->hdhfd.size / ide->blocksize : 0;
        if (totalsecs > 0x0fffffff)
                totalsecs = 0x0fffffff;
-       pw (60, (uae_u16)totalsecs);
-       pw (61, (uae_u16)(totalsecs >> 16));
-       pw (62, 0x0f);
-       pw (63, 0x0f);
-       pw (64, 0x03); /* PIO3 and PIO4 */
-       pw (65, 120); /* MDMA2 supported */
-       pw (66, 120);
-       pw (67, 120);
-       pw (68, 120);
-       pw (80, (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6)); /* ATA-1 to ATA-6 */
-       pw (81, 0x1c); /* ATA revision */
-       pw (82, (1 << 14) | (atapi ? 0x10 | 4 : 0)); /* NOP, ATAPI: PACKET and Removable media features supported */
-       pw (83, (1 << 14) | (1 << 13) | (1 << 12) | (ide->lba48 ? (1 << 10) : 0)); /* cache flushes, LBA 48 supported */
-       pw (84, 1 << 14);
-       pw (85, 1 << 14);
-       pw (86, (1 << 14) | (1 << 13) | (1 << 12) | (ide->lba48 ? (1 << 10) : 0)); /* cache flushes, LBA 48 enabled */
-       pw (87, 1 << 14);
-       pw (88, (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); /* UDMA modes */
-       pw (93, (1 << 14) | (1 << 13) | (1 << 0));
+       pw (ide, 60, (uae_u16)totalsecs);
+       pw (ide, 61, (uae_u16)(totalsecs >> 16));
+       pw (ide, 62, 0x0f);
+       pw (ide, 63, 0x0f);
+       pw (ide, 64, 0x03); /* PIO3 and PIO4 */
+       pw (ide, 65, 120); /* MDMA2 supported */
+       pw (ide, 66, 120);
+       pw (ide, 67, 120);
+       pw (ide, 68, 120);
+       pw (ide, 80, (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6)); /* ATA-1 to ATA-6 */
+       pw (ide, 81, 0x1c); /* ATA revision */
+       pw (ide, 82, (1 << 14) | (atapi ? 0x10 | 4 : 0)); /* NOP, ATAPI: PACKET and Removable media features supported */
+       pw (ide, 83, (1 << 14) | (1 << 13) | (1 << 12) | (ide->lba48 ? (1 << 10) : 0)); /* cache flushes, LBA 48 supported */
+       pw (ide, 84, 1 << 14);
+       pw (ide, 85, 1 << 14);
+       pw (ide, 86, (1 << 14) | (1 << 13) | (1 << 12) | (ide->lba48 ? (1 << 10) : 0)); /* cache flushes, LBA 48 enabled */
+       pw (ide, 87, 1 << 14);
+       pw (ide, 88, (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0)); /* UDMA modes */
+       pw (ide, 93, (1 << 14) | (1 << 13) | (1 << 0));
        if (ide->lba48) {
                totalsecs = ide->hdhfd.size / ide->blocksize;
-               pw (100, (uae_u16)(totalsecs >> 0));
-               pw (101, (uae_u16)(totalsecs >> 16));
-               pw (102, (uae_u16)(totalsecs >> 32));
-               pw (103, (uae_u16)(totalsecs >> 48));
+               pw (ide, 100, (uae_u16)(totalsecs >> 0));
+               pw (ide, 101, (uae_u16)(totalsecs >> 16));
+               pw (ide, 102, (uae_u16)(totalsecs >> 32));
+               pw (ide, 103, (uae_u16)(totalsecs >> 48));
        }
 }
 
@@ -582,23 +582,23 @@ static void set_signature (struct ide_hdf *ide)
        ide->packet_state = 0;
 }
 
-static void reset_device (bool both)
+static void reset_device (struct ide_hdf *ide, bool both)
 {
        set_signature (ide);
        if (both)
                set_signature (ide->pair);
 }
 
-static void ide_execute_drive_diagnostics (bool irq)
+static void ide_execute_drive_diagnostics (struct ide_hdf *ide, bool irq)
 {
-       reset_device (irq);
+       reset_device (ide, irq);
        if (irq)
-               ide_interrupt ();
+               ide_interrupt (ide);
        else
                ide->regs.ide_status &= ~IDE_STATUS_BSY;
 }
 
-static void ide_initialize_drive_parameters (void)
+static void ide_initialize_drive_parameters (struct ide_hdf *ide)
 {
        if (ide->hdhfd.size) {
                ide->hdhfd.secspertrack = ide->regs.ide_nsector == 0 ? 256 : ide->regs.ide_nsector;
@@ -621,26 +621,26 @@ static void ide_initialize_drive_parameters (void)
        }
        write_log (_T("IDE%d initialize drive parameters, CYL=%d,SPT=%d,HEAD=%d\n"),
                ide->num, ide->hdhfd.cyls, ide->hdhfd.secspertrack, ide->hdhfd.heads);
-       ide_interrupt ();
+       ide_interrupt (ide);
 }
-static void ide_set_multiple_mode (void)
+static void ide_set_multiple_mode (struct ide_hdf *ide)
 {
        write_log (_T("IDE%d drive multiple mode = %d\n"), ide->num, ide->regs.ide_nsector);
        ide->multiple_mode = ide->regs.ide_nsector;
-       ide_interrupt ();
+       ide_interrupt (ide);
 }
-static void ide_set_features (void)
+static void ide_set_features (struct ide_hdf *ide)
 {
        int type = ide->regs.ide_nsector >> 3;
        int mode = ide->regs.ide_nsector & 7;
 
        write_log (_T("IDE%d set features %02X (%02X)\n"), ide->num, ide->regs.ide_feat, ide->regs.ide_nsector);
-       ide_fail ();
+       ide_fail (ide);
 }
 
-static void get_lbachs (struct ide_hdf *ide, uae_u64 *lbap, unsigned int *cyl, unsigned int *head, unsigned int *sec, int lba48)
+static void get_lbachs (struct ide_hdf *ide, uae_u64 *lbap, unsigned int *cyl, unsigned int *head, unsigned int *sec)
 {
-       if (lba48 && (ide->regs.ide_select & 0x40)) {
+       if (ide->lba48 && (ide->regs.ide_select & 0x40)) {
                uae_u64 lba;
                lba = (ide->regs.ide_hcyl << 16) | (ide->regs.ide_lcyl << 8) | ide->regs.ide_sector;
                lba |= ((ide->regs.ide_hcyl2 << 16) | (ide->regs.ide_lcyl2 << 8) | ide->regs.ide_sector2) << 24;
@@ -657,16 +657,16 @@ static void get_lbachs (struct ide_hdf *ide, uae_u64 *lbap, unsigned int *cyl, u
        }
 }
 
-static int get_nsec (int lba48)
+static int get_nsec (struct ide_hdf *ide)
 {
-       if (lba48)
+       if (ide->lba48)
                return (ide->regs.ide_nsector == 0 && ide->regs.ide_nsector2 == 0) ? 65536 : (ide->regs.ide_nsector2 * 256 + ide->regs.ide_nsector);
        else
                return ide->regs.ide_nsector == 0 ? 256 : ide->regs.ide_nsector;
 }
-static int dec_nsec (int lba48, int v)
+static int dec_nsec (struct ide_hdf *ide, int v)
 {
-       if (lba48) {
+       if (ide->lba48) {
                uae_u16 nsec;
                nsec = ide->regs.ide_nsector2 * 256 + ide->regs.ide_nsector;
                ide->regs.ide_nsector -= v;
@@ -679,9 +679,9 @@ static int dec_nsec (int lba48, int v)
        }
 }
 
-static void put_lbachs (struct ide_hdf *ide, uae_u64 lba, unsigned int cyl, unsigned int head, unsigned int sec, unsigned int inc, int lba48)
+static void put_lbachs (struct ide_hdf *ide, uae_u64 lba, unsigned int cyl, unsigned int head, unsigned int sec, unsigned int inc)
 {
-       if (lba48) {
+       if (ide->lba48) {
                lba += inc;
                ide->regs.ide_hcyl = (lba >> 16) & 0xff;
                ide->regs.ide_lcyl = (lba >> 8) & 0xff;
@@ -717,7 +717,7 @@ static void put_lbachs (struct ide_hdf *ide, uae_u64 lba, unsigned int cyl, unsi
        }
 }
 
-static void check_maxtransfer (int state)
+static void check_maxtransfer (struct ide_hdf *ide, int state)
 {
        if (state == 1) {
                // transfer was started
@@ -739,20 +739,20 @@ static void check_maxtransfer (int state)
        }
 }
 
-static void process_rw_command (void)
+static void process_rw_command (struct ide_hdf *ide)
 {
        ide->regs.ide_status |= IDE_STATUS_BSY;
        ide->regs.ide_status &= ~IDE_STATUS_DRQ;
        write_comm_pipe_u32 (&requests, ide->num, 1);
 }
-static void process_packet_command (void)
+static void process_packet_command (struct ide_hdf *ide)
 {
        ide->regs.ide_status |= IDE_STATUS_BSY;
        ide->regs.ide_status &= ~IDE_STATUS_DRQ;
        write_comm_pipe_u32 (&requests, ide->num | 0x80, 1);
 }
 
-static void atapi_data_done (void)
+static void atapi_data_done (struct ide_hdf *ide)
 {
        ide->regs.ide_nsector = ATAPI_IO | ATAPI_CD;
        ide->regs.ide_status = IDE_STATUS_DRDY;
@@ -788,7 +788,7 @@ static bool atapi_set_size (struct ide_hdf *ide)
        return false;
 }
 
-static void atapi_packet (void)
+static void atapi_packet (struct ide_hdf *ide)
 {
        ide->packet_data_offset = 0;
        ide->packet_data_size = (ide->regs.ide_hcyl << 8) | ide->regs.ide_lcyl;
@@ -826,14 +826,14 @@ static void do_packet_command (struct ide_hdf *ide)
                        // error
                        ide->regs.ide_status = ATAPI_STATUS_CHK;
                        ide->regs.ide_error = ide->scsi->status << 4;
-                       atapi_data_done ();
+                       atapi_data_done (ide);
                } else if (ide->scsi->data_len) {
                        // data in
                        memcpy (ide->secbuf, ide->scsi->buffer, ide->scsi->data_len);
                        ide->regs.ide_nsector = ATAPI_IO;
                } else {
                        // no data
-                       atapi_data_done ();
+                       atapi_data_done (ide);
                }
        } else {
                // data out
@@ -874,8 +874,8 @@ static void do_process_rw_command (struct ide_hdf *ide)
        bool last;
 
        ide->data_offset = 0;
-       get_lbachs (ide, &lba, &cyl, &head, &sec, ide->lba48);
-       nsec = get_nsec (ide->lba48);
+       get_lbachs (ide, &lba, &cyl, &head, &sec);
+       nsec = get_nsec (ide);
        if (IDE_LOG > 1)
                write_log (_T("IDE%d off=%d, nsec=%d (%d) lba%d\n"), ide->num, (uae_u32)lba, nsec, ide->multiple_mode, ide->lba48 ? 48 : 28);
        if (nsec * ide->blocksize > ide->hdhfd.size - lba * ide->blocksize) {
@@ -884,8 +884,8 @@ static void do_process_rw_command (struct ide_hdf *ide)
                        write_log (_T("IDE%d nsec changed to %d\n"), ide->num, nsec);
        }
        if (nsec <= 0) {
-               ide_data_ready ();
-               ide_fail_err (IDE_ERR_IDNF);
+               ide_data_ready (ide);
+               ide_fail_err (ide, IDE_ERR_IDNF);
                return;
        }
        if (nsec > ide->data_multi)
@@ -901,8 +901,8 @@ static void do_process_rw_command (struct ide_hdf *ide)
                        write_log (_T("IDE%d read, read %d bytes\n"), ide->num, nsec * ide->blocksize);
        }
        ide->regs.ide_status |= IDE_STATUS_DRQ;
-       last = dec_nsec (ide->lba48, nsec) == 0;
-       put_lbachs (ide, lba, cyl, head, sec, last ? nsec - 1 : nsec, ide->lba48);
+       last = dec_nsec (ide, nsec) == 0;
+       put_lbachs (ide, lba, cyl, head, sec, last ? nsec - 1 : nsec);
        if (last) {
                if (ide->direction) {
                        if (IDE_LOG > 1)
@@ -913,74 +913,73 @@ static void do_process_rw_command (struct ide_hdf *ide)
        ide->irq_delay = 1;
 }
 
-static void ide_read_sectors (int flags)
+static void ide_read_sectors (struct ide_hdf *ide, int flags)
 {
        unsigned int cyl, head, sec, nsec;
        uae_u64 lba;
        int multi = flags & 1;
-       int lba48 = flags & 2;
 
        if (multi && ide->multiple_mode == 0) {
-               ide_fail ();
+               ide_fail (ide);
                return;
        }
-       check_maxtransfer(1);
+       check_maxtransfer (ide, 1);
        gui_flicker_led (LED_HD, ide->num, 1);
-       nsec = get_nsec (lba48);
-       get_lbachs (ide, &lba, &cyl, &head, &sec, lba48);
+       nsec = get_nsec (ide);
+       get_lbachs (ide, &lba, &cyl, &head, &sec);
        if (lba * ide->blocksize >= ide->hdhfd.size) {
-               ide_data_ready ();
-               ide_fail_err (IDE_ERR_IDNF);
+               ide_data_ready (ide);
+               ide_fail_err (ide, IDE_ERR_IDNF);
                return;
        }
        ide->data_multi = multi ? ide->multiple_mode : 1;
        ide->data_offset = 0;
-       ide->regs.ide_status |= IDE_STATUS_DRQ;
        ide->data_size = nsec * ide->blocksize;
        ide->direction = 0;
 
-       process_rw_command ();
+       process_rw_command (ide);
 }
 
-static void ide_write_sectors (int flags)
+static void ide_write_sectors (struct ide_hdf *ide, int flags)
 {
        unsigned int cyl, head, sec, nsec;
        uae_u64 lba;
        int multi = flags & 1;
-       int lba48 = flags & 2;
 
        if (multi && ide->multiple_mode == 0) {
-               ide_fail ();
+               ide_fail (ide);
                return;
        }
-       check_maxtransfer (1);
+       check_maxtransfer (ide, 1);
        gui_flicker_led (LED_HD, ide->num, 2);
-       nsec = get_nsec (lba48);
-       get_lbachs (ide, &lba, &cyl, &head, &sec, lba48);
+       nsec = get_nsec (ide);
+       get_lbachs (ide, &lba, &cyl, &head, &sec);
        if (lba * ide->blocksize >= ide->hdhfd.size) {
-               ide_data_ready ();
-               ide_fail_err (IDE_ERR_IDNF);
+               ide_data_ready (ide);
+               ide_fail_err (ide, IDE_ERR_IDNF);
                return;
        }
        if (IDE_LOG > 0)
-               write_log (_T("IDE%d write off=%d, sec=%d (%d) lba%d\n"), ide->num, (uae_u32)lba, nsec, ide->multiple_mode, lba48 ? 48 : 28);
+               write_log (_T("IDE%d write off=%d, sec=%d (%d) lba%d\n"), ide->num, (uae_u32)lba, nsec, ide->multiple_mode, ide->lba48 ? 48 : 28);
        if (nsec * ide->blocksize > ide->hdhfd.size - lba * ide->blocksize)
                nsec = (ide->hdhfd.size - lba * ide->blocksize) / ide->blocksize;
        if (nsec <= 0) {
-               ide_data_ready ();
-               ide_fail_err (IDE_ERR_IDNF);
+               ide_data_ready (ide);
+               ide_fail_err (ide, IDE_ERR_IDNF);
                return;
        }
        ide->data_multi = multi ? ide->multiple_mode : 1;
        ide->data_offset = 0;
-       ide->regs.ide_status |= IDE_STATUS_DRQ;
        ide->data_size = nsec * ide->blocksize;
        ide->direction = 1;
 
-       ide_fast_interrupt ();
+       ide->regs.ide_status |= IDE_STATUS_BSY;
+       ide->regs.ide_status &= ~IDE_STATUS_DRQ;
+
+       ide_fast_interrupt (ide);
 }
 
-static void ide_do_command (uae_u8 cmd)
+static void ide_do_command (struct ide_hdf *ide, uae_u8 cmd)
 {
        int lba48 = ide->lba48;
 
@@ -994,69 +993,69 @@ static void ide_do_command (uae_u8 cmd)
                gui_flicker_led (LED_CD, ide->num, 1);
                ide->atapi_drdy = true;
                if (cmd == 0x00) { /* nop */
-                       ide_interrupt ();
+                       ide_interrupt (ide);
                } else if (cmd == 0x08) { /* device reset */
-                       ide_execute_drive_diagnostics (true);
+                       ide_execute_drive_diagnostics (ide, true);
                } else if (cmd == 0xa1) { /* identify packet device */
-                       ide_identify_drive ();
+                       ide_identify_drive (ide);
                } else if (cmd == 0xa0) { /* packet */
-                       atapi_packet ();
+                       atapi_packet (ide);
                } else if (cmd == 0x90) { /* execute drive diagnostics */
-                       ide_execute_drive_diagnostics (true);
+                       ide_execute_drive_diagnostics (ide, true);
                } else {
-                       ide_execute_drive_diagnostics (false);
+                       ide_execute_drive_diagnostics (ide, false);
                        ide->atapi_drdy = false;
-                       ide_fail ();
+                       ide_fail (ide);
                        write_log (_T("IDE%d: unknown ATAPI command 0x%02x\n"), ide->num, cmd);
                }
 
        } else {
 
                if (cmd == 0x10) { /* recalibrate */
-                       ide_recalibrate ();
+                       ide_recalibrate (ide);
                } else if (cmd == 0xec) { /* identify drive */
-                       ide_identify_drive ();
+                       ide_identify_drive (ide);
                } else if (cmd == 0x90) { /* execute drive diagnostics */
-                       ide_execute_drive_diagnostics (true);
+                       ide_execute_drive_diagnostics (ide, true);
                } else if (cmd == 0x91) { /* initialize drive parameters */
-                       ide_initialize_drive_parameters ();
+                       ide_initialize_drive_parameters (ide);
                } else if (cmd == 0xc6) { /* set multiple mode */
-                       ide_set_multiple_mode ();
+                       ide_set_multiple_mode (ide);
                } else if (cmd == 0x20 || cmd == 0x21) { /* read sectors */
-                       ide_read_sectors (0);
+                       ide_read_sectors (ide, 0);
                } else if (cmd == 0x24 && lba48) { /* read sectors ext */
-                       ide_read_sectors (2);
+                       ide_read_sectors (ide, 2);
                } else if (cmd == 0xc4) { /* read multiple */
-                       ide_read_sectors (1);
+                       ide_read_sectors (ide, 1);
                } else if (cmd == 0x29 && lba48) { /* read multiple ext */
-                       ide_read_sectors (1|2);
+                       ide_read_sectors (ide, 1|2);
                } else if (cmd == 0x30 || cmd == 0x31) { /* write sectors */
-                       ide_write_sectors (0);
+                       ide_write_sectors (ide, 0);
                } else if (cmd == 0x34 && lba48) { /* write sectors ext */
-                       ide_write_sectors (2);
+                       ide_write_sectors (ide, 2);
                } else if (cmd == 0xc5) { /* write multiple */
-                       ide_write_sectors (1);
+                       ide_write_sectors (ide, 1);
                } else if (cmd == 0x39 && lba48) { /* write multiple ext */
-                       ide_write_sectors (1|2);
+                       ide_write_sectors (ide, 1|2);
                } else if (cmd == 0x50) { /* format track (nop) */
-                       ide_interrupt ();
+                       ide_interrupt (ide);
                } else if (cmd == 0xef) { /* set features  */
-                       ide_set_features ();
+                       ide_set_features (ide);
                } else if (cmd == 0x00) { /* nop */
-                       ide_fail ();
+                       ide_fail (ide);
                } else if (cmd == 0xe0 || cmd == 0xe1 || cmd == 0xe7 || cmd == 0xea) { /* standby now/idle/flush cache/flush cache ext */
-                       ide_interrupt ();
+                       ide_interrupt (ide);
                } else if (cmd == 0xe5) { /* check power mode */
                        ide->regs.ide_nsector = 0xff;
-                       ide_interrupt ();
+                       ide_interrupt (ide);
                } else {
-                       ide_fail ();
+                       ide_fail (ide);
                        write_log (_T("IDE%d: unknown ATA command 0x%02x\n"), ide->num, cmd);
                }
        }
 }
 
-static uae_u16 ide_get_data (void)
+static uae_u16 ide_get_data (struct ide_hdf *ide)
 {
        bool irq = false;
        bool last = false;
@@ -1083,12 +1082,12 @@ static uae_u16 ide_get_data (void)
                                write_log (_T("IDE%d ATAPI partial read finished, %d bytes remaining\n"), ide->num, ide->data_size);
                        if (ide->data_size == 0) {
                                ide->packet_state = 0;
-                               atapi_data_done ();
+                               atapi_data_done (ide);
                                if (IDE_LOG > 1)
                                        write_log (_T("IDE%d ATAPI read finished, %d bytes\n"), ide->num, ide->packet_data_offset + ide->data_offset);
                                irq = true;
                        } else {
-                               process_packet_command ();
+                               process_packet_command (ide);
                        }
                }
        } else {
@@ -1100,7 +1099,7 @@ static uae_u16 ide_get_data (void)
                        ide->data_size -= 2;
                        if (((ide->data_offset % ide->blocksize) == 0) && ((ide->data_offset / ide->blocksize) % ide->data_multi) == 0) {
                                if (ide->data_size)
-                                       process_rw_command ();
+                                       process_rw_command (ide);
                        }
                }
                if (ide->data_size == 0) {
@@ -1110,11 +1109,11 @@ static uae_u16 ide_get_data (void)
                }
        }
        if (irq)
-               ide_fast_interrupt ();
+               ide_fast_interrupt (ide);
        return v;
 }
 
-static void ide_put_data (uae_u16 v)
+static void ide_put_data (struct ide_hdf *ide, uae_u16 v)
 {
        if (IDE_LOG > 4)
                write_log (_T("IDE%d DATA write %04x %d/%d\n"), ide->num, v, ide->data_offset, ide->data_size);
@@ -1133,21 +1132,23 @@ static void ide_put_data (uae_u16 v)
                                uae_u16 v = (ide->regs.ide_hcyl << 8) | ide->regs.ide_lcyl;
                                write_log (_T("Data size after command received = %d (%d)\n"), v, ide->packet_data_size);
                        }
-                       process_packet_command ();
+                       process_packet_command (ide);
                }
        } else {
                if (ide->data_size == 0) {
-                       process_rw_command ();
+                       process_rw_command (ide);
                } else if (((ide->data_offset % ide->blocksize) == 0) && ((ide->data_offset / ide->blocksize) % ide->data_multi) == 0) {
-                       process_rw_command ();
+                       process_rw_command (ide);
                }
        }
 }
 
-static int get_gayle_ide_reg (uaecptr addr)
+static int get_gayle_ide_reg (uaecptr addr, struct ide_hdf **ide)
 {
+       int ide2;
        uaecptr a = addr;
        addr &= 0xffff;
+       *ide = NULL;
        if (addr >= GAYLE_IRQ_4000 && addr <= GAYLE_IRQ_4000 + 1 && currprefs.cs_ide == IDE_A4000)
                return -1;
        addr &= ~0x2020;
@@ -1159,15 +1160,18 @@ static int get_gayle_ide_reg (uaecptr addr)
                        addr &= ~0x400;
                }
        }
-       ide = idedrive[ide2 + idedrive[ide2]->ide_drv];
+       *ide = idedrive[ide2 + idedrive[ide2]->ide_drv];
        return addr;
 }
 
-static uae_u32 ide_read_reg (int ide_reg)
+static uae_u32 ide_read_reg (struct ide_hdf *ide, int ide_reg)
 {
        uae_u8 v = 0;
        bool isdrv = isdrive (ide);
 
+       if (!ide)
+               goto end;
+
        if (ide->regs.ide_status & IDE_STATUS_BSY)
                ide_reg = IDE_STATUS;
        if (!isdrive (ide)) {
@@ -1204,7 +1208,7 @@ static uae_u32 ide_read_reg (int ide_reg)
                                v = ide->regs.ide_sector2;
                        else
                                v = ide->regs.ide_sector;
-                       check_maxtransfer (2);
+                       check_maxtransfer (ide, 2);
                }
                break;
        case IDE_LCYL:
@@ -1247,8 +1251,11 @@ end:
        return v;
 }
 
-static void ide_write_reg (int ide_reg, uae_u32 val)
+static void ide_write_reg (struct ide_hdf *ide, int ide_reg, uae_u32 val)
 {
+       if (!ide)
+               return;
+       
        ide->regs1->ide_devcon &= ~0x80; /* clear HOB */
        ide->regs0->ide_devcon &= ~0x80; /* clear HOB */
        if (IDE_LOG > 2 && ide_reg > 0 && (1 || ide->num > 0))
@@ -1260,7 +1267,7 @@ static void ide_write_reg (int ide_reg, uae_u32 val)
                break;
        case IDE_DEVCON:
                if ((ide->regs.ide_devcon & 4) == 0 && (val & 4) != 0) {
-                       reset_device (true);
+                       reset_device (ide, true);
                        if (IDE_LOG > 1)
                                write_log (_T("IDE%d: SRST\n"), ide->num);
                }
@@ -1312,7 +1319,7 @@ static void ide_write_reg (int ide_reg, uae_u32 val)
                ide->irq = 0;
                if (isdrive (ide)) {
                        ide->regs.ide_status |= IDE_STATUS_BSY;
-                       ide_do_command (val);
+                       ide_do_command (ide, val);
                }
                break;
        }
@@ -1320,6 +1327,7 @@ static void ide_write_reg (int ide_reg, uae_u32 val)
 
 static uae_u32 gayle_read2 (uaecptr addr)
 {
+       struct ide_hdf *ide = NULL;
        int ide_reg;
        uae_u8 v = 0;
 
@@ -1348,18 +1356,19 @@ static uae_u32 gayle_read2 (uaecptr addr)
                }
                return 0;
        }
-       ide_reg = get_gayle_ide_reg (addr);
+       ide_reg = get_gayle_ide_reg (addr, &ide);
        /* Emulated "ide killer". Prevents long KS boot delay if no drives installed */
        if (!isdrive (idedrive[0]) && !isdrive (idedrive[1]) && !isdrive (idedrive[2]) && !isdrive (idedrive[3])) {
                if (ide_reg == IDE_STATUS)
                        return 0x7f;
                return 0xff;
        }
-       return ide_read_reg (ide_reg);
+       return ide_read_reg (ide, ide_reg);
 }
 
 static void gayle_write2 (uaecptr addr, uae_u32 val)
 {
+       struct ide_hdf *ide = NULL;
        int ide_reg;
 
        if ((IDE_LOG > 3 && (addr != 0x2000 && addr != 0x2001 && addr != 0x2020 && addr != 0x2021 && addr != GAYLE_IRQ_1200)) || IDE_LOG > 5)
@@ -1378,8 +1387,8 @@ static void gayle_write2 (uaecptr addr, uae_u32 val)
        }
        if (addr >= 0x4000)
                return;
-       ide_reg = get_gayle_ide_reg (addr);
-       ide_write_reg (ide_reg, val);
+       ide_reg = get_gayle_ide_reg (addr, &ide);
+       ide_write_reg (ide, ide_reg, val);
 }
 
 static int gayle_read (uaecptr addr)
@@ -1500,6 +1509,7 @@ static uae_u32 REGPARAM2 gayle_lget (uaecptr addr)
 }
 static uae_u32 REGPARAM2 gayle_wget (uaecptr addr)
 {
+       struct ide_hdf *ide = NULL;
        int ide_reg;
        uae_u16 v;
 #ifdef JIT
@@ -1509,9 +1519,9 @@ static uae_u32 REGPARAM2 gayle_wget (uaecptr addr)
                addr -= NCR_OFFSET;
                return (ncr_bget2 (addr) << 8) | ncr_bget2 (addr + 1);
        }
-       ide_reg = get_gayle_ide_reg (addr);
+       ide_reg = get_gayle_ide_reg (addr, &ide);
        if (ide_reg == IDE_DATA)
-               return ide_get_data ();
+               return ide_get_data (ide);
        v = gayle_bget (addr) << 8;
        v |= gayle_bget (addr + 1);
        return v;
@@ -1538,6 +1548,7 @@ static void REGPARAM2 gayle_lput (uaecptr addr, uae_u32 value)
 }
 static void REGPARAM2 gayle_wput (uaecptr addr, uae_u32 value)
 {
+       struct ide_hdf *ide = NULL;
        int ide_reg;
 #ifdef JIT
        special_mem |= S_WRITE;
@@ -1548,9 +1559,9 @@ static void REGPARAM2 gayle_wput (uaecptr addr, uae_u32 value)
                ncr_bput2 (addr + 1, value);
                return;
        }
-       ide_reg = get_gayle_ide_reg (addr);
+       ide_reg = get_gayle_ide_reg (addr, &ide);
        if (ide_reg == IDE_DATA) {
-               ide_put_data (value);
+               ide_put_data (ide, value);
                return;
        }
        gayle_bput (addr, value >> 8);
@@ -1878,10 +1889,11 @@ static int pcmcia_write_min, pcmcia_write_max;
 static int pcmcia_oddevenflip;
 static uae_u16 pcmcia_idedata;
 
-static int get_pcmcmia_ide_reg (uaecptr addr, int width)
+static int get_pcmcmia_ide_reg (uaecptr addr, int width, struct ide_hdf **ide)
 {
        int reg = -1;
 
+       *ide = NULL;
        addr &= 0x80000 - 1;
        if (addr < 0x20000)
                return -1; /* attribute */
@@ -1893,9 +1905,9 @@ static int get_pcmcmia_ide_reg (uaecptr addr, int width)
                addr &= ~0x10000;
                addr |= 1;
        }
-       ide = idedrive[PCMCIA_IDE_ID * 2];
-       if (ide->ide_drv)
-               ide = idedrive[PCMCIA_IDE_ID * 2 + 1];
+       *ide = idedrive[PCMCIA_IDE_ID * 2];
+       if ((*ide)->ide_drv)
+               *ide = idedrive[PCMCIA_IDE_ID * 2 + 1];
        if (pcmcia_configured == 1) {
                // IO mapped linear
                reg = addr & 15;
@@ -1930,6 +1942,7 @@ static int get_pcmcmia_ide_reg (uaecptr addr, int width)
 
 static uae_u32 gayle_attr_read (uaecptr addr)
 {
+       struct ide_hdf *ide = NULL;
        uae_u8 v = 0;
 
        if (PCMCIA_LOG > 1)
@@ -1948,17 +1961,17 @@ static uae_u32 gayle_attr_read (uaecptr addr)
                        return pcmcia_configuration[offset];
                }
                if (pcmcia_configured >= 0) {
-                       int reg = get_pcmcmia_ide_reg (addr, 1);
+                       int reg = get_pcmcmia_ide_reg (addr, 1, &ide);
                        if (reg >= 0) {
                                if (reg == 0) {
                                        if (addr >= 0x30000) {
                                                return pcmcia_idedata & 0xff;
                                        } else {
-                                               pcmcia_idedata = ide_get_data ();
+                                               pcmcia_idedata = ide_get_data (ide);
                                                return (pcmcia_idedata >> 8) & 0xff;
                                        }
                                } else {
-                                       return ide_read_reg (reg);
+                                       return ide_read_reg (ide, reg);
                                }
                        }
                }
@@ -1969,6 +1982,7 @@ static uae_u32 gayle_attr_read (uaecptr addr)
 
 static void gayle_attr_write (uaecptr addr, uae_u32 v)
 {
+       struct ide_hdf *ide = NULL;
        if (PCMCIA_LOG > 1)
                write_log (_T("PCMCIA ATTR W: %x=%x %x\n"), addr, v, M68K_GETPC);
        addr &= 0x80000 - 1;
@@ -1996,7 +2010,7 @@ static void gayle_attr_write (uaecptr addr, uae_u32 v)
                                }
                        }
                        if (pcmcia_configured >= 0) {
-                               int reg = get_pcmcmia_ide_reg (addr, 1);
+                               int reg = get_pcmcmia_ide_reg (addr, 1, &ide);
                                if (reg >= 0) {
                                        if (reg == 0) {
                                                if (addr >= 0x30000) {
@@ -2004,11 +2018,11 @@ static void gayle_attr_write (uaecptr addr, uae_u32 v)
                                                } else {
                                                        pcmcia_idedata &= 0xff00;
                                                        pcmcia_idedata |= v & 0xff;
-                                                       ide_put_data (pcmcia_idedata);
+                                                       ide_put_data (ide, pcmcia_idedata);
                                                }
                                                return;
                                        }
-                                       ide_write_reg (reg, v);
+                                       ide_write_reg (ide, reg, v);
                                }
                         }
                 }
@@ -2411,10 +2425,11 @@ static uae_u32 REGPARAM2 gayle_attr_wget (uaecptr addr)
 #endif
 
        if (pcmcia_type == PCMCIA_IDE && pcmcia_configured >= 0) {
-               int reg = get_pcmcmia_ide_reg (addr, 2);
+               struct ide_hdf *ide = NULL;
+               int reg = get_pcmcmia_ide_reg (addr, 2, &ide);
                if (reg == IDE_DATA) {
                        // 16-bit register
-                       pcmcia_idedata = ide_get_data ();
+                       pcmcia_idedata = ide_get_data (ide);
                        return pcmcia_idedata;
                }
        }
@@ -2445,11 +2460,12 @@ static void REGPARAM2 gayle_attr_wput (uaecptr addr, uae_u32 value)
 #endif
 
        if (pcmcia_type == PCMCIA_IDE && pcmcia_configured >= 0) {
-               int reg = get_pcmcmia_ide_reg (addr, 2);
+               struct ide_hdf *ide = NULL;
+               int reg = get_pcmcmia_ide_reg (addr, 2, &ide);
                if (reg == IDE_DATA) {
                        // 16-bit register
                        pcmcia_idedata = value;
-                       ide_put_data (pcmcia_idedata);
+                       ide_put_data (ide, pcmcia_idedata);
                        return;
                }
        }
@@ -2647,6 +2663,8 @@ static void initide (void)
        if (isrestore ())
                return;
        for (i = 0; i < TOTAL_IDE; i++) {
+               struct ide_hdf *ide;
+
                ide = idedrive[i * 2 + 0];
                ide->regs0 = &ide->regs;
                ide->regs1 = &idedrive[i * 2 + 1]->regs;
@@ -2657,7 +2675,7 @@ static void initide (void)
                ide->regs0 = &idedrive[i * 2 + 0]->regs;
                ide->pair = idedrive[i * 2 + 0];
 
-               reset_device (true);
+               reset_device (ide, true);
        }
        ide_splitter = 0;
        if (isdrive (idedrive[2]) || isdrive(idedrive[3])) {
index a6b8f637b764145cad90379c3d299edebf2bd5f5..c291ea9203ad47047627d78a69d4cf75873bc120 100644 (file)
@@ -2293,6 +2293,10 @@ static void gen_opcode (unsigned long int opcode)
        case i_BCHG:
        case i_BCLR:
        case i_BSET:
+               // on 68000 these have weird side-effect, if EA points to write-only custom register
+               //during instruction's read access CPU data lines appear as zero to outside world,
+               // (normally previously fetched data appears in data lines if reading write-only register)
+               // this allows stupid things like bset #2,$dff002 to work "correctly"
                genamode (curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
                genamode (curi->dmode, "dstreg", curi->size, "dst", 1, 0, GF_IR2IRC | GF_RMW);
                fill_prefetch_next ();
index 1cd6f8b36c9ca45b7296d50db6c8c8e756c5fc77..246c511a00ba34f67dd27776e664520950c8da03 100644 (file)
@@ -661,7 +661,7 @@ static int hdf_seek (struct hardfiledata *hfd, uae_u64 offset)
                abort();
        }
        if (offset >= hfd->physsize - hfd->virtual_size) {
-               gui_message (_T("hd: tried to seek out of bounds! (%I64X >= %I64X)\n"), offset, hfd->physsize);
+               gui_message (_T("hd: tried to seek out of bounds! (%I64X >= %I64X - %I64X)\n"), offset, hfd->physsize, hfd->virtual_size);
                abort ();
        }
        offset += hfd->offset;
index c035b646a63a7ff446a0e40bb104e442237b3671..bf75cbc0e75f7d4073178017745437db74c7f938 100644 (file)
@@ -1692,7 +1692,7 @@ void rp_screenmode_changed (void)
 {
        write_log (_T("rp_screenmode_changed\n"));
        if (!screenmode_request) {
-               screenmode_request = 2;
+               screenmode_request = 6;
                write_log (_T("rp_screenmode_changed -> screenmode_request started\n"));
        }
 }
@@ -1744,9 +1744,9 @@ void rp_vsync (void)
        if (screenmode_request) {
                screenmode_request--;
                if (screenmode_request == 0) {
+                       write_log (_T("RP_IPC_TO_HOST_SCREENMODE screenmode_request timeout\n"));
                        struct RPScreenMode sm = { 0 };
                        get_screenmode (&sm, &currprefs);
-                       write_log (_T("RP_IPC_TO_HOST_SCREENMODE screenmode_request timeout\n"));
                        RPSendMessagex (RP_IPC_TO_HOST_SCREENMODE, 0, 0, &sm, sizeof sm, &guestinfo, NULL);
                }
        }
index 161f10d0a907224e55af73868fad81824d8f8fdb..bed9792ff628fec0d557bdeff7425817d3b2005b 100644 (file)
@@ -592,7 +592,7 @@ static void releasecapture (void)
 {
        if (!showcursor)
                return;
-       write_log (_T("releasecapture\n"));
+       //write_log (_T("releasecapture\n"));
        ClipCursor (NULL);
        ReleaseCapture ();
        ShowCursor (TRUE);
@@ -603,7 +603,7 @@ void updatemouseclip (void)
 {
        if (showcursor) {
                ClipCursor (&amigawin_rect);
-               write_log (_T("CLIP %dx%d %dx%d %d\n"), amigawin_rect.left, amigawin_rect.top, amigawin_rect.right, amigawin_rect.bottom, isfullscreen ());
+               //write_log (_T("CLIP %dx%d %dx%d %d\n"), amigawin_rect.left, amigawin_rect.top, amigawin_rect.right, amigawin_rect.bottom, isfullscreen ());
        }
 }
 
@@ -613,7 +613,7 @@ void updatewinrect (bool allowfullscreen)
        if (!allowfullscreen && f > 0)
                return;
        GetWindowRect (hAmigaWnd, &amigawin_rect);
-       write_log (_T("GetWindowRect %dx%d %dx%d %d\n"), amigawin_rect.left, amigawin_rect.top, amigawin_rect.right, amigawin_rect.bottom, f);
+       //write_log (_T("GetWindowRect %dx%d %dx%d %d\n"), amigawin_rect.left, amigawin_rect.top, amigawin_rect.right, amigawin_rect.bottom, f);
        if (f == 0) {
                changed_prefs.gfx_size_win.x = amigawin_rect.left;
                changed_prefs.gfx_size_win.y = amigawin_rect.top;
@@ -650,7 +650,7 @@ static bool iswindowfocus (void)
 
 static void setmouseactive2 (int active, bool allowpause)
 {
-       write_log (_T("setmouseactive %d->%d showcursor=%d focus=%d recap=%d\n"), mouseactive, active, showcursor, focus, recapture);
+       //write_log (_T("setmouseactive %d->%d showcursor=%d focus=%d recap=%d\n"), mouseactive, active, showcursor, focus, recapture);
        if (active == 0)
                releasecapture ();
        if (mouseactive == active && active >= 0)
index 4763cdbe715dddc1591234a75845202e0e1cf114..7e997658b28c23ef7c91ea69701ca520498f90fd 100644 (file)
 #define LANG_DLL 1
 
 #if WINUAEPUBLICBETA
-#define WINUAEBETA _T("14")
+#define WINUAEBETA _T("15")
 #else
 #define WINUAEBETA _T("")
 #endif
-#define WINUAEDATE MAKEBD(2013, 3, 30)
+#define WINUAEDATE MAKEBD(2013, 4, 6)
 #define WINUAEEXTRA _T("")
 //#define WINUAEEXTRA _T("AmiKit Preview")
 #define WINUAEREV _T("")
index 239f3631eeadc8fc3d3fde9bba07972f37978697..d6a3af9d23d9aebd018ac149b6363c9ffca5b2ca 100644 (file)
@@ -1,6 +1,17 @@
 
 - restore only single input target to default.
 
+Beta 15:
+
+- IDE emulation drive status bit fix (DRQ and BSY active at the same time), fixes data corruption if IDEFix was active. (b5).
+- Added support for previously unemulated and undocumented feature, sprites can appear 1 lores pixel earlier than first bitplane pixel.
+  (First BPL1DAT access enables sprites immediately, only bitplanes need HRM documented delay).
+  This is not normally visible because horizontal DIWSTRT usually equals bitplane left edge.
+  Fixes "original" Rink-a-Dink/Lemon missing left white border in rotozoomer part.
+- Do not use "8372 (Fat-hr) (agnushr),rev 5" VPOSR chipset id when config is ECS 2M chip RAM. This ID does not appear to exist in real world.
+- Both bordersprite and borderblank active: sprites were incorrectly visible in upper and lower borders (241b13)
+- Rewritten b4 "Subtle Shades" update, it was wrong and caused bad side-effects.
+
 Beta 14:
 
 - A3000 SCSI emulation crashed if no SCSI drives configured.