Browse Source

[psp] initial port

master
Adrian Siekierka 1 month ago
parent
commit
c8b6b57b98
10 changed files with 660 additions and 3 deletions
  1. 35
    0
      Makefile
  2. 40
    0
      Makefile.psp
  3. BIN
      res/6x10.png
  4. BIN
      res/6x8.png
  5. BIN
      res/psp-icon0.png
  6. 1
    1
      src/frontend_curses_tables.c
  7. 61
    0
      src/frontend_null.c
  8. 495
    0
      src/frontend_psp.c
  9. 2
    2
      src/zzt.c
  10. 26
    0
      tools/psp-font2raw.py

+ 35
- 0
Makefile View File

@@ -0,0 +1,35 @@
1
+OBJDIR = obj
2
+RESDIR = res
3
+SRCDIR = src
4
+BUILDDIR = build
5
+
6
+CC = gcc
7
+CFLAGS = -g -O2 -flto -std=c11 -Wall
8
+LDFLAGS = -g -O2
9
+LIBS = -lGL -lSDL2 -lSDL2main
10
+TARGET = $(BUILDDIR)/zeta86
11
+
12
+OBJS =	$(OBJDIR)/8x14.o \
13
+	\
14
+	$(OBJDIR)/cpu.o \
15
+	$(OBJDIR)/zzt.o \
16
+	$(OBJDIR)/audio_stream.o \
17
+	\
18
+	$(OBJDIR)/posix_vfs.o \
19
+	$(OBJDIR)/frontend_sdl.o \
20
+	$(OBJDIR)/render_software.o \
21
+	$(OBJDIR)/screenshot_writer.o
22
+
23
+all: $(TARGET)
24
+
25
+$(TARGET): $(OBJS)
26
+	$(CC) -o $@ $(LDFLAGS) $(LIBS) $(OBJS)
27
+
28
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
29
+	$(CC) $(CFLAGS) -c -o $@ $<
30
+
31
+$(OBJDIR)/8x14.o: $(OBJDIR)/8x14.c
32
+	$(CC) -g -c -o $@ $<
33
+
34
+$(OBJDIR)/8x14.c: $(RESDIR)/8x14.bin
35
+	xxd -i $< > $@

+ 40
- 0
Makefile.psp View File

@@ -0,0 +1,40 @@
1
+OBJDIR = obj
2
+RESDIR = res
3
+SRCDIR = src
4
+TOOLSDIR = tools
5
+BUILDDIR = build
6
+
7
+LIBS = -lpsputility -lpsppower -lpspaudiolib -lpspaudio -lpspgum -lpspgu -lm
8
+CFLAGS = -g -O3 -std=c11 -Wall -DHAS_OSK
9
+LDFLAGS = -g -O3
10
+TARGET = $(BUILDDIR)/zeta86-psp
11
+EXTRA_TARGETS = EBOOT.PBP
12
+PSP_EBOOT_TITLE = Zeta
13
+PSP_EBOOT_ICON = $(RESDIR)/psp-icon0.png
14
+
15
+OBJS =	$(OBJDIR)/6x10_psp.o \
16
+	$(OBJDIR)/8x14.o \
17
+	\
18
+	$(OBJDIR)/cpu.o \
19
+	$(OBJDIR)/zzt.o \
20
+	$(OBJDIR)/audio_stream.o \
21
+	\
22
+	$(OBJDIR)/posix_vfs.o \
23
+	$(OBJDIR)/frontend_psp.o
24
+
25
+PSPSDK = $(shell psp-config --pspsdk-path)
26
+include $(PSPSDK)/lib/build.mak
27
+
28
+all: $(EXTRA_TARGETS)
29
+
30
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
31
+	$(CC) $(CFLAGS) -c -o $@ $<
32
+
33
+$(OBJDIR)/8x14.c: $(RESDIR)/8x14.bin
34
+	xxd -i $< > $@
35
+
36
+$(OBJDIR)/6x10_psp.c: $(OBJDIR)/6x10_psp.bin
37
+	bin2c $< $@ obj_6x10_psp_bin
38
+
39
+$(OBJDIR)/6x10_psp.bin: $(RESDIR)/6x10.png $(TOOLSDIR)/psp-font2raw.py
40
+	python3 $(TOOLSDIR)/psp-font2raw.py $(RESDIR)/6x10.png $@

BIN
res/6x10.png View File


BIN
res/6x8.png View File


BIN
res/psp-icon0.png View File


+ 1
- 1
src/frontend_curses_tables.c View File

@@ -19,7 +19,7 @@
19 19
 
20 20
 static u8 map_char_to_key[512];
21 21
 
22
-static void init_map_char_to_key() {
22
+static void init_map_char_to_key(void) {
23 23
 	map_char_to_key[258] = 0x50; // down
24 24
 	map_char_to_key[260] = 0x4B; // left
25 25
 	map_char_to_key[259] = 0x48; // up

+ 61
- 0
src/frontend_null.c View File

@@ -0,0 +1,61 @@
1
+/**
2
+ * Copyright (c) 2018, 2019 Adrian Siekierka
3
+ *
4
+ * This file is part of Zeta.
5
+ *
6
+ * Zeta is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * Zeta is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with Zeta.  If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#include <stdio.h>
21
+#include <stdlib.h>
22
+#include <string.h>
23
+#include <time.h>
24
+#include "zzt.h"
25
+#include "posix_vfs.h"
26
+
27
+long zeta_time_ms() {
28
+	clock_t c = clock();
29
+	return c / (CLOCKS_PER_SEC/1000);
30
+}
31
+
32
+void cpu_ext_log(const char* s) {
33
+	fprintf(stderr, "%s\n", s);
34
+}
35
+
36
+void speaker_on(double freq) {}
37
+void speaker_off() {}
38
+
39
+int zeta_has_feature(int feature) {
40
+	return 1;
41
+}
42
+
43
+int main(int argc, char** argv) {
44
+	init_posix_vfs("vfs/");
45
+	zzt_init(argc > 1 ? argv[1] : "");
46
+
47
+	clock_t last = clock();
48
+	clock_t curr = last;
49
+
50
+	while (zzt_execute(1)) {
51
+		usleep(50000);
52
+		//zzt_mark_frame();
53
+
54
+		curr = clock();
55
+/*		float secs = (float) (curr - last) / CLOCKS_PER_SEC;
56
+		fprintf(stderr, "%.2f opc/sec\n", 1600000.0f / secs); */
57
+		last = curr;
58
+
59
+		//zzt_mark_timer();
60
+	}
61
+}

+ 495
- 0
src/frontend_psp.c View File

@@ -0,0 +1,495 @@
1
+/**
2
+ * Copyright (c) 2018, 2019 Adrian Siekierka
3
+ *
4
+ * This file is part of Zeta.
5
+ *
6
+ * Zeta is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * Zeta is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with Zeta.  If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#include <stdio.h>
21
+#include <stdlib.h>
22
+#include <string.h>
23
+#include <time.h>
24
+
25
+#include "zzt.h"
26
+#include "posix_vfs.h"
27
+#include "audio_stream.h"
28
+
29
+#include <pspkernel.h>
30
+#include <pspgu.h>
31
+#include <pspgum.h>
32
+#include <pspdisplay.h>
33
+#include <pspctrl.h>
34
+#include <pspaudio.h>
35
+#include <pspaudiolib.h>
36
+#include <psppower.h>
37
+#include <psputility.h>
38
+
39
+static u32 __attribute__((aligned(16))) gu_clut4[16];
40
+static u32 __attribute__((aligned(16))) gu_list[262144];
41
+static u32 palette_colors[16];
42
+
43
+#include "frontend_curses_tables.c"
44
+#include "../obj/6x10_psp.c"
45
+
46
+PSP_MODULE_INFO("Zeta", 0, 1, 1);
47
+PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);
48
+
49
+long zeta_time_ms(void) {
50
+	clock_t c = clock();
51
+	return c / (CLOCKS_PER_SEC/1000);
52
+}
53
+
54
+void cpu_ext_log(const char* s) {
55
+	fprintf(stderr, "%s\n", s);
56
+}
57
+
58
+int zeta_has_feature(int feature) {
59
+	return 1;
60
+}
61
+
62
+void zeta_update_charset(int width, int height, u8* data) {
63
+}
64
+
65
+void zeta_update_palette(u32* data) {
66
+	for (int i = 0; i < 16; i++) {
67
+		palette_colors[i] = (data[i] & 0xFF00) | ((data[i] >> 16) & 0xFF) | ((data[i] & 0xFF) << 16) | 0xFF000000;
68
+	}
69
+}
70
+
71
+typedef struct {
72
+	u32 color;
73
+	u16 x, y, z, v_pad;
74
+} point_bg;
75
+
76
+typedef struct {
77
+	u16 u, v;
78
+	u32 color;
79
+	u16 x, y, z, v_pad;
80
+} point_fg;
81
+
82
+#define FRAME_Y_OFFSET ((272-250)/2)
83
+
84
+int psp_exit_cb(int a1, int a2, void *a3) {
85
+	sceKernelExitGame();
86
+	return 0;
87
+}
88
+
89
+int psp_exit_thread(SceSize args, void *argp) {
90
+	int cbid = sceKernelCreateCallback("exit callback", (void*) psp_exit_cb, NULL);
91
+	sceKernelRegisterExitCallback(cbid);
92
+	sceKernelSleepThreadCB();
93
+	return 0;
94
+}
95
+
96
+static int zzt_thread_running = 1;
97
+static long timer_last_ms;
98
+
99
+int psp_zzt_thread(SceSize args, void *argp) {
100
+	int opcodes = 1000;
101
+
102
+	timer_last_ms = zeta_time_ms();
103
+	while (zzt_thread_running) {
104
+		long duration = zeta_time_ms();
105
+		int rcode = zzt_execute(opcodes);
106
+		long timer_curr_ms = zeta_time_ms();
107
+		duration = timer_curr_ms - duration;
108
+		if (rcode == STATE_CONTINUE) {
109
+			if (duration < 2) {
110
+				opcodes = (opcodes * 20 / 19);
111
+			} else if (duration > 4) {
112
+				opcodes = (opcodes * 19 / 20);
113
+			}
114
+		}
115
+		if (rcode == STATE_END) {
116
+			zzt_thread_running = 0;
117
+		}
118
+
119
+		sceKernelDelayThreadCB(1);
120
+	}
121
+
122
+	return 0;
123
+}
124
+
125
+static long first_timer_tick;
126
+static double timer_time;
127
+
128
+static u16 osk_text[65];
129
+static int osk_text_pos = 0;
130
+static int osk_counter = 0;
131
+
132
+int psp_timer_thread(SceSize args, void *argp) {
133
+	while (zzt_thread_running) {
134
+		long curr_timer_tick = zeta_time_ms();
135
+		zzt_mark_timer();
136
+
137
+		timer_time += SYS_TIMER_TIME;
138
+		long duration = curr_timer_tick - first_timer_tick;
139
+		long tick_time = ((long) (timer_time + SYS_TIMER_TIME)) - duration;
140
+
141
+		while (tick_time <= 0) {
142
+			zzt_mark_timer();
143
+			timer_time += SYS_TIMER_TIME;
144
+			tick_time = ((long) (timer_time + SYS_TIMER_TIME)) - duration;
145
+		}
146
+
147
+		osk_counter = (osk_counter + 1) % 3;
148
+		if (osk_counter == 0 && osk_text[0] != 0) {
149
+			u16 chr = osk_text[osk_text_pos++];
150
+			if (chr == 0) {
151
+				osk_text[0] = 0;
152
+				osk_text_pos = 0;
153
+				zzt_key(13, 0x1C);
154
+				zzt_keyup(0x1C);
155
+			} else {
156
+				if (chr >= 32 && chr <= 127) {
157
+					zzt_key(chr, map_char_to_key[chr]);
158
+					zzt_keyup(map_char_to_key[chr]);
159
+				}
160
+			}
161
+		}
162
+
163
+		sceKernelDelayThreadCB(tick_time * 1000);
164
+	}
165
+
166
+	return 0;
167
+}
168
+
169
+static void psp_timer_init(void) {
170
+	int thid = sceKernelCreateThread("timer", psp_timer_thread, 0x11, 0xFA0, PSP_THREAD_ATTR_USER, NULL);
171
+	if (thid >= 0) {
172
+		sceKernelStartThread(thid, 0, 0);
173
+	}
174
+}
175
+
176
+static int psp_is_blink_phase(long curr_time) {
177
+	return ((curr_time % (BLINK_TOGGLE_DURATION_MS*2)) >= BLINK_TOGGLE_DURATION_MS);
178
+}
179
+
180
+static void psp_draw_frame(void) {
181
+	sceGuStart(GU_DIRECT, gu_list);
182
+
183
+	// draw 2000 BG cells
184
+	point_bg *bg_cells = sceGuGetMemory(sizeof(point_bg) * 4000);
185
+	// draw 2000 FG cells
186
+	point_fg *fg_cells = sceGuGetMemory(sizeof(point_fg) * 4000);
187
+	point_bg *bg_cells_origin = bg_cells;
188
+	point_fg *fg_cells_origin = fg_cells;
189
+
190
+	u8* ram = zzt_get_ram();
191
+	int i = 0;
192
+	int should_blink = psp_is_blink_phase(zeta_time_ms());
193
+
194
+	for (int y = 0; y < 25; y++) {
195
+		u16 cy0 = y*10+FRAME_Y_OFFSET;
196
+		u16 cy1 = (y+1)*10+FRAME_Y_OFFSET;
197
+		for (int x = 0; x < 80; x++, i+=2) {
198
+			u8 chr = ram[TEXT_ADDR(x,y)];
199
+			u8 col = ram[TEXT_ADDR(x,y)+1];
200
+			int should_blink_now = 0;
201
+			if (col >= 0x80) {
202
+				col &= 0x7F;
203
+				should_blink_now = should_blink;
204
+			}
205
+			u32 bg_col = palette_colors[col >> 4];
206
+			u32 fg_col = palette_colors[col & 0xF];
207
+			u16 cx0 = x*6;
208
+			u16 cx1 = (x+1)*6;
209
+			u32 cu = (chr & 31)<<3;
210
+			u32 cv = (chr >> 5)<<4;
211
+
212
+			bg_cells[0].color = bg_col;
213
+			bg_cells[0].x = cx0;
214
+			bg_cells[0].y = cy0;
215
+			bg_cells[0].z = 0;
216
+			bg_cells[1].color = bg_col;
217
+			bg_cells[1].x = cx1;
218
+			bg_cells[1].y = cy1;
219
+			bg_cells[1].z = 0;
220
+			bg_cells += 2;
221
+
222
+			if (!should_blink_now && ((col ^ (col >> 4)) & 0x0F) && chr != 0 && chr != 32) {
223
+				fg_cells[0].u = cu;
224
+				fg_cells[0].v = cv;
225
+				fg_cells[0].color = fg_col;
226
+				fg_cells[0].x = cx0;
227
+				fg_cells[0].y = cy0;
228
+				fg_cells[0].z = 0;
229
+				fg_cells[1].u = cu+6;
230
+				fg_cells[1].v = cv+10;
231
+				fg_cells[1].color = fg_col;
232
+				fg_cells[1].x = cx1;
233
+				fg_cells[1].y = cy1;
234
+				fg_cells[1].z = 0;
235
+				fg_cells += 2;
236
+			}
237
+		}
238
+	}
239
+
240
+	sceGuDisable(GU_TEXTURE_2D);
241
+ 	sceGumDrawArray(GU_SPRITES, GU_COLOR_8888 | GU_VERTEX_16BIT | GU_TRANSFORM_2D, (bg_cells - bg_cells_origin), 0, bg_cells_origin);
242
+	sceGuEnable(GU_TEXTURE_2D);
243
+	sceGumDrawArray(GU_SPRITES, GU_TEXTURE_16BIT | GU_COLOR_8888 | GU_VERTEX_16BIT | GU_TRANSFORM_2D, (fg_cells - fg_cells_origin), 0, fg_cells_origin);
244
+
245
+	sceGuFinish();
246
+	sceGuSync(0, 0);
247
+
248
+	sceDisplayWaitVblankStartCB();
249
+	sceGuSwapBuffers();
250
+
251
+	zzt_mark_frame();
252
+}
253
+
254
+void psp_audio_callback(void *stream, unsigned int len, void *userdata) {
255
+	u8 *stream_u8 = ((u8*) stream) + (len * 3);
256
+	s16 *stream_s16 = ((s16*) stream);
257
+
258
+	audio_stream_generate_u8(zeta_time_ms(), stream_u8, len);
259
+	for (int i = 0; i < len; i++, stream_u8++, stream_s16+=2) {
260
+		s32 val = (((s32) stream_u8[0]) << 8) - 0x8000;
261
+		stream_s16[0] = (s16) val;
262
+		stream_s16[1] = (s16) val;
263
+	}
264
+}
265
+
266
+void speaker_on(double freq) {
267
+	audio_stream_append_on(zeta_time_ms(), freq);
268
+}
269
+
270
+void speaker_off(void) {
271
+	audio_stream_append_off(zeta_time_ms());
272
+}
273
+
274
+int main(int argc, char** argv) {
275
+	SceCtrlData pad;
276
+	u32 last_buttons = 0;
277
+
278
+	{
279
+		init_posix_vfs("");
280
+		zzt_init();
281
+
282
+		int exeh = vfs_open("zzt.exe", 0);
283
+		if (exeh < 0) return -1;
284
+		zzt_load_binary(exeh, "");
285
+		vfs_close(exeh);
286
+
287
+		zzt_set_timer_offset((time(NULL) % 86400) * 1000L);
288
+		zzt_key('k', 0x25);
289
+		zzt_key('c', 0x2E);
290
+		zzt_key(13, 0x1C);
291
+
292
+		init_map_char_to_key();
293
+	}
294
+
295
+	{
296
+		for(int i = 0; i < 15; i++)
297
+			gu_clut4[i] = 0;
298
+		gu_clut4[15] = 0xFFFFFFFF;
299
+
300
+		sceGuInit();
301
+		sceGuStart(GU_DIRECT, gu_list);
302
+		sceGuDrawBuffer(GU_PSM_8888, NULL, 512);
303
+		sceGuDispBuffer(480, 272, (void*) 0x88000, 512);
304
+		sceGuDepthBuffer((void*) 0x110000, 512);
305
+		sceGuOffset(2048 - 240, 2048 - 136);
306
+		sceGuViewport(2048, 2048, 480, 272);
307
+		sceGuDepthRange(0xC350, 0x2710);
308
+		sceGuScissor(0, 0, 480, 272);
309
+		sceGuEnable(GU_SCISSOR_TEST);
310
+		sceGuDisable(GU_DEPTH_TEST);
311
+		sceGuShadeModel(GU_FLAT);
312
+		sceGuAlphaFunc(GU_GREATER, 0, 0xFF);
313
+		sceGuEnable(GU_ALPHA_TEST);
314
+		sceGuEnable(GU_TEXTURE_2D);
315
+		sceGuClutMode(GU_PSM_8888, 0, 0x0F, 0);
316
+		sceGuClutLoad(2, gu_clut4);
317
+		sceGuTexMode(GU_PSM_T4, 0, 0, 0);
318
+		sceGuTexImage(0, 256, 128, 256, obj_6x10_psp_bin);
319
+		sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
320
+		sceGuTexEnvColor(0x0);
321
+		sceGuTexOffset(0.0f, 0.0f);
322
+		sceGuTexScale(1.0f / 256.0f, 1.0f / 128.0f);
323
+		sceGuTexWrap(GU_REPEAT, GU_REPEAT);
324
+		sceGuTexFilter(GU_NEAREST, GU_NEAREST);
325
+		sceGuFinish();
326
+		sceGuSync(0, 0);
327
+		sceGuDisplay(GU_TRUE);
328
+	}
329
+
330
+	psp_timer_init();
331
+
332
+	// TODO: Can we control this dynamically?
333
+	scePowerSetClockFrequency(300, 300, 150);
334
+
335
+	{
336
+		int thid = sceKernelCreateThread("zzt", psp_zzt_thread, 0x1C, 0xFA0, PSP_THREAD_ATTR_USER, NULL);
337
+		if (thid >= 0) {
338
+			sceKernelStartThread(thid, 0, 0);
339
+		} else {
340
+			return 1;
341
+		}
342
+	}
343
+
344
+	{
345
+		int thid = sceKernelCreateThread("exit handler", psp_exit_thread, 0x1E, 0xFA0, PSP_THREAD_ATTR_USER, NULL);
346
+		if (thid >= 0) {
347
+			sceKernelStartThread(thid, 0, 0);
348
+		} else {
349
+			return 1;
350
+		}
351
+	}
352
+
353
+	audio_stream_init(zeta_time_ms(), 44100);
354
+	audio_stream_set_volume(audio_stream_get_max_volume() >> 1);
355
+
356
+	pspAudioInit();
357
+	pspAudioSetChannelCallback(0, psp_audio_callback, NULL);
358
+
359
+	clock_t last = clock();
360
+	clock_t curr = last;
361
+
362
+	sceCtrlSetSamplingCycle(0);
363
+	sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL);
364
+
365
+	while (1) {
366
+		curr = clock();
367
+		last = curr;
368
+
369
+		sceCtrlReadBufferPositive(&pad, 1);
370
+
371
+		u32 bp = (~last_buttons) & (pad.Buttons);
372
+		u32 br = (~(pad.Buttons)) & last_buttons;
373
+		last_buttons = pad.Buttons;
374
+		if (bp != 0) {
375
+			if (bp & PSP_CTRL_UP) zzt_key(0, 0x48);
376
+			if (bp & PSP_CTRL_LEFT) zzt_key(0, 0x4B);
377
+			if (bp & PSP_CTRL_DOWN) zzt_key(0, 0x50);
378
+			if (bp & PSP_CTRL_RIGHT) zzt_key(0, 0x4D);
379
+			if (bp & PSP_CTRL_CROSS) zzt_kmod_set(0x01);
380
+			if (bp & PSP_CTRL_CIRCLE) zzt_key(13, 0x1C);
381
+			if (bp & PSP_CTRL_SELECT) zzt_key('w', 16);
382
+			if (bp & PSP_CTRL_START) {
383
+				if (pad.Buttons & PSP_CTRL_LTRIGGER) {
384
+					zzt_key('q', 15);
385
+					zzt_keyup(15);
386
+				} else {
387
+					zzt_key('p', 24);
388
+					zzt_keyup(24);
389
+				}
390
+			}
391
+			if (bp & PSP_CTRL_SQUARE) {
392
+				if (pad.Buttons & PSP_CTRL_LTRIGGER) {
393
+					zzt_key('r', 30);
394
+					zzt_keyup(30);
395
+				} else {
396
+					zzt_key('t', 19);
397
+					zzt_keyup(19);
398
+				}
399
+			}
400
+			if (bp & PSP_CTRL_TRIANGLE) {
401
+				if (pad.Buttons & PSP_CTRL_LTRIGGER) {
402
+					zzt_key('s', 30);
403
+					zzt_keyup(30);
404
+				} else {
405
+					zzt_key(0x1C, 1);
406
+					zzt_keyup(1);
407
+				}
408
+			}
409
+		}
410
+
411
+		if (br != 0) {
412
+			if (br & PSP_CTRL_UP) zzt_keyup(0x48);
413
+			if (br & PSP_CTRL_LEFT) zzt_keyup(0x4B);
414
+			if (br & PSP_CTRL_DOWN) zzt_keyup(0x50);
415
+			if (br & PSP_CTRL_RIGHT) zzt_keyup(0x4D);
416
+			if (br & PSP_CTRL_CROSS) zzt_kmod_clear(0x01);
417
+			if (bp & PSP_CTRL_CIRCLE) zzt_keyup(0x1C);
418
+			if (br & PSP_CTRL_SELECT) zzt_keyup(16);
419
+			if (br & PSP_CTRL_RTRIGGER && osk_text[0] == 0) {
420
+				int osk_running = 1;
421
+				unsigned short desctext[33];
422
+				unsigned short intext[65];
423
+				SceUtilityOskData data[1];
424
+				SceUtilityOskParams params;
425
+
426
+				desctext[0] = 'K';
427
+				desctext[1] = 'e';
428
+				desctext[2] = 'y';
429
+				desctext[3] = 'b';
430
+				desctext[4] = 'o';
431
+				desctext[5] = 'a';
432
+				desctext[6] = 'r';
433
+				desctext[7] = 'd';
434
+				desctext[8] = ':';
435
+				intext[0] = 0;
436
+				memset(osk_text, 0, sizeof(osk_text));
437
+
438
+				data[0].language = PSP_UTILITY_OSK_LANGUAGE_ENGLISH;
439
+				data[0].lines = 1;
440
+				data[0].unk_24 =  1;
441
+				data[0].inputtype = PSP_UTILITY_OSK_INPUTTYPE_ALL;
442
+				data[0].desc = desctext;
443
+				data[0].intext = intext;
444
+				data[0].outtextlength = 64;
445
+				data[0].outtextlimit = 64;
446
+				data[0].outtext = osk_text;
447
+
448
+				memset(&params, 0, sizeof(params));
449
+				params.base.size = sizeof(params);
450
+				sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_LANGUAGE, &params.base.language);
451
+				sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_UNKNOWN, &params.base.buttonSwap);
452
+				params.base.graphicsThread = 18;
453
+				params.base.accessThread = 20;
454
+				params.base.fontThread = 19;
455
+				params.base.soundThread = 17;
456
+				params.datacount = 1;
457
+				params.data = data;
458
+
459
+				sceUtilityOskInitStart(&params);
460
+				while (osk_running) {
461
+					sceGuStart(GU_DIRECT, gu_list);
462
+					sceGuClearColor(0);
463
+					sceGuClearDepth(0);
464
+					sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT);
465
+					sceGuFinish();
466
+					sceGuSync(0, 0);
467
+					switch (sceUtilityOskGetStatus()) {
468
+						case PSP_UTILITY_DIALOG_VISIBLE:
469
+							sceUtilityOskUpdate(1);
470
+							break;
471
+						case PSP_UTILITY_DIALOG_QUIT:
472
+							sceUtilityOskShutdownStart();
473
+							break;
474
+						case PSP_UTILITY_DIALOG_NONE:
475
+							osk_running = 0;
476
+							break;
477
+					}
478
+					sceDisplayWaitVblankStartCB();
479
+					sceGuSwapBuffers();
480
+				}
481
+
482
+				if (data[0].result != PSP_UTILITY_OSK_RESULT_CHANGED) {
483
+					osk_text[0] = 0;
484
+				}
485
+			}
486
+		}
487
+
488
+		psp_draw_frame();
489
+	}
490
+
491
+	sceGuDisplay(GU_FALSE);
492
+	sceGuTerm();
493
+
494
+	return 0;
495
+}

+ 2
- 2
src/zzt.c View File

@@ -31,8 +31,8 @@
31 31
 # endif
32 32
 #endif
33 33
 
34
-#ifdef ANDROID
35
-#define KEYBUF_SIZE 64
34
+#if defined(ANDROID) || defined(HAS_OSK)
35
+#define KEYBUF_SIZE 192
36 36
 #else
37 37
 #define KEYBUF_SIZE 8
38 38
 #endif

+ 26
- 0
tools/psp-font2raw.py View File

@@ -0,0 +1,26 @@
1
+import sys, struct
2
+from PIL import Image
3
+
4
+im = Image.open(sys.argv[1]).convert("RGB")
5
+fp = open(sys.argv[2], "wb")
6
+imgdata = [0] * (256*128)
7
+
8
+for ic in range(256):
9
+	for iy in range(10):
10
+		for ix in range(6):
11
+			icx = ix + ((ic & 31)*6)
12
+			icy = iy + ((ic >> 5)*10)
13
+			imx = ix + ((ic & 31)*8)
14
+			imy = iy + ((ic >> 5)*16)
15
+#			block_pos = ((imx >> 5) + ((imy >> 3) * 8)) * 128 + (imx & 31) + ((imy & 7) * 32)
16
+			block_pos = imy*256 + imx
17
+			ip = im.getpixel((icx, icy))
18
+			if ip[0] >= 128 and ip[1] >= 128 and ip[2] >= 128:
19
+				imgdata[block_pos] = 15
20
+
21
+for iy in range(128):
22
+	for ix in range(0, 256, 2):
23
+		v = (imgdata[iy*256+ix+1] << 4) | (imgdata[iy*256+ix] << 0)
24
+		fp.write(struct.pack("<B", v))
25
+
26
+fp.close()

Loading…
Cancel
Save