Credits\r
-------\r
\r
-This emulator uses code from these people/projects:\r
+This emulator is made of the code from following people/projects:\r
\r
notaz\r
GP2X, UIQ, PSP, Gizmondo ports, CPU core hacks,\r
#include <stdio.h>
#define lprintf printf
#elif defined(PSP)
- #ifdef LPRINTF_STDIO
- #include <stdio.h>
- #define lprintf printf
- #else
- extern void lprintf_f(const char *fmt, ...);
- #define lprintf lprintf_f
- #endif
+ extern void lprintf_f(const char *fmt, ...);
+ #define lprintf lprintf_f
#else
#include "giz.h"
#endif
amalgamate = 0\r
\r
\r
-CFLAGS += -I../.. -I. -DNO_SYNC -DLPRINTF_STDIO\r
+CFLAGS += -I../.. -I. -DNO_SYNC\r
CFLAGS += -Wall -Winline -G0\r
-CFLAGS += -DLPRINTF_STDIO\r
+#CFLAGS += -DLPRINTF_STDIO\r
#CFLAGS += -fprofile-generate\r
#CFLAGS += -fprofile-use\r
#CFLAGS += -pg\r
PSP_EBOOT_TITLE = PicoDrive\r
PSP_EBOOT_ICON = data/icon.png\r
#PSP_EBOOT_PIC1 = .png\r
+BUILD_PRX = 1\r
\r
CUSTOM_CLEAN = myclean\r
\r
bin2o -i $< $@ bgdatac40\r
\r
#\r
+ifndef UPDIR\r
+UPDIR = /media/disk/PSP/GAME/PicoDrive/\r
+endif\r
up: EBOOT.PBP\r
- @cp -v $^ /media/disk/PSP/GAME/PicoDrive/\r
+ @cp -v $^ $(UPDIR)\r
\r
\r
# cleanup\r
{
if (samples_made - samples_done < samples_block) {
// wait for data (use at least 2 blocks)
- lprintf("sthr: wait... (%i)\n", samples_made - samples_done);
+ //lprintf("sthr: wait... (%i)\n", samples_made - samples_done);
while (samples_made - samples_done <= samples_block*2 && !sound_thread_exit)
ret = sceKernelWaitSema(sound_sem, 1, 0);
if (ret < 0) lprintf("sthr: sceKernelWaitSema: %i\n", ret);
snd_playptr += samples_block;
if (snd_playptr >= sndBuffer_endptr)
snd_playptr = sndBuffer;
- if (ret)
- lprintf("sthr: outf: %i; pos %i/%i\n", ret, samples_done, samples_made);
+ // 1.5 kernel returns 0, newer ones return # of samples queued
+ if (ret < 0)
+ lprintf("sthr: sceAudio_E0727056: %08x; pos %i/%i\n", ret, samples_done, samples_made);
// shouln't happen, but just in case
if (samples_made - samples_done >= samples_block*3) {
static void sound_init(void)
{
SceUID thid;
+ int ret;
sound_sem = sceKernelCreateSema("sndsem", 0, 0, 1, NULL);
if (sound_sem < 0) lprintf("sceKernelCreateSema() failed: %i\n", sound_sem);
thid = sceKernelCreateThread("sndthread", sound_thread, 0x12, 0x10000, 0, NULL);
if (thid >= 0)
{
- sceKernelStartThread(thid, 0, 0);
+ ret = sceKernelStartThread(thid, 0, 0);
+ if (ret < 0) lprintf("sound_init: sceKernelStartThread returned %08x\n", ret);
}
else
lprintf("sceKernelCreateThread failed: %i\n", thid);
void emu_Loop(void)
{
+ static int mp3_init_done = 0;
char fpsbuff[24]; // fps count c string
unsigned int tval, tval_prev = 0, tval_thissec = 0; // timing
int frames_done = 0, frames_shown = 0, oldmodes = 0;
target_frametime = Pico.m.pal ? (1000000<<8)/50 : (1000000<<8)/60+1;
reset_timing = 1;
- // prepare CD buffer
- if (PicoMCD & 1) PicoCDBufferInit();
+ if (PicoMCD & 1) {
+ // prepare CD buffer
+ PicoCDBufferInit();
+ // mp3...
+ if (!mp3_init_done) {
+ i = mp3_init();
+ mp3_init_done = 1;
+ if (i) { engineState = PGS_Menu; return; }
+ }
+ }
// prepare sound stuff
PsndOut = NULL;
+#include <string.h>
#include "psp.h"
#include "emu.h"
#include "menu.h"
#include "../common/lprintf.h"
#include "version.h"
-int main()
+#define GPROF 0
+#define GCOV 0
+
+#if GPROF
+#include <pspprof.h>
+#endif
+
+#if GCOV
+#include <stdio.h>
+#include <stdlib.h>
+
+void dummy(void)
{
- int mp3_ret;
+ engineState = atoi(romFileName);
+ setbuf(NULL, NULL);
+ getenv(NULL);
+}
+#endif
+int main()
+{
lprintf("\nPicoDrive v" VERSION " " __DATE__ " " __TIME__ "\n");
psp_init();
-
emu_ReadConfig(0, 0);
emu_Init();
menu_init();
- mp3_ret = mp3_init();
+ // moved to emu_Loop(), after CPU clock change..
+ //mp3_init();
engineState = PGS_Menu;
switch (engineState)
{
case PGS_Menu:
+#if !GPROF
menu_loop();
+#else
+ strcpy(romFileName, currentConfig.lastRomFile);
+ engineState = PGS_ReloadRom;
+#endif
break;
case PGS_ReloadRom:
case PGS_Running:
emu_Loop();
+#if GPROF
+ goto endloop;
+#endif
break;
case PGS_Quit:
endloop:
- if (mp3_ret == 0) mp3_deinit();
+ mp3_deinit();
emu_Deinit();
+#if GPROF
+ gprof_cleanup();
+#endif
+#if !GCOV
psp_finish();
+#endif
return 0;
}
for (;;)
{
draw_cd_menu_options(menu_sel, &bios_names);
- inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE, 0);
+ inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_LEFT|BTN_RIGHT|BTN_X|BTN_CIRCLE|BTN_START, 0);
if (inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; }
if (inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; }
selected_id = me_index2id(cdopt_entries, CDOPT_ENTRY_COUNT, menu_sel);
}
}
}
- if (inp & BTN_CIRCLE) { // toggleable options
+ if (inp & BTN_CIRCLE) // toggleable options
if (!me_process(cdopt_entries, CDOPT_ENTRY_COUNT, selected_id, 1) &&
selected_id == MA_CDOPT_DONE) {
return;
}
+ if (inp & BTN_START) {
switch (selected_id) { // BIOS testers
case MA_CDOPT_TESTBIOS_USA:
if (emu_findBios(4, &bios)) { // test US
int mp3_last_error = 0;
+static int initialized = 0;
static SceUID thread_job_sem = -1;
static SceUID thread_busy_sem = -1;
static int thread_exit = 0;
continue; // bad frame
}
- if (bytes_read - frame_offset < frame_size) {
+ if (bytes_read - frame_offset < frame_size)
+ {
lprintf("unfit, foffs=%i\n", mp3_src_pos - bytes_read);
mp3_src_pos -= bytes_read - frame_offset;
+ if (mp3_src_size - mp3_src_pos < frame_size) {
+ mp3_src_pos = mp3_src_size;
+ return 0; // EOF
+ }
sceIoLseek32(mp3_handle, mp3_src_pos, PSP_SEEK_SET);
continue; // didn't fit, re-read..
}
}
mp3_last_error = 0;
+ initialized = 1;
return 0;
fail3:
sceAudiocodecReleaseEDRAM(mp3_codec_struct);
fail:
mp3_last_error = ret;
+ initialized = 0;
return 1;
}
void mp3_deinit(void)
{
- lprintf("deinit\n");
+ lprintf("mp3_deinit, initialized=%i\n", initialized);
+
+ if (!initialized) return;
thread_exit = 1;
psp_sem_lock(thread_busy_sem);
psp_sem_unlock(thread_busy_sem);
sceKernelDeleteSema(thread_job_sem);
thread_job_sem = -1;
sceAudiocodecReleaseEDRAM(mp3_codec_struct);
+ initialized = 0;
}
// may overflow stack?
}
+// might be called before initialization
int mp3_get_bitrate(FILE *f, int size)
{
int ret, retval = -1, sample_rate, bitrate;
char *fname = (char *)f;
/* make sure thread is not busy.. */
- psp_sem_lock(thread_busy_sem);
+ if (thread_busy_sem >= 0)
+ psp_sem_lock(thread_busy_sem);
if (mp3_handle >= 0) sceIoClose(mp3_handle);
mp3_handle = sceIoOpen(fname, PSP_O_RDONLY, 0777);
mp3_src_pos = 0;
ret = read_next_frame(0);
if (ret <= 0) {
- lprintf("read_next_frame() failed\n");
+ lprintf("read_next_frame() failed (%s)\n", fname);
goto end;
}
sample_rate = (mp3_src_buffer[0][2] & 0x0c) >> 2;
bitrate = mp3_src_buffer[0][2] >> 4;
if (sample_rate != 0) {
- lprintf("unsupported samplerate\n");
+ lprintf("unsupported samplerate (%s)\n", fname);
goto end; // only 44kHz supported..
}
bitrate = bitrates[bitrate];
if (bitrate == 0) {
- lprintf("unsupported bitrate\n");
+ lprintf("unsupported bitrate (%s)\n", fname);
goto end;
}
if (mp3_handle >= 0) sceIoClose(mp3_handle);
mp3_handle = -1;
mp3_fname = NULL;
- psp_sem_unlock(thread_busy_sem);
+ if (thread_busy_sem >= 0)
+ psp_sem_unlock(thread_busy_sem);
if (retval < 0) mp3_last_error = -1; // remember we had a problem..
return retval;
}
{
char *fname = (char *)f;
+ if (!initialized) return;
+
lprintf("mp3_start_play(%s) @ %i\n", fname, pos);
psp_sem_lock(thread_busy_sem);
#include <stdio.h>
+#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "../common/lprintf.h"
PSP_MODULE_INFO("PicoDrive", 0, 1, 34);
+PSP_HEAP_SIZE_MAX();
unsigned int __attribute__((aligned(16))) guCmdList[GU_CMDLIST_SIZE];
void *psp_screen = VRAM_FB0;
static int current_screen = 0; /* front bufer */
+static SceUID main_thread_id = -1;
+
#define ANALOG_DEADZONE 80
/* Exit callback */
{
SceUID thid;
- lprintf("running in %08x kernel\n", sceKernelDevkitVersion()),
- lprintf("entered psp_init, threadId %08x, priority %i\n", sceKernelGetThreadId(),
+ main_thread_id = sceKernelGetThreadId();
+
+ lprintf("running on %08x kernel\n", sceKernelDevkitVersion()),
+ lprintf("entered psp_init, threadId %08x, priority %i\n", main_thread_id,
sceKernelGetThreadCurrentPriority());
thid = sceKernelCreateThread("update_thread", callback_thread, 0x11, 0xFA0, 0, 0);
}
/* alt logging */
-#define LOG_FILE "log.log"
+#define LOG_FILE "log.txt"
+
+typedef struct _log_entry
+{
+ char buff[256];
+ struct _log_entry *next;
+} log_entry;
-static SceUID logfd = -1;
+static log_entry *le_root = NULL;
void lprintf_f(const char *fmt, ...)
{
va_list vl;
+
+#ifdef LPRINTF_STDIO
+ va_start(vl, fmt);
+ vprintf(fmt, vl);
+ va_end(vl);
+#else
+ static SceUID logfd = -1;
char buff[256];
+ log_entry *le, *le1;
if (logfd == -2) return; // disabled
- if (logfd < 0)
+ va_start(vl, fmt);
+ vsnprintf(buff, sizeof(buff), fmt, vl);
+ va_end(vl);
+
+ // note: this is still unsafe code
+ if (main_thread_id != sceKernelGetThreadId())
{
- logfd = sceIoOpen(LOG_FILE, PSP_O_WRONLY|PSP_O_APPEND, 0777);
- if (logfd < 0) {
- logfd = -2;
- return;
+ le = malloc(sizeof(*le));
+ if (le == NULL) return;
+ le->next = NULL;
+ strcpy(le->buff, buff);
+ if (le_root == NULL) le_root = le;
+ else {
+ for (le1 = le_root; le1->next != NULL; le1 = le1->next);
+ le1->next = le;
}
+ return;
}
- va_start(vl, fmt);
- vsnprintf(buff, sizeof(buff), fmt, vl);
- va_end(vl);
+ logfd = sceIoOpen(LOG_FILE, PSP_O_WRONLY|PSP_O_APPEND, 0777);
+ if (logfd < 0) {
+ logfd = -2;
+ return;
+ }
+
+ if (le_root != NULL)
+ {
+ le1 = le_root;
+ le_root = NULL;
+ sceKernelDelayThread(1000);
+ while (le1 != NULL) {
+ le = le1;
+ le1 = le->next;
+ sceIoWrite(logfd, le->buff, strlen(le->buff));
+ free(le);
+ }
+ }
sceIoWrite(logfd, buff, strlen(buff));
// make sure it gets flushed
sceIoClose(logfd);
logfd = -1;
+#endif
}