]>
Commit | Line | Data |
---|---|---|
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 | 45 | typedef 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 |
53 | static 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 |
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; | |
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 | ||
82 | static 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... */ | |
97 | void 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; | |
e80cfcfc | 107 | page = ts->vram_offset + YOFF*MAXX; |
e80cfcfc FB |
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 | } | |
662f3c86 | 130 | |
e80cfcfc FB |
131 | for(y = 0; y < YSZ; y += 4, page += TARGET_PAGE_SIZE) { |
132 | if (cpu_physical_memory_is_dirty(page)) { | |
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 | } | |
420557e8 FB |
171 | } |
172 | ||
e80cfcfc | 173 | void tcx_invalidate_display(void *opaque) |
420557e8 | 174 | { |
e80cfcfc FB |
175 | TCXState *s = opaque; |
176 | int i; | |
177 | ||
178 | for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) { | |
e80cfcfc | 179 | cpu_physical_memory_set_dirty(s->vram_offset + i); |
e80cfcfc | 180 | } |
420557e8 FB |
181 | } |
182 | ||
e80cfcfc | 183 | static void tcx_save(QEMUFile *f, void *opaque) |
420557e8 FB |
184 | { |
185 | TCXState *s = opaque; | |
e80cfcfc FB |
186 | |
187 | qemu_put_be32s(f, (uint32_t *)&s->addr); | |
188 | qemu_put_be32s(f, (uint32_t *)&s->vram); | |
189 | qemu_put_buffer(f, s->r, 256); | |
190 | qemu_put_buffer(f, s->g, 256); | |
191 | qemu_put_buffer(f, s->b, 256); | |
420557e8 FB |
192 | } |
193 | ||
e80cfcfc | 194 | static int tcx_load(QEMUFile *f, void *opaque, int version_id) |
420557e8 | 195 | { |
e80cfcfc FB |
196 | TCXState *s = opaque; |
197 | ||
198 | if (version_id != 1) | |
199 | return -EINVAL; | |
200 | ||
201 | qemu_get_be32s(f, (uint32_t *)&s->addr); | |
202 | qemu_get_be32s(f, (uint32_t *)&s->vram); | |
203 | qemu_get_buffer(f, s->r, 256); | |
204 | qemu_get_buffer(f, s->g, 256); | |
205 | qemu_get_buffer(f, s->b, 256); | |
206 | return 0; | |
420557e8 FB |
207 | } |
208 | ||
e80cfcfc | 209 | static void tcx_reset(void *opaque) |
420557e8 | 210 | { |
e80cfcfc FB |
211 | TCXState *s = opaque; |
212 | ||
213 | /* Initialize palette */ | |
214 | memset(s->r, 0, 256); | |
215 | memset(s->g, 0, 256); | |
216 | memset(s->b, 0, 256); | |
217 | s->r[255] = s->g[255] = s->b[255] = 255; | |
218 | memset(s->vram, 0, MAXX*MAXY); | |
662f3c86 | 219 | cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY); |
420557e8 FB |
220 | } |
221 | ||
e80cfcfc FB |
222 | void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base, |
223 | unsigned long vram_offset, int vram_size) | |
420557e8 FB |
224 | { |
225 | TCXState *s; | |
226 | ||
227 | s = qemu_mallocz(sizeof(TCXState)); | |
228 | if (!s) | |
e80cfcfc | 229 | return NULL; |
420557e8 | 230 | s->ds = ds; |
8d5f07fa | 231 | s->addr = addr; |
e80cfcfc FB |
232 | s->vram = vram_base; |
233 | s->vram_offset = vram_offset; | |
234 | ||
235 | cpu_register_physical_memory(addr, vram_size, vram_offset); | |
236 | ||
237 | register_savevm("tcx", addr, 1, tcx_save, tcx_load, s); | |
238 | qemu_register_reset(tcx_reset, s); | |
239 | tcx_reset(s); | |
420557e8 | 240 | dpy_resize(s->ds, XSZ, YSZ); |
e80cfcfc | 241 | return s; |
420557e8 FB |
242 | } |
243 | ||
e80cfcfc | 244 | void tcx_screen_dump(void *opaque, const char *filename) |
8d5f07fa | 245 | { |
e80cfcfc | 246 | TCXState *s = opaque; |
8d5f07fa | 247 | FILE *f; |
e80cfcfc | 248 | uint8_t *d, *d1, v; |
8d5f07fa FB |
249 | int y, x; |
250 | ||
251 | f = fopen(filename, "wb"); | |
252 | if (!f) | |
e80cfcfc FB |
253 | return; |
254 | fprintf(f, "P6\n%d %d\n%d\n", XSZ, YSZ, 255); | |
255 | d1 = s->vram + YOFF*MAXX + XOFF; | |
8d5f07fa FB |
256 | for(y = 0; y < YSZ; y++) { |
257 | d = d1; | |
258 | for(x = 0; x < XSZ; x++) { | |
259 | v = *d; | |
e80cfcfc FB |
260 | fputc(s->r[v], f); |
261 | fputc(s->g[v], f); | |
262 | fputc(s->b[v], f); | |
8d5f07fa FB |
263 | d++; |
264 | } | |
e80cfcfc | 265 | d1 += MAXX; |
8d5f07fa FB |
266 | } |
267 | fclose(f); | |
268 | return; | |
269 | } | |
270 | ||
271 | ||
272 |