Subversion Repositories Shiroi

Rev

Rev 5 | Rev 7 | 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 6 2024-08-28 10:29:32Z 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";
81
							} else if(strcmp(line + j + 1, "sound_mark_1") == 0) {
82
								dev = SHIROI_SOUND_MARK_I;
83
								n = "Sound Mark I";
84
							} else if(strcmp(line + j + 1, "math_mark_1") == 0) {
85
								dev = SHIROI_MATH_MARK_I;
86
								n = "Math Mark I";
3 nishi 87
							} else if(strcmp(line + j + 1, "text_mark_1") == 0) {
88
								dev = SHIROI_TEXT_MARK_I;
89
								n = "Text Mark I";
1 nishi 90
							}
91
							if(dev == -1) {
92
								fprintf(stderr, "No such device called `%s' ; ignoring\n", line + j + 1);
93
							} else {
94
								shiroi_install(&shiroi, slot, dev);
95
								printf("Installed `%s' into slot %d\n", n, slot);
96
							}
97
						}
98
						break;
99
					}
100
				}
101
			}
102
 
103
			incr = i + 1;
104
			if(oldc == 0) break;
105
		}
106
	}
107
 
108
	free(ini);
109
 
110
	shiroi_init(&shiroi);
111
 
112
	double scx = 2;
113
	double scy = 2;
114
 
115
	shiroi_card_t* videocard = shiroi_get_video_card(&shiroi);
116
	shiroi_video_t* video = NULL;
117
	if(videocard != NULL) {
118
		video = videocard->videoptr;
119
	}
3 nishi 120
	shiroi_card_t* textcard = shiroi_get_text_card(&shiroi);
121
	shiroi_text_t* text = NULL;
122
	if(textcard != NULL) {
123
		text = textcard->textptr;
124
	}
1 nishi 125
 
126
	SetTraceLogLevel(LOG_NONE);
127
	if(video != NULL) {
6 nishi 128
		InitWindow(video->width * scx + (text == NULL ? 0 : 100), video->height * scy, "Shiroi Emulator");
1 nishi 129
	} else {
6 nishi 130
		InitWindow(640 + (text == NULL ? 0 : 100), 480, "Shiroi Emulator");
1 nishi 131
	}
132
	InitAudioDevice();
133
	SetAudioStreamBufferSizeDefault(512);
134
	AudioStream as = LoadAudioStream(48000, 16, 1);
135
	SetAudioStreamCallback(as, shiroi.play_audio);
136
	SetTargetFPS(60);
137
	uint32_t* fb = NULL;
138
 
139
	if(video != NULL) {
140
		fb = malloc(sizeof(*fb) * video->width * video->height);
141
 
142
		int x, y;
143
		for(y = 0; y < video->height; y++) {
144
			for(x = 0; x < video->width; x++) {
145
				fb[y * video->width + x] = 0xffffff;
146
			}
147
		}
148
	}
149
 
150
	RenderTexture r;
151
	if(video != NULL) r = LoadRenderTexture(video->width, video->height);
152
	PlayAudioStream(as);
153
	thread_start();
154
	while(!WindowShouldClose()) {
155
		BeginDrawing();
156
 
157
		ClearBackground(BLACK);
158
 
3 nishi 159
		if(text != NULL) {
4 nishi 160
			/*
161
			 * / 1 2 3 4 5 6 7 8 9 10 11 12 13
5 nishi 162
			 * 1 1 2 3 4 5 6 7 8 9 0  -  =
4 nishi 163
			 * 2 q w e r t y u i o p  [  ]  rt
164
			 * 3 a s d f g h j k l ;  '  \  cl
165
			 * 4 z x c v b n m , . /  sp
166
			 */
167
			int c = GetKeyPressed();
5 nishi 168
			if(c == 0) {
4 nishi 169
				text->key = 0;
5 nishi 170
			} else if(KEY_ONE <= c && c <= KEY_NINE) {
4 nishi 171
				text->key = (1 << 4) | (c - KEY_ONE + 1);
5 nishi 172
			} else if(c == KEY_ZERO) {
4 nishi 173
				text->key = (1 << 4) | 10;
5 nishi 174
			} else if(c == KEY_MINUS) {
4 nishi 175
				text->key = (1 << 4) | 11;
5 nishi 176
			} else if(c == KEY_EQUAL) {
4 nishi 177
				text->key = (1 << 4) | 12;
5 nishi 178
			} else if(c == KEY_LEFT_BRACKET) {
4 nishi 179
				text->key = (2 << 4) | 11;
5 nishi 180
			} else if(c == KEY_RIGHT_BRACKET) {
4 nishi 181
				text->key = (2 << 4) | 12;
5 nishi 182
			} else if(c == KEY_ENTER) {
4 nishi 183
				text->key = (2 << 4) | 13;
5 nishi 184
			} else if(c == KEY_SEMICOLON) {
4 nishi 185
				text->key = (3 << 4) | 10;
5 nishi 186
			} else if(c == KEY_APOSTROPHE) {
4 nishi 187
				text->key = (3 << 4) | 11;
5 nishi 188
			} else if(c == KEY_BACKSLASH) {
4 nishi 189
				text->key = (3 << 4) | 12;
5 nishi 190
			} else if(c == KEY_LEFT_SHIFT || c == KEY_RIGHT_SHIFT) {
4 nishi 191
				text->key = (3 << 4) | 13;
6 nishi 192
				text->caps = !text->caps;
5 nishi 193
			} else if(c == KEY_COMMA) {
4 nishi 194
				text->key = (4 << 4) | 8;
5 nishi 195
			} else if(c == KEY_PERIOD) {
4 nishi 196
				text->key = (4 << 4) | 9;
5 nishi 197
			} else if(c == KEY_SLASH) {
4 nishi 198
				text->key = (4 << 4) | 10;
5 nishi 199
			} else if(c == KEY_SPACE) {
4 nishi 200
				text->key = (4 << 4) | 11;
5 nishi 201
			} else if(c == KEY_Q) {
4 nishi 202
				text->key = (2 << 4) | 1;
5 nishi 203
			} else if(c == KEY_W) {
4 nishi 204
				text->key = (2 << 4) | 2;
5 nishi 205
			} else if(c == KEY_E) {
4 nishi 206
				text->key = (2 << 4) | 3;
5 nishi 207
			} else if(c == KEY_R) {
4 nishi 208
				text->key = (2 << 4) | 4;
5 nishi 209
			} else if(c == KEY_T) {
4 nishi 210
				text->key = (2 << 4) | 5;
5 nishi 211
			} else if(c == KEY_Y) {
4 nishi 212
				text->key = (2 << 4) | 6;
5 nishi 213
			} else if(c == KEY_U) {
4 nishi 214
				text->key = (2 << 4) | 7;
5 nishi 215
			} else if(c == KEY_I) {
4 nishi 216
				text->key = (2 << 4) | 8;
5 nishi 217
			} else if(c == KEY_O) {
4 nishi 218
				text->key = (2 << 4) | 9;
5 nishi 219
			} else if(c == KEY_P) {
4 nishi 220
				text->key = (2 << 4) | 10;
5 nishi 221
			} else if(c == KEY_A) {
4 nishi 222
				text->key = (3 << 4) | 1;
5 nishi 223
			} else if(c == KEY_S) {
4 nishi 224
				text->key = (3 << 4) | 2;
5 nishi 225
			} else if(c == KEY_D) {
4 nishi 226
				text->key = (3 << 4) | 3;
5 nishi 227
			} else if(c == KEY_F) {
4 nishi 228
				text->key = (3 << 4) | 4;
5 nishi 229
			} else if(c == KEY_G) {
4 nishi 230
				text->key = (3 << 4) | 5;
5 nishi 231
			} else if(c == KEY_H) {
4 nishi 232
				text->key = (3 << 4) | 6;
5 nishi 233
			} else if(c == KEY_J) {
4 nishi 234
				text->key = (3 << 4) | 7;
5 nishi 235
			} else if(c == KEY_K) {
4 nishi 236
				text->key = (3 << 4) | 8;
5 nishi 237
			} else if(c == KEY_L) {
4 nishi 238
				text->key = (3 << 4) | 9;
5 nishi 239
			} else if(c == KEY_Z) {
4 nishi 240
				text->key = (4 << 4) | 1;
5 nishi 241
			} else if(c == KEY_X) {
4 nishi 242
				text->key = (4 << 4) | 2;
5 nishi 243
			} else if(c == KEY_C) {
4 nishi 244
				text->key = (4 << 4) | 3;
5 nishi 245
			} else if(c == KEY_V) {
4 nishi 246
				text->key = (4 << 4) | 4;
5 nishi 247
			} else if(c == KEY_B) {
4 nishi 248
				text->key = (4 << 4) | 5;
5 nishi 249
			} else if(c == KEY_N) {
4 nishi 250
				text->key = (4 << 4) | 6;
5 nishi 251
			} else if(c == KEY_M) {
4 nishi 252
				text->key = (4 << 4) | 7;
253
			}
3 nishi 254
		}
255
 
1 nishi 256
		if(video != NULL) {
257
			BeginTextureMode(r);
258
 
259
			int y, x;
260
			for(y = 0; y < video->height; y++) {
261
				for(x = 0; x < video->width; x++) {
262
					if(video->fb[y * video->width + x] != fb[y * TMS9918_PIXELS_X + x]) {
263
						uint32_t c = video->fb[y * video->width + x];
264
						// printf("%X\n", c);
265
						DrawPixel(x, y, (Color){(c >> 24) & 0xff, (c >> 16) & 0xff, (c >> 8) & 0xff, 0xff});
266
						fb[y * video->width + x] = c;
267
					}
268
				}
269
			}
270
 
271
			EndTextureMode();
272
 
6 nishi 273
			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 274
		} else {
275
			DrawText("No Video", 0, 0, 20, WHITE);
276
		}
277
 
6 nishi 278
		DrawText("Caps Lock", 5, 5, 10, WHITE);
279
 
280
		DrawCircle(100 - 10, 10, 5, text->caps ? RED : BLACK);
281
 
1 nishi 282
		EndDrawing();
283
	}
284
	CloseWindow();
285
	UnloadAudioStream(as);
286
	if(video != NULL) UnloadRenderTexture(r);
287
	shiroi.stop = true;
288
	thread_end();
289
}