]> git.sesse.net Git - pistorm/blob - platforms/amiga/rtg/rtg.c
Fix all the colors, fix some other stuff.
[pistorm] / platforms / amiga / rtg / rtg.c
1 #include <stdint.h>
2 #include <endian.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <time.h>
7 #include "rtg.h"
8 #include "../../../config_file/config_file.h"
9
10 static uint8_t rtg_u8[4];
11 static uint16_t rtg_x[3], rtg_y[3];
12 static uint16_t rtg_format;
13 static uint32_t rtg_address[2];
14 static uint32_t rtg_rgb[2];
15
16 static uint8_t display_enabled = 0xFF;
17
18 uint16_t rtg_display_width, rtg_display_height;
19 uint16_t rtg_display_format;
20 uint16_t rtg_pitch, rtg_total_rows;
21 uint16_t rtg_offset_x, rtg_offset_y;
22
23 uint8_t *rtg_mem; // FIXME
24
25 uint32_t framebuffer_addr;
26
27 static void handle_rtg_command(uint32_t cmd);
28 static struct timespec f1, f2;
29
30 static const char *op_type_names[OP_TYPE_NUM] = {
31     "BYTE",
32     "WORD",
33     "LONGWORD",
34     "MEM",
35 };
36
37 static const char *rtg_format_names[RTGFMT_NUM] = {
38     "8BPP CLUT",
39     "16BPP RGB (565)",
40     "32BPP RGB (RGBA)",
41     "15BPP RGB (555)",
42 };
43
44 int init_rtg_data() {
45     rtg_mem = calloc(1, 32 * SIZE_MEGA);
46     if (!rtg_mem) {
47         printf("Failed to allocate RTG video memory.\n");
48         return 0;
49     }
50
51     return 1;
52 }
53
54 extern uint8_t busy, rtg_on;
55 void rtg_update_screen();
56
57 unsigned int rtg_read(uint32_t address, uint8_t mode) {
58     //printf("%s read from RTG: %.8X\n", op_type_names[mode], address);
59     if (address >= PIGFX_REG_SIZE) {
60         if (rtg_mem) {
61             switch (mode) {
62                 case OP_TYPE_BYTE:
63                     return (rtg_mem[address - PIGFX_REG_SIZE]);
64                     break;
65                 case OP_TYPE_WORD:
66                     return be16toh(*(( uint16_t *) (&rtg_mem[address - PIGFX_REG_SIZE])));
67                     break;
68                 case OP_TYPE_LONGWORD:
69                     return be32toh(*(( uint32_t *) (&rtg_mem[address - PIGFX_REG_SIZE])));
70                     break;
71                 default:
72                     return 0;
73             }
74         }
75     }
76
77     return 0;
78 }
79
80 struct timespec diff(struct timespec start, struct timespec end)
81 {
82     struct timespec temp;
83     if ((end.tv_nsec-start.tv_nsec)<0) {
84         temp.tv_sec = end.tv_sec-start.tv_sec-1;
85         temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
86     } else {
87         temp.tv_sec = end.tv_sec-start.tv_sec;
88         temp.tv_nsec = end.tv_nsec-start.tv_nsec;
89     }
90     return temp;
91 }
92
93 void rtg_write(uint32_t address, uint32_t value, uint8_t mode) {
94     //printf("%s write to RTG: %.8X (%.8X)\n", op_type_names[mode], address, value);
95     if (address >= PIGFX_REG_SIZE) {
96         if (rtg_mem) {
97             switch (mode) {
98                 case OP_TYPE_BYTE:
99                     rtg_mem[address - PIGFX_REG_SIZE] = value;
100                     break;
101                 case OP_TYPE_WORD:
102                     *(( uint16_t *) (&rtg_mem[address - PIGFX_REG_SIZE])) = htobe16(value);
103                     break;
104                 case OP_TYPE_LONGWORD:
105                     *(( uint32_t *) (&rtg_mem[address - PIGFX_REG_SIZE])) = htobe32(value);
106                     break;
107                 default:
108                     return;
109             }
110         }
111     }
112     else {
113         switch (mode) {
114             case OP_TYPE_BYTE:
115                 switch (address) {
116                     case RTG_U81:
117                         rtg_u8[0] = value;
118                         break;
119                     case RTG_U82:
120                         rtg_u8[1] = value;
121                         break;
122                     case RTG_U83:
123                         rtg_u8[2] = value;
124                         break;
125                     case RTG_U84:
126                         rtg_u8[3] = value;
127                         break;
128                 }
129                 break;
130             case OP_TYPE_WORD:
131                 switch (address) {
132                     case RTG_X1:
133                         rtg_x[0] = value;
134                         break;
135                     case RTG_X2:
136                         rtg_x[1] = value;
137                         break;
138                     case RTG_X3:
139                         rtg_x[2] = value;
140                         break;
141                     case RTG_Y1:
142                         rtg_y[0] = value;
143                         break;
144                     case RTG_Y2:
145                         rtg_y[1] = value;
146                         break;
147                     case RTG_Y3:
148                         rtg_y[2] = value;
149                         break;
150                     case RTG_FORMAT:
151                         rtg_format = value;
152                         break;
153                     case RTG_COMMAND:
154                         handle_rtg_command(value);
155                         break;
156                 }
157                 break;
158             case OP_TYPE_LONGWORD:
159                 switch (address) {
160                     case RTG_ADDR1:
161                         rtg_address[0] = value;
162                         break;
163                     case RTG_ADDR2:
164                         rtg_address[1] = value;
165                         break;
166                     case RTG_RGB1:
167                         rtg_rgb[0] = value;
168                         break;
169                     case RTG_RGB2:
170                         rtg_rgb[1] = value;
171                         break;
172                 }
173                 break;
174         }
175     }
176
177     return;
178 }
179
180 static void handle_rtg_command(uint32_t cmd) {
181     //printf("Handling RTG command %d (%.8X)\n", cmd, cmd);
182     switch (cmd) {
183         case RTGCMD_SETGC:
184             rtg_display_format = rtg_format;
185             rtg_display_width = rtg_x[0];
186             rtg_display_height = rtg_y[0];
187             if (rtg_u8[0]) {
188                 rtg_pitch = rtg_x[1];
189                 rtg_total_rows = rtg_y[1];
190             }
191             else {
192                 rtg_pitch = rtg_x[1];
193                 rtg_total_rows = rtg_y[1];
194             }
195             printf("Set RTG mode:\n");
196             printf("%dx%d pixels\n", rtg_display_width, rtg_display_height);
197             printf("Pixel format: %s\n", rtg_format_names[rtg_display_format]);
198             break;
199         case RTGCMD_SETPAN:
200             //printf("Command: SetPan.\n");
201             rtg_offset_x = rtg_x[1];
202             rtg_offset_y = rtg_y[1];
203             rtg_pitch = (rtg_x[0] << rtg_display_format);
204             framebuffer_addr = rtg_address[0] - (PIGFX_RTG_BASE + PIGFX_REG_SIZE);
205             framebuffer_addr += (rtg_offset_x << rtg_display_format) + (rtg_offset_y * rtg_pitch);
206             printf("Set panning to $%.8X\n", framebuffer_addr);
207             printf("Offset X/Y: %d/%d\n", rtg_offset_x, rtg_offset_y);
208             printf("Pitch: %d (%d bytes)\n", rtg_x[0], rtg_pitch);
209             break;
210         case RTGCMD_SETCLUT: {
211             //printf("Command: SetCLUT.\n");
212             //printf("Set palette entry %d to %d, %d, %d\n", rtg_u8[0], rtg_u8[1], rtg_u8[2], rtg_u8[3]);
213             //printf("Set palette entry %d to 32-bit palette color: %.8X\n", rtg_u8[0], rtg_rgb[0]);
214             rtg_set_clut_entry(rtg_u8[0], rtg_rgb[0]);
215             break;
216         }
217         case RTGCMD_SETDISPLAY:
218             //printf("RTG SetDisplay %s\n", (rtg_u8[1]) ? "enabled" : "disabled");
219             // I remeber wrongs.
220             //printf("Command: SetDisplay.\n");
221             break;
222         case RTGCMD_ENABLE:
223         case RTGCMD_SETSWITCH:
224             printf("RTG SetSwitch %s\n", ((rtg_x[0]) & 0x01) ? "enabled" : "disabled");
225             printf("LAL: %.4X\n", rtg_x[0]);
226             if (display_enabled != ((rtg_x[0]) & 0x01)) {
227                 display_enabled = ((rtg_x[0]) & 0x01);
228                 if (display_enabled) {
229                     rtg_init_display();
230                 }
231                 else
232                     rtg_shutdown_display();
233             }
234             break;
235         case RTGCMD_FILLRECT:
236             rtg_fillrect(rtg_x[0], rtg_y[0], rtg_x[1], rtg_y[1], rtg_rgb[0], rtg_x[2], rtg_format, 0xFF);
237             break;
238     }
239 }
240
241 void rtg_fillrect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color, uint16_t pitch, uint16_t format, uint8_t mask) {
242     if (mask || pitch) {}
243     uint8_t *dptr = &rtg_mem[framebuffer_addr + (x << format) + (y * rtg_pitch)];
244     switch(format) {
245         case RTGFMT_8BIT: {
246             //printf("Incoming 8-bit color: %.8X\n", color);
247             for (int xs = 0; xs < w; xs++) {
248                 dptr[xs] = color & 0xFF;
249             }
250             break;
251         }
252         case RTGFMT_RBG565: {
253             //printf("Incoming raw 16-bit color: %.8X\n", htobe32(color));
254             color = htobe16((color & 0xFFFF));
255             //printf("Incoming 16-bit color: %.8X\n", color);
256             uint16_t *ptr = (uint16_t *)dptr;
257             for (int xs = 0; xs < w; xs++) {
258                 ptr[xs] = color;
259             }
260             break;
261         }
262         case RTGFMT_RGB32: {
263             color = htobe32(color);
264             //printf("Incoming 32-bit color: %.8X\n", color);
265             uint32_t *ptr = (uint32_t *)dptr;
266             for (int xs = 0; xs < w; xs++) {
267                 ptr[xs] = color;
268             }
269             break;
270         }
271     }
272     for (int ys = 1; ys < h; ys++) {
273         dptr += rtg_pitch;
274         memcpy(dptr, (void *)(size_t)(dptr - rtg_pitch), (w << format));
275     }
276 }