]> git.sesse.net Git - pistorm/blob - platforms/amiga/rtg/rtg-output-raylib.c
c553e2c32498f452bbbc48d7da9c420902c7f8c6
[pistorm] / platforms / amiga / rtg / rtg-output-raylib.c
1 // SPDX-License-Identifier: MIT
2
3 #include "config_file/config_file.h"
4 #include "emulator.h"
5 #include "rtg.h"
6
7 #include "raylib/raylib.h"
8
9 #include <pthread.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15
16 //#define DEBUG_RAYLIB_RTG
17
18 #define RTG_INIT_ERR(a) { printf(a); *data->running = 0; }
19
20 uint8_t busy = 0, rtg_on = 0, rtg_initialized = 0;
21 extern uint8_t *rtg_mem;
22 extern uint32_t framebuffer_addr;
23 extern uint32_t framebuffer_addr_adj;
24
25 extern uint16_t rtg_display_width, rtg_display_height;
26 extern uint16_t rtg_display_format;
27 extern uint16_t rtg_pitch, rtg_total_rows;
28 extern uint16_t rtg_offset_x, rtg_offset_y;
29
30 static pthread_t thread_id;
31
32 struct rtg_shared_data {
33     uint16_t *width, *height;
34     uint16_t *format, *pitch;
35     uint16_t *offset_x, *offset_y;
36     uint8_t *memory;
37     uint32_t *addr;
38     uint8_t *running;
39 };
40
41 struct rtg_shared_data rtg_share_data;
42 static uint32_t palette[256];
43 static uint32_t cursor_palette[256];
44
45 extern uint8_t cursor_data[256 * 256];
46
47 void rtg_update_screen() {}
48
49 uint32_t rtg_to_raylib[RTGFMT_NUM] = {
50     PIXELFORMAT_UNCOMPRESSED_GRAYSCALE,
51     PIXELFORMAT_UNCOMPRESSED_R5G6B5,
52     PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
53     PIXELFORMAT_UNCOMPRESSED_R5G5B5A1,
54 };
55
56 uint32_t rtg_pixel_size[RTGFMT_NUM] = {
57     1,
58     2,
59     4,
60     2,
61 };
62
63 void *rtgThread(void *args) {
64
65     printf("RTG thread running\n");
66     fflush(stdout);
67
68     int reinit = 0;
69     rtg_on = 1;
70
71     uint32_t *indexed_buf = NULL;
72
73     rtg_share_data.format = &rtg_display_format;
74     rtg_share_data.width = &rtg_display_width;
75     rtg_share_data.height = &rtg_display_height;
76     rtg_share_data.pitch = &rtg_pitch;
77     rtg_share_data.offset_x = &rtg_offset_x;
78     rtg_share_data.offset_y = &rtg_offset_y;
79     rtg_share_data.memory = rtg_mem;
80     rtg_share_data.running = &rtg_on;
81     rtg_share_data.addr = &framebuffer_addr_adj;
82     struct rtg_shared_data *data = &rtg_share_data;
83
84     uint16_t width = rtg_display_width;
85     uint16_t height = rtg_display_height;
86     uint16_t format = rtg_display_format;
87     uint16_t pitch = rtg_pitch;
88
89     Texture raylib_texture, raylib_cursor_texture;
90     Texture raylib_clut_texture, raylib_cursor_clut_texture;
91     Image raylib_fb, raylib_cursor, raylib_clut, raylib_cursor_clut;
92
93     InitWindow(GetScreenWidth(), GetScreenHeight(), "Pistorm RTG");
94     HideCursor();
95     SetTargetFPS(60);
96
97         Color bef = { 0, 64, 128, 255 };
98
99     Shader clut_shader = LoadShader(NULL, "platforms/amiga/rtg/clut.shader");
100     Shader swizzle_shader = LoadShader(NULL, "platforms/amiga/rtg/argbswizzle.shader");
101     int clut_loc = GetShaderLocation(clut_shader, "texture1");
102
103     raylib_clut.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
104     raylib_clut.width = 256;
105     raylib_clut.height = 1;
106     raylib_clut.mipmaps = 1;
107     raylib_clut.data = palette;
108
109     raylib_cursor_clut.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
110     raylib_cursor_clut.width = 256;
111     raylib_cursor_clut.height = 1;
112     raylib_cursor_clut.mipmaps = 1;
113     raylib_cursor_clut.data = cursor_palette;
114
115     raylib_clut_texture = LoadTextureFromImage(raylib_clut);
116     raylib_cursor_clut_texture = LoadTextureFromImage(raylib_cursor_clut);
117
118     raylib_cursor.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
119     raylib_cursor.width = 256;
120     raylib_cursor.height = 256;
121     raylib_cursor.mipmaps = 1;
122     raylib_cursor.data = cursor_data;
123     raylib_cursor_texture = LoadTextureFromImage(raylib_cursor);
124
125     Rectangle srchax, dsthax;
126     Vector2 originhax;
127
128 reinit_raylib:;
129     if (reinit) {
130         printf("Reinitializing raylib...\n");
131         width = rtg_display_width;
132         height = rtg_display_height;
133         format = rtg_display_format;
134         pitch = rtg_pitch;
135         if (indexed_buf) {
136             free(indexed_buf);
137             indexed_buf = NULL;
138         }
139         UnloadTexture(raylib_texture);
140         reinit = 0;
141     }
142
143     printf("Creating %dx%d raylib window...\n", width, height);
144
145     printf("Setting up raylib framebuffer image.\n");
146     raylib_fb.format = rtg_to_raylib[format];
147
148     switch (format) {
149         case RTGFMT_RBG565:
150             raylib_fb.width = width;
151             indexed_buf = calloc(1, width * height * 2);
152             break;
153         default:
154             raylib_fb.width = pitch / rtg_pixel_size[format];
155             break;
156     }
157     raylib_fb.height = height;
158         raylib_fb.mipmaps = 1;
159         raylib_fb.data = &data->memory[*data->addr];
160     printf("Width: %d\nPitch: %d\nBPP: %d\n", raylib_fb.width, pitch, rtg_pixel_size[format]);
161
162     raylib_texture = LoadTextureFromImage(raylib_fb);
163
164     srchax.x = srchax.y = 0;
165     srchax.width = width;
166     srchax.height = height;
167     dsthax.x = dsthax.y = 0;
168     if (GetScreenHeight() == 720) {
169         dsthax.width = 960;
170         dsthax.height = 720;
171     } else if (GetScreenHeight() == 1080) {
172         dsthax.width = 1440;
173         dsthax.height = 1080;
174     }
175     originhax.x = 0.0f;
176     originhax.y = 0.0f;
177
178     while (1) {
179         if (rtg_on) {
180             BeginDrawing();
181
182             switch (format) {
183                 case RTGFMT_8BIT:
184                     UpdateTexture(raylib_clut_texture, palette);
185                     BeginShaderMode(clut_shader);
186                     SetShaderValueTexture(clut_shader, clut_loc, raylib_clut_texture);
187                     break;
188                 case RTGFMT_RGB32:
189                     BeginShaderMode(swizzle_shader);
190                     break;
191             }
192             
193             if (width == 320) {
194                 DrawTexturePro(raylib_texture, srchax, dsthax, originhax, 0.0f, RAYWHITE);
195             }
196             else {
197                 Rectangle srcrect = { 0, 0, width, height };
198                 DrawTexturePro(raylib_texture, srcrect, srcrect, originhax, 0.0f, RAYWHITE);
199                 //DrawTexture(raylib_texture, 0, 0, RAYWHITE);
200             }
201
202             switch (format) {
203                 case RTGFMT_8BIT:
204                 case RTGFMT_RGB32:
205                     EndShaderMode();
206                     break;
207             }
208 #ifdef DEBUG_RAYLIB_RTG
209             if (format == RTGFMT_8BIT) {
210                 Rectangle srcrect = { 0, 0, 256, 1 };
211                 Rectangle dstrect = { 0, 0, 1024, 8 };
212                 //DrawTexture(raylib_clut_texture, 0, 0, RAYWHITE);
213                 DrawTexturePro(raylib_clut_texture, srcrect, dstrect, originhax, 0.0f, RAYWHITE);
214             }
215 #endif
216
217             DrawFPS(width - 200, 0);
218             EndDrawing();
219             if (format == RTGFMT_RBG565) {
220                 for (int y = 0; y < height; y++) {
221                     for (int x = 0; x < width; x++) {
222                         ((uint16_t *)indexed_buf)[x + (y * width)] = be16toh(((uint16_t *)data->memory)[(*data->addr / 2) + x + (y * (pitch / 2))]);
223                     }
224                 }
225                 UpdateTexture(raylib_texture, indexed_buf);
226             }
227             else {
228                 UpdateTexture(raylib_texture, &data->memory[*data->addr]);
229             }
230         } else {
231             BeginDrawing();
232             ClearBackground(bef);
233             DrawText("RTG is currently sleeping.", 16, 16, 12, RAYWHITE);
234             EndDrawing();
235         }
236         if (pitch != *data->pitch || height != *data->height || width != *data->width || format != *data->format) {
237             printf("Reinitializing due to something change.\n");
238             reinit = 1;
239             goto shutdown_raylib;
240         }
241         /*if (!rtg_on) {
242             goto shutdown_raylib;
243         }*/
244     }
245
246     rtg_initialized = 0;
247     printf("RTG thread shut down.\n");
248
249 shutdown_raylib:;
250
251     if (reinit)
252         goto reinit_raylib;
253
254     if (indexed_buf)
255         free(indexed_buf);
256
257     UnloadTexture(raylib_texture);
258     UnloadShader(clut_shader);
259
260     CloseWindow();
261
262     return args;
263 }
264
265 void rtg_set_clut_entry(uint8_t index, uint32_t xrgb) {
266     //palette[index] = xrgb;
267     unsigned char *src = (unsigned char *)&xrgb;
268     unsigned char *dst = (unsigned char *)&palette[index];
269     dst[0] = src[2];
270     dst[1] = src[1];
271     dst[2] = src[0];
272     dst[3] = 0xFF;
273 }
274
275 void rtg_init_display() {
276     int err;
277     rtg_on = 1;
278
279     if (!rtg_initialized) {
280         err = pthread_create(&thread_id, NULL, &rtgThread, (void *)&rtg_share_data);
281         if (err != 0) {
282             rtg_on = 0;
283             printf("can't create RTG thread :[%s]", strerror(err));
284         }
285         else {
286             rtg_initialized = 1;
287             pthread_setname_np(thread_id, "pistorm: rtg");
288             printf("RTG Thread created successfully\n");
289         }
290     }
291     printf("RTG display enabled.\n");
292 }
293
294 void rtg_shutdown_display() {
295     printf("RTG display disabled.\n");
296     rtg_on = 0;
297 }