Revision 6f7e9aec hw/tcx.c
b/hw/tcx.c | ||
---|---|---|
1 | 1 |
/* |
2 |
* QEMU Sun4m System Emulator
|
|
2 |
* QEMU TCX Frame buffer
|
|
3 | 3 |
* |
4 |
* Copyright (c) 2003-2004 Fabrice Bellard
|
|
4 |
* Copyright (c) 2003-2005 Fabrice Bellard
|
|
5 | 5 |
* |
6 | 6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | 7 |
* of this software and associated documentation files (the "Software"), to deal |
... | ... | |
25 | 25 |
|
26 | 26 |
#define MAXX 1024 |
27 | 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 |
|
28 |
#define TCX_DAC_NREGS 16 |
|
44 | 29 |
|
45 | 30 |
typedef struct TCXState { |
46 | 31 |
uint32_t addr; |
47 | 32 |
DisplayState *ds; |
48 | 33 |
uint8_t *vram; |
49 | 34 |
unsigned long vram_offset; |
35 |
uint16_t width, height; |
|
50 | 36 |
uint8_t r[256], g[256], b[256]; |
37 |
uint8_t dac_index, dac_state; |
|
51 | 38 |
} TCXState; |
52 | 39 |
|
53 | 40 |
static void tcx_draw_line32(TCXState *s1, uint8_t *d, |
... | ... | |
58 | 45 |
|
59 | 46 |
for(x = 0; x < width; x++) { |
60 | 47 |
val = *s++; |
61 |
*d++ = s1->r[val]; |
|
62 |
*d++ = s1->g[val]; |
|
63 | 48 |
*d++ = s1->b[val]; |
49 |
*d++ = s1->g[val]; |
|
50 |
*d++ = s1->r[val]; |
|
64 | 51 |
d++; |
65 | 52 |
} |
66 | 53 |
} |
... | ... | |
73 | 60 |
|
74 | 61 |
for(x = 0; x < width; x++) { |
75 | 62 |
val = *s++; |
76 |
*d++ = s1->r[val]; |
|
77 |
*d++ = s1->g[val]; |
|
78 | 63 |
*d++ = s1->b[val]; |
64 |
*d++ = s1->g[val]; |
|
65 |
*d++ = s1->r[val]; |
|
79 | 66 |
} |
80 | 67 |
} |
81 | 68 |
|
... | ... | |
104 | 91 |
|
105 | 92 |
if (ts->ds->depth == 0) |
106 | 93 |
return; |
107 |
page = ts->vram_offset + YOFF*MAXX;
|
|
94 |
page = ts->vram_offset; |
|
108 | 95 |
y_start = -1; |
109 | 96 |
page_min = 0x7fffffff; |
110 | 97 |
page_max = -1; |
111 | 98 |
d = ts->ds->data; |
112 |
s = ts->vram + YOFF*MAXX + XOFF;
|
|
99 |
s = ts->vram; |
|
113 | 100 |
dd = ts->ds->linesize; |
114 | 101 |
ds = 1024; |
115 | 102 |
|
... | ... | |
128 | 115 |
return; |
129 | 116 |
} |
130 | 117 |
|
131 |
for(y = 0; y < YSZ; y += 4, page += TARGET_PAGE_SIZE) {
|
|
118 |
for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
|
|
132 | 119 |
if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) { |
133 | 120 |
if (y_start < 0) |
134 | 121 |
y_start = y; |
... | ... | |
136 | 123 |
page_min = page; |
137 | 124 |
if (page > page_max) |
138 | 125 |
page_max = page; |
139 |
f(ts, d, s, XSZ);
|
|
126 |
f(ts, d, s, ts->width);
|
|
140 | 127 |
d += dd; |
141 | 128 |
s += ds; |
142 |
f(ts, d, s, XSZ);
|
|
129 |
f(ts, d, s, ts->width);
|
|
143 | 130 |
d += dd; |
144 | 131 |
s += ds; |
145 |
f(ts, d, s, XSZ);
|
|
132 |
f(ts, d, s, ts->width);
|
|
146 | 133 |
d += dd; |
147 | 134 |
s += ds; |
148 |
f(ts, d, s, XSZ);
|
|
135 |
f(ts, d, s, ts->width);
|
|
149 | 136 |
d += dd; |
150 | 137 |
s += ds; |
151 | 138 |
} else { |
152 | 139 |
if (y_start >= 0) { |
153 | 140 |
/* flush to display */ |
154 | 141 |
dpy_update(ts->ds, 0, y_start, |
155 |
XSZ, y - y_start);
|
|
142 |
ts->width, y - y_start);
|
|
156 | 143 |
y_start = -1; |
157 | 144 |
} |
158 | 145 |
d += dd * 4; |
... | ... | |
162 | 149 |
if (y_start >= 0) { |
163 | 150 |
/* flush to display */ |
164 | 151 |
dpy_update(ts->ds, 0, y_start, |
165 |
XSZ, y - y_start);
|
|
152 |
ts->width, y - y_start);
|
|
166 | 153 |
} |
167 | 154 |
/* reset modified pages */ |
168 | 155 |
if (page_max != -1) { |
... | ... | |
187 | 174 |
|
188 | 175 |
qemu_put_be32s(f, (uint32_t *)&s->addr); |
189 | 176 |
qemu_put_be32s(f, (uint32_t *)&s->vram); |
177 |
qemu_put_be16s(f, (uint16_t *)&s->height); |
|
178 |
qemu_put_be16s(f, (uint16_t *)&s->width); |
|
190 | 179 |
qemu_put_buffer(f, s->r, 256); |
191 | 180 |
qemu_put_buffer(f, s->g, 256); |
192 | 181 |
qemu_put_buffer(f, s->b, 256); |
182 |
qemu_put_8s(f, &s->dac_index); |
|
183 |
qemu_put_8s(f, &s->dac_state); |
|
193 | 184 |
} |
194 | 185 |
|
195 | 186 |
static int tcx_load(QEMUFile *f, void *opaque, int version_id) |
... | ... | |
201 | 192 |
|
202 | 193 |
qemu_get_be32s(f, (uint32_t *)&s->addr); |
203 | 194 |
qemu_get_be32s(f, (uint32_t *)&s->vram); |
195 |
qemu_get_be16s(f, (uint16_t *)&s->height); |
|
196 |
qemu_get_be16s(f, (uint16_t *)&s->width); |
|
204 | 197 |
qemu_get_buffer(f, s->r, 256); |
205 | 198 |
qemu_get_buffer(f, s->g, 256); |
206 | 199 |
qemu_get_buffer(f, s->b, 256); |
200 |
qemu_get_8s(f, &s->dac_index); |
|
201 |
qemu_get_8s(f, &s->dac_state); |
|
207 | 202 |
return 0; |
208 | 203 |
} |
209 | 204 |
|
... | ... | |
219 | 214 |
memset(s->vram, 0, MAXX*MAXY); |
220 | 215 |
cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY, |
221 | 216 |
VGA_DIRTY_FLAG); |
217 |
s->dac_index = 0; |
|
218 |
s->dac_state = 0; |
|
219 |
} |
|
220 |
|
|
221 |
static uint32_t tcx_dac_readl(void *opaque, target_phys_addr_t addr) |
|
222 |
{ |
|
223 |
return 0; |
|
224 |
} |
|
225 |
|
|
226 |
static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
227 |
{ |
|
228 |
TCXState *s = opaque; |
|
229 |
uint32_t saddr; |
|
230 |
|
|
231 |
saddr = (addr & (TCX_DAC_NREGS - 1)) >> 2; |
|
232 |
switch (saddr) { |
|
233 |
case 0: |
|
234 |
s->dac_index = val >> 24; |
|
235 |
s->dac_state = 0; |
|
236 |
break; |
|
237 |
case 1: |
|
238 |
switch (s->dac_state) { |
|
239 |
case 0: |
|
240 |
s->r[s->dac_index] = val >> 24; |
|
241 |
s->dac_state++; |
|
242 |
break; |
|
243 |
case 1: |
|
244 |
s->g[s->dac_index] = val >> 24; |
|
245 |
s->dac_state++; |
|
246 |
break; |
|
247 |
case 2: |
|
248 |
s->b[s->dac_index] = val >> 24; |
|
249 |
default: |
|
250 |
s->dac_state = 0; |
|
251 |
break; |
|
252 |
} |
|
253 |
break; |
|
254 |
default: |
|
255 |
break; |
|
256 |
} |
|
257 |
return; |
|
222 | 258 |
} |
223 | 259 |
|
260 |
static CPUReadMemoryFunc *tcx_dac_read[3] = { |
|
261 |
tcx_dac_readl, |
|
262 |
tcx_dac_readl, |
|
263 |
tcx_dac_readl, |
|
264 |
}; |
|
265 |
|
|
266 |
static CPUWriteMemoryFunc *tcx_dac_write[3] = { |
|
267 |
tcx_dac_writel, |
|
268 |
tcx_dac_writel, |
|
269 |
tcx_dac_writel, |
|
270 |
}; |
|
271 |
|
|
224 | 272 |
void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base, |
225 |
unsigned long vram_offset, int vram_size)
|
|
273 |
unsigned long vram_offset, int vram_size, int width, int height)
|
|
226 | 274 |
{ |
227 | 275 |
TCXState *s; |
276 |
int io_memory; |
|
228 | 277 |
|
229 | 278 |
s = qemu_mallocz(sizeof(TCXState)); |
230 | 279 |
if (!s) |
... | ... | |
233 | 282 |
s->addr = addr; |
234 | 283 |
s->vram = vram_base; |
235 | 284 |
s->vram_offset = vram_offset; |
285 |
s->width = width; |
|
286 |
s->height = height; |
|
236 | 287 |
|
237 |
cpu_register_physical_memory(addr, vram_size, vram_offset); |
|
288 |
cpu_register_physical_memory(addr + 0x800000, vram_size, vram_offset); |
|
289 |
io_memory = cpu_register_io_memory(0, tcx_dac_read, tcx_dac_write, s); |
|
290 |
cpu_register_physical_memory(addr + 0x200000, TCX_DAC_NREGS, io_memory); |
|
238 | 291 |
|
239 | 292 |
register_savevm("tcx", addr, 1, tcx_save, tcx_load, s); |
240 | 293 |
qemu_register_reset(tcx_reset, s); |
241 | 294 |
tcx_reset(s); |
242 |
dpy_resize(s->ds, XSZ, YSZ);
|
|
295 |
dpy_resize(s->ds, width, height);
|
|
243 | 296 |
return s; |
244 | 297 |
} |
245 | 298 |
|
... | ... | |
253 | 306 |
f = fopen(filename, "wb"); |
254 | 307 |
if (!f) |
255 | 308 |
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++) {
|
|
309 |
fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
|
|
310 |
d1 = s->vram; |
|
311 |
for(y = 0; y < s->height; y++) {
|
|
259 | 312 |
d = d1; |
260 |
for(x = 0; x < XSZ; x++) {
|
|
313 |
for(x = 0; x < s->width; x++) {
|
|
261 | 314 |
v = *d; |
262 | 315 |
fputc(s->r[v], f); |
263 | 316 |
fputc(s->g[v], f); |
Also available in: Unified diff