]> git.proxmox.com Git - qemu.git/blame - hw/tcx.c
SPARC merge
[qemu.git] / hw / tcx.c
CommitLineData
420557e8
FB
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
420557e8
FB
26#define MAXX 1024
27#define MAXY 768
e80cfcfc
FB
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
420557e8
FB
34#define XSZ (8*80)
35#define YSZ (24*11)
36#define XOFF (MAXX-XSZ)
37#define YOFF (MAXY-YSZ)
e80cfcfc
FB
38#else
39#define XSZ MAXX
40#define YSZ MAXY
41#define XOFF 0
42#define YOFF 0
43#endif
420557e8 44
420557e8 45typedef struct TCXState {
8d5f07fa 46 uint32_t addr;
420557e8 47 DisplayState *ds;
8d5f07fa 48 uint8_t *vram;
e80cfcfc
FB
49 unsigned long vram_offset;
50 uint8_t r[256], g[256], b[256];
420557e8
FB
51} TCXState;
52
e80cfcfc
FB
53static void tcx_draw_line32(TCXState *s1, uint8_t *d,
54 const uint8_t *s, int width)
420557e8 55{
e80cfcfc
FB
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 }
420557e8
FB
66}
67
e80cfcfc
FB
68static void tcx_draw_line24(TCXState *s1, uint8_t *d,
69 const uint8_t *s, int width)
70{
71 int x;
72 uint8_t val;
8d5f07fa 73
e80cfcfc
FB
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
82static void tcx_draw_line8(TCXState *s1, uint8_t *d,
83 const uint8_t *s, int width)
420557e8 84{
e80cfcfc
FB
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;
420557e8 92 }
420557e8
FB
93}
94
e80cfcfc
FB
95/* Fixed line length 1024 allows us to do nice tricks not possible on
96 VGA... */
97void tcx_update_display(void *opaque)
420557e8 98{
e80cfcfc
FB
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#ifdef LD_BYPASS_OK
108 page = ts->vram_offset + YOFF*MAXX;
420557e8 109#else
e80cfcfc 110 page = ts->addr + YOFF*MAXX;
420557e8 111#endif
e80cfcfc
FB
112 y_start = -1;
113 page_min = 0x7fffffff;
114 page_max = -1;
115 d = ts->ds->data;
116 s = ts->vram + YOFF*MAXX + XOFF;
117 dd = ts->ds->linesize;
118 ds = 1024;
119
120 switch (ts->ds->depth) {
121 case 32:
122 f = tcx_draw_line32;
123 break;
124 case 24:
125 f = tcx_draw_line24;
126 break;
127 default:
128 case 8:
129 f = tcx_draw_line8;
130 break;
131 case 0:
132 return;
133 }
134
135 for(y = 0; y < YSZ; y += 4, page += TARGET_PAGE_SIZE) {
136 if (cpu_physical_memory_is_dirty(page)) {
137 if (y_start < 0)
138 y_start = y;
139 if (page < page_min)
140 page_min = page;
141 if (page > page_max)
142 page_max = page;
143 f(ts, d, s, XSZ);
144 d += dd;
145 s += ds;
146 f(ts, d, s, XSZ);
147 d += dd;
148 s += ds;
149 f(ts, d, s, XSZ);
150 d += dd;
151 s += ds;
152 f(ts, d, s, XSZ);
153 d += dd;
154 s += ds;
155 } else {
156 if (y_start >= 0) {
157 /* flush to display */
158 dpy_update(ts->ds, 0, y_start,
159 XSZ, y - y_start);
160 y_start = -1;
161 }
162 d += dd * 4;
163 s += ds * 4;
164 }
165 }
166 if (y_start >= 0) {
167 /* flush to display */
168 dpy_update(ts->ds, 0, y_start,
169 XSZ, y - y_start);
170 }
171 /* reset modified pages */
172 if (page_max != -1) {
173 cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
174 }
420557e8
FB
175}
176
e80cfcfc 177void tcx_invalidate_display(void *opaque)
420557e8 178{
e80cfcfc
FB
179 TCXState *s = opaque;
180 int i;
181
182 for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {
183#ifdef LD_BYPASS_OK
184 cpu_physical_memory_set_dirty(s->vram_offset + i);
420557e8 185#else
e80cfcfc 186 cpu_physical_memory_set_dirty(s->addr + i);
420557e8 187#endif
e80cfcfc 188 }
420557e8
FB
189}
190
e80cfcfc 191static void tcx_save(QEMUFile *f, void *opaque)
420557e8
FB
192{
193 TCXState *s = opaque;
e80cfcfc
FB
194
195 qemu_put_be32s(f, (uint32_t *)&s->addr);
196 qemu_put_be32s(f, (uint32_t *)&s->vram);
197 qemu_put_buffer(f, s->r, 256);
198 qemu_put_buffer(f, s->g, 256);
199 qemu_put_buffer(f, s->b, 256);
420557e8
FB
200}
201
e80cfcfc 202static int tcx_load(QEMUFile *f, void *opaque, int version_id)
420557e8 203{
e80cfcfc
FB
204 TCXState *s = opaque;
205
206 if (version_id != 1)
207 return -EINVAL;
208
209 qemu_get_be32s(f, (uint32_t *)&s->addr);
210 qemu_get_be32s(f, (uint32_t *)&s->vram);
211 qemu_get_buffer(f, s->r, 256);
212 qemu_get_buffer(f, s->g, 256);
213 qemu_get_buffer(f, s->b, 256);
214 return 0;
420557e8
FB
215}
216
e80cfcfc 217static void tcx_reset(void *opaque)
420557e8 218{
e80cfcfc
FB
219 TCXState *s = opaque;
220
221 /* Initialize palette */
222 memset(s->r, 0, 256);
223 memset(s->g, 0, 256);
224 memset(s->b, 0, 256);
225 s->r[255] = s->g[255] = s->b[255] = 255;
226 memset(s->vram, 0, MAXX*MAXY);
227#ifdef LD_BYPASS_OK
228 cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY - 1);
420557e8
FB
229#endif
230}
231
e80cfcfc
FB
232void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
233 unsigned long vram_offset, int vram_size)
420557e8
FB
234{
235 TCXState *s;
236
237 s = qemu_mallocz(sizeof(TCXState));
238 if (!s)
e80cfcfc 239 return NULL;
420557e8 240 s->ds = ds;
8d5f07fa 241 s->addr = addr;
e80cfcfc
FB
242 s->vram = vram_base;
243 s->vram_offset = vram_offset;
244
245 cpu_register_physical_memory(addr, vram_size, vram_offset);
246
247 register_savevm("tcx", addr, 1, tcx_save, tcx_load, s);
248 qemu_register_reset(tcx_reset, s);
249 tcx_reset(s);
420557e8 250 dpy_resize(s->ds, XSZ, YSZ);
e80cfcfc 251 return s;
420557e8
FB
252}
253
e80cfcfc 254void tcx_screen_dump(void *opaque, const char *filename)
8d5f07fa 255{
e80cfcfc 256 TCXState *s = opaque;
8d5f07fa 257 FILE *f;
e80cfcfc 258 uint8_t *d, *d1, v;
8d5f07fa
FB
259 int y, x;
260
261 f = fopen(filename, "wb");
262 if (!f)
e80cfcfc
FB
263 return;
264 fprintf(f, "P6\n%d %d\n%d\n", XSZ, YSZ, 255);
265 d1 = s->vram + YOFF*MAXX + XOFF;
8d5f07fa
FB
266 for(y = 0; y < YSZ; y++) {
267 d = d1;
268 for(x = 0; x < XSZ; x++) {
269 v = *d;
e80cfcfc
FB
270 fputc(s->r[v], f);
271 fputc(s->g[v], f);
272 fputc(s->b[v], f);
8d5f07fa
FB
273 d++;
274 }
e80cfcfc 275 d1 += MAXX;
8d5f07fa
FB
276 }
277 fclose(f);
278 return;
279}
280
281
282