summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/display/artist.c110
1 files changed, 69 insertions, 41 deletions
diff --git a/hw/display/artist.c b/hw/display/artist.c
index f37aa9eb49..46eaa10dae 100644
--- a/hw/display/artist.c
+++ b/hw/display/artist.c
@@ -35,9 +35,9 @@
 struct vram_buffer {
     MemoryRegion mr;
     uint8_t *data;
-    int size;
-    int width;
-    int height;
+    unsigned int size;
+    unsigned int width;
+    unsigned int height;
 };
 
 typedef struct ARTISTState {
@@ -274,15 +274,15 @@ static artist_rop_t artist_get_op(ARTISTState *s)
 }
 
 static void artist_rop8(ARTISTState *s, struct vram_buffer *buf,
-                        int offset, uint8_t val)
+                        unsigned int offset, uint8_t val)
 {
     const artist_rop_t op = artist_get_op(s);
     uint8_t plane_mask;
     uint8_t *dst;
 
-    if (offset < 0 || offset >= buf->size) {
+    if (offset >= buf->size) {
         qemu_log_mask(LOG_GUEST_ERROR,
-                      "rop8 offset:%d bufsize:%u\n", offset, buf->size);
+                      "rop8 offset:%u bufsize:%u\n", offset, buf->size);
         return;
     }
     dst = buf->data + offset;
@@ -294,8 +294,7 @@ static void artist_rop8(ARTISTState *s, struct vram_buffer *buf,
         break;
 
     case ARTIST_ROP_COPY:
-        *dst &= ~plane_mask;
-        *dst |= val & plane_mask;
+        *dst = (*dst & ~plane_mask) | (val & plane_mask);
         break;
 
     case ARTIST_ROP_XOR:
@@ -349,7 +348,8 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x,
 {
     struct vram_buffer *buf;
     uint32_t vram_bitmask = s->vram_bitmask;
-    int mask, i, pix_count, pix_length, offset, width;
+    int mask, i, pix_count, pix_length;
+    unsigned int offset, width;
     uint8_t *data8, *p;
 
     pix_count = vram_write_pix_per_transfer(s);
@@ -364,8 +364,7 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x,
         offset = posy * width + posx;
     }
 
-    if (!buf->size) {
-        qemu_log("write to non-existent buffer\n");
+    if (!buf->size || offset >= buf->size) {
         return;
     }
 
@@ -394,7 +393,9 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x,
 
     case 3:
         if (s->cmap_bm_access) {
-            *(uint32_t *)(p + offset) = data;
+            if (offset + 3 < buf->size) {
+                *(uint32_t *)(p + offset) = data;
+            }
             break;
         }
         data8 = (uint8_t *)&data;
@@ -464,12 +465,14 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x,
     }
 }
 
-static void block_move(ARTISTState *s, int source_x, int source_y, int dest_x,
-                       int dest_y, int width, int height)
+static void block_move(ARTISTState *s,
+                       unsigned int source_x, unsigned int source_y,
+                       unsigned int dest_x,   unsigned int dest_y,
+                       unsigned int width,    unsigned int height)
 {
     struct vram_buffer *buf;
     int line, endline, lineincr, startcolumn, endcolumn, columnincr, column;
-    uint32_t dst, src;
+    unsigned int dst, src;
 
     trace_artist_block_move(source_x, source_y, dest_x, dest_y, width, height);
 
@@ -481,6 +484,12 @@ static void block_move(ARTISTState *s, int source_x, int source_y, int dest_x,
     }
 
     buf = &s->vram_buffer[ARTIST_BUFFER_AP];
+    if (height > buf->height) {
+        height = buf->height;
+    }
+    if (width > buf->width) {
+        width = buf->width;
+    }
 
     if (dest_y > source_y) {
         /* move down */
@@ -507,24 +516,27 @@ static void block_move(ARTISTState *s, int source_x, int source_y, int dest_x,
     }
 
     for ( ; line != endline; line += lineincr) {
-        src = source_x + ((line + source_y) * buf->width);
-        dst = dest_x + ((line + dest_y) * buf->width);
+        src = source_x + ((line + source_y) * buf->width) + startcolumn;
+        dst = dest_x + ((line + dest_y) * buf->width) + startcolumn;
 
         for (column = startcolumn; column != endcolumn; column += columnincr) {
-            if (dst + column > buf->size || src + column > buf->size) {
+            if (dst >= buf->size || src >= buf->size) {
                 continue;
             }
-            artist_rop8(s, buf, dst + column, buf->data[src + column]);
+            artist_rop8(s, buf, dst, buf->data[src]);
+            src += columnincr;
+            dst += columnincr;
         }
     }
 
     artist_invalidate_lines(buf, dest_y, height);
 }
 
-static void fill_window(ARTISTState *s, int startx, int starty,
-                        int width, int height)
+static void fill_window(ARTISTState *s,
+                        unsigned int startx, unsigned int starty,
+                        unsigned int width,  unsigned int height)
 {
-    uint32_t offset;
+    unsigned int offset;
     uint8_t color = artist_get_color(s);
     struct vram_buffer *buf;
     int x, y;
@@ -561,7 +573,9 @@ static void fill_window(ARTISTState *s, int startx, int starty,
     artist_invalidate_lines(buf, starty, height);
 }
 
-static void draw_line(ARTISTState *s, int x1, int y1, int x2, int y2,
+static void draw_line(ARTISTState *s,
+                      unsigned int x1, unsigned int y1,
+                      unsigned int x2, unsigned int y2,
                       bool update_start, int skip_pix, int max_pix)
 {
     struct vram_buffer *buf = &s->vram_buffer[ARTIST_BUFFER_AP];
@@ -571,12 +585,12 @@ static void draw_line(ARTISTState *s, int x1, int y1, int x2, int y2,
 
     trace_artist_draw_line(x1, y1, x2, y2);
 
-    if (x1 * y1 >= buf->size || x2 * y2 >= buf->size) {
-        qemu_log_mask(LOG_GUEST_ERROR,
-                      "draw_line (%d,%d) (%d,%d)\n", x1, y1, x2, y2);
-        return;
+    if ((x1 >= buf->width && x2 >= buf->width) ||
+        (y1 >= buf->height && y2 >= buf->height)) {
+	return;
     }
 
+
     if (update_start) {
         s->vram_start = (x2 << 16) | y2;
     }
@@ -633,7 +647,7 @@ static void draw_line(ARTISTState *s, int x1, int y1, int x2, int y2,
     color = artist_get_color(s);
 
     do {
-        int ofs;
+        unsigned int ofs;
 
         if (c1) {
             ofs = x * s->width + y;
@@ -765,13 +779,14 @@ static void font_write16(ARTISTState *s, uint16_t val)
     uint16_t mask;
     int i;
 
-    int startx = artist_get_x(s->vram_start);
-    int starty = artist_get_y(s->vram_start) + s->font_write_pos_y;
-    int offset = starty * s->width + startx;
+    unsigned int startx = artist_get_x(s->vram_start);
+    unsigned int starty = artist_get_y(s->vram_start) + s->font_write_pos_y;
+    unsigned int offset = starty * s->width + startx;
 
     buf = &s->vram_buffer[ARTIST_BUFFER_AP];
 
-    if (offset + 16 > buf->size) {
+    if (startx >= buf->width || starty >= buf->height ||
+        offset + 16 >= buf->size) {
         return;
     }
 
@@ -1135,7 +1150,7 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val,
     struct vram_buffer *buf;
     int posy = (addr >> 11) & 0x3ff;
     int posx = addr & 0x7ff;
-    uint32_t offset;
+    unsigned int offset;
     trace_artist_vram_write(size, addr, val);
 
     if (s->cmap_bm_access) {
@@ -1156,18 +1171,28 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val,
     }
 
     offset = posy * buf->width + posx;
+    if (offset >= buf->size) {
+        return;
+    }
+
     switch (size) {
     case 4:
-        *(uint32_t *)(buf->data + offset) = be32_to_cpu(val);
-        memory_region_set_dirty(&buf->mr, offset, 4);
+        if (offset + 3 < buf->size) {
+            *(uint32_t *)(buf->data + offset) = be32_to_cpu(val);
+            memory_region_set_dirty(&buf->mr, offset, 4);
+        }
         break;
     case 2:
-        *(uint16_t *)(buf->data + offset) = be16_to_cpu(val);
-        memory_region_set_dirty(&buf->mr, offset, 2);
+        if (offset + 1 < buf->size) {
+            *(uint16_t *)(buf->data + offset) = be16_to_cpu(val);
+            memory_region_set_dirty(&buf->mr, offset, 2);
+        }
         break;
     case 1:
-        *(uint8_t *)(buf->data + offset) = val;
-        memory_region_set_dirty(&buf->mr, offset, 1);
+        if (offset < buf->size) {
+            *(uint8_t *)(buf->data + offset) = val;
+            memory_region_set_dirty(&buf->mr, offset, 1);
+        }
         break;
     default:
         break;
@@ -1183,9 +1208,12 @@ static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size)
 
     if (s->cmap_bm_access) {
         buf = &s->vram_buffer[ARTIST_BUFFER_CMAP];
-        val = *(uint32_t *)(buf->data + addr);
+        val = 0;
+        if (addr < buf->size && addr + 3 < buf->size) {
+            val = *(uint32_t *)(buf->data + addr);
+        }
         trace_artist_vram_read(size, addr, 0, 0, val);
-        return 0;
+        return val;
     }
 
     buf = vram_read_buffer(s);