| ... | ... |
@@ -23,6 +23,6 @@ Uint8 audio_get_vu(int instance); |
| 23 | 23 |
Uint16 audio_get_position(int instance); |
| 24 | 24 |
int audio_render(int instance, Sint16 *sample, Sint16 *end); |
| 25 | 25 |
void audio_start(int instance, Uint8 *d, Uxn *u); |
| 26 |
-void audio_finished_handler(int instance); |
|
| 26 |
+void audio_finished_handler(int instance, void *userptr); |
|
| 27 | 27 |
void audio_handler(void *ctx, Uint8 *out_stream, int len); |
| 28 | 28 |
Uint8 audio_dei(int instance, Uint8 *d, Uint8 port); |
| ... | ... |
@@ -63,7 +63,7 @@ screen_2bpp(Uint8 *layer, Uint8 *addr, Uint16 x1, Uint16 y1, Uint16 color, int f |
| 63 | 63 |
Uint16 y, ymod = (fy < 0 ? 7 : 0), ymax = y1 + ymod + fy * 8; |
| 64 | 64 |
Uint16 x, xmod = (fx > 0 ? 7 : 0), xmax = x1 + xmod - fx * 8; |
| 65 | 65 |
for(y = y1 + ymod; y != ymax; y += fy) {
|
| 66 |
- int c = *addr++ | (*(addr + 7) << 8), row = y * w; |
|
| 66 |
+ int c = *addr | ((*(addr + 7) << 8)), row = y * w, addr=addr+1; |
|
| 67 | 67 |
if(y < h) |
| 68 | 68 |
for(x = x1 + xmod; x != xmax; x -= fx, c >>= 1) {
|
| 69 | 69 |
Uint8 ch = (c & 1) | ((c >> 7) & 2); |
| ... | ... |
@@ -154,7 +154,7 @@ screen_palette(Uint8 *addr) |
| 154 | 154 |
} |
| 155 | 155 |
|
| 156 | 156 |
void |
| 157 |
-screen_resize(Uint16 width, Uint16 height) |
|
| 157 |
+screen_resize(Uxn *u, Uint16 width, Uint16 height) |
|
| 158 | 158 |
{
|
| 159 | 159 |
Uint8 *bg, *fg; |
| 160 | 160 |
Uint32 *pixels = NULL; |
| ... | ... |
@@ -174,7 +174,7 @@ screen_resize(Uint16 width, Uint16 height) |
| 174 | 174 |
uxn_screen.pixels = pixels; |
| 175 | 175 |
uxn_screen.width = width, uxn_screen.height = height; |
| 176 | 176 |
screen_fill(uxn_screen.bg, 0), screen_fill(uxn_screen.fg, 0); |
| 177 |
- emu_resize(width, height); |
|
| 177 |
+ emu_resize(u, width, height); |
|
| 178 | 178 |
screen_change(0, 0, width, height); |
| 179 | 179 |
} |
| 180 | 180 |
|
| ... | ... |
@@ -211,18 +211,18 @@ screen_dei(Uxn *u, Uint8 addr) |
| 211 | 211 |
} |
| 212 | 212 |
|
| 213 | 213 |
void |
| 214 |
-screen_deo(Uint8 *ram, Uint8 *d, Uint8 port) |
|
| 214 |
+screen_deo(Uxn *u, Uint8 *ram, Uint8 *d, Uint8 port) |
|
| 215 | 215 |
{
|
| 216 | 216 |
Uint8 *port_x, *port_y, *port_addr; |
| 217 | 217 |
Uint16 x, y, dx, dy, dxy, dyx, addr, addr_incr; |
| 218 | 218 |
switch(port) {
|
| 219 | 219 |
case 0x3: {
|
| 220 | 220 |
Uint8 *port_width = d + 0x2; |
| 221 |
- screen_resize(PEEK2(port_width), uxn_screen.height); |
|
| 221 |
+ screen_resize(u, PEEK2(port_width), uxn_screen.height); |
|
| 222 | 222 |
} break; |
| 223 | 223 |
case 0x5: {
|
| 224 | 224 |
Uint8 *port_height = d + 0x4; |
| 225 |
- screen_resize(uxn_screen.width, PEEK2(port_height)); |
|
| 225 |
+ screen_resize(u, uxn_screen.width, PEEK2(port_height)); |
|
| 226 | 226 |
} break; |
| 227 | 227 |
case 0xe: {
|
| 228 | 228 |
Uint8 ctrl = d[0xe]; |
| ... | ... |
@@ -20,14 +20,14 @@ typedef struct UxnScreen {
|
| 20 | 20 |
} UxnScreen; |
| 21 | 21 |
|
| 22 | 22 |
extern UxnScreen uxn_screen; |
| 23 |
-extern int emu_resize(int width, int height); |
|
| 23 |
+extern int emu_resize(Uxn *u, int width, int height); |
|
| 24 | 24 |
|
| 25 | 25 |
void screen_fill(Uint8 *layer, int color); |
| 26 | 26 |
void screen_rect(Uint8 *layer, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2, int color); |
| 27 | 27 |
void screen_palette(Uint8 *addr); |
| 28 |
-void screen_resize(Uint16 width, Uint16 height); |
|
| 28 |
+void screen_resize(Uxn *u, Uint16 width, Uint16 height); |
|
| 29 | 29 |
void screen_change(Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2); |
| 30 | 30 |
void screen_redraw(Uxn *u); |
| 31 | 31 |
|
| 32 | 32 |
Uint8 screen_dei(Uxn *u, Uint8 addr); |
| 33 |
-void screen_deo(Uint8 *ram, Uint8 *d, Uint8 port); |
|
| 33 |
+void screen_deo(Uxn *u, Uint8 *ram, Uint8 *d, Uint8 port); |
| ... | ... |
@@ -31,6 +31,7 @@ |
| 31 | 31 |
|
| 32 | 32 |
/* |
| 33 | 33 |
Copyright (c) 2021-2023 Devine Lu Linvega, Andrew Alderwick |
| 34 |
+Copyright (c) 2024 Dario Rodriguez |
|
| 34 | 35 |
|
| 35 | 36 |
Permission to use, copy, modify, and distribute this software for any |
| 36 | 37 |
purpose with or without fee is hereby granted, provided that the above |
| ... | ... |
@@ -40,486 +41,686 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 40 | 41 |
WITH REGARD TO THIS SOFTWARE. |
| 41 | 42 |
*/ |
| 42 | 43 |
|
| 44 |
+#define INSTANCESSIZE 256 |
|
| 45 |
+ |
|
| 43 | 46 |
#define PAD 2 |
| 44 | 47 |
#define PAD2 4 |
| 45 | 48 |
#define WIDTH 64 * 8 |
| 46 | 49 |
#define HEIGHT 40 * 8 |
| 47 | 50 |
#define TIMEOUT_MS 334 |
| 48 | 51 |
|
| 49 |
-static SDL_Window *emu_window; |
|
| 50 |
-static SDL_Texture *emu_texture; |
|
| 51 |
-static SDL_Renderer *emu_renderer; |
|
| 52 |
-static SDL_Rect emu_viewport; |
|
| 53 |
-static SDL_AudioDeviceID audio_id; |
|
| 54 |
-static SDL_Thread *stdin_thread; |
|
| 52 |
+typedef struct video_t {
|
|
| 53 |
+ SDL_Window *emu_window; |
|
| 54 |
+ SDL_Texture *emu_texture; |
|
| 55 |
+ SDL_Renderer *emu_renderer; |
|
| 56 |
+ SDL_Rect emu_viewport; |
|
| 57 |
+ Uint32 zoom; |
|
| 58 |
+ int flag_windowcreated; |
|
| 59 |
+ int flag_fullscreen; |
|
| 60 |
+ int flag_borderless; |
|
| 61 |
+} video_t; |
|
| 62 |
+ |
|
| 63 |
+typedef struct instance_t {
|
|
| 64 |
+ video_t *video; |
|
| 65 |
+ Uint8 dev[0x100]; |
|
| 66 |
+ Uxn u; |
|
| 67 |
+ Uxn u_audio; |
|
| 68 |
+ Uint8 *ram; |
|
| 69 |
+ char *rom; |
|
| 70 |
+ SDL_AudioDeviceID audio_id; |
|
| 71 |
+ SDL_Thread *stdin_thread; |
|
| 72 |
+ Uint32 stdin_event; |
|
| 73 |
+ Uint32 audio0_event; |
|
| 74 |
+ Uint64 exec_deadline; |
|
| 75 |
+ Uint64 deadline_interval; |
|
| 76 |
+ Uint64 ms_interval; |
|
| 77 |
+} instance_t; |
|
| 78 |
+ |
|
| 79 |
+typedef struct varvara_t {
|
|
| 80 |
+ video_t video; |
|
| 81 |
+ int sizeinstances; |
|
| 82 |
+ instance_t **instances; |
|
| 83 |
+} varvara_t; |
|
| 84 |
+ |
|
| 85 |
+varvara_t *varvara_init(char *romfilename, int flag_fullscreen, int zoom); |
|
| 86 |
+void varvara_free(varvara_t *varvara); |
|
| 87 |
+ |
|
| 88 |
+instance_t *instance_init(video_t *video); |
|
| 89 |
+void instance_free(instance_t *instance); |
|
| 90 |
+ |
|
| 91 |
+ |
|
| 92 |
+/* prototypes: devices */ |
|
| 93 |
+ |
|
| 94 |
+static int clamp(int v, int min, int max); |
|
| 95 |
+static void audio_deo(instance_t *instance, int instanceno, Uint8 *d, Uint8 port, Uxn *u); |
|
| 96 |
+Uint8 emu_dei(Uxn *u, Uint8 addr); |
|
| 97 |
+void emu_deo(Uxn *u, Uint8 addr, Uint8 value); |
|
| 98 |
+ |
|
| 99 |
+/* prototypes: Handlers */ |
|
| 100 |
+ |
|
| 101 |
+void audio_finished_handler(int instance, void *userptr); |
|
| 102 |
+static int stdin_handler(void *userptr); |
|
| 103 |
+static void set_window_size(video_t *video, SDL_Window *window, int w, int h); |
|
| 104 |
+static void set_zoom(video_t *video, Uint8 z, int win); |
|
| 105 |
+static void set_flag_fullscreen(video_t *video, int value, int win); |
|
| 106 |
+static void set_flag_borderless(video_t *video, int value); |
|
| 107 |
+static void set_debugger(Uxn *u, int value); |
|
| 108 |
+ |
|
| 109 |
+/* prototypes: emulator primitives */ |
|
| 110 |
+ |
|
| 111 |
+int emu_resize(Uxn *u, int width, int height); |
|
| 112 |
+static void emu_redraw(Uxn *u); |
|
| 113 |
+static int emu_init(Uxn *u); |
|
| 114 |
+static void emu_restart(Uxn *u, char *rom, int soft); |
|
| 115 |
+static void capture_screen(Uxn *u); |
|
| 116 |
+static Uint8 get_button(SDL_Event *event); |
|
| 117 |
+static Uint8 get_button_joystick(SDL_Event *event); |
|
| 118 |
+static Uint8 get_vector_joystick(SDL_Event *event); |
|
| 119 |
+static Uint8 get_key(SDL_Event *event); |
|
| 120 |
+static int handle_events(Uxn *u); |
|
| 121 |
+static int emu_run(Uxn *u, char *rom); |
|
| 122 |
+static int emu_end(Uxn *u); |
|
| 123 |
+ |
|
| 124 |
+/* overall init/free */ |
|
| 125 |
+ |
|
| 126 |
+varvara_t * |
|
| 127 |
+varvara_init(char *romfilename, int flag_fullscreen, int zoom) |
|
| 128 |
+{
|
|
| 55 | 129 |
|
| 56 |
-/* devices */ |
|
| 130 |
+ varvara_t *varvara; |
|
| 131 |
+ if((varvara=malloc(sizeof(varvara_t)))==NULL |
|
| 132 |
+ || memset(varvara,0,sizeof(varvara_t))==NULL |
|
| 133 |
+ || (varvara->instances=malloc(sizeof(instance_t *)*INSTANCESSIZE))==NULL |
|
| 134 |
+ || memset(varvara->instances,0,sizeof(instance_t *)*INSTANCESSIZE)==NULL |
|
| 135 |
+ || (varvara->sizeinstances=INSTANCESSIZE)!=INSTANCESSIZE |
|
| 136 |
+ ) {
|
|
| 137 |
+ varvara_free(varvara),varvara=NULL; |
|
| 138 |
+ system_error("Init", "Failed to allocate varvara structs.");
|
|
| 139 |
+ return(NULL); |
|
| 140 |
+ } |
|
| 141 |
+ |
|
| 142 |
+ set_zoom(&(varvara->video),zoom, 0); |
|
| 143 |
+ set_flag_fullscreen(&(varvara->video), flag_fullscreen, 0); |
|
| 144 |
+ /* Start system. */ |
|
| 145 |
+ if((varvara->instances[0]=instance_init(&(varvara->video)))==NULL) {
|
|
| 146 |
+ varvara_free(varvara),varvara=NULL; |
|
| 147 |
+ system_error("Init", "Failed to initialize varvara unx instance.");
|
|
| 148 |
+ return NULL; |
|
| 149 |
+ } |
|
| 150 |
+ varvara->instances[0]->u.userptr=(varvara->instances[0]); |
|
| 151 |
+ varvara->instances[0]->u_audio.userptr=(varvara->instances[0]); |
|
| 152 |
+ varvara->instances[0]->u.dev = (Uint8 *)&(varvara->instances[0]->dev); |
|
| 153 |
+ varvara->instances[0]->u_audio.dev = (Uint8 *)&(varvara->instances[0]->dev); |
|
| 154 |
+ if((varvara->instances[0]->ram=(Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)))==NULL |
|
| 155 |
+ || (varvara->instances[0]->rom=(char *)malloc(strlen(romfilename)+1))==NULL |
|
| 156 |
+ || memcpy(varvara->instances[0]->rom,romfilename,strlen(romfilename)+1)==NULL |
|
| 157 |
+ || !system_init(&(varvara->instances[0]->u), varvara->instances[0]->ram, varvara->instances[0]->rom) |
|
| 158 |
+ || !system_init(&(varvara->instances[0]->u_audio), varvara->instances[0]->ram, varvara->instances[0]->rom)) {
|
|
| 159 |
+ varvara_free(varvara),varvara=NULL; |
|
| 160 |
+ system_error("Init", "Failed to initialize uxn.");
|
|
| 161 |
+ return(NULL); |
|
| 162 |
+ } |
|
| 163 |
+ if(!emu_init(&(varvara->instances[0]->u_audio))) {
|
|
| 164 |
+ varvara_free(varvara),varvara=NULL; |
|
| 165 |
+ system_error("Init", "Failed to initialize varvara.");
|
|
| 166 |
+ return NULL; |
|
| 167 |
+ } |
|
| 168 |
+ return(varvara); |
|
| 169 |
+} |
|
| 170 |
+ |
|
| 171 |
+void |
|
| 172 |
+varvara_free(varvara_t *varvara) |
|
| 173 |
+{
|
|
| 174 |
+ int i; |
|
| 175 |
+ if(varvara==NULL) |
|
| 176 |
+ return; |
|
| 177 |
+ if(varvara->instances!=NULL) {
|
|
| 178 |
+ for(i=0;i<varvara->sizeinstances;i++) {
|
|
| 179 |
+ if(varvara->instances[i]==NULL) |
|
| 180 |
+ continue; |
|
| 181 |
+ instance_free(varvara->instances[i]),varvara->instances[i]=NULL; |
|
| 182 |
+ } |
|
| 183 |
+ free(varvara->instances),varvara->instances=NULL,varvara->sizeinstances=0; |
|
| 184 |
+ } |
|
| 185 |
+ free(varvara),varvara=NULL; |
|
| 186 |
+} |
|
| 57 | 187 |
|
| 58 |
-static int window_created, fullscreen, borderless; |
|
| 59 |
-static Uint32 stdin_event, audio0_event, zoom = 1; |
|
| 60 |
-static Uint64 exec_deadline, deadline_interval, ms_interval; |
|
| 188 |
+instance_t * |
|
| 189 |
+instance_init(video_t *video) |
|
| 190 |
+{
|
|
| 191 |
+ instance_t *instance; |
|
| 192 |
+ if((instance=malloc(sizeof(instance_t)))==NULL) |
|
| 193 |
+ return(NULL); |
|
| 194 |
+ memset(instance,0,sizeof(instance_t)); |
|
| 195 |
+ instance->video=video; |
|
| 196 |
+ return(instance); |
|
| 197 |
+} |
|
| 198 |
+ |
|
| 199 |
+void |
|
| 200 |
+instance_free(instance_t *instance) |
|
| 201 |
+{
|
|
| 202 |
+ if(instance==NULL) |
|
| 203 |
+ return; |
|
| 204 |
+ if(instance->ram!=NULL) |
|
| 205 |
+ free(instance->ram),instance->ram=NULL; |
|
| 206 |
+ if(instance->rom!=NULL) |
|
| 207 |
+ free(instance->rom),instance->rom=NULL; |
|
| 208 |
+ free(instance),instance=NULL; |
|
| 209 |
+ return; |
|
| 210 |
+} |
|
| 211 |
+ |
|
| 212 |
+/* devices */ |
|
| 61 | 213 |
|
| 62 | 214 |
static int |
| 63 | 215 |
clamp(int v, int min, int max) |
| 64 | 216 |
{
|
| 65 |
- return v < min ? min : v > max ? max |
|
| 66 |
- : v; |
|
| 217 |
+ return (v<min)?min |
|
| 218 |
+ :(v>max)?max |
|
| 219 |
+ :v; |
|
| 67 | 220 |
} |
| 68 | 221 |
|
| 69 | 222 |
static void |
| 70 |
-audio_deo(int instance, Uint8 *d, Uint8 port, Uxn *u) |
|
| 223 |
+audio_deo(instance_t *instance, int instanceno, Uint8 *d, Uint8 port, Uxn *u) |
|
| 71 | 224 |
{
|
| 72 |
- if(!audio_id) return; |
|
| 73 |
- if(port == 0xf) {
|
|
| 74 |
- SDL_LockAudioDevice(audio_id); |
|
| 75 |
- audio_start(instance, d, u); |
|
| 76 |
- SDL_UnlockAudioDevice(audio_id); |
|
| 77 |
- SDL_PauseAudioDevice(audio_id, 0); |
|
| 78 |
- } |
|
| 225 |
+ if(instance==NULL) |
|
| 226 |
+ return; /* sanity check failed */ |
|
| 227 |
+ if(!instance->audio_id) return; |
|
| 228 |
+ if(port == 0xf) {
|
|
| 229 |
+ SDL_LockAudioDevice(instance->audio_id); |
|
| 230 |
+ audio_start(instanceno, d, u); |
|
| 231 |
+ SDL_UnlockAudioDevice(instance->audio_id); |
|
| 232 |
+ SDL_PauseAudioDevice(instance->audio_id, 0); |
|
| 233 |
+ } |
|
| 79 | 234 |
} |
| 80 | 235 |
|
| 81 | 236 |
Uint8 |
| 82 | 237 |
emu_dei(Uxn *u, Uint8 addr) |
| 83 | 238 |
{
|
| 84 |
- Uint8 p = addr & 0x0f, d = addr & 0xf0; |
|
| 85 |
- switch(d) {
|
|
| 86 |
- case 0x00: return system_dei(u, addr); |
|
| 87 |
- case 0x20: return screen_dei(u, addr); |
|
| 88 |
- case 0x30: return audio_dei(0, &u->dev[d], p); |
|
| 89 |
- case 0x40: return audio_dei(1, &u->dev[d], p); |
|
| 90 |
- case 0x50: return audio_dei(2, &u->dev[d], p); |
|
| 91 |
- case 0x60: return audio_dei(3, &u->dev[d], p); |
|
| 92 |
- case 0xc0: return datetime_dei(u, addr); |
|
| 93 |
- } |
|
| 94 |
- return u->dev[addr]; |
|
| 239 |
+ instance_t *instance; |
|
| 240 |
+ Uint8 p = addr & 0x0f, d = addr & 0xf0; |
|
| 241 |
+ if(u==NULL || (instance=((instance_t *)u->userptr))==NULL) |
|
| 242 |
+ return(0); /* sanity check failed */ |
|
| 243 |
+ switch(d) {
|
|
| 244 |
+ case 0x00: return system_dei(u, addr); |
|
| 245 |
+ case 0x20: return screen_dei(u, addr); |
|
| 246 |
+ case 0x30: return audio_dei(0, &u->dev[d], p); |
|
| 247 |
+ case 0x40: return audio_dei(1, &u->dev[d], p); |
|
| 248 |
+ case 0x50: return audio_dei(2, &u->dev[d], p); |
|
| 249 |
+ case 0x60: return audio_dei(3, &u->dev[d], p); |
|
| 250 |
+ case 0xc0: return datetime_dei(u, addr); |
|
| 251 |
+ } |
|
| 252 |
+ return u->dev[addr]; |
|
| 95 | 253 |
} |
| 96 | 254 |
|
| 97 | 255 |
void |
| 98 | 256 |
emu_deo(Uxn *u, Uint8 addr, Uint8 value) |
| 99 | 257 |
{
|
| 100 |
- Uint8 p = addr & 0x0f, d = addr & 0xf0; |
|
| 101 |
- u->dev[addr] = value; |
|
| 102 |
- switch(d) {
|
|
| 103 |
- case 0x00: |
|
| 104 |
- system_deo(u, &u->dev[d], p); |
|
| 105 |
- if(p > 0x7 && p < 0xe) screen_palette(&u->dev[0x8]); |
|
| 106 |
- break; |
|
| 107 |
- case 0x10: console_deo(&u->dev[d], p); break; |
|
| 108 |
- case 0x20: screen_deo(u->ram, &u->dev[d], p); break; |
|
| 109 |
- case 0x30: audio_deo(0, &u->dev[d], p, u); break; |
|
| 110 |
- case 0x40: audio_deo(1, &u->dev[d], p, u); break; |
|
| 111 |
- case 0x50: audio_deo(2, &u->dev[d], p, u); break; |
|
| 112 |
- case 0x60: audio_deo(3, &u->dev[d], p, u); break; |
|
| 113 |
- case 0xa0: file_deo(0, u->ram, &u->dev[d], p); break; |
|
| 114 |
- case 0xb0: file_deo(1, u->ram, &u->dev[d], p); break; |
|
| 115 |
- } |
|
| 258 |
+ instance_t *instance; |
|
| 259 |
+ Uint8 p = addr & 0x0f, d = addr & 0xf0; |
|
| 260 |
+ if(u==NULL || (instance=((instance_t *)u->userptr))==NULL) |
|
| 261 |
+ return; /* sanity check failed */ |
|
| 262 |
+ u->dev[addr] = value; |
|
| 263 |
+ switch(d) {
|
|
| 264 |
+ case 0x00: |
|
| 265 |
+ system_deo(u, &u->dev[d], p); |
|
| 266 |
+ if(p > 0x7 && p < 0xe) screen_palette(&u->dev[0x8]); |
|
| 267 |
+ break; |
|
| 268 |
+ case 0x10: console_deo(&u->dev[d], p); break; |
|
| 269 |
+ case 0x20: screen_deo(u, u->ram, &u->dev[d], p); break; |
|
| 270 |
+ case 0x30: audio_deo(instance, 0, &u->dev[d], p, u); break; |
|
| 271 |
+ case 0x40: audio_deo(instance, 1, &u->dev[d], p, u); break; |
|
| 272 |
+ case 0x50: audio_deo(instance, 2, &u->dev[d], p, u); break; |
|
| 273 |
+ case 0x60: audio_deo(instance, 3, &u->dev[d], p, u); break; |
|
| 274 |
+ case 0xa0: file_deo(0, u->ram, &u->dev[d], p); break; |
|
| 275 |
+ case 0xb0: file_deo(1, u->ram, &u->dev[d], p); break; |
|
| 276 |
+ } |
|
| 116 | 277 |
} |
| 117 | 278 |
|
| 118 | 279 |
/* Handlers */ |
| 119 | 280 |
|
| 120 | 281 |
void |
| 121 |
-audio_finished_handler(int instance) |
|
| 282 |
+audio_finished_handler(int instanceno, void *userptr) |
|
| 122 | 283 |
{
|
| 123 |
- SDL_Event event; |
|
| 124 |
- event.type = audio0_event + instance; |
|
| 125 |
- SDL_PushEvent(&event); |
|
| 284 |
+ instance_t *instance; |
|
| 285 |
+ SDL_Event event; |
|
| 286 |
+ if((instance=((instance_t *)userptr))==NULL) |
|
| 287 |
+ return; /* sanity check failed */ |
|
| 288 |
+ event.type = instance->audio0_event + instanceno; |
|
| 289 |
+ SDL_PushEvent(&event); |
|
| 126 | 290 |
} |
| 127 | 291 |
|
| 128 | 292 |
static int |
| 129 |
-stdin_handler(void *p) |
|
| 293 |
+stdin_handler(void *userptr) |
|
| 130 | 294 |
{
|
| 131 |
- SDL_Event event; |
|
| 132 |
- USED(p); |
|
| 133 |
- event.type = stdin_event; |
|
| 134 |
- while(read(0, &event.cbutton.button, 1) > 0 && SDL_PushEvent(&event) >= 0) |
|
| 135 |
- ; |
|
| 136 |
- return 0; |
|
| 295 |
+ instance_t *instance; |
|
| 296 |
+ SDL_Event event; |
|
| 297 |
+ if((instance=((instance_t *)userptr))==NULL) |
|
| 298 |
+ return(0); /* sanity check failed */ |
|
| 299 |
+ USED(userptr); |
|
| 300 |
+ event.type = instance->stdin_event; |
|
| 301 |
+ while(read(0, &event.cbutton.button, 1) > 0 && SDL_PushEvent(&event) >= 0) |
|
| 302 |
+ ; |
|
| 303 |
+ return 0; |
|
| 137 | 304 |
} |
| 138 | 305 |
|
| 139 | 306 |
static void |
| 140 |
-set_window_size(SDL_Window *window, int w, int h) |
|
| 307 |
+set_window_size(video_t *video, SDL_Window *window, int w, int h) |
|
| 141 | 308 |
{
|
| 142 |
- SDL_Point win_old; |
|
| 143 |
- SDL_GetWindowSize(window, &win_old.x, &win_old.y); |
|
| 144 |
- if(w == win_old.x && h == win_old.y) return; |
|
| 145 |
- SDL_RenderClear(emu_renderer); |
|
| 146 |
- SDL_SetWindowSize(window, w, h); |
|
| 309 |
+ SDL_Point win_old; |
|
| 310 |
+ if(video==NULL || window==NULL) |
|
| 311 |
+ return; /* sanity check failed */ |
|
| 312 |
+ SDL_GetWindowSize(window, &win_old.x, &win_old.y); |
|
| 313 |
+ if(w == win_old.x && h == win_old.y) return; |
|
| 314 |
+ SDL_RenderClear(video->emu_renderer); |
|
| 315 |
+ SDL_SetWindowSize(window, w, h); |
|
| 147 | 316 |
} |
| 148 | 317 |
|
| 149 | 318 |
static void |
| 150 |
-set_zoom(Uint8 z, int win) |
|
| 319 |
+set_zoom(video_t *video, Uint8 z, int win) |
|
| 151 | 320 |
{
|
| 152 |
- if(z < 1) return; |
|
| 153 |
- if(win) |
|
| 154 |
- set_window_size(emu_window, (uxn_screen.width + PAD2) * z, (uxn_screen.height + PAD2) * z); |
|
| 155 |
- zoom = z; |
|
| 321 |
+ if(video==NULL) |
|
| 322 |
+ return; /* sanity check failed */ |
|
| 323 |
+ if(z < 1) return; |
|
| 324 |
+ if(win) |
|
| 325 |
+ set_window_size(video, video->emu_window, (uxn_screen.width + PAD2) * z, (uxn_screen.height + PAD2) * z); |
|
| 326 |
+ video->zoom = z; |
|
| 156 | 327 |
} |
| 157 | 328 |
|
| 158 | 329 |
static void |
| 159 |
-set_fullscreen(int value, int win) |
|
| 330 |
+set_flag_fullscreen(video_t *video, int value, int win) |
|
| 160 | 331 |
{
|
| 161 |
- Uint32 flags = 0; /* windowed mode; SDL2 has no constant for this */ |
|
| 162 |
- fullscreen = value; |
|
| 163 |
- if(fullscreen) |
|
| 164 |
- flags = SDL_WINDOW_FULLSCREEN_DESKTOP; |
|
| 165 |
- if(win) |
|
| 166 |
- SDL_SetWindowFullscreen(emu_window, flags); |
|
| 332 |
+ Uint32 flags = 0; /* windowed mode; SDL2 has no constant for this */ |
|
| 333 |
+ if(video==NULL) |
|
| 334 |
+ return; /* sanity check failed */ |
|
| 335 |
+ video->flag_fullscreen = value; |
|
| 336 |
+ if(video->flag_fullscreen) |
|
| 337 |
+ flags = SDL_WINDOW_FULLSCREEN_DESKTOP; |
|
| 338 |
+ if(win) |
|
| 339 |
+ SDL_SetWindowFullscreen(video->emu_window, flags); |
|
| 167 | 340 |
} |
| 168 | 341 |
|
| 169 | 342 |
static void |
| 170 |
-set_borderless(int value) |
|
| 343 |
+set_flag_borderless(video_t *video, int value) |
|
| 171 | 344 |
{
|
| 172 |
- if(fullscreen) return; |
|
| 173 |
- borderless = value; |
|
| 174 |
- SDL_SetWindowBordered(emu_window, !value); |
|
| 345 |
+ if(video==NULL) |
|
| 346 |
+ return; /* sanity check failed */ |
|
| 347 |
+ if(video->flag_fullscreen) return; |
|
| 348 |
+ video->flag_borderless = value; |
|
| 349 |
+ SDL_SetWindowBordered(video->emu_window, !value); |
|
| 175 | 350 |
} |
| 176 | 351 |
|
| 177 | 352 |
static void |
| 178 | 353 |
set_debugger(Uxn *u, int value) |
| 179 | 354 |
{
|
| 180 |
- u->dev[0x0e] = value; |
|
| 181 |
- screen_fill(uxn_screen.fg, 0); |
|
| 182 |
- screen_redraw(u); |
|
| 355 |
+ u->dev[0x0e] = value; |
|
| 356 |
+ screen_fill(uxn_screen.fg, 0); |
|
| 357 |
+ screen_redraw(u); |
|
| 183 | 358 |
} |
| 184 | 359 |
|
| 185 | 360 |
/* emulator primitives */ |
| 186 | 361 |
|
| 187 | 362 |
int |
| 188 |
-emu_resize(int width, int height) |
|
| 363 |
+emu_resize(Uxn *u, int width, int height) |
|
| 189 | 364 |
{
|
| 190 |
- if(!window_created) |
|
| 191 |
- return 0; |
|
| 192 |
- if(emu_texture != NULL) |
|
| 193 |
- SDL_DestroyTexture(emu_texture); |
|
| 194 |
- SDL_RenderSetLogicalSize(emu_renderer, width + PAD2, height + PAD2); |
|
| 195 |
- emu_texture = SDL_CreateTexture(emu_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STATIC, width, height); |
|
| 196 |
- if(emu_texture == NULL || SDL_SetTextureBlendMode(emu_texture, SDL_BLENDMODE_NONE)) |
|
| 197 |
- return system_error("SDL_SetTextureBlendMode", SDL_GetError());
|
|
| 198 |
- if(SDL_UpdateTexture(emu_texture, NULL, uxn_screen.pixels, sizeof(Uint32)) != 0) |
|
| 199 |
- return system_error("SDL_UpdateTexture", SDL_GetError());
|
|
| 200 |
- emu_viewport.x = PAD; |
|
| 201 |
- emu_viewport.y = PAD; |
|
| 202 |
- emu_viewport.w = uxn_screen.width; |
|
| 203 |
- emu_viewport.h = uxn_screen.height; |
|
| 204 |
- set_window_size(emu_window, (width + PAD2) * zoom, (height + PAD2) * zoom); |
|
| 205 |
- return 1; |
|
| 365 |
+ video_t *video; |
|
| 366 |
+ if(u==NULL || u->userptr==NULL || (video=((instance_t *)u->userptr)->video)==NULL) |
|
| 367 |
+ return(0); |
|
| 368 |
+ if(!video->flag_windowcreated) |
|
| 369 |
+ return 0; |
|
| 370 |
+ if(video->emu_texture != NULL) |
|
| 371 |
+ SDL_DestroyTexture(video->emu_texture); |
|
| 372 |
+ SDL_RenderSetLogicalSize(video->emu_renderer, width + PAD2, height + PAD2); |
|
| 373 |
+ video->emu_texture = SDL_CreateTexture(video->emu_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STATIC, width, height); |
|
| 374 |
+ if(video->emu_texture == NULL || SDL_SetTextureBlendMode(video->emu_texture, SDL_BLENDMODE_NONE)) |
|
| 375 |
+ return system_error("SDL_SetTextureBlendMode", SDL_GetError());
|
|
| 376 |
+ if(SDL_UpdateTexture(video->emu_texture, NULL, uxn_screen.pixels, sizeof(Uint32)) != 0) |
|
| 377 |
+ return system_error("SDL_UpdateTexture", SDL_GetError());
|
|
| 378 |
+ video->emu_viewport.x = PAD; |
|
| 379 |
+ video->emu_viewport.y = PAD; |
|
| 380 |
+ video->emu_viewport.w = uxn_screen.width; |
|
| 381 |
+ video->emu_viewport.h = uxn_screen.height; |
|
| 382 |
+ set_window_size(video, video->emu_window, (width + PAD2) * video->zoom, (height + PAD2) * video->zoom); |
|
| 383 |
+ return 1; |
|
| 206 | 384 |
} |
| 207 | 385 |
|
| 208 | 386 |
static void |
| 209 | 387 |
emu_redraw(Uxn *u) |
| 210 | 388 |
{
|
| 211 |
- screen_redraw(u); |
|
| 212 |
- if(SDL_UpdateTexture(emu_texture, NULL, uxn_screen.pixels, uxn_screen.width * sizeof(Uint32)) != 0) |
|
| 213 |
- system_error("SDL_UpdateTexture", SDL_GetError());
|
|
| 214 |
- SDL_RenderClear(emu_renderer); |
|
| 215 |
- SDL_RenderCopy(emu_renderer, emu_texture, NULL, &emu_viewport); |
|
| 216 |
- SDL_RenderPresent(emu_renderer); |
|
| 389 |
+ video_t *video; |
|
| 390 |
+ if(u==NULL || u->userptr==NULL || (video=((instance_t *)u->userptr)->video)==NULL) |
|
| 391 |
+ return; |
|
| 392 |
+ screen_redraw(u); |
|
| 393 |
+ if(SDL_UpdateTexture(video->emu_texture, NULL, uxn_screen.pixels, uxn_screen.width * sizeof(Uint32)) != 0) |
|
| 394 |
+ system_error("SDL_UpdateTexture", SDL_GetError());
|
|
| 395 |
+ SDL_RenderClear(video->emu_renderer); |
|
| 396 |
+ SDL_RenderCopy(video->emu_renderer, video->emu_texture, NULL, &(video->emu_viewport)); |
|
| 397 |
+ SDL_RenderPresent(video->emu_renderer); |
|
| 217 | 398 |
} |
| 218 | 399 |
|
| 219 | 400 |
static int |
| 220 | 401 |
emu_init(Uxn *u) |
| 221 | 402 |
{
|
| 222 |
- SDL_AudioSpec as; |
|
| 223 |
- SDL_zero(as); |
|
| 224 |
- as.freq = SAMPLE_FREQUENCY; |
|
| 225 |
- as.format = AUDIO_S16SYS; |
|
| 226 |
- as.channels = 2; |
|
| 227 |
- as.callback = audio_handler; |
|
| 228 |
- as.samples = AUDIO_BUFSIZE; |
|
| 229 |
- as.userdata = u; |
|
| 230 |
- if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) |
|
| 231 |
- return system_error("sdl", SDL_GetError());
|
|
| 232 |
- audio_id = SDL_OpenAudioDevice(NULL, 0, &as, NULL, 0); |
|
| 233 |
- if(!audio_id) |
|
| 234 |
- system_error("sdl_audio", SDL_GetError());
|
|
| 235 |
- if(SDL_NumJoysticks() > 0 && SDL_JoystickOpen(0) == NULL) |
|
| 236 |
- system_error("sdl_joystick", SDL_GetError());
|
|
| 237 |
- stdin_event = SDL_RegisterEvents(1); |
|
| 238 |
- audio0_event = SDL_RegisterEvents(POLYPHONY); |
|
| 239 |
- SDL_DetachThread(stdin_thread = SDL_CreateThread(stdin_handler, "stdin", NULL)); |
|
| 240 |
- SDL_StartTextInput(); |
|
| 241 |
- SDL_ShowCursor(SDL_DISABLE); |
|
| 242 |
- SDL_EventState(SDL_DROPFILE, SDL_ENABLE); |
|
| 243 |
- SDL_SetRenderDrawColor(emu_renderer, 0x00, 0x00, 0x00, 0xff); |
|
| 244 |
- ms_interval = SDL_GetPerformanceFrequency() / 1000; |
|
| 245 |
- deadline_interval = ms_interval * TIMEOUT_MS; |
|
| 246 |
- exec_deadline = SDL_GetPerformanceCounter() + deadline_interval; |
|
| 247 |
- screen_resize(WIDTH, HEIGHT); |
|
| 248 |
- SDL_PauseAudioDevice(audio_id, 1); |
|
| 249 |
- return 1; |
|
| 403 |
+ instance_t *instance; |
|
| 404 |
+ SDL_AudioSpec as; |
|
| 405 |
+ if(u==NULL || (instance=((instance_t *)u->userptr))==NULL) |
|
| 406 |
+ return system_error("emu_init", "corrupted parameters");
|
|
| 407 |
+ SDL_zero(as); |
|
| 408 |
+ as.freq = SAMPLE_FREQUENCY; |
|
| 409 |
+ as.format = AUDIO_S16SYS; |
|
| 410 |
+ as.channels = 2; |
|
| 411 |
+ as.callback = audio_handler; |
|
| 412 |
+ as.samples = AUDIO_BUFSIZE; |
|
| 413 |
+ as.userdata = u; |
|
| 414 |
+ if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) |
|
| 415 |
+ return system_error("sdl", SDL_GetError());
|
|
| 416 |
+ instance->audio_id = SDL_OpenAudioDevice(NULL, 0, &as, NULL, 0); |
|
| 417 |
+ if(!instance->audio_id) |
|
| 418 |
+ system_error("sdl_audio", SDL_GetError());
|
|
| 419 |
+ if(SDL_NumJoysticks() > 0 && SDL_JoystickOpen(0) == NULL) |
|
| 420 |
+ system_error("sdl_joystick", SDL_GetError());
|
|
| 421 |
+ instance->stdin_event = SDL_RegisterEvents(1); |
|
| 422 |
+ instance->audio0_event = SDL_RegisterEvents(POLYPHONY); |
|
| 423 |
+ SDL_DetachThread(instance->stdin_thread = SDL_CreateThread(stdin_handler, "stdin", (void *)instance)); |
|
| 424 |
+ SDL_StartTextInput(); |
|
| 425 |
+ SDL_ShowCursor(SDL_DISABLE); |
|
| 426 |
+ SDL_EventState(SDL_DROPFILE, SDL_ENABLE); |
|
| 427 |
+ SDL_SetRenderDrawColor(instance->video->emu_renderer, 0x00, 0x00, 0x00, 0xff); |
|
| 428 |
+ instance->ms_interval = SDL_GetPerformanceFrequency() / 1000; |
|
| 429 |
+ instance->deadline_interval = instance->ms_interval * TIMEOUT_MS; |
|
| 430 |
+ instance->exec_deadline = SDL_GetPerformanceCounter() + instance->deadline_interval; |
|
| 431 |
+ screen_resize(u,WIDTH, HEIGHT); |
|
| 432 |
+ SDL_PauseAudioDevice(instance->audio_id, 1); |
|
| 433 |
+ return 1; |
|
| 250 | 434 |
} |
| 251 | 435 |
|
| 252 | 436 |
static void |
| 253 | 437 |
emu_restart(Uxn *u, char *rom, int soft) |
| 254 | 438 |
{
|
| 255 |
- screen_resize(WIDTH, HEIGHT); |
|
| 256 |
- screen_fill(uxn_screen.bg, 0); |
|
| 257 |
- screen_fill(uxn_screen.fg, 0); |
|
| 258 |
- system_reboot(u, rom, soft); |
|
| 259 |
- SDL_SetWindowTitle(emu_window, boot_rom); |
|
| 439 |
+ instance_t *instance; |
|
| 440 |
+ if(u==NULL || (instance=((instance_t *)u->userptr))==NULL) |
|
| 441 |
+ return; /* sanity check error */ |
|
| 442 |
+ screen_resize(u,WIDTH, HEIGHT); |
|
| 443 |
+ screen_fill(uxn_screen.bg, 0); |
|
| 444 |
+ screen_fill(uxn_screen.fg, 0); |
|
| 445 |
+ system_reboot(u, rom, soft); |
|
| 446 |
+ SDL_SetWindowTitle(instance->video->emu_window, boot_rom); |
|
| 260 | 447 |
} |
| 261 | 448 |
|
| 262 | 449 |
static void |
| 263 |
-capture_screen(void) |
|
| 450 |
+capture_screen(Uxn *u) |
|
| 264 | 451 |
{
|
| 265 |
- const Uint32 format = SDL_PIXELFORMAT_RGB24; |
|
| 452 |
+ const Uint32 format = SDL_PIXELFORMAT_RGB24; |
|
| 266 | 453 |
#if SDL_BYTEORDER == SDL_BIG_ENDIAN |
| 267 |
- /* SDL_PIXELFORMAT_RGB24 */ |
|
| 268 |
- Uint32 Rmask = 0x000000FF; |
|
| 269 |
- Uint32 Gmask = 0x0000FF00; |
|
| 270 |
- Uint32 Bmask = 0x00FF0000; |
|
| 454 |
+ /* SDL_PIXELFORMAT_RGB24 */ |
|
| 455 |
+ Uint32 Rmask = 0x000000FF; |
|
| 456 |
+ Uint32 Gmask = 0x0000FF00; |
|
| 457 |
+ Uint32 Bmask = 0x00FF0000; |
|
| 271 | 458 |
#else |
| 272 |
- /* SDL_PIXELFORMAT_BGR24 */ |
|
| 273 |
- Uint32 Rmask = 0x00FF0000; |
|
| 274 |
- Uint32 Gmask = 0x0000FF00; |
|
| 275 |
- Uint32 Bmask = 0x000000FF; |
|
| 459 |
+ /* SDL_PIXELFORMAT_BGR24 */ |
|
| 460 |
+ Uint32 Rmask = 0x00FF0000; |
|
| 461 |
+ Uint32 Gmask = 0x0000FF00; |
|
| 462 |
+ Uint32 Bmask = 0x000000FF; |
|
| 276 | 463 |
#endif |
| 277 |
- time_t t = time(NULL); |
|
| 278 |
- char fname[64]; |
|
| 279 |
- int w, h; |
|
| 280 |
- SDL_Surface *surface; |
|
| 281 |
- SDL_GetRendererOutputSize(emu_renderer, &w, &h); |
|
| 282 |
- if((surface = SDL_CreateRGBSurface(0, w, h, 24, Rmask, Gmask, Bmask, 0)) == NULL) |
|
| 283 |
- return; |
|
| 284 |
- SDL_RenderReadPixels(emu_renderer, NULL, format, surface->pixels, surface->pitch); |
|
| 285 |
- strftime(fname, sizeof(fname), "screenshot-%Y%m%d-%H%M%S.bmp", localtime(&t)); |
|
| 286 |
- if(SDL_SaveBMP(surface, fname) == 0) {
|
|
| 287 |
- fprintf(stderr, "Saved %s\n", fname); |
|
| 288 |
- fflush(stderr); |
|
| 289 |
- } |
|
| 290 |
- SDL_FreeSurface(surface); |
|
| 464 |
+ time_t t = time(NULL); |
|
| 465 |
+ char fname[64]; |
|
| 466 |
+ int w, h; |
|
| 467 |
+ SDL_Surface *surface; |
|
| 468 |
+ instance_t *instance; |
|
| 469 |
+ if(u==NULL || (instance=((instance_t *)u->userptr))==NULL) |
|
| 470 |
+ return; /* sanity check error */ |
|
| 471 |
+ SDL_GetRendererOutputSize(instance->video->emu_renderer, &w, &h); |
|
| 472 |
+ if((surface = SDL_CreateRGBSurface(0, w, h, 24, Rmask, Gmask, Bmask, 0)) == NULL) |
|
| 473 |
+ return; |
|
| 474 |
+ SDL_RenderReadPixels(instance->video->emu_renderer, NULL, format, surface->pixels, surface->pitch); |
|
| 475 |
+ strftime(fname, sizeof(fname), "screenshot-%Y%m%d-%H%M%S.bmp", localtime(&t)); |
|
| 476 |
+ if(SDL_SaveBMP(surface, fname) == 0) {
|
|
| 477 |
+ fprintf(stderr, "Saved %s\n", fname); |
|
| 478 |
+ fflush(stderr); |
|
| 479 |
+ } |
|
| 480 |
+ SDL_FreeSurface(surface); |
|
| 291 | 481 |
} |
| 292 | 482 |
|
| 293 | 483 |
static Uint8 |
| 294 | 484 |
get_button(SDL_Event *event) |
| 295 | 485 |
{
|
| 296 |
- switch(event->key.keysym.sym) {
|
|
| 297 |
- case SDLK_LCTRL: return 0x01; |
|
| 298 |
- case SDLK_LALT: return 0x02; |
|
| 299 |
- case SDLK_LSHIFT: return 0x04; |
|
| 300 |
- case SDLK_HOME: return 0x08; |
|
| 301 |
- case SDLK_UP: return 0x10; |
|
| 302 |
- case SDLK_DOWN: return 0x20; |
|
| 303 |
- case SDLK_LEFT: return 0x40; |
|
| 304 |
- case SDLK_RIGHT: return 0x80; |
|
| 305 |
- } |
|
| 306 |
- return 0x00; |
|
| 486 |
+ switch(event->key.keysym.sym) {
|
|
| 487 |
+ case SDLK_LCTRL: return 0x01; |
|
| 488 |
+ case SDLK_LALT: return 0x02; |
|
| 489 |
+ case SDLK_LSHIFT: return 0x04; |
|
| 490 |
+ case SDLK_HOME: return 0x08; |
|
| 491 |
+ case SDLK_UP: return 0x10; |
|
| 492 |
+ case SDLK_DOWN: return 0x20; |
|
| 493 |
+ case SDLK_LEFT: return 0x40; |
|
| 494 |
+ case SDLK_RIGHT: return 0x80; |
|
| 495 |
+ } |
|
| 496 |
+ return 0x00; |
|
| 307 | 497 |
} |
| 308 | 498 |
|
| 309 | 499 |
static Uint8 |
| 310 | 500 |
get_button_joystick(SDL_Event *event) |
| 311 | 501 |
{
|
| 312 |
- return 0x01 << (event->jbutton.button & 0x3); |
|
| 502 |
+ return 0x01 << (event->jbutton.button & 0x3); |
|
| 313 | 503 |
} |
| 314 | 504 |
|
| 315 | 505 |
static Uint8 |
| 316 | 506 |
get_vector_joystick(SDL_Event *event) |
| 317 | 507 |
{
|
| 318 |
- if(event->jaxis.value < -3200) |
|
| 319 |
- return 1; |
|
| 320 |
- if(event->jaxis.value > 3200) |
|
| 321 |
- return 2; |
|
| 322 |
- return 0; |
|
| 508 |
+ if(event->jaxis.value < -3200) |
|
| 509 |
+ return 1; |
|
| 510 |
+ if(event->jaxis.value > 3200) |
|
| 511 |
+ return 2; |
|
| 512 |
+ return 0; |
|
| 323 | 513 |
} |
| 324 | 514 |
|
| 325 | 515 |
static Uint8 |
| 326 | 516 |
get_key(SDL_Event *event) |
| 327 | 517 |
{
|
| 328 |
- int sym = event->key.keysym.sym; |
|
| 329 |
- SDL_Keymod mods = SDL_GetModState(); |
|
| 330 |
- if(sym < 0x20 || sym == SDLK_DELETE) |
|
| 331 |
- return sym; |
|
| 332 |
- if(mods & KMOD_CTRL) {
|
|
| 333 |
- if(sym < SDLK_a) |
|
| 334 |
- return sym; |
|
| 335 |
- else if(sym <= SDLK_z) |
|
| 336 |
- return sym - (mods & KMOD_SHIFT) * 0x20; |
|
| 337 |
- } |
|
| 338 |
- return 0x00; |
|
| 518 |
+ int sym = event->key.keysym.sym; |
|
| 519 |
+ SDL_Keymod mods = SDL_GetModState(); |
|
| 520 |
+ if(sym < 0x20 || sym == SDLK_DELETE) |
|
| 521 |
+ return sym; |
|
| 522 |
+ if(mods & KMOD_CTRL) {
|
|
| 523 |
+ if(sym < SDLK_a) |
|
| 524 |
+ return sym; |
|
| 525 |
+ else if(sym <= SDLK_z) |
|
| 526 |
+ return sym - (mods & KMOD_SHIFT) * 0x20; |
|
| 527 |
+ } |
|
| 528 |
+ return 0x00; |
|
| 339 | 529 |
} |
| 340 | 530 |
|
| 341 | 531 |
static int |
| 342 | 532 |
handle_events(Uxn *u) |
| 343 | 533 |
{
|
| 344 |
- SDL_Event event; |
|
| 345 |
- while(SDL_PollEvent(&event)) {
|
|
| 346 |
- /* Window */ |
|
| 347 |
- if(event.type == SDL_QUIT) |
|
| 348 |
- return 0; |
|
| 349 |
- else if(event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_EXPOSED) |
|
| 350 |
- emu_redraw(u); |
|
| 351 |
- else if(event.type == SDL_DROPFILE) {
|
|
| 352 |
- emu_restart(u, event.drop.file, 0); |
|
| 353 |
- SDL_free(event.drop.file); |
|
| 354 |
- } |
|
| 355 |
- /* Mouse */ |
|
| 356 |
- else if(event.type == SDL_MOUSEMOTION) |
|
| 357 |
- mouse_pos(u, &u->dev[0x90], clamp(event.motion.x - PAD, 0, uxn_screen.width - 1), clamp(event.motion.y - PAD, 0, uxn_screen.height - 1)); |
|
| 358 |
- else if(event.type == SDL_MOUSEBUTTONUP) |
|
| 359 |
- mouse_up(u, &u->dev[0x90], SDL_BUTTON(event.button.button)); |
|
| 360 |
- else if(event.type == SDL_MOUSEBUTTONDOWN) |
|
| 361 |
- mouse_down(u, &u->dev[0x90], SDL_BUTTON(event.button.button)); |
|
| 362 |
- else if(event.type == SDL_MOUSEWHEEL) |
|
| 363 |
- mouse_scroll(u, &u->dev[0x90], event.wheel.x, event.wheel.y); |
|
| 364 |
- /* Controller */ |
|
| 365 |
- else if(event.type == SDL_TEXTINPUT) |
|
| 366 |
- controller_key(u, &u->dev[0x80], event.text.text[0]); |
|
| 367 |
- else if(event.type == SDL_KEYDOWN) {
|
|
| 368 |
- int ksym; |
|
| 369 |
- if(get_key(&event)) |
|
| 370 |
- controller_key(u, &u->dev[0x80], get_key(&event)); |
|
| 371 |
- else if(get_button(&event)) |
|
| 372 |
- controller_down(u, &u->dev[0x80], get_button(&event)); |
|
| 373 |
- else if(event.key.keysym.sym == SDLK_F1) |
|
| 374 |
- set_zoom(zoom == 3 ? 1 : zoom + 1, 1); |
|
| 375 |
- else if(event.key.keysym.sym == SDLK_F2) |
|
| 376 |
- set_debugger(u, !u->dev[0x0e]); |
|
| 377 |
- else if(event.key.keysym.sym == SDLK_F3) |
|
| 378 |
- capture_screen(); |
|
| 379 |
- else if(event.key.keysym.sym == SDLK_F4) |
|
| 380 |
- emu_restart(u, boot_rom, 0); |
|
| 381 |
- else if(event.key.keysym.sym == SDLK_F5) |
|
| 382 |
- emu_restart(u, boot_rom, 1); |
|
| 383 |
- else if(event.key.keysym.sym == SDLK_F11) |
|
| 384 |
- set_fullscreen(!fullscreen, 1); |
|
| 385 |
- else if(event.key.keysym.sym == SDLK_F12) |
|
| 386 |
- set_borderless(!borderless); |
|
| 387 |
- ksym = event.key.keysym.sym; |
|
| 388 |
- if(SDL_PeepEvents(&event, 1, SDL_PEEKEVENT, SDL_KEYUP, SDL_KEYUP) == 1 && ksym == event.key.keysym.sym) |
|
| 389 |
- return 1; |
|
| 390 |
- } else if(event.type == SDL_KEYUP) |
|
| 391 |
- controller_up(u, &u->dev[0x80], get_button(&event)); |
|
| 392 |
- else if(event.type == SDL_JOYAXISMOTION) {
|
|
| 393 |
- Uint8 vec = get_vector_joystick(&event); |
|
| 394 |
- if(!vec) |
|
| 395 |
- controller_up(u, &u->dev[0x80], (3 << (!event.jaxis.axis * 2)) << 4); |
|
| 396 |
- else |
|
| 397 |
- controller_down(u, &u->dev[0x80], (1 << ((vec + !event.jaxis.axis * 2) - 1)) << 4); |
|
| 398 |
- } else if(event.type == SDL_JOYBUTTONDOWN) |
|
| 399 |
- controller_down(u, &u->dev[0x80], get_button_joystick(&event)); |
|
| 400 |
- else if(event.type == SDL_JOYBUTTONUP) |
|
| 401 |
- controller_up(u, &u->dev[0x80], get_button_joystick(&event)); |
|
| 402 |
- else if(event.type == SDL_JOYHATMOTION) {
|
|
| 403 |
- /* NOTE: Assuming there is only one joyhat in the controller */ |
|
| 404 |
- switch(event.jhat.value) {
|
|
| 405 |
- case SDL_HAT_UP: controller_down(u, &u->dev[0x80], 0x10); break; |
|
| 406 |
- case SDL_HAT_DOWN: controller_down(u, &u->dev[0x80], 0x20); break; |
|
| 407 |
- case SDL_HAT_LEFT: controller_down(u, &u->dev[0x80], 0x40); break; |
|
| 408 |
- case SDL_HAT_RIGHT: controller_down(u, &u->dev[0x80], 0x80); break; |
|
| 409 |
- case SDL_HAT_LEFTDOWN: controller_down(u, &u->dev[0x80], 0x40 | 0x20); break; |
|
| 410 |
- case SDL_HAT_LEFTUP: controller_down(u, &u->dev[0x80], 0x40 | 0x10); break; |
|
| 411 |
- case SDL_HAT_RIGHTDOWN: controller_down(u, &u->dev[0x80], 0x80 | 0x20); break; |
|
| 412 |
- case SDL_HAT_RIGHTUP: controller_down(u, &u->dev[0x80], 0x80 | 0x10); break; |
|
| 413 |
- case SDL_HAT_CENTERED: controller_up(u, &u->dev[0x80], 0x10 | 0x20 | 0x40 | 0x80); break; |
|
| 414 |
- } |
|
| 415 |
- } |
|
| 416 |
- /* Console */ |
|
| 417 |
- else if(event.type == stdin_event) |
|
| 418 |
- console_input(u, event.cbutton.button, CONSOLE_STD); |
|
| 419 |
- } |
|
| 420 |
- return 1; |
|
| 534 |
+ SDL_Event event; |
|
| 535 |
+ instance_t *instance; |
|
| 536 |
+ if(u==NULL || (instance=((instance_t *)u->userptr))==NULL) |
|
| 537 |
+ return 0; /* sanity check error */ |
|
| 538 |
+ while(SDL_PollEvent(&event)) {
|
|
| 539 |
+ /* Window */ |
|
| 540 |
+ if(event.type == SDL_QUIT) |
|
| 541 |
+ return 0; |
|
| 542 |
+ else if(event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_EXPOSED) |
|
| 543 |
+ emu_redraw(u); |
|
| 544 |
+ else if(event.type == SDL_DROPFILE) {
|
|
| 545 |
+ emu_restart(u, event.drop.file, 0); |
|
| 546 |
+ SDL_free(event.drop.file); |
|
| 547 |
+ } |
|
| 548 |
+ /* Mouse */ |
|
| 549 |
+ else if(event.type == SDL_MOUSEMOTION) |
|
| 550 |
+ mouse_pos(u, &u->dev[0x90], clamp(event.motion.x - PAD, 0, uxn_screen.width - 1), clamp(event.motion.y - PAD, 0, uxn_screen.height - 1)); |
|
| 551 |
+ else if(event.type == SDL_MOUSEBUTTONUP) |
|
| 552 |
+ mouse_up(u, &u->dev[0x90], SDL_BUTTON(event.button.button)); |
|
| 553 |
+ else if(event.type == SDL_MOUSEBUTTONDOWN) |
|
| 554 |
+ mouse_down(u, &u->dev[0x90], SDL_BUTTON(event.button.button)); |
|
| 555 |
+ else if(event.type == SDL_MOUSEWHEEL) |
|
| 556 |
+ mouse_scroll(u, &u->dev[0x90], event.wheel.x, event.wheel.y); |
|
| 557 |
+ /* Controller */ |
|
| 558 |
+ else if(event.type == SDL_TEXTINPUT) |
|
| 559 |
+ controller_key(u, &u->dev[0x80], event.text.text[0]); |
|
| 560 |
+ else if(event.type == SDL_KEYDOWN) {
|
|
| 561 |
+ int ksym; |
|
| 562 |
+ if(get_key(&event)) |
|
| 563 |
+ controller_key(u, &u->dev[0x80], get_key(&event)); |
|
| 564 |
+ else if(get_button(&event)) |
|
| 565 |
+ controller_down(u, &u->dev[0x80], get_button(&event)); |
|
| 566 |
+ else if(event.key.keysym.sym == SDLK_F1) |
|
| 567 |
+ set_zoom(instance->video,(instance->video->zoom==4)?1:(instance->video->zoom+1), 1); |
|
| 568 |
+ else if(event.key.keysym.sym == SDLK_F2) |
|
| 569 |
+ set_debugger(u, !u->dev[0x0e]); |
|
| 570 |
+ else if(event.key.keysym.sym == SDLK_F3) |
|
| 571 |
+ capture_screen(u); |
|
| 572 |
+ else if(event.key.keysym.sym == SDLK_F4) |
|
| 573 |
+ emu_restart(u, boot_rom, 0); |
|
| 574 |
+ else if(event.key.keysym.sym == SDLK_F5) |
|
| 575 |
+ emu_restart(u, boot_rom, 1); |
|
| 576 |
+ else if(event.key.keysym.sym == SDLK_F11) |
|
| 577 |
+ set_flag_fullscreen(instance->video, !instance->video->flag_fullscreen, 1); |
|
| 578 |
+ else if(event.key.keysym.sym == SDLK_F12) |
|
| 579 |
+ set_flag_borderless(instance->video, !instance->video->flag_borderless); |
|
| 580 |
+ ksym = event.key.keysym.sym; |
|
| 581 |
+ if(SDL_PeepEvents(&event, 1, SDL_PEEKEVENT, SDL_KEYUP, SDL_KEYUP) == 1 && ksym == event.key.keysym.sym) |
|
| 582 |
+ return 1; |
|
| 583 |
+ } else if(event.type == SDL_KEYUP) |
|
| 584 |
+ controller_up(u, &u->dev[0x80], get_button(&event)); |
|
| 585 |
+ else if(event.type == SDL_JOYAXISMOTION) {
|
|
| 586 |
+ Uint8 vec = get_vector_joystick(&event); |
|
| 587 |
+ if(!vec) |
|
| 588 |
+ controller_up(u, &u->dev[0x80], (3 << (!event.jaxis.axis * 2)) << 4); |
|
| 589 |
+ else |
|
| 590 |
+ controller_down(u, &u->dev[0x80], (1 << ((vec + !event.jaxis.axis * 2) - 1)) << 4); |
|
| 591 |
+ } else if(event.type == SDL_JOYBUTTONDOWN) |
|
| 592 |
+ controller_down(u, &u->dev[0x80], get_button_joystick(&event)); |
|
| 593 |
+ else if(event.type == SDL_JOYBUTTONUP) |
|
| 594 |
+ controller_up(u, &u->dev[0x80], get_button_joystick(&event)); |
|
| 595 |
+ else if(event.type == SDL_JOYHATMOTION) {
|
|
| 596 |
+ /* NOTE: Assuming there is only one joyhat in the controller */ |
|
| 597 |
+ switch(event.jhat.value) {
|
|
| 598 |
+ case SDL_HAT_UP: controller_down(u, &u->dev[0x80], 0x10); break; |
|
| 599 |
+ case SDL_HAT_DOWN: controller_down(u, &u->dev[0x80], 0x20); break; |
|
| 600 |
+ case SDL_HAT_LEFT: controller_down(u, &u->dev[0x80], 0x40); break; |
|
| 601 |
+ case SDL_HAT_RIGHT: controller_down(u, &u->dev[0x80], 0x80); break; |
|
| 602 |
+ case SDL_HAT_LEFTDOWN: controller_down(u, &u->dev[0x80], 0x40 | 0x20); break; |
|
| 603 |
+ case SDL_HAT_LEFTUP: controller_down(u, &u->dev[0x80], 0x40 | 0x10); break; |
|
| 604 |
+ case SDL_HAT_RIGHTDOWN: controller_down(u, &u->dev[0x80], 0x80 | 0x20); break; |
|
| 605 |
+ case SDL_HAT_RIGHTUP: controller_down(u, &u->dev[0x80], 0x80 | 0x10); break; |
|
| 606 |
+ case SDL_HAT_CENTERED: controller_up(u, &u->dev[0x80], 0x10 | 0x20 | 0x40 | 0x80); break; |
|
| 607 |
+ } |
|
| 608 |
+ } |
|
| 609 |
+ /* Console */ |
|
| 610 |
+ else if(event.type == instance->stdin_event) |
|
| 611 |
+ console_input(u, event.cbutton.button, CONSOLE_STD); |
|
| 612 |
+ } |
|
| 613 |
+ return 1; |
|
| 421 | 614 |
} |
| 422 | 615 |
|
| 423 | 616 |
static int |
| 424 | 617 |
emu_run(Uxn *u, char *rom) |
| 425 | 618 |
{
|
| 426 |
- Uint64 next_refresh = 0; |
|
| 427 |
- Uint64 frame_interval = SDL_GetPerformanceFrequency() / 60; |
|
| 428 |
- Uint8 *vector_addr = &u->dev[0x20]; |
|
| 429 |
- Uint32 window_flags = SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI; |
|
| 430 |
- window_created = 1; |
|
| 431 |
- if(fullscreen) |
|
| 432 |
- window_flags = window_flags | SDL_WINDOW_FULLSCREEN_DESKTOP; |
|
| 433 |
- emu_window = SDL_CreateWindow(rom, |
|
| 434 |
- SDL_WINDOWPOS_UNDEFINED, |
|
| 435 |
- SDL_WINDOWPOS_UNDEFINED, |
|
| 436 |
- (uxn_screen.width + PAD2) * zoom, |
|
| 437 |
- (uxn_screen.height + PAD2) * zoom, |
|
| 438 |
- window_flags); |
|
| 439 |
- if(emu_window == NULL) |
|
| 440 |
- return system_error("sdl_window", SDL_GetError());
|
|
| 441 |
- emu_renderer = SDL_CreateRenderer(emu_window, -1, SDL_RENDERER_ACCELERATED); |
|
| 442 |
- if(emu_renderer == NULL) |
|
| 443 |
- return system_error("sdl_renderer", SDL_GetError());
|
|
| 444 |
- emu_resize(uxn_screen.width, uxn_screen.height); |
|
| 445 |
- /* game loop */ |
|
| 446 |
- for(;;) {
|
|
| 447 |
- Uint16 screen_vector; |
|
| 448 |
- Uint64 now = SDL_GetPerformanceCounter(); |
|
| 449 |
- /* .System/halt */ |
|
| 450 |
- if(u->dev[0x0f]) |
|
| 451 |
- return system_error("Run", "Ended.");
|
|
| 452 |
- exec_deadline = now + deadline_interval; |
|
| 453 |
- if(!handle_events(u)) |
|
| 454 |
- return 0; |
|
| 455 |
- screen_vector = PEEK2(vector_addr); |
|
| 456 |
- if(now >= next_refresh) {
|
|
| 457 |
- now = SDL_GetPerformanceCounter(); |
|
| 458 |
- next_refresh = now + frame_interval; |
|
| 459 |
- uxn_eval(u, screen_vector); |
|
| 460 |
- if(uxn_screen.x2) |
|
| 461 |
- emu_redraw(u); |
|
| 462 |
- } |
|
| 463 |
- if(screen_vector || uxn_screen.x2) {
|
|
| 464 |
- Uint64 delay_ms = (next_refresh - now) / ms_interval; |
|
| 465 |
- if(delay_ms > 0) SDL_Delay(delay_ms); |
|
| 466 |
- } else |
|
| 467 |
- SDL_WaitEvent(NULL); |
|
| 468 |
- } |
|
| 619 |
+ Uint64 next_refresh = 0; |
|
| 620 |
+ Uint64 frame_interval; |
|
| 621 |
+ Uint8 *vector_addr; |
|
| 622 |
+ Uint32 window_flags = SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI; |
|
| 623 |
+ instance_t *instance; |
|
| 624 |
+ if(u==NULL || (instance=((instance_t *)u->userptr))==NULL) |
|
| 625 |
+ return system_error("Init", "emu_run parameters corrupted");
|
|
| 626 |
+ instance->video->flag_windowcreated = 1; |
|
| 627 |
+ if(u==NULL || rom==NULL || (instance=((instance_t *)u->userptr))==NULL) |
|
| 628 |
+ return system_error("Init", "emu_run parameters");
|
|
| 629 |
+ frame_interval=SDL_GetPerformanceFrequency()/60; |
|
| 630 |
+ vector_addr=&u->dev[0x20]; |
|
| 631 |
+ if(instance->video->flag_fullscreen) |
|
| 632 |
+ window_flags = window_flags | SDL_WINDOW_FULLSCREEN_DESKTOP; |
|
| 633 |
+ instance->video->emu_window = SDL_CreateWindow(rom, |
|
| 634 |
+ SDL_WINDOWPOS_UNDEFINED, |
|
| 635 |
+ SDL_WINDOWPOS_UNDEFINED, |
|
| 636 |
+ (uxn_screen.width + PAD2) * instance->video->zoom, |
|
| 637 |
+ (uxn_screen.height + PAD2) * instance->video->zoom, |
|
| 638 |
+ window_flags); |
|
| 639 |
+ if(instance->video->emu_window == NULL) |
|
| 640 |
+ return system_error("sdl_window", SDL_GetError());
|
|
| 641 |
+ instance->video->emu_renderer = SDL_CreateRenderer(instance->video->emu_window, -1, SDL_RENDERER_ACCELERATED); |
|
| 642 |
+ if(instance->video->emu_renderer == NULL) |
|
| 643 |
+ return system_error("sdl_renderer", SDL_GetError());
|
|
| 644 |
+ emu_resize(u, uxn_screen.width, uxn_screen.height); |
|
| 645 |
+ /* game loop */ |
|
| 646 |
+ for(;;) {
|
|
| 647 |
+ Uint16 screen_vector; |
|
| 648 |
+ Uint64 now = SDL_GetPerformanceCounter(); |
|
| 649 |
+ /* .System/halt */ |
|
| 650 |
+ if(u->dev[0x0f]) |
|
| 651 |
+ return system_error("Run", "Ended.");
|
|
| 652 |
+ instance->exec_deadline = now + instance->deadline_interval; |
|
| 653 |
+ if(!handle_events(u)) |
|
| 654 |
+ return 0; |
|
| 655 |
+ screen_vector = PEEK2(vector_addr); |
|
| 656 |
+ if(now >= next_refresh) {
|
|
| 657 |
+ now = SDL_GetPerformanceCounter(); |
|
| 658 |
+ next_refresh = now + frame_interval; |
|
| 659 |
+ uxn_eval(u, screen_vector); |
|
| 660 |
+ if(uxn_screen.x2) |
|
| 661 |
+ emu_redraw(u); |
|
| 662 |
+ } |
|
| 663 |
+ if(screen_vector || uxn_screen.x2) {
|
|
| 664 |
+ Uint64 delay_ms = (next_refresh - now) / instance->ms_interval; |
|
| 665 |
+ if(delay_ms > 0) SDL_Delay(delay_ms); |
|
| 666 |
+ } else |
|
| 667 |
+ SDL_WaitEvent(NULL); |
|
| 668 |
+ } |
|
| 469 | 669 |
} |
| 470 | 670 |
|
| 471 | 671 |
static int |
| 472 | 672 |
emu_end(Uxn *u) |
| 473 | 673 |
{
|
| 474 |
- SDL_CloseAudioDevice(audio_id); |
|
| 674 |
+ instance_t *instance; |
|
| 675 |
+ if(u==NULL || (instance=((instance_t *)u->userptr))==NULL) |
|
| 676 |
+ return 0; |
|
| 677 |
+ SDL_CloseAudioDevice(instance->audio_id); |
|
| 475 | 678 |
#ifdef _WIN32 |
| 476 | 679 |
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" |
| 477 |
- TerminateThread((HANDLE)SDL_GetThreadID(stdin_thread), 0); |
|
| 680 |
+ TerminateThread((HANDLE)SDL_GetThreadID(instance->stdin_thread), 0); |
|
| 478 | 681 |
#elif !defined(__APPLE__) |
| 479 |
- close(0); /* make stdin thread exit */ |
|
| 682 |
+ close(0); /* make stdin thread exit */ |
|
| 480 | 683 |
#endif |
| 481 |
- SDL_Quit(); |
|
| 482 |
- free(u->ram); |
|
| 483 |
- return u->dev[0x0f] & 0x7f; |
|
| 684 |
+ SDL_Quit(); |
|
| 685 |
+ free(u->ram); |
|
| 686 |
+ return u->dev[0x0f] & 0x7f; |
|
| 484 | 687 |
} |
| 485 | 688 |
|
| 486 | 689 |
int |
| 487 | 690 |
main(int argc, char **argv) |
| 488 | 691 |
{
|
| 489 |
- Uint8 *ram; |
|
| 490 |
- char *rom; |
|
| 491 |
- Uint8 dev[0x100] = {0};
|
|
| 492 |
- Uxn u = {0}, u_audio = {0};
|
|
| 493 |
- u.dev = (Uint8 *)&dev; |
|
| 494 |
- u_audio.dev = (Uint8 *)&dev; |
|
| 495 |
- int i = 1; |
|
| 496 |
- if(i == argc) |
|
| 497 |
- return system_error("usage", "uxnemu [-v] | uxnemu [-f | -2x | -3x | --] file.rom [args...]");
|
|
| 498 |
- /* Read flag. Right now, there can be only one. */ |
|
| 499 |
- if(argv[i][0] == '-') {
|
|
| 500 |
- if(argv[i][1] == 'v') |
|
| 501 |
- return system_version("Uxnemu - Graphical Varvara Emulator", "18 Dec 2023");
|
|
| 502 |
- if(argv[i][1] == '-') |
|
| 503 |
- i++; |
|
| 504 |
- if(strcmp(argv[i], "-2x") == 0 || strcmp(argv[i], "-3x") == 0) |
|
| 505 |
- set_zoom(argv[i++][1] - '0', 0); |
|
| 506 |
- if(strcmp(argv[i], "-f") == 0) {
|
|
| 507 |
- i++; |
|
| 508 |
- set_fullscreen(1, 0); |
|
| 509 |
- } |
|
| 510 |
- } |
|
| 511 |
- /* Start system. */ |
|
| 512 |
- ram = (Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)); |
|
| 513 |
- rom = argv[i++]; |
|
| 514 |
- if(!system_init(&u, ram, rom) || !system_init(&u_audio, ram, rom)) |
|
| 515 |
- return system_error("Init", "Failed to initialize uxn.");
|
|
| 516 |
- if(!emu_init(&u_audio)) |
|
| 517 |
- return system_error("Init", "Failed to initialize varvara.");
|
|
| 518 |
- /* Game Loop */ |
|
| 519 |
- u.dev[0x17] = argc - i; |
|
| 520 |
- if(uxn_eval(&u, PAGE_PROGRAM)) {
|
|
| 521 |
- console_listen(&u, i, argc, argv); |
|
| 522 |
- emu_run(&u, boot_rom); |
|
| 523 |
- } |
|
| 524 |
- return emu_end(&u); |
|
| 692 |
+ int zoom; |
|
| 693 |
+ int flag_fullscreen; |
|
| 694 |
+ char *rom; |
|
| 695 |
+ varvara_t *varvara; |
|
| 696 |
+ int i; |
|
| 697 |
+ |
|
| 698 |
+ zoom=1; |
|
| 699 |
+ flag_fullscreen=0; |
|
| 700 |
+ i = 1; |
|
| 701 |
+ if(i == argc) |
|
| 702 |
+ return system_error("usage", "uxn256emu [-v] | uxnemu [-f | -2x | -3x | --] file.rom [args...]");
|
|
| 703 |
+ /* Read flag. Right now, there can be only one. */ |
|
| 704 |
+ if(argv[i][0] == '-') {
|
|
| 705 |
+ if(argv[i][1] == 'v') |
|
| 706 |
+ return system_version("Uxn256emu - Graphical Varvara256 Emulator", "31 Dec 2023");
|
|
| 707 |
+ if(argv[i][1] == '-') |
|
| 708 |
+ i++; |
|
| 709 |
+ if(strcmp(argv[i], "-2x") == 0 || strcmp(argv[i], "-3x") == 0 || strcmp(argv[i], "-4x") == 0 ) |
|
| 710 |
+ zoom=argv[i++][1] - '0'; |
|
| 711 |
+ if(strcmp(argv[i], "-f") == 0) {
|
|
| 712 |
+ i++; |
|
| 713 |
+ flag_fullscreen=1; |
|
| 714 |
+ } |
|
| 715 |
+ } |
|
| 716 |
+ rom = argv[i++]; |
|
| 717 |
+ if((varvara=varvara_init(rom,flag_fullscreen,zoom))==NULL) |
|
| 718 |
+ return system_error("init", "Couln't init varvara256");
|
|
| 719 |
+ /* Game Loop */ |
|
| 720 |
+ varvara->instances[0]->u.dev[0x17] = argc - i; |
|
| 721 |
+ if(uxn_eval(&(varvara->instances[0]->u), PAGE_PROGRAM)) {
|
|
| 722 |
+ console_listen(&(varvara->instances[0]->u), i, argc, argv); |
|
| 723 |
+ emu_run(&(varvara->instances[0]->u), boot_rom); |
|
| 724 |
+ } |
|
| 725 |
+ return emu_end(&(varvara->instances[0]->u)); |
|
| 525 | 726 |
} |