]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Custom emulation update WIP
authorToni Wilen <twilen@winuae.net>
Tue, 6 Apr 2021 18:18:23 +0000 (21:18 +0300)
committerToni Wilen <twilen@winuae.net>
Tue, 6 Apr 2021 18:18:23 +0000 (21:18 +0300)
custom.cpp
drawing.cpp

index 0ac81657936599ea257d0d62edabcb4fb64ddb84..1dad84ea065da09e6cdeaffd97950a5ee2e6cc00 100644 (file)
@@ -4432,7 +4432,8 @@ static void init_hz (bool checkvposw)
                                minfirstline = 0;
                        firstblankedline = vbstrt;
                }
-               
+               minfirstline++;
+
                if (minfirstline < 2)
                        minfirstline = 2;
                if (minfirstline >= maxvpos)
@@ -4441,7 +4442,7 @@ static void init_hz (bool checkvposw)
                if (firstblankedline < minfirstline)
                        firstblankedline = maxvpos + 1;
 
-               sprite_vblank_endline = minfirstline - 2;
+               sprite_vblank_endline = minfirstline - 1;
                maxvpos_nom = maxvpos;
                maxvpos_display = maxvpos;
                equ_vblank_endline = -1;
@@ -4469,19 +4470,20 @@ static void init_hz (bool checkvposw)
        if (vblank_hz > 300)
                vblank_hz = 300;
        maxhpos_short = maxhpos;
-       set_delay_lastcycle ();
+       set_delay_lastcycle();
        updateextblk();
-       eventtab[ev_hsync].oldcycles = get_cycles ();
-       eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME;
-       events_schedule ();
+       eventtab[ev_hsync].oldcycles = get_cycles();
+       eventtab[ev_hsync].evtime = get_cycles() + HSYNCTIME;
+       events_schedule();
        if (hzc) {
                interlace_seen = islace;
-               reset_drawing ();
+               reset_drawing();
        }
 
        maxvpos_total = ecs_agnus ? (MAXVPOS_LINES_ECS - 1) : (MAXVPOS_LINES_OCS - 1);
-       if (maxvpos_total > MAXVPOS)
+       if (maxvpos_total > MAXVPOS) {
                maxvpos_total = MAXVPOS;
+       }
 #ifdef PICASSO96
        if (!p96refresh_active) {
                maxvpos_stored = maxvpos;
@@ -4490,19 +4492,20 @@ static void init_hz (bool checkvposw)
        }
 #endif
 
-       compute_framesync ();
+       compute_framesync();
        devices_syncchange();
 
 #ifdef PICASSO96
        init_hz_p96(0);
 #endif
-       if (vblank_hz != ovblank)
+       if (vblank_hz != ovblank) {
                updatedisplayarea(0);
-       inputdevice_tablet_strobe ();
+       }
+       inputdevice_tablet_strobe();
 
        if (varsync_changed) {
                varsync_changed = false;
-               dumpsync ();
+               dumpsync();
        }
 }
 
@@ -5268,32 +5271,34 @@ bool INTREQ_0 (uae_u16 v)
        return true;
 }
 
-void INTREQ (uae_u16 data)
+void INTREQ(uae_u16 data)
 {
        if (INTREQ_0(data)) {
                rethink_intreq();
        }
 }
 
-static void ADKCON (int hpos, uae_u16 v)
+static void ADKCON(int hpos, uae_u16 v)
 {
-       if (currprefs.produce_sound > 0)
-               update_audio ();
-       DISK_update (hpos);
-       DISK_update_adkcon (hpos, v);
-       setclr (&adkcon, v);
-       audio_update_adkmasks ();
-       if ((v >> 11) & 1)
-               serial_uartbreak ((adkcon >> 11) & 1);
+       if (currprefs.produce_sound > 0) {
+               update_audio();
+       }
+       DISK_update(hpos);
+       DISK_update_adkcon(hpos, v);
+       setclr(&adkcon, v);
+       audio_update_adkmasks();
+       if ((v >> 11) & 1) {
+               serial_uartbreak((adkcon >> 11) & 1);
+       }
 }
 
-static void BEAMCON0 (uae_u16 v)
+static void BEAMCON0(uae_u16 v)
 {
        if (ecs_agnus) {
                if (v != new_beamcon0) {
                        new_beamcon0 = v;
                        if (v & ~0x20) {
-                               write_log (_T("warning: %04X written to BEAMCON0 PC=%08X\n"), v, M68K_GETPC);
+                               write_log(_T("warning: %04X written to BEAMCON0 PC=%08X\n"), v, M68K_GETPC);
                                dumpsync();
                        }
                }
@@ -5302,7 +5307,7 @@ static void BEAMCON0 (uae_u16 v)
        }
 }
 
-static void varsync (void)
+static void varsync(void)
 {
        struct amigadisplay *ad = &adisplays[0];
        if (!ecs_agnus)
@@ -5319,7 +5324,7 @@ static void varsync (void)
 }
 
 #ifdef PICASSO96
-void set_picasso_hack_rate (int hz)
+void set_picasso_hack_rate(int hz)
 {
        struct amigadisplay *ad = &adisplays[0];
        if (!ad->picasso_on)
@@ -5412,18 +5417,21 @@ static void BPLCON0_Denise(int hpos, uae_u16 v, bool immediate)
 
 static void BPLCON0(int hpos, uae_u16 v)
 {
+       uae_u16 old = bplcon0;
        bplcon0_saved = v;
-       if (!ecs_denise)
+       if (!ecs_denise) {
                v &= ~0x00F1;
-       else if (!aga_mode)
+       } else if (!aga_mode) {
                v &= ~0x00B0;
+       }
        v &= ~0x0080;
 
 #if SPRBORDER
        v |= 1;
 #endif
-       if (bplcon0 == v)
+       if (bplcon0 == v) {
                return;
+       }
 
        SET_LINE_CYCLEBASED;
        decide_diw(hpos);
@@ -5434,10 +5442,6 @@ static void BPLCON0(int hpos, uae_u16 v)
                hpos_previous = hpos;
        }
 
-       if ((v & 1) != (bplcon0 & 1)) {
-               updateextblk();
-       }
-
        if (v & 4) {
                bplcon0_interlace_seen = true;
        }
@@ -5456,6 +5460,10 @@ static void BPLCON0(int hpos, uae_u16 v)
        
        bplcon0 = v;
 
+       if ((old & 1) != (bplcon0 & 1)) {
+               updateextblk();
+       }
+
        bpldmainitdelay(hpos);
 
        if (thisline_decision.plfleft < 0) {
@@ -5495,6 +5503,7 @@ static void BPLCON2(int hpos, uae_u16 v)
 #ifdef ECS_DENISE
 static void BPLCON3(int hpos, uae_u16 v)
 {
+       uae_u16 old = bplcon3;
        bplcon3_saved = v;
        if (!ecs_denise)
                return;
@@ -5509,10 +5518,10 @@ static void BPLCON3(int hpos, uae_u16 v)
                return;
        decide_vline(hpos);
        decide_sprites(hpos);
-       if ((bplcon3 & 1) != (v & 1)) {
+       bplcon3 = v;
+       if ((bplcon3 & 1) != (old & 1)) {
                updateextblk();
        }
-       bplcon3 = v;
        sprres = expand_sprres(bplcon0, bplcon3);
        record_register_change(hpos, 0x106, v);
 }
@@ -6290,69 +6299,6 @@ static void COLOR_WRITE(int hpos, uae_u16 v, int num)
        }
 #endif
 }
-
-/* The copper code.  The biggest nightmare in the whole emulator.
-
-Alright.  The current theory:
-1. Copper moves happen 2 cycles after state READ2 is reached.
-It can't happen immediately when we reach READ2, because the
-data needs time to get back from the bus.  An additional 2
-cycles are needed for non-Agnus registers, to take into account
-the delay for moving data from chip to chip.
-2. As stated in the HRM, a WAIT really does need an extra cycle
-to wake up.  This is implemented by _not_ falling through from
-a successful wait to READ1, but by starting the next cycle.
-(Note: the extra cycle for the WAIT apparently really needs a
-free cycle; i.e. contention with the bitplane fetch can slow
-it down).
-3. Apparently, to compensate for the extra wake up cycle, a WAIT
-will use the _incremented_ horizontal position, so the WAIT
-cycle normally finishes two clocks earlier than the position
-it was waiting for.  The extra cycle then takes us to the
-position that was waited for.
-If the earlier cycle is busy with a bitplane, things change a bit.
-E.g., waiting for position 0x50 in a 6 plane display: In cycle
-0x4e, we fetch BPL5, so the wait wakes up in 0x50, the extra cycle
-takes us to 0x54 (since 0x52 is busy), then we have READ1/READ2,
-and the next register write is at 0x5c.
-4. The last cycle in a line is not usable for the copper.
-5. A 4 cycle delay also applies to the WAIT instruction.  This means
-that the second of two back-to-back WAITs (or a WAIT whose
-condition is immediately true) takes 8 cycles.
-6. This also applies to a SKIP instruction.  The copper does not
-fetch the next instruction while waiting for the second word of
-a WAIT or a SKIP to arrive.
-7. A SKIP also seems to need an unexplained additional two cycles
-after its second word arrives; this is _not_ a memory cycle (I
-think, the documentation is pretty clear on this).
-8. Two additional cycles are inserted when writing to COPJMP1/2.  */
-
-/* Determine which cycles are available for the copper in a display
-* with a agiven number of planes.  */
-
-#if 0
-STATIC_INLINE int copper_cant_read2 (int hpos, int alloc)
-{
-//     if (hpos + 1 >= maxhpos) // first refresh slot
-//             return 1;
-       if ((hpos == 0) && (maxhpos & 1) && alloc >= 0) {
-               if (alloc) {
-                       alloc_cycle (hpos, CYCLE_COPPER);
-#ifdef DEBUGGER
-                       if (debug_dma) {
-                               record_dma_event(DMA_EVENT_NOONEGETS, hpos, vpos);
-                               record_dma_read(0x1fe, cop_state.ip, hpos, vpos, DMARECORD_COPPER, 2);
-                               uae_u16 v = chipmem_wget_indirect(cop_state.ip);
-                               record_dma_read_value(v);
-                       }
-#endif
-               }
-               return -1;
-       }
-       return is_bitplane_dma_inline (hpos);
-}
-#endif
-
 static bool copper_cant_read(uae_u16 *cp, uae_u16 alloc)
 {
        if (!dmaen(DMA_COPPER)) {
@@ -6361,14 +6307,6 @@ static bool copper_cant_read(uae_u16 *cp, uae_u16 alloc)
        if (*cp != 0) {
                return true;
        }
-#if 0
-       int cant = copper_cant_read2 (hpos, alloc);
-#ifdef DEBUGGER
-       if (cant && debug_dma)
-               record_dma_event (DMA_EVENT_COPPERWANTED, hpos, vpos);
-#endif
-       return cant;
-#endif
        if (alloc) {
                *cp = alloc;
        }
@@ -6498,7 +6436,7 @@ static void decide_line_decision(int endhpos)
                        if (!bprun && dma && diw && hwi && !hwi_old) {
                                // Bitplane sequencer activated
                                bprun = -1;
-                               plfstrt_sprite = hpos + 3;
+                               plfstrt_sprite = hpos + 4;
                        }
 
                        hwi_old = hwi;
@@ -6898,14 +6836,18 @@ static void copper_ff(int hpos)
        last_copper_hpos = hpos;
 }
 
-static int getcoppercomp(int hpos, bool blitwait)
+static int coppercomp(int hpos, bool blitwait)
 {
-       int hpos_cmp = hpos + 1;
+       int hpos_cmp = hpos;
        int vpos_cmp = vpos;
+
+       // Copper internal operations use mostly odd cycles
+       hpos_cmp += 1;
        if (hpos_cmp >= maxhpos) {
                hpos_cmp -= maxhpos;
                vpos_cmp++;
        }
+
        int vp = vpos_cmp & (((cop_state.ir[1] >> 8) & 0x7F) | 0x80);
        int hp = hpos_cmp & (cop_state.ir[1] & 0xFE);
 
@@ -6935,22 +6877,12 @@ static void update_copper(int until_hpos)
 {
        int hpos = last_copper_hpos;
 
-       if (0 && (nocustom() || !copper_enabled_thisline)) {
+       if (1 && (nocustom() || !copper_enabled_thisline)) {
                copper_ff(until_hpos);
                decide_line_decision(until_hpos);
                return;
        }
 
-#if 0
-       if (cop_state.state == COP_wait && vp < cop_state.vcmp) {
-               dump_copper (_T("error2"), until_hpos);
-               copper_enabled_thisline = 0;
-               cop_state.state = COP_stop;
-               unset_special (SPCFLAG_COPPER);
-               return;
-       }
-#endif
-
        while (hpos < until_hpos) {
                uae_u16 *cp;
 
@@ -6968,11 +6900,9 @@ static void update_copper(int until_hpos)
                        rga_pipeline[rpos] = 0;
                }
 
-#if 1
                if (!copper_enabled_thisline) {
                        goto next;
                }
-#endif
 
                if ((hpos & 1) != COPPER_CYCLE_POLARITY) {
                        goto next;
@@ -7048,23 +6978,34 @@ static void update_copper(int until_hpos)
                        copper_cant_read(cp, 0x81);
                        break;
 
+                       // Request IR1
                case COP_read1:
                        copper_cant_read(cp, 0x82);
                        break;
 
+                       // Request IR2
                case COP_read2:
                        copper_cant_read(cp, 0x83);
                        break;
 
+                       // WAIT: Got IR2, first idle cycle.
+                       // Need free cycle, cycle allocated.
                case COP_wait_in2:
                        {
                                if (copper_cant_read(cp, 0x8f)) {
                                        goto next;
                                }
                                cop_state.state = COP_wait1;
+                       }
+                       break;
 
-                               int comp = getcoppercomp(hpos, true);
+                       // WAIT: Second idle cycle. Wait until comparison matches.
+                       // Need free cycle, cycle allocated.
+               case COP_wait1:
+                       {
+                               int comp = coppercomp(hpos, true);
                                if (comp < 0) {
+                                       // If we need to wait for later scanline or blitter: no need to emulate copper cycle-by-cycle
                                        if (cop_state.ir[0] == 0xFFFF && cop_state.ir[1] == 0xFFFE) {
                                                cop_state.state = COP_waitforever;
                                        }
@@ -7072,18 +7013,12 @@ static void update_copper(int until_hpos)
                                        unset_special(SPCFLAG_COPPER);
                                        goto next;
                                }
-
-                       }
-                       break;
-
-               case COP_wait1:
-                       {
-                               if (copper_cant_read(cp, 0)) {
+                       
+                               if (comp) {
                                        goto next;
                                }
 
-                               int comp = getcoppercomp(hpos, true);
-                               if (comp) {
+                               if (copper_cant_read(cp, 0)) {
                                        goto next;
                                }
 
@@ -7092,6 +7027,7 @@ static void update_copper(int until_hpos)
                        }
                        break;
 
+                       // Wait finished, request IR1.
                case COP_wait:
                        {
                                if (copper_cant_read(cp, 0x84)) {
@@ -7110,6 +7046,8 @@ static void update_copper(int until_hpos)
                        }
                        break;
 
+                       // SKIP: Got IR2. First idle cycle.
+                       // Free cycle needed, cycle allocated.
                case COP_skip_in2:
 
                        if (copper_cant_read(cp, 0x8f)) {
@@ -7118,28 +7056,34 @@ static void update_copper(int until_hpos)
                        cop_state.state = COP_skip1;
                        break;
 
+                       // SKIP: Second idle cycle. Check comparison.
+                       // Free cycle needed, cycle allocated.
                case COP_skip1:
                        if (copper_cant_read(cp, 0)) {
                                goto next;
                        }
                        cop_state.state = COP_skip;
 
-                       if (!getcoppercomp(hpos, false)) {
+                       if (copper_cant_read(cp, 0x8f)) {
+                               goto next;
+                       }
+
+                       if (!coppercomp(hpos, false)) {
                                cop_state.ignore_next = 1;
                        } else {
                                cop_state.ignore_next = -1;
                        }
 
-                       if (copper_cant_read(cp, 0x8f)) {
-                               goto next;
-                       }
                        break;
 
+                       // SKIP finished. Request IR1.
                case COP_skip:
                        {
 
+                               if (copper_cant_read(cp, 0x85)) {
+                                       goto next;
+                               }
                                cop_state.state = COP_read1;
-                               copper_cant_read(cp, 0x85);
 
 #ifdef DEBUGGER
                                if (debug_dma && cop_state.ignore_next > 0)
@@ -7175,7 +7119,7 @@ static void compute_spcflag_copper(void)
 {
        if (!dmaen(DMA_COPPER) || cop_state.state == COP_stop || cop_state.state == COP_waitforever || cop_state.state == COP_bltwait || nocustom())
                return;
-       if (cop_state.state == COP_wait) {
+       if (cop_state.state == COP_wait1) {
                int vp = vpos & (((cop_state.ir[1] >> 8) & 0x7F) | 0x80);
                if (vp < cop_state.vcmp)
                        return;
index b1180fdb9f2198d277ad59aa41f96668f3c0897a..4dd75874b288db089a08cfe29490859493398349 100644 (file)
@@ -459,27 +459,27 @@ void get_custom_topedge (int *xp, int *yp, bool max)
        }
 }
 
-static void reset_custom_limits (void)
+static void reset_custom_limits(void)
 {
        gclow = gcloh = gclox = gcloy = 0;
        gclorealh = -1;
        center_reset = true;
 }
 
-static void set_blanking_limits (void)
+static void set_blanking_limits(void)
 {
        hblank_left_start = visible_left_start;
        hblank_right_stop = visible_right_stop;
 
        if (programmedmode) {
-               if (hblank_left_start < coord_hw_to_window_x (hsyncendpos * 2))
-                       hblank_left_start = coord_hw_to_window_x (hsyncendpos * 2);
-               if (hblank_right_stop > coord_hw_to_window_x (hsyncstartpos * 2))
-                       hblank_right_stop = coord_hw_to_window_x (hsyncstartpos * 2);
+               if (hblank_left_start < coord_hw_to_window_x(hsyncendpos * 2 + 1))
+                       hblank_left_start = coord_hw_to_window_x(hsyncendpos * 2 + 1);
+               if (hblank_right_stop > coord_hw_to_window_x(hsyncstartpos * 2 + 1))
+                       hblank_right_stop = coord_hw_to_window_x(hsyncstartpos * 2 + 1);
        }
 }
 
-void get_custom_raw_limits (int *pw, int *ph, int *pdx, int *pdy)
+void get_custom_raw_limits(int *pw, int *ph, int *pdx, int *pdy)
 {
        if (stored_width > 0) {
                *pw = stored_width;