Statistics
| Branch: | Revision:

root / hw / tcx.c @ afc7df11

History | View | Annotate | Download (6.4 kB)

1
/*
2
 * QEMU Sun4m System Emulator
3
 * 
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "vl.h"
25

    
26
#define MAXX 1024
27
#define MAXY 768
28
/*
29
 * Proll uses only small part of display, we need to switch to full
30
 * display when we get linux framebuffer console or X11 running. For
31
 * now it's just slower and awkward.
32
*/
33
#if 1
34
#define XSZ (8*80)
35
#define YSZ (24*11)
36
#define XOFF (MAXX-XSZ)
37
#define YOFF (MAXY-YSZ)
38
#else
39
#define XSZ MAXX
40
#define YSZ MAXY
41
#define XOFF 0
42
#define YOFF 0
43
#endif
44

    
45
typedef struct TCXState {
46
    uint32_t addr;
47
    DisplayState *ds;
48
    uint8_t *vram;
49
    unsigned long vram_offset;
50
    uint8_t r[256], g[256], b[256];
51
} TCXState;
52

    
53
static void tcx_draw_line32(TCXState *s1, uint8_t *d, 
54
                            const uint8_t *s, int width)
55
{
56
    int x;
57
    uint8_t val;
58

    
59
    for(x = 0; x < width; x++) {
60
        val = *s++;
61
        *d++ = s1->r[val];
62
        *d++ = s1->g[val];
63
        *d++ = s1->b[val];
64
        d++;
65
    }
66
}
67

    
68
static void tcx_draw_line24(TCXState *s1, uint8_t *d, 
69
                            const uint8_t *s, int width)
70
{
71
    int x;
72
    uint8_t val;
73

    
74
    for(x = 0; x < width; x++) {
75
        val = *s++;
76
        *d++ = s1->r[val];
77
        *d++ = s1->g[val];
78
        *d++ = s1->b[val];
79
    }
80
}
81

    
82
static void tcx_draw_line8(TCXState *s1, uint8_t *d, 
83
                           const uint8_t *s, int width)
84
{
85
    int x;
86
    uint8_t val;
87

    
88
    for(x = 0; x < width; x++) {
89
        val = *s++;
90
        /* XXX translate between palettes? */
91
        *d++ = val;
92
    }
93
}
94

    
95
/* Fixed line length 1024 allows us to do nice tricks not possible on
96
   VGA... */
97
void tcx_update_display(void *opaque)
98
{
99
    TCXState *ts = opaque;
100
    uint32_t page;
101
    int y, page_min, page_max, y_start, dd, ds;
102
    uint8_t *d, *s;
103
    void (*f)(TCXState *s1, uint8_t *d, const uint8_t *s, int width);
104

    
105
    if (ts->ds->depth == 0)
106
        return;
107
    page = ts->vram_offset + YOFF*MAXX;
108
    y_start = -1;
109
    page_min = 0x7fffffff;
110
    page_max = -1;
111
    d = ts->ds->data;
112
    s = ts->vram + YOFF*MAXX + XOFF;
113
    dd = ts->ds->linesize;
114
    ds = 1024;
115

    
116
    switch (ts->ds->depth) {
117
    case 32:
118
        f = tcx_draw_line32;
119
        break;
120
    case 24:
121
        f = tcx_draw_line24;
122
        break;
123
    default:
124
    case 8:
125
        f = tcx_draw_line8;
126
        break;
127
    case 0:
128
        return;
129
    }
130
    
131
    for(y = 0; y < YSZ; y += 4, page += TARGET_PAGE_SIZE) {
132
        if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
133
            if (y_start < 0)
134
                y_start = y;
135
            if (page < page_min)
136
                page_min = page;
137
            if (page > page_max)
138
                page_max = page;
139
            f(ts, d, s, XSZ);
140
            d += dd;
141
            s += ds;
142
            f(ts, d, s, XSZ);
143
            d += dd;
144
            s += ds;
145
            f(ts, d, s, XSZ);
146
            d += dd;
147
            s += ds;
148
            f(ts, d, s, XSZ);
149
            d += dd;
150
            s += ds;
151
        } else {
152
            if (y_start >= 0) {
153
                /* flush to display */
154
                dpy_update(ts->ds, 0, y_start, 
155
                           XSZ, y - y_start);
156
                y_start = -1;
157
            }
158
            d += dd * 4;
159
            s += ds * 4;
160
        }
161
    }
162
    if (y_start >= 0) {
163
        /* flush to display */
164
        dpy_update(ts->ds, 0, y_start, 
165
                   XSZ, y - y_start);
166
    }
167
    /* reset modified pages */
168
    if (page_max != -1) {
169
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
170
                                        VGA_DIRTY_FLAG);
171
    }
172
}
173

    
174
void tcx_invalidate_display(void *opaque)
175
{
176
    TCXState *s = opaque;
177
    int i;
178

    
179
    for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {
180
        cpu_physical_memory_set_dirty(s->vram_offset + i);
181
    }
182
}
183

    
184
static void tcx_save(QEMUFile *f, void *opaque)
185
{
186
    TCXState *s = opaque;
187
    
188
    qemu_put_be32s(f, (uint32_t *)&s->addr);
189
    qemu_put_be32s(f, (uint32_t *)&s->vram);
190
    qemu_put_buffer(f, s->r, 256);
191
    qemu_put_buffer(f, s->g, 256);
192
    qemu_put_buffer(f, s->b, 256);
193
}
194

    
195
static int tcx_load(QEMUFile *f, void *opaque, int version_id)
196
{
197
    TCXState *s = opaque;
198
    
199
    if (version_id != 1)
200
        return -EINVAL;
201

    
202
    qemu_get_be32s(f, (uint32_t *)&s->addr);
203
    qemu_get_be32s(f, (uint32_t *)&s->vram);
204
    qemu_get_buffer(f, s->r, 256);
205
    qemu_get_buffer(f, s->g, 256);
206
    qemu_get_buffer(f, s->b, 256);
207
    return 0;
208
}
209

    
210
static void tcx_reset(void *opaque)
211
{
212
    TCXState *s = opaque;
213

    
214
    /* Initialize palette */
215
    memset(s->r, 0, 256);
216
    memset(s->g, 0, 256);
217
    memset(s->b, 0, 256);
218
    s->r[255] = s->g[255] = s->b[255] = 255;
219
    memset(s->vram, 0, MAXX*MAXY);
220
    cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY,
221
                                    VGA_DIRTY_FLAG);
222
}
223

    
224
void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
225
              unsigned long vram_offset, int vram_size)
226
{
227
    TCXState *s;
228

    
229
    s = qemu_mallocz(sizeof(TCXState));
230
    if (!s)
231
        return NULL;
232
    s->ds = ds;
233
    s->addr = addr;
234
    s->vram = vram_base;
235
    s->vram_offset = vram_offset;
236

    
237
    cpu_register_physical_memory(addr, vram_size, vram_offset);
238

    
239
    register_savevm("tcx", addr, 1, tcx_save, tcx_load, s);
240
    qemu_register_reset(tcx_reset, s);
241
    tcx_reset(s);
242
    dpy_resize(s->ds, XSZ, YSZ);
243
    return s;
244
}
245

    
246
void tcx_screen_dump(void *opaque, const char *filename)
247
{
248
    TCXState *s = opaque;
249
    FILE *f;
250
    uint8_t *d, *d1, v;
251
    int y, x;
252

    
253
    f = fopen(filename, "wb");
254
    if (!f)
255
        return;
256
    fprintf(f, "P6\n%d %d\n%d\n", XSZ, YSZ, 255);
257
    d1 = s->vram + YOFF*MAXX + XOFF;
258
    for(y = 0; y < YSZ; y++) {
259
        d = d1;
260
        for(x = 0; x < XSZ; x++) {
261
            v = *d;
262
            fputc(s->r[v], f);
263
            fputc(s->g[v], f);
264
            fputc(s->b[v], f);
265
            d++;
266
        }
267
        d1 += MAXX;
268
    }
269
    fclose(f);
270
    return;
271
}
272

    
273

    
274