25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_fb.c,v 1.90 2005/03/29 09:46:06 debug Exp $ |
* $Id: dev_fb.c,v 1.99 2005/06/26 13:49:06 debug Exp $ |
29 |
* |
* |
30 |
* Generic framebuffer device. |
* Generic framebuffer device. |
31 |
* |
* |
115 |
|
|
116 |
|
|
117 |
/* |
/* |
118 |
|
* dev_fb_resize(): |
119 |
|
* |
120 |
|
* Resize a framebuffer window. (This functionality is probably a bit buggy, |
121 |
|
* because I didn't think of including it from the start.) |
122 |
|
*/ |
123 |
|
void dev_fb_resize(struct vfb_data *d, int new_xsize, int new_ysize) |
124 |
|
{ |
125 |
|
unsigned char *new_framebuffer; |
126 |
|
int y, new_bytes_per_line; |
127 |
|
size_t size; |
128 |
|
|
129 |
|
if (d == NULL) { |
130 |
|
fatal("dev_fb_resize(): d == NULL\n"); |
131 |
|
return; |
132 |
|
} |
133 |
|
|
134 |
|
new_bytes_per_line = new_xsize * d->bit_depth / 8; |
135 |
|
size = new_ysize * new_bytes_per_line; |
136 |
|
|
137 |
|
new_framebuffer = malloc(size); |
138 |
|
if (new_framebuffer == NULL) { |
139 |
|
fprintf(stderr, "dev_fb_resize(): out of memory\n"); |
140 |
|
exit(1); |
141 |
|
} |
142 |
|
|
143 |
|
/* Copy the old framebuffer to the new: */ |
144 |
|
if (d->framebuffer != NULL) { |
145 |
|
for (y=0; y<new_ysize; y++) { |
146 |
|
size_t fromofs = d->bytes_per_line * y; |
147 |
|
size_t toofs = new_bytes_per_line * y; |
148 |
|
size_t len_to_copy = d->bytes_per_line < |
149 |
|
new_bytes_per_line? d->bytes_per_line |
150 |
|
: new_bytes_per_line; |
151 |
|
memset(new_framebuffer + toofs, 0, new_bytes_per_line); |
152 |
|
if (y < d->x11_ysize) |
153 |
|
memmove(new_framebuffer + toofs, |
154 |
|
d->framebuffer + fromofs, len_to_copy); |
155 |
|
} |
156 |
|
|
157 |
|
free(d->framebuffer); |
158 |
|
} |
159 |
|
|
160 |
|
d->framebuffer = new_framebuffer; |
161 |
|
d->framebuffer_size = size; |
162 |
|
|
163 |
|
if (new_xsize > d->x11_xsize || new_ysize > d->x11_ysize) { |
164 |
|
d->update_x1 = d->update_y1 = 0; |
165 |
|
d->update_x2 = new_xsize - 1; |
166 |
|
d->update_y2 = new_ysize - 1; |
167 |
|
} |
168 |
|
|
169 |
|
d->bytes_per_line = new_bytes_per_line; |
170 |
|
d->x11_xsize = d->visible_xsize = new_xsize; |
171 |
|
d->x11_ysize = d->visible_ysize = new_ysize; |
172 |
|
|
173 |
|
#ifdef WITH_X11 |
174 |
|
if (d->fb_window != NULL) |
175 |
|
x11_fb_resize(d->fb_window, new_xsize, new_ysize); |
176 |
|
#endif |
177 |
|
} |
178 |
|
|
179 |
|
|
180 |
|
/* |
181 |
* dev_fb_setcursor(): |
* dev_fb_setcursor(): |
182 |
*/ |
*/ |
183 |
void dev_fb_setcursor(struct vfb_data *d, int cursor_x, int cursor_y, int on, |
void dev_fb_setcursor(struct vfb_data *d, int cursor_x, int cursor_y, int on, |
445 |
r = r & 31; |
r = r & 31; |
446 |
g = (g & 31) * 2; |
g = (g & 31) * 2; |
447 |
b = b & 31; |
b = b & 31; |
448 |
|
} else if (d->psp_15bit) { |
449 |
|
int tmp; |
450 |
|
r = (b >> 10) & 0x1f; |
451 |
|
g = (b >> 5) & 0x1f; |
452 |
|
b = b & 0x1f; |
453 |
|
g <<= 1; |
454 |
|
tmp = r; r = b; b = tmp; |
455 |
} else { |
} else { |
456 |
r = (b >> 11) & 0x1f; |
r = (b >> 11) & 0x1f; |
457 |
g = (b >> 5) & 0x3f; |
g = (b >> 5) & 0x3f; |
820 |
} |
} |
821 |
#endif |
#endif |
822 |
|
|
823 |
|
if (relative_addr >= d->framebuffer_size) |
824 |
|
return 0; |
825 |
|
|
826 |
/* See if a write actually modifies the framebuffer contents: */ |
/* See if a write actually modifies the framebuffer contents: */ |
827 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
828 |
for (i=0; i<len; i++) { |
for (i=0; i<len; i++) { |
908 |
/* |
/* |
909 |
* dev_fb_init(): |
* dev_fb_init(): |
910 |
* |
* |
911 |
* xsize and ysize are ignored if vfb_type is VFB_DEC_VFB01 or 02. |
* This function is big and ugly, but the point is to initialize a framebuffer |
912 |
|
* device. :-) |
913 |
|
* |
914 |
|
* visible_xsize and visible_ysize are the sizes of the visible display area. |
915 |
|
* xsize and ysize tell how much memory is actually allocated (for example |
916 |
|
* visible_xsize could be 640, but xsize could be 1024, for better alignment). |
917 |
|
* |
918 |
|
* vfb_type is useful for selecting special features. |
919 |
|
* |
920 |
|
* type = VFB_GENERIC is the most useful type, especially when bit_depth = 24. |
921 |
|
* |
922 |
|
* VFB_DEC_VFB01, _VFB02, and VFB_DEC_MAXINE are DECstation specific. |
923 |
|
* |
924 |
|
* If type is VFB_HPCMIPS, then color encoding differs from the generic case. |
925 |
|
* |
926 |
|
* If bit_depth = -15 (note the minus sign), then a special hack is used for |
927 |
|
* the Playstation Portable's 5-bit R, 5-bit G, 5-bit B. |
928 |
*/ |
*/ |
929 |
struct vfb_data *dev_fb_init(struct machine *machine, struct memory *mem, |
struct vfb_data *dev_fb_init(struct machine *machine, struct memory *mem, |
930 |
uint64_t baseaddr, int vfb_type, int visible_xsize, int visible_ysize, |
uint64_t baseaddr, int vfb_type, int visible_xsize, int visible_ysize, |
931 |
int xsize, int ysize, int bit_depth, char *name, int logo) |
int xsize, int ysize, int bit_depth, char *name, int logo) |
932 |
{ |
{ |
933 |
struct vfb_data *d; |
struct vfb_data *d; |
934 |
size_t size; |
size_t size, nlen; |
935 |
int x, y; |
int x, y, flags; |
936 |
char title[400]; |
char title[400]; |
937 |
char *name2; |
char *name2; |
|
int flags; |
|
938 |
|
|
939 |
d = malloc(sizeof(struct vfb_data)); |
d = malloc(sizeof(struct vfb_data)); |
940 |
if (d == NULL) { |
if (d == NULL) { |
954 |
if (bit_depth == 15) { |
if (bit_depth == 15) { |
955 |
d->color32k = 1; |
d->color32k = 1; |
956 |
bit_depth = d->bit_depth = 16; |
bit_depth = d->bit_depth = 16; |
957 |
|
} else if (bit_depth == -15) { |
958 |
|
d->psp_15bit = 1; |
959 |
|
bit_depth = d->bit_depth = 16; |
960 |
} |
} |
961 |
|
|
962 |
/* Specific types: */ |
/* Specific types: */ |
1032 |
int b = fb_logo[(y*LOGO_XSIZE+x) / 8] & |
int b = fb_logo[(y*LOGO_XSIZE+x) / 8] & |
1033 |
(128 >> (x&7)); |
(128 >> (x&7)); |
1034 |
for (s=0; s<d->bit_depth / 8; s++) |
for (s=0; s<d->bit_depth / 8; s++) |
1035 |
d->framebuffer[a+s] = b? 0 : 255; |
if (a+s >= 0 && a+s < size) |
1036 |
|
d->framebuffer[a+s] = b? 0:255; |
1037 |
} |
} |
1038 |
} |
} |
1039 |
|
|
1040 |
snprintf(title, sizeof(title), "GXemul: %ix%ix%i %s framebuffer", |
/* Don't set the title to include the size of the framebuffer for |
1041 |
d->visible_xsize, d->visible_ysize, d->bit_depth, name); |
VGA, since then the resolution might change during runtime. */ |
1042 |
|
if (strcmp(name, "VGA") == 0) |
1043 |
|
snprintf(title, sizeof(title),"GXemul: %s framebuffer", name); |
1044 |
|
else |
1045 |
|
snprintf(title, sizeof(title),"GXemul: %ix%ix%i %s framebuffer", |
1046 |
|
d->visible_xsize, d->visible_ysize, d->bit_depth, name); |
1047 |
title[sizeof(title)-1] = '\0'; |
title[sizeof(title)-1] = '\0'; |
1048 |
|
|
1049 |
#ifdef WITH_X11 |
#ifdef WITH_X11 |
1054 |
#endif |
#endif |
1055 |
d->fb_window = NULL; |
d->fb_window = NULL; |
1056 |
|
|
1057 |
name2 = malloc(strlen(name) + 10); |
nlen = strlen(name) + 10; |
1058 |
|
name2 = malloc(nlen); |
1059 |
if (name2 == NULL) { |
if (name2 == NULL) { |
1060 |
fprintf(stderr, "out of memory in dev_fb_init()\n"); |
fprintf(stderr, "out of memory in dev_fb_init()\n"); |
1061 |
exit(1); |
exit(1); |
1062 |
} |
} |
1063 |
sprintf(name2, "fb [%s]", name); |
snprintf(name2, nlen, "fb [%s]", name); |
1064 |
|
|
1065 |
flags = MEM_DEFAULT; |
flags = MEM_DEFAULT; |
1066 |
if ((baseaddr & 0xfff) == 0) |
if ((baseaddr & 0xfff) == 0) |
1067 |
flags = MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK; |
flags = MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK; |
1068 |
|
|
1069 |
|
flags |= MEM_READING_HAS_NO_SIDE_EFFECTS; |
1070 |
|
|
1071 |
memory_device_register(mem, name2, baseaddr, size, dev_fb_access, |
memory_device_register(mem, name2, baseaddr, size, dev_fb_access, |
1072 |
d, flags, d->framebuffer); |
d, flags, d->framebuffer); |
1073 |
|
|