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