diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 9f61a01..a7f0d3c 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -676,15 +676,17 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
     int sx, sy;
     int dx, dy;
     int width, height;
+    uint32_t start_addr, line_offset, line_compare;
     int depth;
     int notify = 0;
 
     depth = s->vga.get_bpp(&s->vga) / 8;
     s->vga.get_resolution(&s->vga, &width, &height);
+    s->vga.get_offsets(&s->vga, &line_offset, &start_addr, &line_compare);
 
     /* extra x, y */
-    sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;
-    sy = (src / ABS(s->cirrus_blt_srcpitch));
+    sx = (src % line_offset) / depth;
+    sy = (src / line_offset);
     dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;
     dy = (dst / ABS(s->cirrus_blt_dstpitch));
 
@@ -725,18 +727,23 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
 		      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
 		      s->cirrus_blt_width, s->cirrus_blt_height);
 
-    if (notify)
-	qemu_console_copy(s->vga.ds,
-			  sx, sy, dx, dy,
-			  s->cirrus_blt_width / depth,
-			  s->cirrus_blt_height);
-
-    /* we don't have to notify the display that this portion has
-       changed since qemu_console_copy implies this */
-
-    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
-				s->cirrus_blt_dstpitch, s->cirrus_blt_width,
-				s->cirrus_blt_height);
+     if (ABS(s->cirrus_blt_dstpitch) != line_offset ||
+             ABS(s->cirrus_blt_srcpitch) != line_offset) {
+             /* this is not going to happen very often */
+             vga_hw_invalidate();
+     } else {
+         if (notify)
+             /* we don't have to notify the display that this portion has
+                changed since qemu_console_copy implies this */
+             qemu_console_copy(s->vga.ds,
+                               sx, sy, dx, dy,
+                               s->cirrus_blt_width / depth,
+                               s->cirrus_blt_height);
+         else
+             cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+                                      s->cirrus_blt_dstpitch, s->cirrus_blt_width,
+                                      s->cirrus_blt_height);
+     }
 }
 
 static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
diff --git a/hw/cirrus_vga_rop.h b/hw/cirrus_vga_rop.h
index 39a7b72..80f135b 100644
--- a/hw/cirrus_vga_rop.h
+++ b/hw/cirrus_vga_rop.h
@@ -32,10 +32,10 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
     dstpitch -= bltwidth;
     srcpitch -= bltwidth;
 
-    if (dstpitch < 0 || srcpitch < 0) {
-        /* is 0 valid? srcpitch == 0 could be useful */
+    if (dstpitch < 0)
         return;
-    }
+    if (srcpitch < 0)
+        srcpitch = 0;
 
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
@@ -57,6 +57,12 @@ glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
     int x,y;
     dstpitch += bltwidth;
     srcpitch += bltwidth;
+
+    if (dstpitch > 0)
+        return;
+    if (srcpitch > 0)
+        srcpitch = 0;
+
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
             ROP_OP(*dst, *src);
@@ -78,6 +84,12 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
     uint8_t p;
     dstpitch -= bltwidth;
     srcpitch -= bltwidth;
+
+    if (dstpitch < 0)
+        return;
+    if (srcpitch < 0)
+        srcpitch = 0;
+
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
 	    p = *dst;
@@ -101,6 +113,12 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s,
     uint8_t p;
     dstpitch += bltwidth;
     srcpitch += bltwidth;
+
+    if (dstpitch > 0)
+        return;
+    if (srcpitch > 0)
+        srcpitch = 0;
+
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x++) {
 	    p = *dst;
@@ -124,6 +142,12 @@ glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
     uint8_t p1, p2;
     dstpitch -= bltwidth;
     srcpitch -= bltwidth;
+
+    if (dstpitch < 0)
+        return;
+    if (srcpitch < 0)
+        srcpitch = 0;
+
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x+=2) {
 	    p1 = *dst;
@@ -152,6 +176,12 @@ glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s,
     uint8_t p1, p2;
     dstpitch += bltwidth;
     srcpitch += bltwidth;
+
+    if (dstpitch > 0)
+        return;
+    if (srcpitch > 0)
+        srcpitch = 0;
+
     for (y = 0; y < bltheight; y++) {
         for (x = 0; x < bltwidth; x+=2) {
 	    p1 = *(dst-1);
