Subversion Repositories Shiroi

Rev

Rev 10 | Rev 12 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 nishi 1
/* $Id: main.c 11 2024-08-29 02:49:47Z nishi $ */
2
 
3
#include <stdio.h>
4
#include <stdbool.h>
5
#include <sys/stat.h>
6
#include <stdlib.h>
7
#include <string.h>
8
 
9
#include <raylib.h>
10
 
11
#include "shiroi.h"
12
 
13
shiroi_t shiroi;
14
 
15
void thread_start(void);
16
void thread_end(void);
17
 
18
int main(int argc, char** argv) {
19
	FILE* fconf = fopen("shiroi.ini", "r");
20
	if(fconf == NULL) {
21
		printf("Creating config.\n");
22
		fconf = fopen("shiroi.ini", "w");
23
		if(fconf == NULL) {
24
			fprintf(stderr, "Failed to create config\n");
25
			return 1;
26
		}
27
		fprintf(fconf, "slot1=video_mark_1\n");
28
		fprintf(fconf, "slot2=sound_mark_1\n");
29
		fprintf(fconf, "slot3=math_mark_1\n");
3 nishi 30
		fprintf(fconf, "slot4=text_mark_1\n");
1 nishi 31
		fprintf(fconf, "rom=shiroi.rom\n");
32
		fclose(fconf);
33
	}
34
 
35
	shiroi_init_cards(&shiroi);
36
 
37
	fconf = fopen("shiroi.ini", "r");
38
 
39
	struct stat s;
40
	stat("shiroi.ini", &s);
41
 
42
	char* ini = malloc(s.st_size + 1);
43
	fread(ini, s.st_size, 1, fconf);
44
 
45
	ini[s.st_size] = 0;
46
 
47
	fclose(fconf);
48
 
49
	int incr = 0;
50
	int i;
51
	for(i = 0;; i++) {
52
		if(ini[i] == 0 || ini[i] == '\n') {
53
			char oldc = ini[i];
54
			ini[i] = 0;
55
 
56
			char* line = ini + incr;
57
 
3 nishi 58
			if(strlen(line) != 0 && line[0] != '#') {
1 nishi 59
				int j;
60
				for(j = 0; line[j] != 0; j++) {
61
					if(line[j] == '=') {
62
						line[j] = 0;
63
						if(strcmp(line, "rom") == 0) {
64
							printf("ROM: %s\n", line + j + 1);
65
							if(stat(line + j + 1, &s) != 0) {
66
								fprintf(stderr, "ROM not found\n");
67
								free(ini);
68
								return 1;
69
							}
70
							printf("ROM size: %d\n", s.st_size);
71
							FILE* f = fopen(line + j + 1, "rb");
72
							fread(shiroi.ram, s.st_size, 1, f);
73
							fclose(f);
74
						} else if(line[0] == 's' && line[1] == 'l' && line[2] == 'o' && line[3] == 't') {
75
							int slot = atoi(line + 4);
76
							const char* n = "";
77
							int dev = -1;
78
							if(strcmp(line + j + 1, "video_mark_1") == 0) {
79
								dev = SHIROI_VIDEO_MARK_I;
80
								n = "Video Mark I";
7 nishi 81
							} else if(strcmp(line + j + 1, "video_mark_2") == 0) {
82
								dev = SHIROI_VIDEO_MARK_II;
83
								n = "Video Mark II";
1 nishi 84
							} else if(strcmp(line + j + 1, "sound_mark_1") == 0) {
85
								dev = SHIROI_SOUND_MARK_I;
86
								n = "Sound Mark I";
87
							} else if(strcmp(line + j + 1, "math_mark_1") == 0) {
88
								dev = SHIROI_MATH_MARK_I;
89
								n = "Math Mark I";
3 nishi 90
							} else if(strcmp(line + j + 1, "text_mark_1") == 0) {
91
								dev = SHIROI_TEXT_MARK_I;
92
								n = "Text Mark I";
1 nishi 93
							}
94
							if(dev == -1) {
95
								fprintf(stderr, "No such device called `%s' ; ignoring\n", line + j + 1);
96
							} else {
97
								shiroi_install(&shiroi, slot, dev);
98
								printf("Installed `%s' into slot %d\n", n, slot);
99
							}
100
						}
101
						break;
102
					}
103
				}
104
			}
105
 
106
			incr = i + 1;
107
			if(oldc == 0) break;
108
		}
109
	}
110
 
111
	free(ini);
112
 
113
	shiroi_init(&shiroi);
114
 
115
	double scx = 2;
116
	double scy = 2;
117
 
118
	shiroi_card_t* videocard = shiroi_get_video_card(&shiroi);
119
	shiroi_video_t* video = NULL;
120
	if(videocard != NULL) {
121
		video = videocard->videoptr;
122
	}
3 nishi 123
	shiroi_card_t* textcard = shiroi_get_text_card(&shiroi);
124
	shiroi_text_t* text = NULL;
125
	if(textcard != NULL) {
126
		text = textcard->textptr;
127
	}
1 nishi 128
 
129
	SetTraceLogLevel(LOG_NONE);
130
	if(video != NULL) {
6 nishi 131
		InitWindow(video->width * scx + (text == NULL ? 0 : 100), video->height * scy, "Shiroi Emulator");
1 nishi 132
	} else {
6 nishi 133
		InitWindow(640 + (text == NULL ? 0 : 100), 480, "Shiroi Emulator");
1 nishi 134
	}
135
	InitAudioDevice();
136
	SetAudioStreamBufferSizeDefault(512);
137
	AudioStream as = LoadAudioStream(48000, 16, 1);
138
	SetAudioStreamCallback(as, shiroi.play_audio);
139
	SetTargetFPS(60);
140
	uint32_t* fb = NULL;
141
 
142
	if(video != NULL) {
143
		fb = malloc(sizeof(*fb) * video->width * video->height);
144
 
145
		int x, y;
146
		for(y = 0; y < video->height; y++) {
147
			for(x = 0; x < video->width; x++) {
148
				fb[y * video->width + x] = 0xffffff;
149
			}
150
		}
151
	}
152
 
153
	RenderTexture r;
154
	if(video != NULL) r = LoadRenderTexture(video->width, video->height);
155
	PlayAudioStream(as);
156
	thread_start();
157
	while(!WindowShouldClose()) {
158
		BeginDrawing();
159
 
160
		ClearBackground(BLACK);
161
 
3 nishi 162
		if(text != NULL) {
4 nishi 163
			/*
164
			 * / 1 2 3 4 5 6 7 8 9 10 11 12 13
7 nishi 165
			 * 1 1 2 3 4 5 6 7 8 9 0  -  =  bs
4 nishi 166
			 * 2 q w e r t y u i o p  [  ]  rt
167
			 * 3 a s d f g h j k l ;  '  \  cl
168
			 * 4 z x c v b n m , . /  sp
169
			 */
170
			int c = GetKeyPressed();
7 nishi 171
			if(KEY_ONE <= c && c <= KEY_NINE) {
4 nishi 172
				text->key = (1 << 4) | (c - KEY_ONE + 1);
5 nishi 173
			} else if(c == KEY_ZERO) {
4 nishi 174
				text->key = (1 << 4) | 10;
5 nishi 175
			} else if(c == KEY_MINUS) {
4 nishi 176
				text->key = (1 << 4) | 11;
5 nishi 177
			} else if(c == KEY_EQUAL) {
4 nishi 178
				text->key = (1 << 4) | 12;
7 nishi 179
			} else if(c == KEY_BACKSPACE) {
180
				text->key = (1 << 4) | 13;
5 nishi 181
			} else if(c == KEY_LEFT_BRACKET) {
4 nishi 182
				text->key = (2 << 4) | 11;
5 nishi 183
			} else if(c == KEY_RIGHT_BRACKET) {
4 nishi 184
				text->key = (2 << 4) | 12;
5 nishi 185
			} else if(c == KEY_ENTER) {
4 nishi 186
				text->key = (2 << 4) | 13;
5 nishi 187
			} else if(c == KEY_SEMICOLON) {
4 nishi 188
				text->key = (3 << 4) | 10;
5 nishi 189
			} else if(c == KEY_APOSTROPHE) {
4 nishi 190
				text->key = (3 << 4) | 11;
5 nishi 191
			} else if(c == KEY_BACKSLASH) {
4 nishi 192
				text->key = (3 << 4) | 12;
5 nishi 193
			} else if(c == KEY_LEFT_SHIFT || c == KEY_RIGHT_SHIFT) {
4 nishi 194
				text->key = (3 << 4) | 13;
6 nishi 195
				text->caps = !text->caps;
11 nishi 196
			} else if(c == KEY_F1) {
197
				if(shiroi.stop) {
198
					shiroi.stop = false;
199
					shiroi.reset = true;
200
					thread_start();
201
				} else {
202
					shiroi.reset = true;
203
					shiroi.stop = true;
204
					thread_end();
205
				}
10 nishi 206
			} else if(c == KEY_F2) {
207
				shiroi.reset = true;
5 nishi 208
			} else if(c == KEY_COMMA) {
4 nishi 209
				text->key = (4 << 4) | 8;
5 nishi 210
			} else if(c == KEY_PERIOD) {
4 nishi 211
				text->key = (4 << 4) | 9;
5 nishi 212
			} else if(c == KEY_SLASH) {
4 nishi 213
				text->key = (4 << 4) | 10;
5 nishi 214
			} else if(c == KEY_SPACE) {
4 nishi 215
				text->key = (4 << 4) | 11;
5 nishi 216
			} else if(c == KEY_Q) {
4 nishi 217
				text->key = (2 << 4) | 1;
5 nishi 218
			} else if(c == KEY_W) {
4 nishi 219
				text->key = (2 << 4) | 2;
5 nishi 220
			} else if(c == KEY_E) {
4 nishi 221
				text->key = (2 << 4) | 3;
5 nishi 222
			} else if(c == KEY_R) {
4 nishi 223
				text->key = (2 << 4) | 4;
5 nishi 224
			} else if(c == KEY_T) {
4 nishi 225
				text->key = (2 << 4) | 5;
5 nishi 226
			} else if(c == KEY_Y) {
4 nishi 227
				text->key = (2 << 4) | 6;
5 nishi 228
			} else if(c == KEY_U) {
4 nishi 229
				text->key = (2 << 4) | 7;
5 nishi 230
			} else if(c == KEY_I) {
4 nishi 231
				text->key = (2 << 4) | 8;
5 nishi 232
			} else if(c == KEY_O) {
4 nishi 233
				text->key = (2 << 4) | 9;
5 nishi 234
			} else if(c == KEY_P) {
4 nishi 235
				text->key = (2 << 4) | 10;
5 nishi 236
			} else if(c == KEY_A) {
4 nishi 237
				text->key = (3 << 4) | 1;
5 nishi 238
			} else if(c == KEY_S) {
4 nishi 239
				text->key = (3 << 4) | 2;
5 nishi 240
			} else if(c == KEY_D) {
4 nishi 241
				text->key = (3 << 4) | 3;
5 nishi 242
			} else if(c == KEY_F) {
4 nishi 243
				text->key = (3 << 4) | 4;
5 nishi 244
			} else if(c == KEY_G) {
4 nishi 245
				text->key = (3 << 4) | 5;
5 nishi 246
			} else if(c == KEY_H) {
4 nishi 247
				text->key = (3 << 4) | 6;
5 nishi 248
			} else if(c == KEY_J) {
4 nishi 249
				text->key = (3 << 4) | 7;
5 nishi 250
			} else if(c == KEY_K) {
4 nishi 251
				text->key = (3 << 4) | 8;
5 nishi 252
			} else if(c == KEY_L) {
4 nishi 253
				text->key = (3 << 4) | 9;
5 nishi 254
			} else if(c == KEY_Z) {
4 nishi 255
				text->key = (4 << 4) | 1;
5 nishi 256
			} else if(c == KEY_X) {
4 nishi 257
				text->key = (4 << 4) | 2;
5 nishi 258
			} else if(c == KEY_C) {
4 nishi 259
				text->key = (4 << 4) | 3;
5 nishi 260
			} else if(c == KEY_V) {
4 nishi 261
				text->key = (4 << 4) | 4;
5 nishi 262
			} else if(c == KEY_B) {
4 nishi 263
				text->key = (4 << 4) | 5;
5 nishi 264
			} else if(c == KEY_N) {
4 nishi 265
				text->key = (4 << 4) | 6;
5 nishi 266
			} else if(c == KEY_M) {
4 nishi 267
				text->key = (4 << 4) | 7;
268
			}
3 nishi 269
		}
270
 
1 nishi 271
		if(video != NULL) {
272
			BeginTextureMode(r);
273
 
274
			int y, x;
275
			for(y = 0; y < video->height; y++) {
276
				for(x = 0; x < video->width; x++) {
7 nishi 277
					if(video->fb[y * video->width + x] != fb[y * video->width + x]) {
1 nishi 278
						uint32_t c = video->fb[y * video->width + x];
7 nishi 279
						DrawPixel(x, y, (Color){(c >> 24) & 0xff, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff});
1 nishi 280
						fb[y * video->width + x] = c;
281
					}
282
				}
283
			}
284
 
285
			EndTextureMode();
286
 
6 nishi 287
			DrawTexturePro(r.texture, (Rectangle){0, 0, video->width, -video->height}, (Rectangle){text == NULL ? 0 : 100, 0, GetScreenWidth() - (text == NULL ? 0 : 100), GetScreenHeight()}, (Vector2){0, 0}, 0, WHITE);
1 nishi 288
		} else {
7 nishi 289
			DrawText("No Video", 0, 20, 20, WHITE);
1 nishi 290
		}
291
 
6 nishi 292
		DrawText("Caps Lock", 5, 5, 10, WHITE);
293
 
294
		DrawCircle(100 - 10, 10, 5, text->caps ? RED : BLACK);
295
 
1 nishi 296
		EndDrawing();
297
	}
298
	CloseWindow();
299
	UnloadAudioStream(as);
300
	if(video != NULL) UnloadRenderTexture(r);
301
	shiroi.stop = true;
302
	thread_end();
303
}