remove PicoDrive-specific stuff, add readme

This commit is contained in:
notaz 2012-09-08 20:31:36 +03:00 committed by Grazvydas Ignotas
parent ca69c3e5a0
commit f506842df2
73 changed files with 13 additions and 16178 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.o
*.swp

11
README Normal file
View file

@ -0,0 +1,11 @@
libpicofe, or LIB-PICOdrive's-FrontEnd, is an attempt to reuse PicoDrive's
frontend code for other projects. To accommodate various needs, this is
tripple-licensed with these licenses:
- GNU GPL, version 2 or later.
- GNU LGPL, version 2.1 or later.
- MAME license.
When used as part of another project, host project's license usually applies
to combined source code as a whole.
- notaz

File diff suppressed because it is too large Load diff

View file

@ -1,14 +0,0 @@
// (c) Copyright 2006-2009 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
void bgr444_to_rgb32(void *to, void *from);
void bgr444_to_rgb32_sh(void *to, void *from);
void vidcpy_m2(void *dest, void *src, int m32col, int with_32c_border);
void vidcpy_m2_rot(void *dest, void *src, int m32col, int with_32c_border);
void spend_cycles(int c); // utility
void rotated_blit8 (void *dst, void *linesx4, int y, int is_32col);
void rotated_blit16(void *dst, void *linesx4, int y, int is_32col);

View file

@ -1,337 +0,0 @@
@ vim:filetype=armasm
@ some color conversion and blitting routines
@ (c) Copyright 2006, 2007 notaz
@ All Rights Reserved
@ vim:filetype=armasm
.text
.align 4
@ Convert 0000bbb0 ggg0rrr0 0000bbb0 ggg0rrr0
@ to 00000000 rrr00000 ggg00000 bbb00000 ...
@ lr = 0x00e000e0, out: r3=lower_pix, r2=higher_pix; trashes rin
.macro convRGB32_2 rin sh=0
and r2, lr, \rin, lsr #4 @ blue
and r3, \rin, lr
orr r2, r2, r3, lsl #8 @ g0b0g0b0
mov r3, r2, lsl #16 @ g0b00000
and \rin,lr, \rin, ror #12 @ 00r000r0 (reversed)
orr r3, r3, \rin, lsr #16 @ g0b000r0
.if \sh == 1
mov r3, r3, ror #17 @ shadow mode
.elseif \sh == 2
adds r3, r3, #0x40000000 @ green
orrcs r3, r3, #0xe0000000
mov r3, r3, ror #8
adds r3, r3, #0x40000000
orrcs r3, r3, #0xe0000000
mov r3, r3, ror #16
adds r3, r3, #0x40000000
orrcs r3, r3, #0xe0000000
mov r3, r3, ror #24
.else
mov r3, r3, ror #16 @ r3=low
.endif
orr r3, r3, r3, lsr #3
str r3, [r0], #4
mov r2, r2, lsr #16
orr r2, r2, \rin, lsl #16
.if \sh == 1
mov r2, r2, lsr #1
.elseif \sh == 2
mov r2, r2, ror #8
adds r2, r2, #0x40000000 @ blue
orrcs r2, r2, #0xe0000000
mov r2, r2, ror #8
adds r2, r2, #0x40000000
orrcs r2, r2, #0xe0000000
mov r2, r2, ror #8
adds r2, r2, #0x40000000
orrcs r2, r2, #0xe0000000
mov r2, r2, ror #8
.endif
orr r2, r2, r2, lsr #3
.if \sh == 1
str r2, [r0, #0x40*2*4]
.endif
str r2, [r0], #4
.endm
.global bgr444_to_rgb32 @ void *to, void *from
bgr444_to_rgb32:
stmfd sp!, {r4-r7,lr}
mov r12, #0x40>>3 @ repeats
mov lr, #0x00e00000
orr lr, lr, #0x00e0
.loopRGB32:
subs r12, r12, #1
ldmia r1!, {r4-r7}
convRGB32_2 r4
convRGB32_2 r5
convRGB32_2 r6
convRGB32_2 r7
bgt .loopRGB32
ldmfd sp!, {r4-r7,pc}
.global bgr444_to_rgb32_sh @ void *to, void *from
bgr444_to_rgb32_sh:
stmfd sp!, {r4-r7,lr}
mov r12, #0x40>>3 @ repeats
add r0, r0, #0x40*4
mov lr, #0x00e00000
orr lr, lr, #0x00e0
.loopRGB32sh:
subs r12, r12, #1
ldmia r1!, {r4-r7}
convRGB32_2 r4, 1
convRGB32_2 r5, 1
convRGB32_2 r6, 1
convRGB32_2 r7, 1
bgt .loopRGB32sh
mov r12, #0x40>>3 @ repeats
sub r1, r1, #0x40*2
.loopRGB32hi:
ldmia r1!, {r4-r7}
convRGB32_2 r4, 2
convRGB32_2 r5, 2
convRGB32_2 r6, 2
convRGB32_2 r7, 2
subs r12, r12, #1
bgt .loopRGB32hi
ldmfd sp!, {r4-r7,lr}
bx lr
@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ mode2 blitter
.global vidcpy_m2 @ void *dest, void *src, int m32col, int with_32c_border
vidcpy_m2:
stmfd sp!, {r4-r6,lr}
mov r12, #224 @ lines
add r0, r0, #320*8
add r1, r1, #8
mov lr, #0
tst r2, r2
movne lr, #64
tstne r3, r3
addne r0, r0, #32
vidCpyM2_loop_out:
mov r6, #10
sub r6, r6, lr, lsr #5 @ -= 2 in 32col mode
vidCpyM2_loop:
subs r6, r6, #1
ldmia r1!, {r2-r5}
stmia r0!, {r2-r5}
ldmia r1!, {r2-r5}
stmia r0!, {r2-r5}
bne vidCpyM2_loop
subs r12,r12,#1
add r0, r0, lr
add r1, r1, #8
add r1, r1, lr
bne vidCpyM2_loop_out
ldmfd sp!, {r4-r6,pc}
.global vidcpy_m2_rot @ void *dest, void *src, int m32col, int with_32c_border
vidcpy_m2_rot:
stmfd sp!,{r4-r8,lr}
add r1, r1, #8
tst r2, r2
subne r1, r1, #32 @ adjust
mov r4, r0
mov r5, r1
mov r6, r2
mov r7, #8+4
vidcpy_m2_rot_loop:
@ a bit lame but oh well..
mov r0, r4
mov r1, r5
mov r2, r7
mov r3, r6
mov r8, #328
adr lr, after_rot_blit8
stmfd sp!,{r4-r8,lr}
b rotated_blit8_2
after_rot_blit8:
add r5, r5, #328*4
add r7, r7, #4
cmp r7, #224+8+4
ldmgefd sp!,{r4-r8,pc}
b vidcpy_m2_rot_loop
.global rotated_blit8 @ void *dst, void *linesx4, u32 y, int is_32col
rotated_blit8:
stmfd sp!,{r4-r8,lr}
mov r8, #320
rotated_blit8_2:
add r0, r0, #(240*320)
sub r0, r0, #(240+4) @ y starts from 4
add r0, r0, r2
tst r3, r3
subne r0, r0, #(240*32)
addne r1, r1, #32
movne lr, #256/4
moveq lr, #320/4
rotated_blit_loop8:
mov r6, r1
ldr r2, [r6], r8
ldr r3, [r6], r8
ldr r4, [r6], r8
ldr r5, [r6], r8
mov r6, r2, lsl #24
mov r6, r6, lsr #8
orr r6, r6, r3, lsl #24
mov r6, r6, lsr #8
orr r6, r6, r4, lsl #24
mov r6, r6, lsr #8
orr r6, r6, r5, lsl #24
str r6, [r0], #-240
and r6, r3, #0xff00
and r7, r2, #0xff00
orr r6, r6, r7, lsr #8
and r7, r4, #0xff00
orr r6, r6, r7, lsl #8
and r7, r5, #0xff00
orr r6, r6, r7, lsl #16
str r6, [r0], #-240
and r6, r4, #0xff0000
and r7, r2, #0xff0000
orr r6, r6, r7, lsr #16
and r7, r3, #0xff0000
orr r6, r6, r7, lsr #8
and r7, r5, #0xff0000
orr r6, r6, r7, lsl #8
str r6, [r0], #-240
mov r6, r5, lsr #24
mov r6, r6, lsl #8
orr r6, r6, r4, lsr #24
mov r6, r6, lsl #8
orr r6, r6, r3, lsr #24
mov r6, r6, lsl #8
orr r6, r6, r2, lsr #24
str r6, [r0], #-240
subs lr, lr, #1
add r1, r1, #4
bne rotated_blit_loop8
ldmfd sp!,{r4-r8,pc}
@ input: r2-r5
@ output: r7,r8
@ trash: r6
.macro rb_line_low
mov r6, r2, lsl #16
mov r7, r3, lsl #16
orr r7, r7, r6, lsr #16
mov r6, r4, lsl #16
mov r8, r5, lsl #16
orr r8, r8, r6, lsr #16
.endm
.macro rb_line_hi
mov r6, r2, lsr #16
mov r7, r3, lsr #16
orr r7, r6, r7, lsl #16
mov r6, r4, lsr #16
mov r8, r5, lsr #16
orr r8, r6, r8, lsl #16
.endm
.global rotated_blit16 @ void *dst, void *linesx4, u32 y, int is_32col
rotated_blit16:
stmfd sp!,{r4-r8,lr}
add r0, r0, #(240*320)*2
sub r0, r0, #(240+4)*2 @ y starts from 4
add r0, r0, r2, lsl #1
tst r3, r3
subne r0, r0, #(240*32)*2
addne r1, r1, #32*2
movne lr, #256/4
moveq lr, #320/4
rotated_blit_loop16:
ldr r2, [r1, #320*0*2]
ldr r3, [r1, #320*1*2]
ldr r4, [r1, #320*2*2]
ldr r5, [r1, #320*3*2]
rb_line_low
stmia r0, {r7,r8}
sub r0, r0, #240*2
rb_line_hi
stmia r0, {r7,r8}
sub r0, r0, #240*2
ldr r2, [r1, #320*0*2+4]
ldr r3, [r1, #320*1*2+4]
ldr r4, [r1, #320*2*2+4]
ldr r5, [r1, #320*3*2+4]
rb_line_low
stmia r0, {r7,r8}
sub r0, r0, #240*2
rb_line_hi
stmia r0, {r7,r8}
sub r0, r0, #240*2
subs lr, lr, #1
add r1, r1, #8
bne rotated_blit_loop16
ldmfd sp!,{r4-r8,pc}
.global spend_cycles @ c
spend_cycles:
mov r0, r0, lsr #2 @ 4 cycles/iteration
sub r0, r0, #2 @ entry/exit/init
.sc_loop:
subs r0, r0, #1
bpl .sc_loop
bx lr

View file

@ -1,154 +0,0 @@
ifneq ($(DEBUG),)
CFLAGS += -ggdb
endif
ifeq "$(profile)" "1"
CFLAGS += -fprofile-generate
endif
ifeq "$(profile)" "2"
CFLAGS += -fprofile-use
endif
ifeq "$(pdb)" "1"
DEFINES += PDB
OBJS += cpu/debug.o
ifeq "$(pdb_net)" "1"
DEFINES += PDB_NET
endif
ifeq "$(readline)" "1"
DEFINES += HAVE_READLINE
LDFLAGS += -lreadline
endif
endif
ifeq "$(pprof)" "1"
DEFINES += PPROF
OBJS += platform/linux/pprof.o
endif
# === Pico core ===
# Pico
OBJS += pico/state.o pico/cart.o pico/memory.o pico/pico.o pico/sek.o pico/z80if.o \
pico/videoport.o pico/draw2.o pico/draw.o pico/mode4.o \
pico/misc.o pico/eeprom.o pico/patch.o pico/debug.o
# SMS
ifneq "$(no_sms)" "1"
OBJS += pico/sms.o
else
DEFINES += NO_SMS
endif
# CD
OBJS += pico/cd/pico.o pico/cd/memory.o pico/cd/sek.o pico/cd/LC89510.o \
pico/cd/cd_sys.o pico/cd/cd_file.o pico/cd/cue.o pico/cd/gfx_cd.o \
pico/cd/misc.o pico/cd/pcm.o pico/cd/buffering.o
# 32X
ifneq "$(no_32x)" "1"
OBJS += pico/32x/32x.o pico/32x/memory.o pico/32x/draw.o pico/32x/pwm.o
else
DEFINES += NO_32X
endif
# Pico
OBJS += pico/pico/pico.o pico/pico/memory.o pico/pico/xpcm.o
# carthw
OBJS += pico/carthw/carthw.o
# SVP
OBJS += pico/carthw/svp/svp.o pico/carthw/svp/memory.o \
pico/carthw/svp/ssp16.o
# sound
OBJS += pico/sound/sound.o
OBJS += pico/sound/sn76496.o pico/sound/ym2612.o
# === CPU cores ===
# --- M68k ---
ifeq "$(use_musashi)" "1"
DEFINES += EMU_M68K
OBJS += cpu/musashi/m68kops.o cpu/musashi/m68kcpu.o
#OBJS += cpu/musashi/m68kdasm.o
endif
ifeq "$(use_cyclone)" "1"
DEFINES += EMU_C68K
OBJS += pico/m68kif_cyclone.o cpu/Cyclone/proj/Cyclone.o cpu/Cyclone/tools/idle.o
endif
ifeq "$(use_fame)" "1"
DEFINES += EMU_F68K
OBJS += cpu/fame/famec.o
endif
# --- Z80 ---
ifeq "$(use_drz80)" "1"
DEFINES += _USE_DRZ80
OBJS += cpu/DrZ80/drz80.o
endif
#
ifeq "$(use_cz80)" "1"
DEFINES += _USE_CZ80
OBJS += cpu/cz80/cz80.o
endif
# --- SH2 ---
OBJS += cpu/drc/cmn.o
ifneq "$(no_32x)" "1"
OBJS += cpu/sh2/sh2.o
#
ifeq "$(use_sh2drc)" "1"
DEFINES += DRC_SH2
OBJS += cpu/sh2/compiler.o
ifdef drc_debug
DEFINES += DRC_DEBUG=$(drc_debug)
OBJS += cpu/sh2/mame/sh2dasm.o
OBJS += platform/linux/host_dasm.o
LDFLAGS += -lbfd -lopcodes -liberty
endif
ifeq "$(drc_debug_interp)" "1"
DEFINES += DRC_DEBUG_INTERP
use_sh2mame = 1
endif
endif # use_sh2drc
#
ifeq "$(use_sh2mame)" "1"
OBJS += cpu/sh2/mame/sh2pico.o
endif
endif # !no_32x
DIRS += platform platform/common pico pico/cd pico/pico pico/32x pico/sound pico/carthw/svp \
cpu cpu/musashi cpu/cz80 cpu/fame cpu/sh2/mame cpu/drc
# common rules
.c.o:
@echo ">>>" $<
$(CC) $(CFLAGS) -c $< -o $@
.s.o:
@echo ">>>" $<
$(CC) $(CFLAGS) -c $< -o $@
clean_prof:
find ../.. -name '*.gcno' -delete
find ../.. -name '*.gcda' -delete
mkdirs:
mkdir -p $(DIRS)
../../tools/textfilter: ../../tools/textfilter.c
make -C ../../tools/ textfilter
# random deps
pico/carthw/svp/compiler.o : ../../cpu/drc/emit_$(ARCH).c
cpu/sh2/compiler.o : ../../cpu/drc/emit_$(ARCH).c
cpu/sh2/mame/sh2pico.o : ../../cpu/sh2/mame/sh2.c
pico/pico.o pico/cd/pico.o : ../../pico/pico_cmn.c ../../pico/pico_int.h
pico/memory.o pico/cd/memory.o : ../../pico/pico_int.h ../../pico/memory.h
../../cpu/musashi/m68kops.c :
@make -C ../../cpu/musashi
../../cpu/mz80/mz80.asm :
@make -C ../../cpu/mz80/
cpu/fame/famec.o : ../../cpu/fame/famec.c ../../cpu/fame/famec_opcodes.h
@echo ">>>" $<
$(CC) $(CFLAGS) -Wno-unused -c $< -o $@
../../cpu/Cyclone/proj/Cyclone.s:
@echo building Cyclone...
@make -C ../../cpu/Cyclone/proj CONFIG_FILE=config_pico.h

View file

@ -1,39 +0,0 @@
# asm stuff
ifeq "$(asm_render)" "1"
DEFINES += _ASM_DRAW_C
OBJS += pico/draw_arm.o pico/draw2_arm.o
endif
ifeq "$(asm_memory)" "1"
DEFINES += _ASM_MEMORY_C
OBJS += pico/memory_arm.o
endif
ifeq "$(asm_ym2612)" "1"
DEFINES += _ASM_YM2612_C
OBJS += pico/sound/ym2612_arm.o
endif
ifeq "$(asm_misc)" "1"
DEFINES += _ASM_MISC_C
OBJS += pico/misc_arm.o
OBJS += pico/cd/misc_arm.o
endif
ifeq "$(asm_cdpico)" "1"
DEFINES += _ASM_CD_PICO_C
OBJS += pico/cd/pico_arm.o
endif
ifeq "$(asm_cdmemory)" "1"
DEFINES += _ASM_CD_MEMORY_C
OBJS += pico/cd/memory_arm.o
endif
ifeq "$(asm_32xdraw)" "1"
DEFINES += _ASM_32X_DRAW
OBJS += pico/32x/draw_arm.o
endif
DIRS += cpu/Cyclone cpu/Cyclone/proj cpu/Cyclone/tools cpu/DrZ80
# build helix libs
../common/helix/$(CROSS)helix-mp3.a:
make -C ../common/helix CROSS=$(CROSS) clean all

View file

@ -1,840 +0,0 @@
/*
* Human-readable config file management for PicoDrive
* (c) notaz, 2008
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef __EPOC32__
#include <unistd.h>
#endif
#include "config.h"
#include "plat.h"
#include "input.h"
#include "lprintf.h"
static char *mystrip(char *str);
#ifndef _MSC_VER
#include "menu.h"
#include "menu_pico.h"
#include "emu.h"
#include <pico/pico.h>
// always output DOS endlines
#ifdef _WIN32
#define NL "\n"
#else
#define NL "\r\n"
#endif
static int seek_sect(FILE *f, const char *section)
{
char line[128], *tmp;
int len;
len = strlen(section);
// seek to the section needed
while (!feof(f))
{
tmp = fgets(line, sizeof(line), f);
if (tmp == NULL) break;
if (line[0] != '[') continue; // not section start
if (strncmp(line + 1, section, len) == 0 && line[len+1] == ']')
return 1; // found it
}
return 0;
}
static void keys_write(FILE *fn, const char *bind_str, int dev_id, const int *binds, int no_defaults)
{
char act[48];
int key_count = 0, k, i;
const int *def_binds;
in_get_config(dev_id, IN_CFG_BIND_COUNT, &key_count);
def_binds = in_get_dev_def_binds(dev_id);
for (k = 0; k < key_count; k++)
{
const char *name;
int t, mask;
act[0] = act[31] = 0;
for (t = 0; t < IN_BINDTYPE_COUNT; t++)
if (binds[IN_BIND_OFFS(k, t)] != def_binds[IN_BIND_OFFS(k, t)])
break;
if (no_defaults && t == IN_BINDTYPE_COUNT)
continue; /* no change from defaults */
name = in_get_key_name(dev_id, k);
for (t = 0; t < IN_BINDTYPE_COUNT; t++)
if (binds[IN_BIND_OFFS(k, t)] != 0 || def_binds[IN_BIND_OFFS(k, t)] == 0)
break;
if (t == IN_BINDTYPE_COUNT) {
/* key has default bind removed */
fprintf(fn, "%s %s =" NL, bind_str, name);
continue;
}
for (i = 0; me_ctrl_actions[i].name != NULL; i++) {
mask = me_ctrl_actions[i].mask;
if (mask & binds[IN_BIND_OFFS(k, IN_BINDTYPE_PLAYER12)]) {
strncpy(act, me_ctrl_actions[i].name, 31);
fprintf(fn, "%s %s = player1 %s" NL, bind_str, name, mystrip(act));
}
mask = me_ctrl_actions[i].mask << 16;
if (mask & binds[IN_BIND_OFFS(k, IN_BINDTYPE_PLAYER12)]) {
strncpy(act, me_ctrl_actions[i].name, 31);
fprintf(fn, "%s %s = player2 %s" NL, bind_str, name, mystrip(act));
}
}
for (i = 0; emuctrl_actions[i].name != NULL; i++) {
mask = emuctrl_actions[i].mask;
if (mask & binds[IN_BIND_OFFS(k, IN_BINDTYPE_EMU)]) {
strncpy(act, emuctrl_actions[i].name, 31);
fprintf(fn, "%s %s = %s" NL, bind_str, name, mystrip(act));
}
}
}
}
/* XXX: this should go to menu structures instead */
static int default_var(const menu_entry *me)
{
switch (me->id)
{
case MA_OPT2_ENABLE_YM2612:
case MA_OPT2_ENABLE_SN76496:
case MA_OPT2_ENABLE_Z80:
case MA_OPT_6BUTTON_PAD:
case MA_OPT_ACC_SPRITES:
case MA_OPT_ARM940_SOUND:
case MA_CDOPT_PCM:
case MA_CDOPT_CDDA:
case MA_CDOPT_SCALEROT_CHIP:
case MA_CDOPT_BETTER_SYNC:
case MA_CDOPT_SAVERAM:
case MA_32XOPT_ENABLE_32X:
case MA_32XOPT_PWM:
case MA_OPT2_SVP_DYNAREC:
case MA_OPT2_NO_SPRITE_LIM:
case MA_OPT2_NO_IDLE_LOOPS:
return defaultConfig.s_PicoOpt;
case MA_OPT_SRAM_STATES:
case MA_OPT_SHOW_FPS:
case MA_OPT_ENABLE_SOUND:
case MA_OPT2_GZIP_STATES:
case MA_OPT2_SQUIDGEHACK:
case MA_OPT2_NO_LAST_ROM:
case MA_OPT2_RAMTIMINGS:
case MA_CDOPT_LEDS:
case MA_OPT2_A_SN_GAMMA:
case MA_OPT2_VSYNC:
case MA_OPT_INTERLACED:
case MA_OPT2_DBLBUFF:
case MA_OPT2_STATUS_LINE:
case MA_OPT2_NO_FRAME_LIMIT:
case MA_OPT_TEARING_FIX:
return defaultConfig.EmuOpt;
case MA_CTRL_TURBO_RATE: return defaultConfig.turbo_rate;
case MA_OPT_SCALING: return defaultConfig.scaling;
case MA_OPT_ROTATION: return defaultConfig.rotation;
case MA_OPT2_GAMMA: return defaultConfig.gamma;
case MA_OPT_FRAMESKIP: return defaultConfig.Frameskip;
case MA_OPT_CONFIRM_STATES: return defaultConfig.confirm_save;
case MA_OPT_CPU_CLOCKS: return defaultConfig.CPUclock;
case MA_OPT_RENDERER: return defaultConfig.renderer;
case MA_32XOPT_RENDERER: return defaultConfig.renderer32x;
case MA_OPT_SAVE_SLOT:
return 0;
default:
lprintf("missing default for %d\n", me->id);
return 0;
}
}
static int is_cust_val_default(const menu_entry *me)
{
switch (me->id)
{
case MA_OPT_REGION:
return defaultConfig.s_PicoRegion == PicoRegionOverride &&
defaultConfig.s_PicoAutoRgnOrder == PicoAutoRgnOrder;
case MA_OPT_SOUND_QUALITY:
return defaultConfig.s_PsndRate == PsndRate &&
((defaultConfig.s_PicoOpt ^ PicoOpt) & POPT_EN_STEREO) == 0;
case MA_CDOPT_READAHEAD:
return defaultConfig.s_PicoCDBuffers == PicoCDBuffers;
case MA_32XOPT_MSH2_CYCLES:
return p32x_msh2_multiplier == MSH2_MULTI_DEFAULT;
case MA_32XOPT_SSH2_CYCLES:
return p32x_ssh2_multiplier == SSH2_MULTI_DEFAULT;
default:break;
}
lprintf("is_cust_val_default: unhandled id %i\n", me->id);
return 0;
}
int config_writesect(const char *fname, const char *section)
{
FILE *fo = NULL, *fn = NULL; // old and new
int no_defaults = 0; // avoid saving defaults
menu_entry *me;
int t, tlen, ret;
char line[128], *tmp;
if (section != NULL)
{
no_defaults = 1;
fo = fopen(fname, "r");
if (fo == NULL) {
fn = fopen(fname, "w");
goto write;
}
ret = seek_sect(fo, section);
if (!ret) {
// sect not found, we can simply append
fclose(fo); fo = NULL;
fn = fopen(fname, "a");
goto write;
}
// use 2 files..
fclose(fo);
rename(fname, "tmp.cfg");
fo = fopen("tmp.cfg", "r");
fn = fopen(fname, "w");
if (fo == NULL || fn == NULL) goto write;
// copy everything until sect
tlen = strlen(section);
while (!feof(fo))
{
tmp = fgets(line, sizeof(line), fo);
if (tmp == NULL) break;
if (line[0] == '[' && strncmp(line + 1, section, tlen) == 0 && line[tlen+1] == ']')
break;
fputs(line, fn);
}
// now skip to next sect
while (!feof(fo))
{
tmp = fgets(line, sizeof(line), fo);
if (tmp == NULL) break;
if (line[0] == '[') {
fseek(fo, -strlen(line), SEEK_CUR);
break;
}
}
if (feof(fo))
{
fclose(fo); fo = NULL;
remove("tmp.cfg");
}
}
else
{
fn = fopen(fname, "w");
}
write:
if (fn == NULL) {
if (fo) fclose(fo);
return -1;
}
if (section != NULL)
fprintf(fn, "[%s]" NL, section);
for (me = me_list_get_first(); me != NULL; me = me_list_get_next())
{
int dummy;
if (!me->need_to_save)
continue;
if (me->name == NULL || me->name[0] == 0)
continue;
if (me->beh == MB_OPT_ONOFF || me->beh == MB_OPT_CUSTONOFF) {
if (!no_defaults || ((*(int *)me->var ^ default_var(me)) & me->mask))
fprintf(fn, "%s = %i" NL, me->name, (*(int *)me->var & me->mask) ? 1 : 0);
}
else if (me->beh == MB_OPT_RANGE || me->beh == MB_OPT_CUSTRANGE) {
if (!no_defaults || (*(int *)me->var ^ default_var(me)))
fprintf(fn, "%s = %i" NL, me->name, *(int *)me->var);
}
else if (me->beh == MB_OPT_ENUM && me->data != NULL) {
const char **names = (const char **)me->data;
for (t = 0; names[t] != NULL; t++)
if (*(int *)me->var == t && (!no_defaults || (*(int *)me->var ^ default_var(me)))) {
strncpy(line, names[t], sizeof(line));
goto write_line;
}
}
else if (me->generate_name != NULL) {
if (!no_defaults || !is_cust_val_default(me)) {
strncpy(line, me->generate_name(0, &dummy), sizeof(line));
goto write_line;
}
}
else
lprintf("config: unhandled write: %i\n", me->id);
continue;
write_line:
line[sizeof(line) - 1] = 0;
mystrip(line);
fprintf(fn, "%s = %s" NL, me->name, line);
}
/* input: save device names */
for (t = 0; t < IN_MAX_DEVS; t++)
{
const int *binds = in_get_dev_binds(t);
const char *name = in_get_dev_name(t, 0, 0);
if (binds == NULL || name == NULL)
continue;
fprintf(fn, "input%d = %s" NL, t, name);
}
/* input: save binds */
for (t = 0; t < IN_MAX_DEVS; t++)
{
const int *binds = in_get_dev_binds(t);
const char *name = in_get_dev_name(t, 0, 0);
char strbind[16];
int count = 0;
if (binds == NULL || name == NULL)
continue;
sprintf(strbind, "bind%d", t);
if (t == 0) strbind[4] = 0;
in_get_config(t, IN_CFG_BIND_COUNT, &count);
keys_write(fn, strbind, t, binds, no_defaults);
}
#ifndef PSP
if (section == NULL)
fprintf(fn, "Sound Volume = %i" NL, currentConfig.volume);
#endif
fprintf(fn, NL);
if (fo != NULL)
{
// copy whatever is left
while (!feof(fo))
{
tmp = fgets(line, sizeof(line), fo);
if (tmp == NULL) break;
fputs(line, fn);
}
fclose(fo);
remove("tmp.cfg");
}
fclose(fn);
return 0;
}
int config_writelrom(const char *fname)
{
char line[128], *tmp, *optr = NULL;
char *old_data = NULL;
int size;
FILE *f;
if (strlen(rom_fname_loaded) == 0) return -1;
f = fopen(fname, "r");
if (f != NULL)
{
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
old_data = malloc(size + size/8);
if (old_data != NULL)
{
optr = old_data;
while (!feof(f))
{
tmp = fgets(line, sizeof(line), f);
if (tmp == NULL) break;
mystrip(line);
if (strncasecmp(line, "LastUsedROM", 11) == 0)
continue;
sprintf(optr, "%s", line);
optr += strlen(optr);
}
}
fclose(f);
}
f = fopen(fname, "w");
if (f == NULL) return -1;
if (old_data != NULL) {
fwrite(old_data, 1, optr - old_data, f);
free(old_data);
}
fprintf(f, "LastUsedROM = %s" NL, rom_fname_loaded);
fclose(f);
return 0;
}
/* --------------------------------------------------------------------------*/
int config_readlrom(const char *fname)
{
char line[128], *tmp;
int i, len, ret = -1;
FILE *f;
f = fopen(fname, "r");
if (f == NULL) return -1;
// seek to the section needed
while (!feof(f))
{
tmp = fgets(line, sizeof(line), f);
if (tmp == NULL) break;
if (strncasecmp(line, "LastUsedROM", 11) != 0) continue;
len = strlen(line);
for (i = 0; i < len; i++)
if (line[i] == '#' || line[i] == '\r' || line[i] == '\n') { line[i] = 0; break; }
tmp = strchr(line, '=');
if (tmp == NULL) break;
tmp++;
mystrip(tmp);
len = sizeof(rom_fname_loaded);
strncpy(rom_fname_loaded, tmp, len);
rom_fname_loaded[len-1] = 0;
ret = 0;
break;
}
fclose(f);
return ret;
}
static int custom_read(menu_entry *me, const char *var, const char *val)
{
char *tmp;
switch (me->id)
{
case MA_OPT_FRAMESKIP:
if (strcasecmp(var, "Frameskip") != 0) return 0;
if (strcasecmp(val, "Auto") == 0)
currentConfig.Frameskip = -1;
else currentConfig.Frameskip = atoi(val);
return 1;
case MA_OPT_SOUND_QUALITY:
if (strcasecmp(var, "Sound Quality") != 0) return 0;
PsndRate = strtoul(val, &tmp, 10);
if (PsndRate < 8000 || PsndRate > 44100)
PsndRate = 22050;
if (*tmp == 'H' || *tmp == 'h') tmp++;
if (*tmp == 'Z' || *tmp == 'z') tmp++;
while (*tmp == ' ') tmp++;
if (strcasecmp(tmp, "stereo") == 0) {
PicoOpt |= POPT_EN_STEREO;
} else if (strcasecmp(tmp, "mono") == 0) {
PicoOpt &= ~POPT_EN_STEREO;
} else
return 0;
return 1;
case MA_OPT_REGION:
if (strcasecmp(var, "Region") != 0) return 0;
if (strncasecmp(val, "Auto: ", 6) == 0)
{
const char *p = val + 5, *end = val + strlen(val);
int i;
PicoRegionOverride = PicoAutoRgnOrder = 0;
for (i = 0; p < end && i < 3; i++)
{
while (*p == ' ') p++;
if (p[0] == 'J' && p[1] == 'P') {
PicoAutoRgnOrder |= 1 << (i*4);
} else if (p[0] == 'U' && p[1] == 'S') {
PicoAutoRgnOrder |= 4 << (i*4);
} else if (p[0] == 'E' && p[1] == 'U') {
PicoAutoRgnOrder |= 8 << (i*4);
}
while (*p != ' ' && *p != 0) p++;
if (*p == 0) break;
}
}
else if (strcasecmp(val, "Auto") == 0) {
PicoRegionOverride = 0;
} else if (strcasecmp(val, "Japan NTSC") == 0) {
PicoRegionOverride = 1;
} else if (strcasecmp(val, "Japan PAL") == 0) {
PicoRegionOverride = 2;
} else if (strcasecmp(val, "USA") == 0) {
PicoRegionOverride = 4;
} else if (strcasecmp(val, "Europe") == 0) {
PicoRegionOverride = 8;
} else
return 0;
return 1;
case MA_OPT2_GAMMA:
if (strcasecmp(var, "Gamma correction") != 0) return 0;
currentConfig.gamma = (int) (atof(val) * 100.0);
return 1;
case MA_CDOPT_READAHEAD:
if (strcasecmp(var, "ReadAhead buffer") != 0) return 0;
PicoCDBuffers = atoi(val) / 2;
return 1;
case MA_32XOPT_MSH2_CYCLES:
case MA_32XOPT_SSH2_CYCLES: {
int *mul = (me->id == MA_32XOPT_MSH2_CYCLES) ? &p32x_msh2_multiplier : &p32x_ssh2_multiplier;
*mul = ((unsigned int)atoi(val) << SH2_MULTI_SHIFT) / 7670;
return 1;
}
/* PSP */
case MA_OPT3_SCALE:
if (strcasecmp(var, "Scale factor") != 0) return 0;
currentConfig.scale = atof(val);
return 1;
case MA_OPT3_HSCALE32:
if (strcasecmp(var, "Hor. scale (for low res. games)") != 0) return 0;
currentConfig.hscale32 = atof(val);
return 1;
case MA_OPT3_HSCALE40:
if (strcasecmp(var, "Hor. scale (for hi res. games)") != 0) return 0;
currentConfig.hscale40 = atof(val);
return 1;
case MA_OPT3_VSYNC:
// XXX: use enum
if (strcasecmp(var, "Wait for vsync") != 0) return 0;
if (strcasecmp(val, "never") == 0) {
currentConfig.EmuOpt &= ~0x12000;
} else if (strcasecmp(val, "sometimes") == 0) {
currentConfig.EmuOpt |= 0x12000;
} else if (strcasecmp(val, "always") == 0) {
currentConfig.EmuOpt &= ~0x12000;
currentConfig.EmuOpt |= 0x02000;
} else
return 0;
return 1;
default:
lprintf("unhandled custom_read %i: %s\n", me->id, var);
return 0;
}
}
static unsigned int keys_encountered = 0;
static int parse_bind_val(const char *val, int *type)
{
int i;
*type = IN_BINDTYPE_NONE;
if (val[0] == 0)
return 0;
if (strncasecmp(val, "player", 6) == 0)
{
int player, shift = 0;
player = atoi(val + 6) - 1;
if (player > 1)
return -1;
if (player == 1)
shift = 16;
*type = IN_BINDTYPE_PLAYER12;
for (i = 0; me_ctrl_actions[i].name != NULL; i++) {
if (strncasecmp(me_ctrl_actions[i].name, val + 8, strlen(val + 8)) == 0)
return me_ctrl_actions[i].mask << shift;
}
}
for (i = 0; emuctrl_actions[i].name != NULL; i++) {
if (strncasecmp(emuctrl_actions[i].name, val, strlen(val)) == 0) {
*type = IN_BINDTYPE_EMU;
return emuctrl_actions[i].mask;
}
}
return -1;
}
static void keys_parse(const char *key, const char *val, int dev_id)
{
int acts, type;
acts = parse_bind_val(val, &type);
if (acts == -1) {
lprintf("config: unhandled action \"%s\"\n", val);
return;
}
in_config_bind_key(dev_id, key, acts, type);
}
static int get_numvar_num(const char *var)
{
char *p = NULL;
int num;
if (var[0] == ' ')
return 0;
num = strtoul(var, &p, 10);
if (*p == 0 || *p == ' ')
return num;
return -1;
}
/* map dev number in confing to input dev number */
static unsigned char input_dev_map[IN_MAX_DEVS];
static void parse(const char *var, const char *val)
{
menu_entry *me;
int tmp;
if (strcasecmp(var, "LastUsedROM") == 0)
return; /* handled elsewhere */
if (strcasecmp(var, "Sound Volume") == 0) {
currentConfig.volume = atoi(val);
return;
}
/* input: device name */
if (strncasecmp(var, "input", 5) == 0) {
int num = get_numvar_num(var + 5);
if (num >= 0 && num < IN_MAX_DEVS)
input_dev_map[num] = in_config_parse_dev(val);
else
lprintf("config: failed to parse: %s\n", var);
return;
}
// key binds
if (strncasecmp(var, "bind", 4) == 0) {
const char *p = var + 4;
int num = get_numvar_num(p);
if (num < 0 || num >= IN_MAX_DEVS) {
lprintf("config: failed to parse: %s\n", var);
return;
}
num = input_dev_map[num];
if (num < 0 || num >= IN_MAX_DEVS) {
lprintf("config: invalid device id: %s\n", var);
return;
}
while (*p && *p != ' ') p++;
while (*p && *p == ' ') p++;
keys_parse(p, val, num);
return;
}
for (me = me_list_get_first(); me != NULL; me = me_list_get_next())
{
char *p;
if (!me->need_to_save)
continue;
if (me->name == NULL || strcasecmp(var, me->name) != 0)
continue;
if (me->beh == MB_OPT_ONOFF) {
tmp = strtol(val, &p, 0);
if (*p != 0)
goto bad_val;
if (tmp) *(int *)me->var |= me->mask;
else *(int *)me->var &= ~me->mask;
return;
}
else if (me->beh == MB_OPT_RANGE) {
tmp = strtol(val, &p, 0);
if (*p != 0)
goto bad_val;
if (tmp < me->min) tmp = me->min;
if (tmp > me->max) tmp = me->max;
*(int *)me->var = tmp;
return;
}
else if (me->beh == MB_OPT_ENUM) {
const char **names, *p1;
int i;
names = (const char **)me->data;
if (names == NULL)
goto bad_val;
for (i = 0; names[i] != NULL; i++) {
for (p1 = names[i]; *p1 == ' '; p1++)
;
if (strcasecmp(p1, val) == 0) {
*(int *)me->var = i;
return;
}
}
goto bad_val;
}
else if (custom_read(me, var, val))
return;
}
lprintf("config_readsect: unhandled var: \"%s\"\n", var);
return;
bad_val:
lprintf("config_readsect: unhandled val for \"%s\": %s\n", var, val);
}
int config_havesect(const char *fname, const char *section)
{
FILE *f;
int ret;
f = fopen(fname, "r");
if (f == NULL) return 0;
ret = seek_sect(f, section);
fclose(f);
return ret;
}
int config_readsect(const char *fname, const char *section)
{
char line[128], *var, *val;
FILE *f;
int ret;
f = fopen(fname, "r");
if (f == NULL) return -1;
if (section != NULL)
{
ret = seek_sect(f, section);
if (!ret) {
lprintf("config_readsect: %s: missing section [%s]\n", fname, section);
fclose(f);
return -1;
}
}
keys_encountered = 0;
memset(input_dev_map, 0xff, sizeof(input_dev_map));
while (!feof(f))
{
ret = config_get_var_val(f, line, sizeof(line), &var, &val);
if (ret == 0) break;
if (ret == -1) continue;
parse(var, val);
}
fclose(f);
return 0;
}
#endif // _MSC_VER
static char *mystrip(char *str)
{
int i, len;
len = strlen(str);
for (i = 0; i < len; i++)
if (str[i] != ' ') break;
if (i > 0) memmove(str, str + i, len - i + 1);
len = strlen(str);
for (i = len - 1; i >= 0; i--)
if (str[i] != ' ') break;
str[i+1] = 0;
return str;
}
/* returns:
* 0 - EOF, end
* 1 - parsed ok
* -1 - failed to parse line
*/
int config_get_var_val(void *file, char *line, int lsize, char **rvar, char **rval)
{
char *var, *val, *tmp;
FILE *f = file;
int len, i;
tmp = fgets(line, lsize, f);
if (tmp == NULL) return 0;
if (line[0] == '[') return 0; // other section
// strip comments, linefeed, spaces..
len = strlen(line);
for (i = 0; i < len; i++)
if (line[i] == '#' || line[i] == '\r' || line[i] == '\n') { line[i] = 0; break; }
mystrip(line);
len = strlen(line);
if (len <= 0) return -1;;
// get var and val
for (i = 0; i < len; i++)
if (line[i] == '=') break;
if (i >= len || strchr(&line[i+1], '=') != NULL) {
lprintf("config_readsect: can't parse: %s\n", line);
return -1;
}
line[i] = 0;
var = line;
val = &line[i+1];
mystrip(var);
mystrip(val);
#ifndef _MSC_VER
if (strlen(var) == 0 || (strlen(val) == 0 && strncasecmp(var, "bind", 4) != 0)) {
lprintf("config_readsect: something's empty: \"%s\" = \"%s\"\n", var, val);
return -1;;
}
#endif
*rvar = var;
*rval = val;
return 1;
}

View file

@ -1,16 +0,0 @@
#ifdef __cplusplus
extern "C" {
#endif
int config_writesect(const char *fname, const char *section);
int config_writelrom(const char *fname);
int config_readsect(const char *fname, const char *section);
int config_readlrom(const char *fname);
int config_havesect(const char *fname, const char *section);
int config_get_var_val(void *file, char *line, int lsize, char **rvar, char **rval);
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,155 +0,0 @@
// (c) Copyright 2006-2007 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include "port_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#define array_size(x) (sizeof(x) / sizeof(x[0]))
extern void *g_screen_ptr;
#if SCREEN_SIZE_FIXED
#define g_screen_width SCREEN_WIDTH
#define g_screen_height SCREEN_HEIGHT
#else
extern int g_screen_width;
extern int g_screen_height;
#endif
#define EOPT_EN_SRAM (1<<0)
#define EOPT_SHOW_FPS (1<<1)
#define EOPT_EN_SOUND (1<<2)
#define EOPT_GZIP_SAVES (1<<3)
#define EOPT_MMUHACK (1<<4)
#define EOPT_NO_AUTOSVCFG (1<<5)
#define EOPT_16BPP (1<<7) // depreceted for .renderer
#define EOPT_RAM_TIMINGS (1<<8)
#define EOPT_EN_CD_LEDS (1<<10)
#define EOPT_A_SN_GAMMA (1<<12)
#define EOPT_VSYNC (1<<13)
#define EOPT_GIZ_SCANLN (1<<14)
#define EOPT_GIZ_DBLBUF (1<<15)
#define EOPT_VSYNC_MODE (1<<16)
#define EOPT_SHOW_RTC (1<<17)
#define EOPT_NO_FRMLIMIT (1<<18)
#define EOPT_WIZ_TEAR_FIX (1<<19)
#define EOPT_EXT_FRMLIMIT (1<<20) // no internal frame limiter (limited by snd, etc)
enum {
EOPT_SCALE_NONE = 0,
EOPT_SCALE_SW,
EOPT_SCALE_HW,
};
enum {
EOPT_CONFIRM_NONE = 0,
EOPT_CONFIRM_SAVE = 1,
EOPT_CONFIRM_LOAD = 2,
EOPT_CONFIRM_BOTH = 3,
};
typedef struct _currentConfig_t {
int EmuOpt;
int s_PicoOpt;
int s_PsndRate;
int s_PicoRegion;
int s_PicoAutoRgnOrder;
int s_PicoCDBuffers;
int Frameskip;
int confirm_save;
int CPUclock;
int volume;
int gamma;
int scaling; // gp2x: EOPT_SCALE_*; psp: bilinear filtering
int vscaling;
int rotation; // for UIQ
float scale; // psp: screen scale
float hscale32, hscale40; // psp: horizontal scale
int gamma2; // psp: black level
int turbo_rate;
int renderer;
int renderer32x;
int filter; // pandora
int analog_deadzone;
} currentConfig_t;
extern currentConfig_t currentConfig, defaultConfig;
extern char *PicoConfigFile;
extern int rom_loaded;
extern int state_slot;
extern int config_slot, config_slot_current;
extern unsigned char *movie_data;
extern int reset_timing;
#define PICO_PEN_ADJUST_X 4
#define PICO_PEN_ADJUST_Y 2
extern int pico_pen_x, pico_pen_y;
extern int pico_inp_mode;
extern char rom_fname_reload[512]; // ROM to try loading on next PGS_ReloadRom
extern char rom_fname_loaded[512]; // currently loaded ROM filename
// engine states
extern int engineState;
enum TPicoGameState {
PGS_Paused = 1,
PGS_Running,
PGS_Quit,
PGS_KeyConfig,
PGS_ReloadRom,
PGS_Menu,
PGS_TrayMenu,
PGS_RestartRun,
PGS_Suspending, /* PSP */
PGS_SuspendWake, /* PSP */
};
// media types
enum {
PM_BAD = 0,
PM_MD_CART, /* also 32x */
PM_MARK3,
PM_CD,
};
void emu_init(void);
void emu_finish(void);
void emu_loop(void);
int emu_reload_rom(char *rom_fname);
int emu_swap_cd(const char *fname);
int emu_save_load_game(int load, int sram);
void emu_reset_game(void);
void emu_prep_defconfig(void);
void emu_set_defconfig(void);
int emu_read_config(const char *rom_fname, int no_defaults);
int emu_write_config(int game);
char *emu_get_save_fname(int load, int is_sram, int slot);
int emu_check_save_file(int slot, int *time);
void emu_text_out8 (int x, int y, const char *text);
void emu_text_out16(int x, int y, const char *text);
void emu_text_out8_rot (int x, int y, const char *text);
void emu_text_out16_rot(int x, int y, const char *text);
void emu_make_path(char *buff, const char *end, int size);
void emu_update_input(void);
void emu_get_game_name(char *str150);
void emu_set_fastforward(int set_on);
void emu_status_msg(const char *format, ...);
/* used by some (but not all) platforms */
void emu_cmn_forced_frame(int no_scale, int do_emu);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -1,148 +0,0 @@
// (c) Copyright 2006-2009 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "menu.h"
#include "emu.h"
#include "config.h"
#include "input.h"
#include "plat.h"
#include <cpu/debug.h>
#include <version.h>
extern char *PicoConfigFile;
static int load_state_slot = -1;
char **g_argv;
void parse_cmd_line(int argc, char *argv[])
{
int x, unrecognized = 0;
for (x = 1; x < argc; x++)
{
if (argv[x][0] == '-')
{
if (strcasecmp(argv[x], "-config") == 0) {
if (x+1 < argc) { ++x; PicoConfigFile = argv[x]; }
}
else if (strcasecmp(argv[x], "-loadstate") == 0) {
if (x+1 < argc) { ++x; load_state_slot = atoi(argv[x]); }
}
else if (strcasecmp(argv[x], "-pdb") == 0) {
if (x+1 < argc) { ++x; pdb_command(argv[x]); }
}
else if (strcasecmp(argv[x], "-pdb_connect") == 0) {
if (x+2 < argc) { pdb_net_connect(argv[x+1], argv[x+2]); x += 2; }
}
else {
unrecognized = 1;
break;
}
} else {
/* External Frontend: ROM Name */
FILE *f;
strncpy(rom_fname_reload, argv[x], sizeof(rom_fname_reload));
rom_fname_reload[sizeof(rom_fname_reload) - 1] = 0;
f = fopen(rom_fname_reload, "rb");
if (f) fclose(f);
else unrecognized = 1;
engineState = PGS_ReloadRom;
break;
}
}
if (unrecognized) {
printf("\n\n\nPicoDrive v" VERSION " (c) notaz, 2006-2009\n");
printf("usage: %s [options] [romfile]\n", argv[0]);
printf("options:\n"
" -config <file> use specified config file instead of default 'config.cfg'\n"
" -loadstate <num> if ROM is specified, try loading slot <num>\n");
}
}
int main(int argc, char *argv[])
{
g_argv = argv;
plat_early_init();
in_init();
in_probe();
plat_init();
emu_prep_defconfig(); // depends on input
emu_read_config(NULL, 0);
emu_init();
menu_init();
engineState = PGS_Menu;
if (argc > 1)
parse_cmd_line(argc, argv);
if (engineState == PGS_ReloadRom)
{
if (emu_reload_rom(rom_fname_reload)) {
engineState = PGS_Running;
if (load_state_slot >= 0) {
state_slot = load_state_slot;
emu_save_load_game(1, 0);
}
}
}
for (;;)
{
switch (engineState)
{
case PGS_Menu:
menu_loop();
break;
case PGS_TrayMenu:
menu_loop_tray();
break;
case PGS_ReloadRom:
if (emu_reload_rom(rom_fname_reload))
engineState = PGS_Running;
else {
printf("PGS_ReloadRom == 0\n");
engineState = PGS_Menu;
}
break;
case PGS_RestartRun:
engineState = PGS_Running;
/* vvv fallthrough */
case PGS_Running:
emu_loop();
break;
case PGS_Quit:
goto endloop;
default:
printf("engine got into unknown state (%i), exitting\n", engineState);
goto endloop;
}
}
endloop:
emu_finish();
plat_finish();
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -1,94 +0,0 @@
typedef enum
{
MA_NONE = 1,
MA_MAIN_RESUME_GAME,
MA_MAIN_SAVE_STATE,
MA_MAIN_LOAD_STATE,
MA_MAIN_RESET_GAME,
MA_MAIN_LOAD_ROM,
MA_MAIN_CONTROLS,
MA_MAIN_CREDITS,
MA_MAIN_PATCHES,
MA_MAIN_EXIT,
MA_OPT_RENDERER,
MA_OPT_SCALING,
MA_OPT_VSCALING,
MA_OPT_ACC_SPRITES,
MA_OPT_SHOW_FPS,
MA_OPT_FRAMESKIP,
MA_OPT_ENABLE_SOUND,
MA_OPT_SOUND_QUALITY,
MA_OPT_ARM940_SOUND,
MA_OPT_6BUTTON_PAD,
MA_OPT_REGION,
MA_OPT_SRAM_STATES,
MA_OPT_CONFIRM_STATES,
MA_OPT_SAVE_SLOT,
MA_OPT_CPU_CLOCKS,
MA_OPT_SCD_OPTS,
MA_OPT_ADV_OPTS,
MA_OPT_DISP_OPTS, /* psp */
MA_OPT_SAVECFG,
MA_OPT_SAVECFG_GAME,
MA_OPT_LOADCFG,
MA_OPT_INTERLACED, /* giz */
MA_OPT_ROTATION, /* uiq */
MA_OPT_TEARING_FIX, /* wiz */
MA_OPT2_GAMMA,
MA_OPT2_A_SN_GAMMA,
MA_OPT2_DBLBUFF, /* giz */
MA_OPT2_VSYNC,
MA_OPT2_ENABLE_Z80,
MA_OPT2_ENABLE_YM2612,
MA_OPT2_ENABLE_SN76496,
MA_OPT2_GZIP_STATES,
MA_OPT2_NO_LAST_ROM,
MA_OPT2_RAMTIMINGS, /* gp2x */
MA_OPT2_SQUIDGEHACK, /* gp2x */
MA_OPT2_STATUS_LINE, /* psp */
MA_OPT2_NO_FRAME_LIMIT, /* psp */
MA_OPT2_SVP_DYNAREC,
MA_OPT2_NO_SPRITE_LIM,
MA_OPT2_NO_IDLE_LOOPS,
MA_OPT2_DONE,
MA_OPT3_SCALE, /* psp (all OPT3) */
MA_OPT3_HSCALE32,
MA_OPT3_HSCALE40,
MA_OPT3_PRES_NOSCALE,
MA_OPT3_PRES_SCALE43,
MA_OPT3_PRES_FULLSCR,
MA_OPT3_FILTERING,
MA_OPT3_VSYNC,
MA_OPT3_GAMMAA,
MA_OPT3_BLACKLVL,
MA_OPT3_LAYER_X,
MA_OPT3_LAYER_Y,
MA_OPT3_LAYER_W,
MA_OPT3_LAYER_H,
MA_OPT3_DONE,
MA_CDOPT_TESTBIOS_USA,
MA_CDOPT_TESTBIOS_EUR,
MA_CDOPT_TESTBIOS_JAP,
MA_CDOPT_LEDS,
MA_CDOPT_CDDA,
MA_CDOPT_PCM,
MA_CDOPT_READAHEAD,
MA_CDOPT_SAVERAM,
MA_CDOPT_SCALEROT_CHIP,
MA_CDOPT_BETTER_SYNC,
MA_CDOPT_DONE,
MA_32XOPT_ENABLE_32X,
MA_32XOPT_RENDERER,
MA_32XOPT_PWM,
MA_32XOPT_MSH2_CYCLES,
MA_32XOPT_SSH2_CYCLES,
MA_CTRL_PLAYER1,
MA_CTRL_PLAYER2,
MA_CTRL_EMU,
MA_CTRL_TURBO_RATE,
MA_CTRL_DEADZONE,
MA_CTRL_DEV_FIRST,
MA_CTRL_DEV_NEXT,
MA_CTRL_DONE,
} menu_id;

View file

@ -1,29 +0,0 @@
#include "mp3.h"
int mp3_find_sync_word(const unsigned char *buf, int size)
{
const unsigned char *p, *pe;
/* find byte-aligned syncword - need 12 (MPEG 1,2) or 11 (MPEG 2.5) matching bits */
for (p = buf, pe = buf + size - 3; p <= pe; p++)
{
int pn;
if (p[0] != 0xff)
continue;
pn = p[1];
if ((pn & 0xf8) != 0xf8 || // currently must be MPEG1
(pn & 6) == 0) { // invalid layer
p++; continue;
}
pn = p[2];
if ((pn & 0xf0) < 0x20 || (pn & 0xf0) == 0xf0 || // bitrates
(pn & 0x0c) != 0) { // not 44kHz
continue;
}
return p - buf;
}
return -1;
}

View file

@ -1,8 +0,0 @@
int mp3_find_sync_word(const unsigned char *buf, int size);
#ifdef __GP2X__
void mp3_update_local(int *buffer, int length, int stereo);
void mp3_start_play_local(void *f, int pos);
#endif

View file

@ -1,220 +0,0 @@
// Some mp3 related code for Sega/Mega CD.
// Uses the Helix Fixed-point MP3 decoder
// (c) Copyright 2007, Grazvydas "notaz" Ignotas
#include <stdio.h>
#include <string.h>
#include <pico/pico_int.h>
#include <pico/sound/mix.h>
#include "helix/pub/mp3dec.h"
#include "mp3.h"
#include "lprintf.h"
static HMP3Decoder mp3dec = 0;
static FILE *mp3_current_file = NULL;
static int mp3_file_len = 0, mp3_file_pos = 0;
static int mp3_buffer_offs = 0;
static unsigned char mp3_input_buffer[2*1024];
#ifdef __GP2X__
#define mp3_update mp3_update_local
#define mp3_start_play mp3_start_play_local
#endif
static int try_get_header(unsigned char *buff, MP3FrameInfo *fi)
{
int ret, offs1, offs = 0;
while (1)
{
offs1 = mp3_find_sync_word(buff + offs, 2048 - offs);
if (offs1 < 0) return -2;
offs += offs1;
if (2048 - offs < 4) return -3;
// printf("trying header %08x\n", *(int *)(buff + offs));
ret = MP3GetNextFrameInfo(mp3dec, fi, buff + offs);
if (ret == 0 && fi->bitrate != 0) break;
offs++;
}
return ret;
}
int mp3_get_bitrate(void *f_, int len)
{
unsigned char buff[2048];
MP3FrameInfo fi;
FILE *f = f_;
int ret;
memset(buff, 0, sizeof(buff));
if (mp3dec)
MP3FreeDecoder(mp3dec);
mp3dec = MP3InitDecoder();
fseek(f, 0, SEEK_SET);
ret = fread(buff, 1, sizeof(buff), f);
fseek(f, 0, SEEK_SET);
if (ret <= 0)
return -1;
ret = try_get_header(buff, &fi);
if (ret != 0 || fi.bitrate == 0) {
// try to read somewhere around the middle
fseek(f, len>>1, SEEK_SET);
fread(buff, 1, 2048, f);
fseek(f, 0, SEEK_SET);
ret = try_get_header(buff, &fi);
}
if (ret != 0)
return ret;
// printf("bitrate: %i\n", fi.bitrate / 1000);
return fi.bitrate / 1000;
}
static int mp3_decode(void)
{
unsigned char *readPtr;
int bytesLeft;
int offset; // mp3 frame offset from readPtr
int had_err;
int err = 0;
do
{
if (mp3_file_pos >= mp3_file_len)
return 1; /* EOF, nothing to do */
fseek(mp3_current_file, mp3_file_pos, SEEK_SET);
bytesLeft = fread(mp3_input_buffer, 1, sizeof(mp3_input_buffer), mp3_current_file);
offset = mp3_find_sync_word(mp3_input_buffer, bytesLeft);
if (offset < 0) {
lprintf("find_sync_word (%i/%i) err %i\n", mp3_file_pos, mp3_file_len, offset);
mp3_file_pos = mp3_file_len;
return 1; // EOF
}
readPtr = mp3_input_buffer + offset;
bytesLeft -= offset;
had_err = err;
err = MP3Decode(mp3dec, &readPtr, &bytesLeft, cdda_out_buffer, 0);
if (err) {
if (err == ERR_MP3_MAINDATA_UNDERFLOW && !had_err) {
// just need another frame
mp3_file_pos += readPtr - mp3_input_buffer;
continue;
}
if (err == ERR_MP3_INDATA_UNDERFLOW && !had_err) {
if (offset == 0)
// something's really wrong here, frame had to fit
mp3_file_pos = mp3_file_len;
else
mp3_file_pos += offset;
continue;
}
if (-12 <= err && err <= -6) {
// ERR_MP3_INVALID_FRAMEHEADER, ERR_MP3_INVALID_*
// just try to skip the offending frame..
mp3_file_pos += offset + 1;
continue;
}
lprintf("MP3Decode err (%i/%i) %i\n", mp3_file_pos, mp3_file_len, err);
mp3_file_pos = mp3_file_len;
return 1;
}
mp3_file_pos += readPtr - mp3_input_buffer;
}
while (0);
return 0;
}
void mp3_start_play(void *f_, int pos)
{
FILE *f = f_;
mp3_file_len = mp3_file_pos = 0;
mp3_current_file = NULL;
mp3_buffer_offs = 0;
if (!(PicoOpt & POPT_EN_MCD_CDDA) || f == NULL) // cdda disabled or no file?
return;
// must re-init decoder for new track
if (mp3dec)
MP3FreeDecoder(mp3dec);
mp3dec = MP3InitDecoder();
mp3_current_file = f;
fseek(f, 0, SEEK_END);
mp3_file_len = ftell(f);
// search for first sync word, skipping stuff like ID3 tags
while (mp3_file_pos < 128*1024) {
int offs, bytes;
fseek(f, mp3_file_pos, SEEK_SET);
bytes = fread(mp3_input_buffer, 1, sizeof(mp3_input_buffer), f);
if (bytes < 4)
break;
offs = mp3_find_sync_word(mp3_input_buffer, bytes);
if (offs >= 0) {
mp3_file_pos += offs;
break;
}
mp3_file_pos += bytes - 2;
}
// seek..
if (pos) {
unsigned long long pos64 = mp3_file_len - mp3_file_pos;
pos64 *= pos;
mp3_file_pos += pos64 >> 10;
}
mp3_decode();
}
void mp3_update(int *buffer, int length, int stereo)
{
int length_mp3, shr = 0;
void (*mix_samples)(int *dest_buf, short *mp3_buf, int count) = mix_16h_to_32;
if (mp3_current_file == NULL || mp3_file_pos >= mp3_file_len)
return; /* no file / EOF */
length_mp3 = length;
if (PsndRate <= 11025 + 100) {
mix_samples = mix_16h_to_32_s2;
length_mp3 <<= 2; shr = 2;
}
else if (PsndRate <= 22050 + 100) {
mix_samples = mix_16h_to_32_s1;
length_mp3 <<= 1; shr = 1;
}
if (1152 - mp3_buffer_offs >= length_mp3) {
mix_samples(buffer, cdda_out_buffer + mp3_buffer_offs*2, length<<1);
mp3_buffer_offs += length_mp3;
} else {
int ret, left = 1152 - mp3_buffer_offs;
mix_samples(buffer, cdda_out_buffer + mp3_buffer_offs*2, (left>>shr)<<1);
ret = mp3_decode();
if (ret == 0) {
mp3_buffer_offs = length_mp3 - left;
mix_samples(buffer + ((left>>shr)<<1), cdda_out_buffer, (mp3_buffer_offs>>shr)<<1);
} else
mp3_buffer_offs = 0;
}
}

View file

@ -1,12 +0,0 @@
platform/common/menu.o : revision.h
revision.h: FORCE
ifndef NOREVISION
@echo "#define REVISION \"`svn info -r HEAD | grep Revision | cut -c 11-`\"" > /tmp/r.tmp
else
@echo "#define REVISION \"0\"" > /tmp/r.tmp
endif
@diff -q $@ /tmp/r.tmp > /dev/null 2>&1 || mv -f /tmp/r.tmp $@
FORCE:

View file

@ -1,166 +0,0 @@
#
# Sega/Mega CD games
#
[CD|GM MK-4432 -00|U|ADVENTURES OF BA]
Scale/Rot. fx (slow) = 1
Better sync (slow) = 1
[CD|GM T-60055-00|U|AH3-THUNDERSTRIKE]
Scale/Rot. fx (slow) = 1
[CD|GM MK-4401 -00|U|BATMAN RETURNS]
Scale/Rot. fx (slow) = 1
[CD|GM T-115075-00|U|BCRACERS]
Scale/Rot. fx (slow) = 1
[CD|GM MK-4402|U|COBRA COMMAND]
Better sync (slow) = 1
[CD|GM T-121015-00|U|DRAGONS LAIR]
Renderer = 16bit accurate
[CD|GM T-60094|J|JAGUAR XJ220]
Renderer = 16bit accurate
[CD|GM T-127015-00|U|LUNAR]
Scale/Rot. fx (slow) = 1
[CD|GM T-111065 -0|U|MAD DOG II THE LOST GOLD]
Renderer = 16bit accurate
[CD|GM T-11105 -00|U|MAD DOG MCCREE]
Renderer = 16bit accurate
[CD|GM T-81025-00|U|MORTAL KOMBAT]
Renderer = 16bit accurate
Better sync (slow) = 1
[CD|GM T-04903-01|U|NIGHT TRAP]
Renderer = 16bit accurate
[CD|GM T-113025-00|U|NOVASTORM]
Better sync (slow) = 1
[CD|GM T-127035-00|U|Popful MAIL]
Better sync (slow) = 1
[CD|MK 4603-50|JUE|ROAD AVENGER]
Renderer = 16bit accurate
Better sync (slow) = 1
[CD|GM T-50085|U|ROAD RASH]
Renderer = 16bit accurate
Better sync (slow) = 1
[CD|GM MK-4416 -00|E|ROBO ALESTE]
Renderer = 16bit accurate
[CD|GM T-06201-03|U|SEWER SHARK]
Renderer = 16bit accurate
[CD|GM T-113045-00|E|SHADOW OF THE BEAST TWO]
Renderer = 16bit accurate
[CD|GM MK-4404|U|SOL-FEACE]
Better sync (slow) = 1
[CD|GM MK-4407-00|E|SONIC THE HEDGEHOG-CD]
Scale/Rot. fx (slow) = 1
[CD|GM MK-4407 -00|U|SONIC THE HEDGEHOG-CD]
Scale/Rot. fx (slow) = 1
[CD|GM T-22025-00|U|THE 3RD WORLD WAR]
Better sync (slow) = 1
[CD|GM MK- 4430 -|E|YUMEMI MISTERY MANSION]
Renderer = 16bit accurate
#
# Virtua Racing
#
[MD|GM MK-1229 -00|U|Virtua Racing]
Renderer = 8bit fast
Show FPS = 1
GP2X CPU clocks = 235
[MD|GM G-7001 -00|J|Virtua Racing]
Renderer = 8bit fast
Show FPS = 1
GP2X CPU clocks = 235
[MD|GM MK-1229 -00|E|Virtua Racing]
Renderer = 8bit fast
Show FPS = 1
GP2X CPU clocks = 235
[MD|GM MK-1229 -00|E|VIRTUA RACING \00\00\00\00\00\00\00\00\00]
Renderer = 8bit fast
Show FPS = 1
GP2X CPU clocks = 235
#
# Genesis/MegaDrive games
#
[MD|GM MK-1029-00|E| BURNING FORCE]
Renderer = 16bit accurate
[MD|GM T-14023 -00|J| BURNING FORCE]
Renderer = 16bit accurate
[MD|GM T-14026 -00|U| BURNING FORCE]
Renderer = 16bit accurate
[MD|GM T-95076-00|U|CASTLEVANIA BLOODLINES]
Renderer = 16bit accurate
[MD|GM T-95076-00|E|CASTLEVANIA THE NEW GENERATION]
Renderer = 16bit accurate
[MD|GM MK-1569 -50|A|COMIX ZONE]
Renderer = 16bit accurate
[MD|GM G-4132 -00|1|]
Renderer = 16bit accurate
[MD|GM MK-1569 -00|4|COMIX ZONE]
Renderer = 16bit accurate
[MD|GM T-097116 00|4|MORTAL KOMBAT 3]
Renderer = 16bit accurate
[MD|GM G-4119-00|J| OUT_RUNNERS 1994/03/03 Ver.FINAL!!]
Renderer = 16bit accurate
[MD|GM T-13096-00|U| OUT_RUNNERS]
Renderer = 16bit accurate
[MD|GM T-48376 00|JUE|RED-ZONE]
Renderer = 16bit accurate
[MD|GM T-177016-00|F|STREET RACER]
Renderer = 16bit accurate
[MD|GM T-95043-00|J|]
Renderer = 16bit accurate
[MD|GM T-25036 -00|U| SHOVE IT!]
Renderer = 16bit accurate
[MD|GM MK-1104 -00|U|AFTER BURNERII]
Renderer = 16bit accurate
[MD|GM T-32053 -00|U|ARCUS ODYSSEY]
Renderer = 16bit accurate
[MD|GM 00054010-00|JUE|RAMBO \87V]
Renderer = 16bit accurate
[MD|GM 00054010-01|JUE|RAMBO \87V]
Renderer = 16bit accurate
[MD|GM T-50406 -01|U|GALAHAD]
Renderer = 16bit accurate

View file

@ -1,529 +0,0 @@
// Code for communication with ARM940 and control of it.
// (c) Copyright 2007, Grazvydas "notaz" Ignotas
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include "code940/940shared.h"
#include "soc_mmsp2.h"
#include "soc.h"
#include "../common/mp3.h"
#include "../common/arm_utils.h"
#include "../common/menu.h"
#include "../common/emu.h"
#include "../common/input.h"
#include "../../pico/pico_int.h"
#include "../../pico/sound/ym2612.h"
#include "../../pico/sound/mix.h"
static unsigned char *shared_mem = 0;
static _940_data_t *shared_data = 0;
_940_ctl_t *shared_ctl = 0;
unsigned char *mp3_mem = 0;
#define MP3_SIZE_MAX (0x400000 + 0x800000) // 12M
#define CODE940_FILE "pico940_v3.bin"
int crashed_940 = 0;
static FILE *loaded_mp3 = 0;
/***********************************************************/
#define MAXOUT (+32767)
#define MINOUT (-32768)
/* limitter */
#define Limit(val, max,min) { \
if ( val > max ) val = max; \
else if ( val < min ) val = min; \
}
/* these will be managed locally on our side */
static UINT8 ST_address; /* address register */
static INT32 addr_A1; /* address line A1 */
static int writebuff_ptr = 0;
/* YM2612 write */
/* a = address */
/* v = value */
/* returns 1 if sample affecting state changed */
int YM2612Write_940(unsigned int a, unsigned int v, int scanline)
{
int upd = 1; /* the write affects sample generation */
a &= 3;
//printf("%05i:%03i: ym w ([%i] %02x)\n", Pico.m.frame_count, Pico.m.scanline, a, v);
switch (a)
{
case 0: /* address port 0 */
if (addr_A1 == 0 && ST_address == v)
return 0; /* address already selected, don't send this command to 940 */
ST_address = v;
addr_A1 = 0;
/* don't send DAC or timer related address changes to 940 */
if (v == 0x24 || v == 0x25 || v == 0x26 || v == 0x2a)
return 0;
upd = 0;
break;
case 2: /* address port 1 */
if (addr_A1 == 1 && ST_address == v)
return 0;
ST_address = v;
addr_A1 = 1;
upd = 0;
break;
}
//printf("ym pass\n");
if (currentConfig.EmuOpt & 4)
{
UINT16 *writebuff = shared_ctl->writebuffsel ? shared_ctl->writebuff0 : shared_ctl->writebuff1;
/* detect rapid ym updates */
if (upd && !(writebuff_ptr & 0x80000000) && scanline < 224)
{
int mid = Pico.m.pal ? 68 : 93;
if (scanline > mid) {
//printf("%05i:%03i: rapid ym\n", Pico.m.frame_count, scanline);
writebuff[writebuff_ptr++ & 0xffff] = 0xfffe;
writebuff_ptr |= 0x80000000;
//printf("%05i:%03i: ym w ([%02x] %02x, upd=%i)\n", Pico.m.frame_count, scanline, addr, v, upd);
}
}
/* queue this write for 940 */
if ((writebuff_ptr&0xffff) < 2047) {
writebuff[writebuff_ptr++ & 0xffff] = (a<<8)|v;
} else {
printf("warning: writebuff_ptr > 2047 ([%i] %02x)\n", a, v);
}
}
return 0; // cause the engine to do updates once per frame only
}
#define CHECK_BUSY(job) \
(gp2x_memregs[0x3b46>>1] & (1<<(job-1)))
static void wait_busy_940(int job)
{
int i;
job--;
for (i = 0; (gp2x_memregs[0x3b46>>1] & (1<<job)) && i < 0x10000; i++)
spend_cycles(8*1024); // tested to be best for mp3 dec
if (i < 0x10000) return;
/* 940 crashed */
printf("940 crashed (cnt: %i, ve: ", shared_ctl->loopc);
for (i = 0; i < 8; i++)
printf("%i ", shared_ctl->vstarts[i]);
printf(")\n");
printf("irq pending flags: DUALCPU %04x, SRCPND %08lx (see 26), INTPND %08lx\n",
gp2x_memregs[0x3b46>>1], gp2x_memregl[0x4500>>2], gp2x_memregl[0x4510>>2]);
printf("last lr: %08x, lastjob: %i\n", shared_ctl->last_lr, shared_ctl->lastjob);
printf("trying to interrupt..\n");
gp2x_memregs[0x3B3E>>1] = 0xffff;
for (i = 0; gp2x_memregs[0x3b46>>1] && i < 0x10000; i++)
spend_cycles(8*1024);
printf("i = 0x%x\n", i);
printf("irq pending flags: DUALCPU %04x, SRCPND %08lx (see 26), INTPND %08lx\n",
gp2x_memregs[0x3b46>>1], gp2x_memregl[0x4500>>2], gp2x_memregl[0x4510>>2]);
printf("last lr: %08x, lastjob: %i\n", shared_ctl->last_lr, shared_ctl->lastjob);
me_update_msg("940 crashed, too much overclock?");
engineState = PGS_Menu;
crashed_940 = 1;
}
static void add_job_940(int job)
{
if (job <= 0 || job > 16) {
printf("add_job_940: bad job: %i\n", job);
return;
}
// generate interrupt for this job
job--;
gp2x_memregs[(0x3B20+job*2)>>1] = 1;
// printf("added %i, pending %04x\n", job+1, gp2x_memregs[0x3b46>>1]);
}
void YM2612PicoStateLoad_940(void)
{
UINT8 *REGS = YM2612GetRegs();
/* make sure JOB940_PICOSTATELOAD gets done before next JOB940_YM2612UPDATEONE */
add_job_940(JOB940_PICOSTATELOAD);
if (CHECK_BUSY(JOB940_PICOSTATELOAD)) wait_busy_940(JOB940_PICOSTATELOAD);
writebuff_ptr = 0;
addr_A1 = *(INT32 *) (REGS + 0x200);
}
void YM2612PicoStateSave2_940(int tat, int tbt)
{
UINT8 *ym_remote_regs, *ym_local_regs;
add_job_940(JOB940_PICOSTATESAVE2);
if (CHECK_BUSY(JOB940_PICOSTATESAVE2)) wait_busy_940(JOB940_PICOSTATESAVE2);
ym_remote_regs = (UINT8 *) shared_ctl->writebuff0;
ym_local_regs = YM2612GetRegs();
if (*(UINT32 *)(ym_remote_regs + 0x100) != 0x41534d59) {
printf("code940 didn't return valid save data\n");
return;
}
/* copy addin data only */
memcpy(ym_local_regs, ym_remote_regs, 0x20);
memcpy(ym_local_regs + 0x100, ym_remote_regs + 0x100, 0x30);
memcpy(ym_local_regs + 0x0b8, ym_remote_regs + 0x0b8, 0x48);
memcpy(ym_local_regs + 0x1b8, ym_remote_regs + 0x1b8, 0x48);
*(INT32 *)(ym_local_regs + 0x108) = tat;
*(INT32 *)(ym_local_regs + 0x10c) = tbt;
}
int YM2612PicoStateLoad2_940(int *tat, int *tbt)
{
UINT8 *ym_remote_regs, *ym_local_regs;
ym_local_regs = YM2612GetRegs();
ym_remote_regs = (UINT8 *) shared_ctl->writebuff0;
if (*(UINT32 *)(ym_local_regs + 0x100) != 0x41534d59)
return -1;
*tat = *(INT32 *)(ym_local_regs + 0x108);
*tbt = *(INT32 *)(ym_local_regs + 0x10c);
if (CHECK_BUSY(JOB940_YM2612UPDATEONE)) wait_busy_940(JOB940_YM2612UPDATEONE);
/* flush writes */
if (shared_ctl->writebuffsel == 1) {
shared_ctl->writebuff0[writebuff_ptr & 0xffff] = 0xffff;
} else {
shared_ctl->writebuff1[writebuff_ptr & 0xffff] = 0xffff;
}
shared_ctl->writebuffsel ^= 1;
writebuff_ptr = 0;
add_job_940(JOB940_PICOSTATELOAD2_PREP);
if (CHECK_BUSY(JOB940_PICOSTATELOAD2_PREP)) wait_busy_940(JOB940_PICOSTATELOAD2_PREP);
memcpy(ym_remote_regs, ym_local_regs, 0x200);
add_job_940(JOB940_PICOSTATELOAD2);
if (CHECK_BUSY(JOB940_PICOSTATELOAD2)) wait_busy_940(JOB940_PICOSTATELOAD2);
return 0;
}
static void internal_reset(void)
{
writebuff_ptr = 0;
ST_address = addr_A1 = -1;
}
/* this must be called after mmu hack, the allocated regions must not get cached */
void sharedmem940_init(void)
{
if (shared_mem != NULL) return;
shared_mem = (unsigned char *) mmap(0, 0x210000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0x2000000);
if (shared_mem == MAP_FAILED)
{
printf("mmap(shared_data) failed with %i\n", errno);
exit(1);
}
shared_data = (_940_data_t *) (shared_mem+0x100000);
/* this area must not get buffered on either side */
shared_ctl = (_940_ctl_t *) (shared_mem+0x200000);
mp3_mem = (unsigned char *) mmap(0, MP3_SIZE_MAX, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0x2400000);
if (mp3_mem == MAP_FAILED)
{
printf("mmap(mp3_mem) failed with %i\n", errno);
exit(1);
}
crashed_940 = 1;
}
void sharedmem940_finish(void)
{
munmap(shared_mem, 0x210000);
munmap(mp3_mem, MP3_SIZE_MAX);
shared_mem = mp3_mem = NULL;
shared_data = NULL;
shared_ctl = NULL;
}
void YM2612Init_940(int baseclock, int rate)
{
printf("YM2612Init_940()\n");
printf("Mem usage: shared_data: %i, shared_ctl: %i\n", sizeof(*shared_data), sizeof(*shared_ctl));
reset940(1, 2);
pause940(1);
gp2x_memregs[0x3B40>>1] = 0; // disable DUALCPU interrupts for 920
gp2x_memregs[0x3B42>>1] = 1; // enable DUALCPU interrupts for 940
gp2x_memregl[0x4504>>2] = 0; // make sure no FIQs will be generated
gp2x_memregl[0x4508>>2] = ~(1<<26); // unmask DUALCPU ints in the undocumented 940's interrupt controller
if (crashed_940)
{
unsigned char ucData[1024];
int nRead, nLen = 0;
char binpath[512];
FILE *fp;
emu_make_path(binpath, CODE940_FILE, sizeof(binpath));
fp = fopen(binpath, "rb");
if(!fp)
{
memset(g_screen_ptr, 0, 320*240*2);
text_out16(10, 100, "failed to open required file:");
text_out16(10, 110, CODE940_FILE);
gp2x_video_flip2();
in_menu_wait(PBTN_MOK|PBTN_MBACK, 100);
printf("failed to open %s\n", binpath);
exit(1);
}
while(1)
{
nRead = fread(ucData, 1, 1024, fp);
if(nRead <= 0)
break;
memcpy(shared_mem + nLen, ucData, nRead);
nLen += nRead;
}
fclose(fp);
crashed_940 = 0;
}
memset(shared_data, 0, sizeof(*shared_data));
memset(shared_ctl, 0, sizeof(*shared_ctl));
/* cause local ym2612 to init REGS */
YM2612Init_(baseclock, rate);
internal_reset();
loaded_mp3 = 0;
gp2x_memregs[0x3B46>>1] = 0xffff; // clear pending DUALCPU interrupts for 940
gp2x_memregl[0x4500>>2] = 0xffffffff; // clear pending IRQs in SRCPND
gp2x_memregl[0x4510>>2] = 0xffffffff; // clear pending IRQs in INTPND
/* start the 940 */
reset940(0, 2);
pause940(0);
// YM2612ResetChip_940(); // will be done on JOB940_YM2612INIT
/* now cause 940 to init it's ym2612 stuff */
shared_ctl->baseclock = baseclock;
shared_ctl->rate = rate;
add_job_940(JOB940_INITALL);
}
void YM2612ResetChip_940(void)
{
//printf("YM2612ResetChip_940()\n");
if (shared_data == NULL) {
printf("YM2612ResetChip_940: reset before init?\n");
return;
}
YM2612ResetChip_();
internal_reset();
add_job_940(JOB940_YM2612RESETCHIP);
}
int YM2612UpdateOne_940(int *buffer, int length, int stereo, int is_buf_empty)
{
int *ym_buf = shared_data->ym_buffer;
int ym_active_chs;
//printf("YM2612UpdateOne_940()\n");
if (CHECK_BUSY(JOB940_YM2612UPDATEONE)) wait_busy_940(JOB940_YM2612UPDATEONE);
ym_active_chs = shared_ctl->ym_active_chs;
// mix in ym buffer. is_buf_empty means nobody mixed there anything yet and it may contain trash
if (is_buf_empty && ym_active_chs) memcpy32(buffer, ym_buf, length<<stereo);
else memset32(buffer, 0, length<<stereo);
if (shared_ctl->writebuffsel == 1) {
shared_ctl->writebuff0[writebuff_ptr & 0xffff] = 0xffff;
} else {
shared_ctl->writebuff1[writebuff_ptr & 0xffff] = 0xffff;
}
writebuff_ptr = 0;
/* predict sample counter for next frame */
if (PsndLen_exc_add) {
length = PsndLen;
if (PsndLen_exc_cnt + PsndLen_exc_add >= 0x10000) length++;
}
/* give 940 ym job */
shared_ctl->writebuffsel ^= 1;
shared_ctl->length = length;
shared_ctl->stereo = stereo;
add_job_940(JOB940_YM2612UPDATEONE);
return ym_active_chs;
}
/***********************************************************/
static int mp3_samples_ready = 0, mp3_buffer_offs = 0;
static int mp3_play_bufsel = 0, mp3_job_started = 0;
void mp3_update(int *buffer, int length, int stereo)
{
int length_mp3;
if (!(PicoOpt & POPT_EXT_FM)) {
mp3_update_local(buffer, length, stereo);
return;
}
// check if playback was started, track not ended
if (loaded_mp3 == NULL || shared_ctl->mp3_offs >= shared_ctl->mp3_len)
return;
length_mp3 = length;
if (PsndRate == 22050) length_mp3 <<= 1; // mp3s are locked to 44100Hz stereo
else if (PsndRate == 11025) length_mp3 <<= 2; // so make length 44100ish
/* do we have to wait? */
if (mp3_job_started && mp3_samples_ready < length_mp3) {
if (CHECK_BUSY(JOB940_MP3DECODE)) wait_busy_940(JOB940_MP3DECODE);
mp3_job_started = 0;
mp3_samples_ready += 1152;
}
/* mix mp3 data, only stereo */
if (mp3_samples_ready >= length_mp3)
{
int shr = 0;
void (*mix_samples)(int *dest_buf, short *mp3_buf, int count) = mix_16h_to_32;
if (PsndRate == 22050) { mix_samples = mix_16h_to_32_s1; shr = 1; }
else if (PsndRate == 11025) { mix_samples = mix_16h_to_32_s2; shr = 2; }
if (1152 - mp3_buffer_offs >= length_mp3) {
mix_samples(buffer, shared_data->mp3_buffer[mp3_play_bufsel] + mp3_buffer_offs*2, length<<1);
mp3_buffer_offs += length_mp3;
} else {
// collect samples from both buffers..
int left = 1152 - mp3_buffer_offs;
if (mp3_play_bufsel == 0)
{
mix_samples(buffer, shared_data->mp3_buffer[0] + mp3_buffer_offs*2, length<<1);
mp3_buffer_offs = length_mp3 - left;
mp3_play_bufsel = 1;
} else {
mix_samples(buffer, shared_data->mp3_buffer[1] + mp3_buffer_offs*2, (left>>shr)<<1);
mp3_buffer_offs = length_mp3 - left;
mix_samples(buffer + ((left>>shr)<<1),
shared_data->mp3_buffer[0], (mp3_buffer_offs>>shr)<<1);
mp3_play_bufsel = 0;
}
}
mp3_samples_ready -= length_mp3;
}
// ask to decode more if we already can
if (!mp3_job_started)
{
mp3_job_started = 1;
shared_ctl->mp3_buffsel ^= 1;
add_job_940(JOB940_MP3DECODE);
}
}
void mp3_start_play(void *f_, int pos) // pos is 0-1023
{
int byte_offs = 0;
FILE *f = f_;
if (!(PicoOpt & POPT_EN_MCD_CDDA) || f == NULL)
return;
if (!(PicoOpt & POPT_EXT_FM)) {
mp3_start_play_local(f, pos);
return;
}
if (loaded_mp3 != f)
{
if (PicoMessage != NULL)
{
fseek(f, 0, SEEK_END);
if (ftell(f) > 2*1024*1024)
PicoMessage("Loading MP3...");
}
fseek(f, 0, SEEK_SET);
fread(mp3_mem, 1, MP3_SIZE_MAX, f);
if (!feof(f)) printf("Warning: mp3 was too large, not all data loaded.\n");
shared_ctl->mp3_len = ftell(f);
loaded_mp3 = f;
if (PicoOpt & POPT_EXT_FM) {
// as we are going to change 940's cacheable area, we must invalidate it's cache..
if (CHECK_BUSY(JOB940_MP3DECODE)) wait_busy_940(JOB940_MP3DECODE);
add_job_940(JOB940_INVALIDATE_DCACHE);
}
reset_timing = 1;
}
// seek..
if (pos) {
byte_offs = (shared_ctl->mp3_len << 6) >> 10;
byte_offs *= pos;
byte_offs >>= 6;
}
printf(" mp3 pos1024: %i, byte_offs %i/%i\n", pos, byte_offs, shared_ctl->mp3_len);
shared_ctl->mp3_offs = byte_offs;
// reset buffer pointers and stuff..
mp3_samples_ready = mp3_buffer_offs = mp3_play_bufsel = 0;
mp3_job_started = 0;
shared_ctl->mp3_buffsel = 1; // will change to 0 on first decode
add_job_940(JOB940_MP3RESET);
if (CHECK_BUSY(JOB940_MP3RESET)) wait_busy_940(JOB940_MP3RESET);
}

View file

@ -1,13 +0,0 @@
void sharedmem940_init(void);
void sharedmem940_finish(void);
void YM2612Init_940(int baseclock, int rate);
void YM2612ResetChip_940(void);
int YM2612UpdateOne_940(int *buffer, int length, int stereo, int is_buf_empty);
int YM2612Write_940(unsigned int a, unsigned int v, int scanline);
int YM2612PicoTick_940(int n);
void YM2612PicoStateLoad_940(void);
void YM2612PicoStateSave2_940(int tat, int tbt);
int YM2612PicoStateLoad2_940(int *tat, int *tbt);

View file

@ -1,128 +0,0 @@
CROSS ?= arm-linux-
# settings
use_cyclone = 1
#use_musashi = 1
use_drz80 = 1
use_sh2drc = 1
#use_sh2mame = 1
asm_memory = 1
asm_render = 1
asm_ym2612 = 1
asm_misc = 1
asm_cdpico = 1
asm_cdmemory = 1
asm_32xdraw = 1
#profile = 1
#drc_debug = 3
-include Makefile.local
ifeq "$(debug_cyclone)" "1"
use_cyclone = 1
use_musashi = 1
endif
ifeq "$(use_musashi)" "1"
# due to CPU stop flag acces
asm_cdpico = 0
asm_cdmemory = 0
endif
ARCH = arm
DEFINES += ARM __GP2X__ IN_GP2X IN_EVDEV # BENCHMARK
CFLAGS += -Wall -Winline -I../.. -I.
ifeq ($(DEBUG),)
CFLAGS += -O3 -fomit-frame-pointer -fstrict-aliasing -ffast-math
endif
CFLAGS += -mcpu=arm920t -mtune=arm920t
ASFLAGS = -mcpu=arm920t -mfloat-abi=soft
LDFLAGS += -lm -lpng
CC = $(CROSS)gcc
STRIP = $(CROSS)strip
AS = $(CROSS)as
LD = $(CROSS)ld
OBJCOPY = $(CROSS)objcopy
# frontend
OBJS += plat.o warm.o pollux_set.o soc.o soc_mmsp2.o soc_pollux.o soc_dummy.o emu.o in_gp2x.o
# 940 core control
OBJS += 940ctl.o
# ARM stuff
OBJS += pico/carthw/svp/compiler.o pico/carthw/svp/stub_arm.o
OBJS += pico/sound/mix_arm.o
# common
OBJS += platform/common/emu.o platform/common/menu_pico.o platform/common/fonts.o platform/common/config.o \
platform/common/arm_utils.o platform/common/arm_linux.o platform/common/readpng.o \
platform/common/mp3_helix.o platform/common/input.o platform/common/main.o platform/common/mp3.o \
platform/linux/sndout_oss.o platform/linux/plat.o platform/linux/in_evdev.o
# unzip
OBJS += unzip/unzip.o unzip/unzip_stream.o
# zlib
OBJS += zlib/gzio.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o \
zlib/deflate.o zlib/crc32.o zlib/adler32.o zlib/zutil.o zlib/compress.o
vpath %.c = ../..
vpath %.s = ../..
vpath %.S = ../..
DIRS += platform/gp2x platform/linux zlib unzip
all: mkdirs PicoDrive
include ../common/common.mak
include ../common/common_arm.mak
include ../common/revision.mak
CFLAGS += $(addprefix -D,$(DEFINES))
# partial linking helps profiled builds due to section merging
PicoDrive.o : $(OBJS) ../common/helix/$(CROSS)helix-mp3.a
$(LD) -r -o $@ $^
# still using static, dynamic linking slows Wiz 1-10%
# also libm on F100 is not compatible
PicoDrive : PicoDrive.o
@echo ">>>" $@
$(CC) -static -o $@ $(CFLAGS) $^ $(LDFLAGS) -Wl,-Map=$@.map
ifeq ($(DEBUG),)
$(STRIP) $@
endif
up: PicoDrive
@cp -v PicoDrive /mnt/gp2x/mnt/sd/emus/PicoDrive/
clean: tidy
$(RM) PicoDrive
tidy:
$(RM) $(OBJS)
readme.txt: ../../tools/textfilter ../base_readme.txt
../../tools/textfilter ../base_readme.txt $@ GP2X
# ----------- release -----------
VER ?= $(shell head -n 1 version.h | sed 's/.*"\(.*\)\.\(.*\)".*/\1\2/g')
CODE940 = code940/pico940_v3.bin
rel: PicoDrive PicoDrive.gpe $(CODE940) readme.txt ../game_def.cfg \
PicoDrive.png PicoDrive_s.png PicoDrive_t.png \
warm_2.4.25.o warm_2.4.26-open2x.o warm_2.6.24.ko \
../../pico/carthw.cfg
mkdir -p out/PicoDrive/skin/
cp $^ out/PicoDrive/
cp PicoDrive.ini out/
cp skin/*.png out/PicoDrive/skin/
cp skin/*.txt out/PicoDrive/skin/
mkdir out/bin_to_cso_mp3
cp ../../tools/bin_to_cso_mp3/* out/bin_to_cso_mp3/
cd out && zip -9 -r ../../../PicoDrive_$(VER).zip *
rm -rf out
$(CODE940):
make -C code940/

View file

@ -1,915 +0,0 @@
/*
* (c) Copyright 2006-2010 notaz, All rights reserved.
*
* For performance reasons 3 renderers are exported for both MD and 32x modes:
* - 16bpp line renderer
* - 8bpp line renderer (slightly faster)
* - 8bpp tile renderer
* In 32x mode:
* - 32x layer is overlayed on top of 16bpp one
* - line internal one done on PicoDraw2FB, then mixed with 32x
* - tile internal one done on PicoDraw2FB, then mixed with 32x
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "plat_gp2x.h"
#include "soc.h"
#include "soc_pollux.h"
#include "../common/plat.h"
#include "../common/menu.h"
#include "../common/arm_utils.h"
#include "../common/fonts.h"
#include "../common/emu.h"
#include "../common/config.h"
#include "../common/input.h"
#include "../linux/sndout_oss.h"
#include "version.h"
#include <pico/pico_int.h>
#include <pico/patch.h>
#include <pico/sound/mix.h>
#include <zlib/zlib.h>
#ifdef BENCHMARK
#define OSD_FPS_X 220
#else
#define OSD_FPS_X 260
#endif
extern int crashed_940;
static short __attribute__((aligned(4))) sndBuffer[2*(44100+100)/50];
static unsigned char PicoDraw2FB_[(8+320) * (8+240+8)];
unsigned char *PicoDraw2FB = PicoDraw2FB_;
static int osd_fps_x, osd_y, doing_bg_frame;
const char *renderer_names[] = { "16bit accurate", " 8bit accurate", " 8bit fast", NULL };
const char *renderer_names32x[] = { "accurate", "faster", "fastest", NULL };
enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT };
static int (*emu_scan_begin)(unsigned int num) = NULL;
static int (*emu_scan_end)(unsigned int num) = NULL;
extern void *gp2x_screens[4];
void pemu_prep_defconfig(void)
{
gp2x_soc_t soc;
defaultConfig.CPUclock = default_cpu_clock;
defaultConfig.renderer32x = RT_8BIT_FAST;
defaultConfig.analog_deadzone = 50;
soc = soc_detect();
if (soc == SOCID_MMSP2)
defaultConfig.s_PicoOpt |= POPT_EXT_FM;
else if (soc == SOCID_POLLUX) {
defaultConfig.EmuOpt |= EOPT_WIZ_TEAR_FIX|EOPT_SHOW_RTC;
defaultConfig.s_PicoOpt |= POPT_EN_MCD_GFX;
}
}
void pemu_validate_config(void)
{
if (gp2x_dev_id != GP2X_DEV_GP2X)
PicoOpt &= ~POPT_EXT_FM;
if (gp2x_dev_id != GP2X_DEV_WIZ)
currentConfig.EmuOpt &= ~EOPT_WIZ_TEAR_FIX;
if (currentConfig.gamma < 10 || currentConfig.gamma > 300)
currentConfig.gamma = 100;
if (currentConfig.CPUclock < 10 || currentConfig.CPUclock > 1024)
currentConfig.CPUclock = default_cpu_clock;
}
static int get_renderer(void)
{
if (PicoAHW & PAHW_32X)
return currentConfig.renderer32x;
else
return currentConfig.renderer;
}
static void change_renderer(int diff)
{
int *r;
if (PicoAHW & PAHW_32X)
r = &currentConfig.renderer32x;
else
r = &currentConfig.renderer;
*r += diff;
// 8bpp fast is not there (yet?)
if ((PicoAHW & PAHW_SMS) && *r == RT_8BIT_FAST)
(*r)++;
if (*r >= RT_COUNT)
*r = 0;
else if (*r < 0)
*r = RT_COUNT - 1;
}
#define is_16bit_mode() \
(get_renderer() == RT_16BIT || (PicoAHW & PAHW_32X))
static void (*osd_text)(int x, int y, const char *text);
static void osd_text8(int x, int y, const char *text)
{
int len = strlen(text)*8;
int *p, i, h, offs;
len = (len+3) >> 2;
for (h = 0; h < 8; h++) {
offs = (x + g_screen_width * (y+h)) & ~3;
p = (int *) ((char *)g_screen_ptr + offs);
for (i = len; i; i--, p++)
*p = 0xe0e0e0e0;
}
emu_text_out8(x, y, text);
}
static void osd_text16(int x, int y, const char *text)
{
int len = strlen(text)*8;
int *p, i, h, offs;
len = (len+1) >> 1;
for (h = 0; h < 8; h++) {
offs = (x + g_screen_width * (y+h)) & ~1;
p = (int *) ((short *)g_screen_ptr + offs);
for (i = len; i; i--, p++)
*p = (*p >> 2) & 0x39e7;
}
emu_text_out16(x, y, text);
}
static void osd_text8_rot(int x, int y, const char *text)
{
int len = strlen(text) * 8;
char *p = (char *)g_screen_ptr + 240*(320-x) + y;
while (len--) {
memset(p, 0xe0, 8);
p -= 240;
}
emu_text_out8_rot(x, y, text);
}
static void osd_text16_rot(int x, int y, const char *text)
{
int len = strlen(text) * 8;
short *p = (short *)g_screen_ptr + 240*(320-x) + y;
while (len--) {
memset(p, 0, 8*2);
p -= 240;
}
emu_text_out16_rot(x, y, text);
}
static void draw_cd_leds(void)
{
int led_reg, pitch, scr_offs, led_offs;
led_reg = Pico_mcd->s68k_regs[0];
if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) {
pitch = 240;
led_offs = -pitch * 6;
scr_offs = pitch * (320 - 4);
} else {
pitch = 320;
led_offs = 4;
scr_offs = pitch * 2 + 4;
}
if (!is_16bit_mode()) {
#define p(x) px[(x) >> 2]
// 8-bit modes
unsigned int *px = (unsigned int *)((char *)g_screen_ptr + scr_offs);
unsigned int col_g = (led_reg & 2) ? 0xc0c0c0c0 : 0xe0e0e0e0;
unsigned int col_r = (led_reg & 1) ? 0xd0d0d0d0 : 0xe0e0e0e0;
p(pitch*0) = p(pitch*1) = p(pitch*2) = col_g;
p(pitch*0 + led_offs) = p(pitch*1 + led_offs) = p(pitch*2 + led_offs) = col_r;
#undef p
} else {
#define p(x) px[(x)*2 >> 2] = px[((x)*2 >> 2) + 1]
// 16-bit modes
unsigned int *px = (unsigned int *)((short *)g_screen_ptr + scr_offs);
unsigned int col_g = (led_reg & 2) ? 0x06000600 : 0;
unsigned int col_r = (led_reg & 1) ? 0xc000c000 : 0;
p(pitch*0) = p(pitch*1) = p(pitch*2) = col_g;
p(pitch*0 + led_offs) = p(pitch*1 + led_offs) = p(pitch*2 + led_offs) = col_r;
#undef p
}
}
static void draw_pico_ptr(void)
{
unsigned short *p = (unsigned short *)g_screen_ptr;
int x, y, pitch = 320;
// only if pen enabled and for 16bit modes
if (pico_inp_mode == 0 || currentConfig.EmuOpt != RT_16BIT)
return;
x = pico_pen_x + PICO_PEN_ADJUST_X;
y = pico_pen_y + PICO_PEN_ADJUST_Y;
if (!(Pico.video.reg[12]&1) && !(PicoOpt & POPT_DIS_32C_BORDER))
x += 32;
if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) {
pitch = 240;
p += (319 - x) * pitch + y;
} else
p += x + y * pitch;
p[0] ^= 0xffff;
p[pitch-1] ^= 0xffff;
p[pitch] ^= 0xffff;
p[pitch+1] ^= 0xffff;
p[pitch*2] ^= 0xffff;
}
/* rot thing for Wiz */
static unsigned char __attribute__((aligned(4))) rot_buff[320*4*2];
static int EmuScanBegin16_rot(unsigned int num)
{
DrawLineDest = rot_buff + (num & 3) * 320 * 2;
return 0;
}
static int EmuScanEnd16_rot(unsigned int num)
{
if ((num & 3) != 3)
return 0;
rotated_blit16(g_screen_ptr, rot_buff, num + 1,
!(Pico.video.reg[12] & 1) && !(PicoOpt & POPT_EN_SOFTSCALE));
return 0;
}
static int EmuScanBegin8_rot(unsigned int num)
{
DrawLineDest = rot_buff + (num & 3) * 320;
return 0;
}
static int EmuScanEnd8_rot(unsigned int num)
{
if ((num & 3) != 3)
return 0;
rotated_blit8(g_screen_ptr, rot_buff, num + 1,
!(Pico.video.reg[12] & 1));
return 0;
}
/* line doublers */
static unsigned int ld_counter;
static int ld_left, ld_lines;
static int EmuScanBegin16_ld(unsigned int num)
{
if ((signed int)(ld_counter - num) > 100)
ld_counter = 0;
if (emu_scan_begin)
return emu_scan_begin(ld_counter);
else
DrawLineDest = (char *)g_screen_ptr + 320 * ld_counter * gp2x_current_bpp / 8;
return 0;
}
static int EmuScanEnd16_ld(unsigned int num)
{
void *oldline = DrawLineDest;
if (emu_scan_end)
emu_scan_end(ld_counter);
ld_counter++;
ld_left--;
if (ld_left <= 0) {
ld_left = ld_lines;
EmuScanBegin16_ld(num);
memcpy32(DrawLineDest, oldline, 320 * gp2x_current_bpp / 8 / 4);
if (emu_scan_end)
emu_scan_end(ld_counter);
ld_counter++;
}
return 0;
}
static int localPal[0x100];
static void (*vidcpyM2)(void *dest, void *src, int m32col, int with_32c_border);
static int (*make_local_pal)(int fast_mode);
static int make_local_pal_md(int fast_mode)
{
int pallen = 0xc0;
bgr444_to_rgb32(localPal, Pico.cram);
if (fast_mode)
return 0x40;
if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode
bgr444_to_rgb32_sh(localPal, Pico.cram);
localPal[0xc0] = 0x0000c000;
localPal[0xd0] = 0x00c00000;
localPal[0xe0] = 0x00000000; // reserved pixels for OSD
localPal[0xf0] = 0x00ffffff;
pallen = 0x100;
}
else if (rendstatus & PDRAW_SONIC_MODE) { // mid-frame palette changes
bgr444_to_rgb32(localPal+0x40, HighPal);
bgr444_to_rgb32(localPal+0x80, HighPal+0x40);
}
else
memcpy32(localPal+0x80, localPal, 0x40); // for spr prio mess
return pallen;
}
static int make_local_pal_sms(int fast_mode)
{
unsigned short *spal = Pico.cram;
unsigned int *dpal = (void *)localPal;
unsigned int i, t;
for (i = 0x40; i > 0; i--) {
t = *spal++;
t = ((t & 0x0003) << 22) | ((t & 0x000c) << 12) | ((t & 0x0030) << 2);
t |= t >> 2;
t |= t >> 4;
*dpal++ = t;
}
return 0x40;
}
void pemu_finalize_frame(const char *fps, const char *notice)
{
int emu_opt = currentConfig.EmuOpt;
int ret;
if (PicoAHW & PAHW_32X)
; // nothing to do
else if (get_renderer() == RT_8BIT_FAST)
{
// 8bit fast renderer
if (Pico.m.dirtyPal) {
Pico.m.dirtyPal = 0;
ret = make_local_pal(1);
// feed new palette to our device
gp2x_video_setpalette(localPal, ret);
}
// a hack for VR
if (PicoAHW & PAHW_SVP)
memset32((int *)(PicoDraw2FB+328*8+328*223), 0xe0e0e0e0, 328);
// do actual copy
vidcpyM2(g_screen_ptr, PicoDraw2FB+328*8,
!(Pico.video.reg[12] & 1), !(PicoOpt & POPT_DIS_32C_BORDER));
}
else if (get_renderer() == RT_8BIT_ACC)
{
// 8bit accurate renderer
if (Pico.m.dirtyPal)
{
Pico.m.dirtyPal = 0;
ret = make_local_pal(0);
gp2x_video_setpalette(localPal, ret);
}
}
if (notice)
osd_text(4, osd_y, notice);
if (emu_opt & EOPT_SHOW_FPS)
osd_text(osd_fps_x, osd_y, fps);
if ((PicoAHW & PAHW_MCD) && (emu_opt & EOPT_EN_CD_LEDS))
draw_cd_leds();
if (PicoAHW & PAHW_PICO)
draw_pico_ptr();
}
void plat_video_flip(void)
{
int stride = g_screen_width;
gp2x_video_flip();
if (is_16bit_mode())
stride *= 2;
PicoDrawSetOutBuf(g_screen_ptr, stride);
}
/* XXX */
#ifdef __GP2X__
unsigned int plat_get_ticks_ms(void)
{
return gp2x_get_ticks_ms();
}
unsigned int plat_get_ticks_us(void)
{
return gp2x_get_ticks_us();
}
#endif
void plat_wait_till_us(unsigned int us_to)
{
unsigned int now;
spend_cycles(1024);
now = plat_get_ticks_us();
while ((signed int)(us_to - now) > 512)
{
spend_cycles(1024);
now = plat_get_ticks_us();
}
}
void plat_video_wait_vsync(void)
{
gp2x_video_wait_vsync();
}
void plat_status_msg_clear(void)
{
int is_8bit = !is_16bit_mode();
if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) {
/* ugh.. */
int i, u, *p;
if (is_8bit) {
for (i = 0; i < 4; i++) {
p = (int *)gp2x_screens[i] + (240-8) / 4;
for (u = 320; u > 0; u--, p += 240/4)
p[0] = p[1] = 0xe0e0e0e0;
}
} else {
for (i = 0; i < 4; i++) {
p = (int *)gp2x_screens[i] + (240-8)*2 / 4;
for (u = 320; u > 0; u--, p += 240*2/4)
p[0] = p[1] = p[2] = p[3] = 0;
}
}
return;
}
if (is_8bit)
gp2x_memset_all_buffers(320*232, 0xe0, 320*8);
else
gp2x_memset_all_buffers(320*232*2, 0, 320*8*2);
}
void plat_status_msg_busy_next(const char *msg)
{
plat_status_msg_clear();
pemu_finalize_frame("", msg);
plat_video_flip();
emu_status_msg("");
/* assumption: msg_busy_next gets called only when
* something slow is about to happen */
reset_timing = 1;
}
void plat_status_msg_busy_first(const char *msg)
{
gp2x_memcpy_all_buffers(g_screen_ptr, 0, 320*240*2);
plat_status_msg_busy_next(msg);
}
static void vid_reset_mode(void)
{
int gp2x_mode = 16;
int renderer = get_renderer();
PicoOpt &= ~POPT_ALT_RENDERER;
emu_scan_begin = NULL;
emu_scan_end = NULL;
switch (renderer) {
case RT_16BIT:
PicoDrawSetOutFormat(PDF_RGB555, 0);
PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
break;
case RT_8BIT_ACC:
PicoDrawSetOutFormat(PDF_8BIT, 0);
PicoDrawSetOutBuf(g_screen_ptr, g_screen_width);
gp2x_mode = 8;
break;
case RT_8BIT_FAST:
PicoOpt |= POPT_ALT_RENDERER;
PicoDrawSetOutFormat(PDF_NONE, 0);
vidcpyM2 = vidcpy_m2;
gp2x_mode = 8;
break;
default:
printf("bad renderer\n");
break;
}
if (PicoAHW & PAHW_32X) {
// Wiz 16bit is an exception, uses line rendering due to rotation mess
if (renderer == RT_16BIT && (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX)) {
PicoDrawSetOutFormat(PDF_RGB555, 1);
PicoDraw32xSetFrameMode(0, 0);
}
else {
PicoDrawSetOutFormat(PDF_NONE, 0);
PicoDraw32xSetFrameMode(1, 0);
}
PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
gp2x_mode = 16;
}
if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) {
if ((PicoAHW & PAHW_32X) || renderer == RT_16BIT) {
emu_scan_begin = EmuScanBegin16_rot;
emu_scan_end = EmuScanEnd16_rot;
}
else if (renderer == RT_8BIT_ACC) {
emu_scan_begin = EmuScanBegin8_rot;
emu_scan_end = EmuScanEnd8_rot;
}
else if (renderer == RT_8BIT_FAST)
vidcpyM2 = vidcpy_m2_rot;
}
PicoDrawSetCallbacks(emu_scan_begin, emu_scan_end);
if (is_16bit_mode())
osd_text = (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) ? osd_text16_rot : osd_text16;
else
osd_text = (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) ? osd_text8_rot : osd_text8;
gp2x_video_wait_vsync();
if (!is_16bit_mode()) {
// setup pal for 8-bit modes
localPal[0xc0] = 0x0000c000; // MCD LEDs
localPal[0xd0] = 0x00c00000;
localPal[0xe0] = 0x00000000; // reserved pixels for OSD
localPal[0xf0] = 0x00ffffff;
gp2x_video_setpalette(localPal, 0x100);
gp2x_memset_all_buffers(0, 0xe0, 320*240);
}
else
gp2x_memset_all_buffers(0, 0, 320*240*2);
if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX)
gp2x_mode = -gp2x_mode;
gp2x_video_changemode(gp2x_mode);
Pico.m.dirtyPal = 1;
PicoOpt &= ~POPT_EN_SOFTSCALE;
if (currentConfig.scaling == EOPT_SCALE_SW)
PicoOpt |= POPT_EN_SOFTSCALE;
// palette converters for 8bit modes
make_local_pal = (PicoAHW & PAHW_SMS) ? make_local_pal_sms : make_local_pal_md;
}
void emu_video_mode_change(int start_line, int line_count, int is_32cols)
{
int scalex = 320, scaley = 240;
int ln_offs = 0;
if (doing_bg_frame)
return;
osd_fps_x = OSD_FPS_X;
osd_y = 232;
/* set up hwscaling here */
PicoOpt &= ~POPT_DIS_32C_BORDER;
if (is_32cols && currentConfig.scaling == EOPT_SCALE_HW) {
scalex = 256;
PicoOpt |= POPT_DIS_32C_BORDER;
osd_fps_x = OSD_FPS_X - 64;
}
if (currentConfig.vscaling == EOPT_SCALE_HW) {
ln_offs = start_line;
scaley = line_count;
osd_y = start_line + line_count - 8;
}
gp2x_video_RGB_setscaling(ln_offs, scalex, scaley);
/* line doubling */
if (currentConfig.vscaling == EOPT_SCALE_SW && line_count < 240) {
ld_lines = ld_left = line_count / (240 - line_count);
PicoDrawSetCallbacks(EmuScanBegin16_ld, EmuScanEnd16_ld);
}
// clear whole screen in all buffers
if (!is_16bit_mode())
gp2x_memset_all_buffers(0, 0xe0, 320*240);
else
gp2x_memset_all_buffers(0, 0, 320*240*2);
}
void plat_video_toggle_renderer(int change, int is_menu_call)
{
change_renderer(change);
if (is_menu_call)
return;
vid_reset_mode();
rendstatus_old = -1;
if (PicoAHW & PAHW_32X)
emu_status_msg(renderer_names32x[get_renderer()]);
else
emu_status_msg(renderer_names[get_renderer()]);
}
#if 0 // TODO
static void RunEventsPico(unsigned int events)
{
int ret, px, py, lim_x;
static int pdown_frames = 0;
// for F200
ret = gp2x_touchpad_read(&px, &py);
if (ret >= 0)
{
if (ret > 35000)
{
if (pdown_frames++ > 5)
PicoPad[0] |= 0x20;
pico_pen_x = px;
pico_pen_y = py;
if (!(Pico.video.reg[12]&1)) {
pico_pen_x -= 32;
if (pico_pen_x < 0) pico_pen_x = 0;
if (pico_pen_x > 248) pico_pen_x = 248;
}
if (pico_pen_y > 224) pico_pen_y = 224;
}
else
pdown_frames = 0;
//if (ret == 0)
// PicoPicohw.pen_pos[0] = PicoPicohw.pen_pos[1] = 0x8000;
}
}
#endif
void plat_update_volume(int has_changed, int is_up)
{
static int prev_frame = 0, wait_frames = 0;
int vol = currentConfig.volume;
int need_low_volume = 0;
gp2x_soc_t soc;
soc = soc_detect();
if ((PicoOpt & POPT_EN_STEREO) && soc == SOCID_MMSP2)
need_low_volume = 1;
if (has_changed)
{
if (need_low_volume && vol < 5 && prev_frame == Pico.m.frame_count - 1 && wait_frames < 12)
wait_frames++;
else {
if (is_up) {
if (vol < 99) vol++;
} else {
if (vol > 0) vol--;
}
wait_frames = 0;
sndout_oss_setvol(vol, vol);
currentConfig.volume = vol;
}
emu_status_msg("VOL: %02i", vol);
prev_frame = Pico.m.frame_count;
}
if (!need_low_volume)
return;
/* set the right mixer func */
if (vol >= 5)
PsndMix_32_to_16l = mix_32_to_16l_stereo;
else {
mix_32_to_16l_level = 5 - vol;
PsndMix_32_to_16l = mix_32_to_16l_stereo_lvl;
}
}
static void oss_write_nonblocking(int len)
{
// sndout_oss_can_write() is not reliable, only use with no_frmlimit
if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && !sndout_oss_can_write(len))
return;
sndout_oss_write_nb(PsndOut, len);
}
void pemu_sound_start(void)
{
static int PsndRate_old = 0, PicoOpt_old = 0, pal_old = 0;
PsndOut = NULL;
// prepare sound stuff
if (currentConfig.EmuOpt & EOPT_EN_SOUND)
{
int is_stereo = (PicoOpt & POPT_EN_STEREO) ? 1 : 0;
int snd_rate_oss = PsndRate;
gp2x_soc_t soc;
memset(sndBuffer, 0, sizeof(sndBuffer));
PsndOut = sndBuffer;
PicoWriteSound = oss_write_nonblocking;
plat_update_volume(0, 0);
printf("starting audio: %i len: %i stereo: %i, pal: %i\n",
PsndRate, PsndLen, is_stereo, Pico.m.pal);
sndout_oss_start(snd_rate_oss, is_stereo, 1);
sndout_oss_setvol(currentConfig.volume, currentConfig.volume);
soc = soc_detect();
if (soc == SOCID_POLLUX)
PsndRate = pollux_get_real_snd_rate(PsndRate);
#define SOUND_RERATE_FLAGS (POPT_EN_FM|POPT_EN_PSG|POPT_EN_STEREO|POPT_EXT_FM|POPT_EN_MCD_CDDA)
if (PsndRate != PsndRate_old || Pico.m.pal != pal_old || ((PicoOpt & POPT_EXT_FM) && crashed_940) ||
((PicoOpt ^ PicoOpt_old) & SOUND_RERATE_FLAGS)) {
PsndRerate(Pico.m.frame_count ? 1 : 0);
}
PsndRate_old = PsndRate;
PicoOpt_old = PicoOpt;
pal_old = Pico.m.pal;
}
}
static const int sound_rates[] = { 44100, 32000, 22050, 16000, 11025, 8000 };
void pemu_sound_stop(void)
{
int i;
/* get back from Pollux pain */
PsndRate += 1000;
for (i = 0; i < ARRAY_SIZE(sound_rates); i++) {
if (PsndRate >= sound_rates[i]) {
PsndRate = sound_rates[i];
break;
}
}
}
void pemu_sound_wait(void)
{
// don't need to do anything, writes will block by themselves
}
void pemu_forced_frame(int no_scale, int do_emu)
{
doing_bg_frame = 1;
PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
PicoDraw32xSetFrameMode(0, 0);
PicoDrawSetCallbacks(NULL, NULL);
Pico.m.dirtyPal = 1;
emu_cmn_forced_frame(no_scale, do_emu);
g_menubg_src_ptr = g_screen_ptr;
doing_bg_frame = 0;
}
void plat_debug_cat(char *str)
{
}
#if 0
static void tga_dump(void)
{
#define BYTE unsigned char
#define WORD unsigned short
struct
{
BYTE IDLength; /* 00h Size of Image ID field */
BYTE ColorMapType; /* 01h Color map type */
BYTE ImageType; /* 02h Image type code */
WORD CMapStart; /* 03h Color map origin */
WORD CMapLength; /* 05h Color map length */
BYTE CMapDepth; /* 07h Depth of color map entries */
WORD XOffset; /* 08h X origin of image */
WORD YOffset; /* 0Ah Y origin of image */
WORD Width; /* 0Ch Width of image */
WORD Height; /* 0Eh Height of image */
BYTE PixelDepth; /* 10h Image pixel size */
BYTE ImageDescriptor; /* 11h Image descriptor byte */
} __attribute__((packed)) TGAHEAD;
static unsigned short oldscr[320*240];
FILE *f; char name[128]; int i;
memset(&TGAHEAD, 0, sizeof(TGAHEAD));
TGAHEAD.ImageType = 2;
TGAHEAD.Width = 320;
TGAHEAD.Height = 240;
TGAHEAD.PixelDepth = 16;
TGAHEAD.ImageDescriptor = 2<<4; // image starts at top-left
#define CONV(X) (((X>>1)&0x7fe0)|(X&0x1f)) // 555?
for (i = 0; i < 320*240; i++)
if(oldscr[i] != CONV(((unsigned short *)g_screen_ptr)[i])) break;
if (i < 320*240)
{
for (i = 0; i < 320*240; i++)
oldscr[i] = CONV(((unsigned short *)g_screen_ptr)[i]);
sprintf(name, "%05i.tga", Pico.m.frame_count);
f = fopen(name, "wb");
if (!f) { printf("!f\n"); exit(1); }
fwrite(&TGAHEAD, 1, sizeof(TGAHEAD), f);
fwrite(oldscr, 1, 320*240*2, f);
fclose(f);
}
}
#endif
void pemu_loop_prep(void)
{
static int gp2x_old_clock = -1, EmuOpt_old = 0, pal_old = 0;
static int gp2x_old_gamma = 100;
gp2x_soc_t soc;
soc = soc_detect();
if ((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_RAM_TIMINGS) {
if (currentConfig.EmuOpt & EOPT_RAM_TIMINGS)
set_ram_timings();
else
unset_ram_timings();
}
if (gp2x_old_clock < 0)
gp2x_old_clock = default_cpu_clock;
if (gp2x_old_clock != currentConfig.CPUclock && gp2x_set_cpuclk != NULL) {
printf("changing clock to %i...", currentConfig.CPUclock); fflush(stdout);
gp2x_set_cpuclk(currentConfig.CPUclock);
gp2x_old_clock = currentConfig.CPUclock;
printf(" done\n");
}
if (gp2x_old_gamma != currentConfig.gamma || ((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_A_SN_GAMMA)) {
set_lcd_gamma(currentConfig.gamma, !!(currentConfig.EmuOpt & EOPT_A_SN_GAMMA));
gp2x_old_gamma = currentConfig.gamma;
printf("updated gamma to %i, A_SN's curve: %i\n", currentConfig.gamma, !!(currentConfig.EmuOpt&0x1000));
}
if (((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_VSYNC) || Pico.m.pal != pal_old) {
if ((currentConfig.EmuOpt & EOPT_VSYNC) || soc == SOCID_POLLUX)
set_lcd_custom_rate(Pico.m.pal);
else if (EmuOpt_old & EOPT_VSYNC)
unset_lcd_custom_rate();
}
if (gp2x_dev_id == GP2X_DEV_CAANOO)
in_set_config_int(in_name_to_id("evdev:pollux-analog"), IN_CFG_ABS_DEAD_ZONE,
currentConfig.analog_deadzone);
if ((EmuOpt_old ^ currentConfig.EmuOpt) & EOPT_MMUHACK)
gp2x_make_fb_bufferable(currentConfig.EmuOpt & EOPT_MMUHACK);
EmuOpt_old = currentConfig.EmuOpt;
pal_old = Pico.m.pal;
// make sure we are in correct mode
change_renderer(0);
vid_reset_mode();
// dirty buffers better go now than during gameplay
sync();
sleep(0);
pemu_sound_start();
}
void pemu_loop_end(void)
{
pemu_sound_stop();
/* do one more frame for menu bg */
pemu_forced_frame(0, 1);
}

View file

@ -1,128 +0,0 @@
#include <time.h>
#include "soc.h"
#include "plat_gp2x.h"
static void menu_main_plat_draw(void)
{
static time_t last_bat_read = 0;
static int last_bat_val = -1;
unsigned short *bp = g_screen_ptr;
int bat_h = me_mfont_h * 2 / 3;
int i, u, w, wfill, batt_val;
struct tm *tmp;
time_t ltime;
char time_s[16];
if (!(currentConfig.EmuOpt & EOPT_SHOW_RTC))
return;
ltime = time(NULL);
tmp = gmtime(&ltime);
strftime(time_s, sizeof(time_s), "%H:%M", tmp);
text_out16(g_screen_width - me_mfont_w * 6, me_mfont_h + 2, time_s);
if (ltime - last_bat_read > 10) {
last_bat_read = ltime;
last_bat_val = batt_val = gp2x_read_battery();
}
else
batt_val = last_bat_val;
if (batt_val < 0 || batt_val > 100)
return;
/* battery info */
bp += (me_mfont_h * 2 + 2) * g_screen_width + g_screen_width - me_mfont_w * 3 - 3;
for (i = 0; i < me_mfont_w * 2; i++)
bp[i] = menu_text_color;
for (i = 0; i < me_mfont_w * 2; i++)
bp[i + g_screen_width * bat_h] = menu_text_color;
for (i = 0; i <= bat_h; i++)
bp[i * g_screen_width] =
bp[i * g_screen_width + me_mfont_w * 2] = menu_text_color;
for (i = 2; i < bat_h - 1; i++)
bp[i * g_screen_width - 1] =
bp[i * g_screen_width - 2] = menu_text_color;
w = me_mfont_w * 2 - 1;
wfill = batt_val * w / 100;
for (u = 1; u < bat_h; u++)
for (i = 0; i < wfill; i++)
bp[(w - i) + g_screen_width * u] = menu_text_color;
}
// ------------ gfx options menu ------------
static const char *mgn_aopt_gamma(int id, int *offs)
{
sprintf(static_buff, "%i.%02i", currentConfig.gamma / 100, currentConfig.gamma % 100);
return static_buff;
}
const char *men_scaling_opts[] = { "OFF", "software", "hardware", NULL };
#define MENU_OPTIONS_GFX \
mee_enum ("Horizontal scaling", MA_OPT_SCALING, currentConfig.scaling, men_scaling_opts), \
mee_enum ("Vertical scaling", MA_OPT_VSCALING, currentConfig.vscaling, men_scaling_opts), \
mee_onoff ("Tearing Fix", MA_OPT_TEARING_FIX, currentConfig.EmuOpt, EOPT_WIZ_TEAR_FIX), \
mee_range_cust("Gamma correction", MA_OPT2_GAMMA, currentConfig.gamma, 1, 300, mgn_aopt_gamma), \
mee_onoff ("A_SN's gamma curve", MA_OPT2_A_SN_GAMMA, currentConfig.EmuOpt, EOPT_A_SN_GAMMA), \
mee_onoff ("Vsync", MA_OPT2_VSYNC, currentConfig.EmuOpt, EOPT_VSYNC),
#define MENU_OPTIONS_ADV \
mee_onoff ("Use second CPU for sound", MA_OPT_ARM940_SOUND, PicoOpt, POPT_EXT_FM), \
mee_onoff ("RAM overclock", MA_OPT2_RAMTIMINGS, currentConfig.EmuOpt, EOPT_RAM_TIMINGS), \
mee_onoff ("MMU hack", MA_OPT2_SQUIDGEHACK, currentConfig.EmuOpt, EOPT_MMUHACK), \
mee_onoff ("SVP dynarec", MA_OPT2_SVP_DYNAREC, PicoOpt, POPT_EN_SVP_DRC), \
mee_onoff ("Status line in main menu", MA_OPT2_STATUS_LINE, currentConfig.EmuOpt, EOPT_SHOW_RTC),
static menu_entry e_menu_adv_options[];
static menu_entry e_menu_gfx_options[];
static menu_entry e_menu_options[];
static menu_entry e_menu_keyconfig[];
void gp2x_menu_init(void)
{
static menu_entry *cpu_clk_ent;
int i;
i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS);
cpu_clk_ent = &e_menu_options[i];
/* disable by default.. */
me_enable(e_menu_adv_options, MA_OPT_ARM940_SOUND, 0);
me_enable(e_menu_gfx_options, MA_OPT_TEARING_FIX, 0);
me_enable(e_menu_gfx_options, MA_OPT2_GAMMA, 0);
me_enable(e_menu_gfx_options, MA_OPT2_A_SN_GAMMA, 0);
switch (gp2x_dev_id) {
case GP2X_DEV_GP2X:
me_enable(e_menu_adv_options, MA_OPT_ARM940_SOUND, 1);
me_enable(e_menu_gfx_options, MA_OPT2_GAMMA, 1);
me_enable(e_menu_gfx_options, MA_OPT2_A_SN_GAMMA, 1);
cpu_clk_ent->name = "GP2X CPU clocks";
break;
case GP2X_DEV_WIZ:
me_enable(e_menu_gfx_options, MA_OPT_TEARING_FIX, 1);
cpu_clk_ent->name = "Wiz/Caanoo CPU clock";
break;
case GP2X_DEV_CAANOO:
cpu_clk_ent->name = "Wiz/Caanoo CPU clock";
break;
default:
break;
}
if (gp2x_set_cpuclk == NULL)
cpu_clk_ent->name = "";
if (gp2x_dev_id != GP2X_DEV_GP2X)
men_scaling_opts[2] = NULL; /* leave only off and sw */
if (gp2x_dev_id != GP2X_DEV_CAANOO)
me_enable(e_menu_keyconfig, MA_CTRL_DEADZONE, 0);
}

View file

@ -1,233 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "plat_gp2x.h"
#include "soc.h"
#include "warm.h"
#include "../common/plat.h"
#include "../common/readpng.h"
#include "../common/menu.h"
#include "../common/emu.h"
#include "../common/input.h"
#include "../linux/sndout_oss.h"
#include <pico/pico.h>
/* GP2X local */
int default_cpu_clock;
int gp2x_dev_id;
int gp2x_current_bpp;
void *gp2x_screens[4];
#include <linux/input.h>
static const char * const caanoo_keys[KEY_MAX + 1] = {
[0 ... KEY_MAX] = NULL,
[KEY_UP] = "Up",
[KEY_LEFT] = "Left",
[KEY_RIGHT] = "Right",
[KEY_DOWN] = "Down",
[BTN_TRIGGER] = "A",
[BTN_THUMB] = "X",
[BTN_THUMB2] = "B",
[BTN_TOP] = "Y",
[BTN_TOP2] = "L",
[BTN_PINKIE] = "R",
[BTN_BASE] = "Home",
[BTN_BASE2] = "Lock",
[BTN_BASE3] = "I",
[BTN_BASE4] = "II",
[BTN_BASE5] = "Push",
};
struct in_default_bind in_evdev_defbinds[] =
{
/* MXYZ SACB RLDU */
{ KEY_UP, IN_BINDTYPE_PLAYER12, 0 },
{ KEY_DOWN, IN_BINDTYPE_PLAYER12, 1 },
{ KEY_LEFT, IN_BINDTYPE_PLAYER12, 2 },
{ KEY_RIGHT, IN_BINDTYPE_PLAYER12, 3 },
{ KEY_S, IN_BINDTYPE_PLAYER12, 4 }, /* B */
{ KEY_D, IN_BINDTYPE_PLAYER12, 5 }, /* C */
{ KEY_A, IN_BINDTYPE_PLAYER12, 6 }, /* A */
{ KEY_ENTER, IN_BINDTYPE_PLAYER12, 7 },
{ KEY_BACKSLASH, IN_BINDTYPE_EMU, PEVB_MENU },
/* Caanoo */
{ BTN_THUMB, IN_BINDTYPE_PLAYER12, 4 }, /* B */
{ BTN_THUMB2, IN_BINDTYPE_PLAYER12, 5 }, /* C */
{ BTN_TRIGGER, IN_BINDTYPE_PLAYER12, 6 }, /* A */
{ BTN_BASE3, IN_BINDTYPE_PLAYER12, 7 },
{ BTN_TOP2, IN_BINDTYPE_EMU, PEVB_STATE_SAVE },
{ BTN_PINKIE, IN_BINDTYPE_EMU, PEVB_STATE_LOAD },
{ BTN_BASE, IN_BINDTYPE_EMU, PEVB_MENU },
{ 0, 0, 0 }
};
void gp2x_video_changemode(int bpp)
{
gp2x_video_changemode_ll(bpp);
gp2x_current_bpp = bpp < 0 ? -bpp : bpp;
}
static void gp2x_memcpy_buffers(int buffers, void *data, int offset, int len)
{
char *dst;
if (buffers & (1<<0)) { dst = (char *)gp2x_screens[0] + offset; if (dst != data) memcpy(dst, data, len); }
if (buffers & (1<<1)) { dst = (char *)gp2x_screens[1] + offset; if (dst != data) memcpy(dst, data, len); }
if (buffers & (1<<2)) { dst = (char *)gp2x_screens[2] + offset; if (dst != data) memcpy(dst, data, len); }
if (buffers & (1<<3)) { dst = (char *)gp2x_screens[3] + offset; if (dst != data) memcpy(dst, data, len); }
}
void gp2x_memcpy_all_buffers(void *data, int offset, int len)
{
gp2x_memcpy_buffers(0xf, data, offset, len);
}
void gp2x_memset_all_buffers(int offset, int byte, int len)
{
memset((char *)gp2x_screens[0] + offset, byte, len);
memset((char *)gp2x_screens[1] + offset, byte, len);
memset((char *)gp2x_screens[2] + offset, byte, len);
memset((char *)gp2x_screens[3] + offset, byte, len);
}
void gp2x_make_fb_bufferable(int yes)
{
int ret = 0;
yes = yes ? 1 : 0;
ret |= warm_change_cb_range(WCB_B_BIT, yes, gp2x_screens[0], 320*240*2);
ret |= warm_change_cb_range(WCB_B_BIT, yes, gp2x_screens[1], 320*240*2);
ret |= warm_change_cb_range(WCB_B_BIT, yes, gp2x_screens[2], 320*240*2);
ret |= warm_change_cb_range(WCB_B_BIT, yes, gp2x_screens[3], 320*240*2);
if (ret)
fprintf(stderr, "could not make fb buferable.\n");
else
printf("made fb buferable.\n");
}
/* common */
void plat_video_menu_enter(int is_rom_loaded)
{
if (gp2x_current_bpp != 16 || gp2x_dev_id == GP2X_DEV_WIZ) {
/* try to switch nicely avoiding glitches */
gp2x_video_wait_vsync();
memset(gp2x_screens[0], 0, 320*240*2);
memset(gp2x_screens[1], 0, 320*240*2);
gp2x_video_flip2(); // might flip to fb2/3
gp2x_video_flip2(); // ..so we do it again
}
else
gp2x_video_flip2();
// switch to 16bpp
gp2x_video_changemode_ll(16);
gp2x_video_RGB_setscaling(0, 320, 240);
}
void plat_video_menu_begin(void)
{
g_menuscreen_ptr = g_screen_ptr;
}
void plat_video_menu_end(void)
{
gp2x_video_flip2();
}
void plat_early_init(void)
{
gp2x_soc_t soc;
FILE *f;
soc = soc_detect();
switch (soc)
{
case SOCID_MMSP2:
default_cpu_clock = 200;
gp2x_dev_id = GP2X_DEV_GP2X;
break;
case SOCID_POLLUX:
default_cpu_clock = 533;
f = fopen("/dev/accel", "rb");
if (f) {
printf("detected Caanoo\n");
gp2x_dev_id = GP2X_DEV_CAANOO;
fclose(f);
}
else {
printf("detected Wiz\n");
gp2x_dev_id = GP2X_DEV_WIZ;
}
break;
default:
printf("could not recognize SoC, running in dummy mode.\n");
break;
}
// just use gettimeofday until plat_init()
gp2x_get_ticks_ms = plat_get_ticks_ms_good;
gp2x_get_ticks_us = plat_get_ticks_us_good;
}
void plat_init(void)
{
gp2x_soc_t soc;
soc = soc_detect();
switch (soc)
{
case SOCID_MMSP2:
mmsp2_init();
break;
case SOCID_POLLUX:
pollux_init();
break;
default:
dummy_init();
break;
}
warm_init();
gp2x_memset_all_buffers(0, 0, 320*240*2);
// use buffer2 for menubg to save mem (using only buffers 0, 1 in menu)
g_menubg_ptr = gp2x_screens[2];
// snd
sndout_oss_init();
if (gp2x_dev_id == GP2X_DEV_CAANOO)
in_set_config(in_name_to_id("evdev:pollux-analog"), IN_CFG_KEY_NAMES,
caanoo_keys, sizeof(caanoo_keys));
gp2x_menu_init();
}
void plat_finish(void)
{
gp2x_soc_t soc;
warm_finish();
soc = soc_detect();
switch (soc)
{
case SOCID_MMSP2:
mmsp2_finish();
break;
case SOCID_POLLUX:
pollux_finish();
break;
default:
dummy_finish();
break;
}
sndout_oss_exit();
}

View file

@ -1,37 +0,0 @@
// port specific settings
#ifndef PORT_CONFIG_H
#define PORT_CONFIG_H
#define CASE_SENSITIVE_FS 1 // CS filesystem
#define DONT_OPEN_MANY_FILES 0
#define REDUCE_IO_CALLS 0
#define SIMPLE_WRITE_SOUND 0
#define SCREEN_SIZE_FIXED 1
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define MSCREEN_SIZE_FIXED 1
#define MSCREEN_WIDTH SCREEN_WIDTH
#define MSCREEN_HEIGHT SCREEN_HEIGHT
// draw2.c
#define START_ROW 0 // which row of tiles to start rendering at?
#define END_ROW 28 // ..end
// pico.c
#define CAN_HANDLE_240_LINES 1
// logging emu events
#define EL_LOGMASK (EL_STATUS)
// (EL_STATUS|EL_ANOMALY|EL_UIO|EL_SRAMIO|EL_INTS|EL_CDPOLL|EL_IDLE)
//#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__)
#define dprintf(x...)
// platform
#define PATH_SEP "/"
#define PATH_SEP_C '/'
#define MENU_X2 0
#endif //PORT_CONFIG_H

View file

@ -1,13 +0,0 @@
@ vim:filetype=armasm
@ .equiv START_ROW, 1
@ .equiv END_ROW, 27
@ one row means 8 pixels. If above example was used, (27-1)*8=208 lines would be rendered.
.equiv START_ROW, 0
.equiv END_ROW, 28
.equiv UNALIGNED_DRAWLINEDEST, 0
@ this should be set to one only for GP2X port
.equiv EXTERNAL_YM2612, 1

View file

@ -1,37 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include "gp2x.h"
void spend_cycles(int c);
int main(void)
{
struct timeval tval; // timing
int thissec = 0, frames_done = 0;
gp2x_init();
for (;;)
{
gettimeofday(&tval, 0);
if(thissec != tval.tv_sec)
{
thissec = tval.tv_sec;
printf("frames_done: %i\n", frames_done);
frames_done = 0;
}
//gp2x_video_wait_vsync();
//usleep(1); // sleeps a minimum of ~20ms
//gp2x_video_flip(); // can be called ~430000 times/sec
spend_cycles(1000);
frames_done++;
}
}

View file

@ -1,2 +0,0 @@
#define VERSION "1.80"

View file

@ -1,254 +0,0 @@
/*
* wARM - exporting ARM processor specific privileged services to userspace
* userspace part
*
* Copyright (c) Gražvydas "notaz" Ignotas, 2009
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the organization nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <sys/syscall.h>
#include <errno.h>
#define WARM_CODE
#include "warm.h"
/* provided by glibc */
extern long init_module(void *, unsigned long, const char *);
extern long delete_module(const char *, unsigned int);
static int warm_fd = -1;
static int kernel_version;
static void sys_cacheflush(void *start, void *end)
{
#ifdef __ARM_EABI__
/* EABI version */
int num = __ARM_NR_cacheflush;
__asm__("mov r0, %0 ;"
"mov r1, %1 ;"
"mov r2, #0 ;"
"mov r7, %2 ;"
"swi 0" : : "r" (start), "r" (end), "r" (num)
: "r0", "r1", "r2", "r3", "r7");
#else
/* OABI */
__asm__("mov r0, %0 ;"
"mov r1, %1 ;"
"mov r2, #0 ;"
"swi %2" : : "r" (start), "r" (end), "i" __ARM_NR_cacheflush
: "r0", "r1", "r2", "r3");
#endif
}
/* Those are here because system() occasionaly fails on Wiz
* with errno 12 for some unknown reason */
static int manual_insmod_26(const char *fname, const char *opts)
{
unsigned long len, read_len;
int ret = -1;
void *buff;
FILE *f;
f = fopen(fname, "rb");
if (f == NULL)
return -1;
fseek(f, 0, SEEK_END);
len = ftell(f);
fseek(f, 0, SEEK_SET);
buff = malloc(len);
if (buff == NULL)
goto fail0;
read_len = fread(buff, 1, len, f);
if (read_len != len) {
fprintf(stderr, "failed to read module\n");
goto fail1;
}
ret = init_module(buff, len, opts);
fail1:
free(buff);
fail0:
fclose(f);
return ret;
}
static int manual_rmmod(const char *name)
{
return delete_module(name, O_NONBLOCK|O_EXCL);
}
int warm_init(void)
{
struct utsname unm;
char buff1[32], buff2[128];
int ret;
memset(&unm, 0, sizeof(unm));
uname(&unm);
if (strlen(unm.release) < 3 || unm.release[1] != '.') {
fprintf(stderr, "unexpected version string: %s\n", unm.release);
goto fail;
}
kernel_version = ((unm.release[0] - '0') << 4) | (unm.release[2] - '0');
warm_fd = open("/proc/warm", O_RDWR);
if (warm_fd >= 0)
return 0;
snprintf(buff1, sizeof(buff1), "warm_%s.%s", unm.release, kernel_version >= 0x26 ? "ko" : "o");
snprintf(buff2, sizeof(buff2), "/sbin/insmod %s verbose=1", buff1);
/* try to insmod */
ret = system(buff2);
if (ret != 0) {
fprintf(stderr, "system/insmod failed: %d %d\n", ret, errno);
if (kernel_version >= 0x26) {
ret = manual_insmod_26(buff1, "verbose=1");
if (ret != 0)
fprintf(stderr, "manual insmod also failed: %d\n", ret);
}
}
warm_fd = open("/proc/warm", O_RDWR);
if (warm_fd >= 0)
return 0;
fail:
fprintf(stderr, "wARM: can't init, acting as sys_cacheflush wrapper\n");
return -1;
}
void warm_finish(void)
{
char name[32], cmd[64];
int ret;
if (warm_fd < 0)
return;
close(warm_fd);
warm_fd = -1;
if (kernel_version < 0x26) {
struct utsname unm;
memset(&unm, 0, sizeof(unm));
uname(&unm);
snprintf(name, sizeof(name), "warm_%s", unm.release);
}
else
strcpy(name, "warm");
snprintf(cmd, sizeof(cmd), "/sbin/rmmod %s", name);
ret = system(cmd);
if (ret != 0) {
fprintf(stderr, "system/rmmod failed: %d %d\n", ret, errno);
manual_rmmod(name);
}
}
int warm_cache_op_range(int op, void *addr, unsigned long size)
{
struct warm_cache_op wop;
int ret;
if (warm_fd < 0) {
/* note that this won't work for warm_cache_op_all */
sys_cacheflush(addr, (char *)addr + size);
return -1;
}
wop.ops = op;
wop.addr = (unsigned long)addr;
wop.size = size;
ret = ioctl(warm_fd, WARMC_CACHE_OP, &wop);
if (ret != 0) {
perror("WARMC_CACHE_OP failed");
return -1;
}
return 0;
}
int warm_cache_op_all(int op)
{
return warm_cache_op_range(op, NULL, (unsigned long)-1);
}
int warm_change_cb_range(int cb, int is_set, void *addr, unsigned long size)
{
struct warm_change_cb ccb;
int ret;
if (warm_fd < 0)
return -1;
ccb.addr = (unsigned long)addr;
ccb.size = size;
ccb.cb = cb;
ccb.is_set = is_set;
ret = ioctl(warm_fd, WARMC_CHANGE_CB, &ccb);
if (ret != 0) {
perror("WARMC_CHANGE_CB failed");
return -1;
}
return 0;
}
int warm_change_cb_upper(int cb, int is_set)
{
return warm_change_cb_range(cb, is_set, 0, 0);
}
unsigned long warm_virt2phys(const void *ptr)
{
unsigned long ptrio;
int ret;
ptrio = (unsigned long)ptr;
ret = ioctl(warm_fd, WARMC_VIRT2PHYS, &ptrio);
if (ret != 0) {
perror("WARMC_VIRT2PHYS failed");
return (unsigned long)-1;
}
return ptrio;
}

View file

@ -1,100 +0,0 @@
/*
* wARM - exporting ARM processor specific privileged services to userspace
* library functions
*
* Copyright (c) Gražvydas "notaz" Ignotas, 2009
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the organization nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __WARM_H__
#define __WARM_H__ 1
/* cache operations (warm_cache_op_*):
* o clean - write dirty data to memory, but also leave in cache.
* o invalidate - throw away everything in cache, losing dirty data.
*
* Write buffer is always drained, no ops will only drain WB
*/
#define WOP_D_CLEAN (1 << 0)
#define WOP_D_INVALIDATE (1 << 1)
#define WOP_I_INVALIDATE (1 << 2)
/* change C and B bits (warm_change_cb_*)
* if is_set in not zero, bits are set, else cleared.
* the address for range function is virtual address.
*/
#define WCB_C_BIT (1 << 0)
#define WCB_B_BIT (1 << 1)
#ifndef __ASSEMBLER__
#ifdef __cplusplus
extern "C"
{
#endif
int warm_init(void);
int warm_cache_op_range(int ops, void *virt_addr, unsigned long size);
int warm_cache_op_all(int ops);
int warm_change_cb_upper(int cb, int is_set);
int warm_change_cb_range(int cb, int is_set, void *virt_addr, unsigned long size);
unsigned long warm_virt2phys(const void *ptr);
void warm_finish(void);
#ifdef __cplusplus
}
#endif
/* internal */
#ifdef WARM_CODE
#include <linux/ioctl.h>
#define WARM_IOCTL_BASE 'A'
struct warm_cache_op
{
unsigned long addr;
unsigned long size;
int ops;
};
struct warm_change_cb
{
unsigned long addr;
unsigned long size;
int cb;
int is_set;
};
#define WARMC_CACHE_OP _IOW(WARM_IOCTL_BASE, 0, struct warm_cache_op)
#define WARMC_CHANGE_CB _IOW(WARM_IOCTL_BASE, 1, struct warm_change_cb)
#define WARMC_VIRT2PHYS _IOWR(WARM_IOCTL_BASE, 2, unsigned long)
#endif /* WARM_CODE */
#endif /* !__ASSEMBLER__ */
#endif /* __WARM_H__ */

View file

@ -1,97 +0,0 @@
# settings
#use_fbdev = 1
#fake_in_gp2x = 1
use_musashi = 1
#use_fame = 1
use_cz80 = 1
use_sh2drc = 1
#use_sh2mame = 1
#drc_debug = 3
#drc_debug_interp = 1
#profile = 1
all: mkdirs PicoDrive
-include Makefile.local
ifndef ARCH
ARCH = x86
endif
DEFINES = _UNZIP_SUPPORT IO_STATS IN_EVDEV
CFLAGS += -ggdb -Wall -falign-functions=2
CFLAGS += -I../.. -I.
LDFLAGS += -lm -lpng
ifeq "$(ARCH)" "arm"
CFLAGS += -mcpu=arm920t
DEFINES += ARM
endif
CC ?= $(CROSS)gcc
# frontend
OBJS += io.o emu.o blit.o in_evdev.o plat.o sndout_oss.o log_io.o
# common
OBJS += platform/common/main.o platform/common/emu.o platform/common/menu_pico.o \
platform/common/config.o platform/common/fonts.o platform/common/readpng.o \
platform/common/input.o
ifeq "$(use_fbdev)" "1"
DEFINES += FBDEV
OBJS += fbdev.o
else
LDFLAGS += -lpthread
LDFLAGS += -lX11
endif
ifeq "$(fake_in_gp2x)" "1"
DEFINES += IN_GP2X FAKE_IN_GP2X
OBJS += platform/gp2x/in_gp2x.o
DIRS += platform/gp2x
endif
ifeq "$(ARCH)" "arm"
OBJS += pico/carthw/svp/stub_arm.o
endif
OBJS += pico/sound/mix.o
OBJS += pico/carthw/svp/compiler.o
# zlib
OBJS += zlib/gzio.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o \
zlib/deflate.o zlib/crc32.o zlib/adler32.o zlib/zutil.o zlib/compress.o zlib/uncompr.o
# unzip
OBJS += unzip/unzip.o unzip/unzip_stream.o
vpath %.c = ../..
vpath %.s = ../..
vpath %.S = ../..
vpath %.asm = ../..
DIRS += platform/linux zlib unzip
include ../common/common.mak
include ../common/revision.mak
CFLAGS += $(addprefix -D,$(DEFINES))
clean: tidy
@$(RM) PicoDrive
tidy:
$(RM) $(OBJS)
rm -rf $(DIRS)
@make -C ../../cpu/mz80/ clean
PicoDrive : $(OBJS)
@echo ">>>" $@
$(CC) $(CFLAGS) $^ $(LDFLAGS) -Wl,-Map=PicoDrive.map -o $@
pprof: pprof.c
$(CROSS)gcc -O2 -ggdb -DPPROF -DPPROF_TOOL -I../../ -I. $^ -o $@
%.o : %.asm
@echo ">>>" $<
nasm -f elf $< -o $@

View file

@ -1,4 +0,0 @@
This port tries to emulate gp2x environment on a standard linux box for testing
(i.e. to be able to use things like valgrind and efence, gcc runtime
optimizations, etc.).

View file

@ -1,83 +0,0 @@
// Convert 0000bbb0 ggg0rrr0 0000bbb0 ggg0rrr0
// to 00000000 rrr00000 ggg00000 bbb00000 ...
// TODO: rm when gp2x/emu.c is no longer used
void bgr444_to_rgb32(void *to, void *from)
{
unsigned short *ps = from;
unsigned int *pd = to;
int pixels;
for (pixels = 0x40; pixels; pixels--, ps++, pd++)
{
*pd = ((*ps<<20)&0xe00000) | ((*ps<<8)&0xe000) | ((*ps>>4)&0xe0);
*pd |= *pd >> 3;
}
}
void bgr444_to_rgb32_sh(void *to, void *from)
{
unsigned short *ps = from;
unsigned int *pd = to;
int pixels;
pd += 0x40;
for (pixels = 0x40; pixels; pixels--, ps++, pd++)
{
*pd = ((*ps<<20)&0xe00000) | ((*ps<<8)&0xe000) | ((*ps>>4)&0xe0);
*pd >>= 1;
*pd |= *pd >> 3;
pd[0x40*2] = *pd;
}
ps -= 0x40;
for (pixels = 0x40; pixels; pixels--, ps++, pd++)
{
*pd = ((*ps<<20)&0xe00000) | ((*ps<<8)&0xe000) | ((*ps>>4)&0xe0);
continue;
*pd += 0x00404040;
if (*pd & 0x01000000) *pd |= 0x00e00000;
if (*pd & 0x00010000) *pd |= 0x0000e000;
if (*pd & 0x00000100) *pd |= 0x000000e0;
*pd &= 0x00e0e0e0;
*pd |= *pd >> 3;
}
}
void vidcpy_m2(void *dest, void *src, int m32col, int with_32c_border)
{
unsigned char *pd = dest, *ps = src;
int i, u;
if (m32col) {
for (i = 0; i < 224; i++)
{
ps += 8;
pd += 32;
for (u = 0; u < 256; u++)
*pd++ = *ps++;
ps += 64;
pd += 32;
}
} else {
for (i = 0; i < 224; i++)
{
ps += 8;
for (u = 0; u < 320; u++)
*pd++ = *ps++;
}
}
}
void vidcpy_m2_rot(void *dest, void *src, int m32col, int with_32c_border)
{
}
void rotated_blit8 (void *dst, void *linesx4, int y, int is_32col)
{
}
void rotated_blit16(void *dst, void *linesx4, int y, int is_32col)
{
}

View file

@ -1,300 +0,0 @@
// (c) Copyright 2006-2009 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include <stdio.h>
#include <unistd.h>
#include "../common/emu.h"
#include "../common/menu.h"
#include "../common/plat.h"
#include "../common/arm_utils.h"
#include "../linux/sndout_oss.h"
#include "version.h"
#include <pico/pico_int.h>
static short __attribute__((aligned(4))) sndBuffer[2*44100/50];
const char *renderer_names[] = { "16bit accurate", " 8bit accurate", " 8bit fast", NULL };
const char *renderer_names32x[] = { "accurate", "faster", "fastest", NULL };
enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT };
void pemu_prep_defconfig(void)
{
}
void pemu_validate_config(void)
{
extern int PicoOpt;
// PicoOpt &= ~POPT_EXT_FM;
PicoOpt &= ~POPT_EN_SVP_DRC;
}
// FIXME: dupes from GP2X, need cleanup
static void (*osd_text)(int x, int y, const char *text);
/*
static void osd_text8(int x, int y, const char *text)
{
int len = strlen(text)*8;
int *p, i, h, offs;
len = (len+3) >> 2;
for (h = 0; h < 8; h++) {
offs = (x + g_screen_width * (y+h)) & ~3;
p = (int *) ((char *)g_screen_ptr + offs);
for (i = len; i; i--, p++)
*p = 0xe0e0e0e0;
}
emu_text_out8(x, y, text);
}
*/
static void osd_text16(int x, int y, const char *text)
{
int len = strlen(text)*8;
int *p, i, h, offs;
len = (len+1) >> 1;
for (h = 0; h < 8; h++) {
offs = (x + g_screen_width * (y+h)) & ~1;
p = (int *) ((short *)g_screen_ptr + offs);
for (i = len; i; i--, p++)
*p = (*p >> 2) & 0x39e7;
}
emu_text_out16(x, y, text);
}
static void draw_cd_leds(void)
{
int led_reg, pitch, scr_offs, led_offs;
led_reg = Pico_mcd->s68k_regs[0];
pitch = 320;
led_offs = 4;
scr_offs = pitch * 2 + 4;
if (currentConfig.renderer != RT_16BIT) {
#define p(x) px[(x) >> 2]
// 8-bit modes
unsigned int *px = (unsigned int *)((char *)g_screen_ptr + scr_offs);
unsigned int col_g = (led_reg & 2) ? 0xc0c0c0c0 : 0xe0e0e0e0;
unsigned int col_r = (led_reg & 1) ? 0xd0d0d0d0 : 0xe0e0e0e0;
p(pitch*0) = p(pitch*1) = p(pitch*2) = col_g;
p(pitch*0 + led_offs) = p(pitch*1 + led_offs) = p(pitch*2 + led_offs) = col_r;
#undef p
} else {
#define p(x) px[(x)*2 >> 2] = px[((x)*2 >> 2) + 1]
// 16-bit modes
unsigned int *px = (unsigned int *)((short *)g_screen_ptr + scr_offs);
unsigned int col_g = (led_reg & 2) ? 0x06000600 : 0;
unsigned int col_r = (led_reg & 1) ? 0xc000c000 : 0;
p(pitch*0) = p(pitch*1) = p(pitch*2) = col_g;
p(pitch*0 + led_offs) = p(pitch*1 + led_offs) = p(pitch*2 + led_offs) = col_r;
#undef p
}
}
void pemu_finalize_frame(const char *fps, const char *notice)
{
if (currentConfig.renderer != RT_16BIT && !(PicoAHW & PAHW_32X)) {
unsigned short *pd = (unsigned short *)g_screen_ptr + 8 * g_screen_width;
unsigned char *ps = PicoDraw2FB + 328*8 + 8;
unsigned short *pal = HighPal;
int i, x;
if (Pico.m.dirtyPal)
PicoDrawUpdateHighPal();
for (i = 0; i < 224; i++, ps += 8)
for (x = 0; x < 320; x++)
*pd++ = pal[*ps++];
}
if (notice || (currentConfig.EmuOpt & EOPT_SHOW_FPS)) {
if (notice)
osd_text(4, g_screen_height - 8, notice);
if (currentConfig.EmuOpt & EOPT_SHOW_FPS)
osd_text(g_screen_width - 60, g_screen_height - 8, fps);
}
if ((PicoAHW & PAHW_MCD) && (currentConfig.EmuOpt & EOPT_EN_CD_LEDS))
draw_cd_leds();
}
static void apply_renderer(void)
{
switch (currentConfig.renderer) {
case RT_16BIT:
PicoOpt &= ~POPT_ALT_RENDERER;
PicoDrawSetOutFormat(PDF_RGB555, 0);
PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
break;
case RT_8BIT_ACC:
PicoOpt &= ~POPT_ALT_RENDERER;
PicoDrawSetOutFormat(PDF_8BIT, 0);
PicoDrawSetOutBuf(PicoDraw2FB + 8, 328);
break;
case RT_8BIT_FAST:
PicoOpt |= POPT_ALT_RENDERER;
PicoDrawSetOutFormat(PDF_NONE, 0);
break;
}
if (PicoAHW & PAHW_32X) {
int only_32x = 0;
if (currentConfig.renderer == RT_16BIT)
only_32x = 1;
else
PicoDrawSetOutFormat(PDF_NONE, 0);
PicoDraw32xSetFrameMode(1, only_32x);
PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
}
//PicoDraw32xSetFrameMode(0, 0);
//PicoDrawSetOutFormat(PDF_RGB555, 1);
}
void plat_video_toggle_renderer(int change, int is_menu)
{
currentConfig.renderer += change;
if (currentConfig.renderer >= RT_COUNT)
currentConfig.renderer = 0;
else if (currentConfig.renderer < 0)
currentConfig.renderer = RT_COUNT - 1;
if (!is_menu)
apply_renderer();
emu_status_msg(renderer_names[currentConfig.renderer]);
}
void plat_video_menu_enter(int is_rom_loaded)
{
}
void plat_video_menu_begin(void)
{
g_menuscreen_ptr = g_screen_ptr;
}
void plat_video_menu_end(void)
{
plat_video_flip();
}
void plat_status_msg_clear(void)
{
unsigned short *d = (unsigned short *)g_screen_ptr + g_screen_width * g_screen_height;
int l = g_screen_width * 8;
memset32((int *)(d - l), 0, l * 2 / 4);
}
void plat_status_msg_busy_next(const char *msg)
{
plat_status_msg_clear();
pemu_finalize_frame("", msg);
plat_video_flip();
emu_status_msg("");
reset_timing = 1;
}
void plat_status_msg_busy_first(const char *msg)
{
// memset32(g_screen_ptr, 0, g_screen_width * g_screen_height * 2 / 4);
plat_status_msg_busy_next(msg);
}
void plat_update_volume(int has_changed, int is_up)
{
}
void pemu_forced_frame(int no_scale, int do_emu)
{
PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
PicoDraw32xSetFrameMode(0, 0);
PicoDrawSetCallbacks(NULL, NULL);
Pico.m.dirtyPal = 1;
emu_cmn_forced_frame(no_scale, do_emu);
g_menubg_src_ptr = g_screen_ptr;
}
static void oss_write_nonblocking(int len)
{
// sndout_oss_can_write() is not reliable, only use with no_frmlimit
if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && !sndout_oss_can_write(len))
return;
sndout_oss_write_nb(PsndOut, len);
}
void pemu_sound_start(void)
{
PsndOut = NULL;
if (currentConfig.EmuOpt & EOPT_EN_SOUND)
{
int is_stereo = (PicoOpt & POPT_EN_STEREO) ? 1 : 0;
PsndRerate(Pico.m.frame_count ? 1 : 0);
printf("starting audio: %i len: %i stereo: %i, pal: %i\n",
PsndRate, PsndLen, is_stereo, Pico.m.pal);
sndout_oss_start(PsndRate, is_stereo, 1);
sndout_oss_setvol(currentConfig.volume, currentConfig.volume);
PicoWriteSound = oss_write_nonblocking;
plat_update_volume(0, 0);
memset(sndBuffer, 0, sizeof(sndBuffer));
PsndOut = sndBuffer;
}
}
void pemu_sound_stop(void)
{
}
void pemu_sound_wait(void)
{
// don't need to do anything, writes will block by themselves
}
void plat_debug_cat(char *str)
{
}
void emu_video_mode_change(int start_line, int line_count, int is_32cols)
{
// clear whole screen in all buffers
memset32(g_screen_ptr, 0, g_screen_width * g_screen_height * 2 / 4);
}
void pemu_loop_prep(void)
{
apply_renderer();
osd_text = osd_text16;
pemu_sound_start();
}
void pemu_loop_end(void)
{
pemu_sound_stop();
/* do one more frame for menu bg */
pemu_forced_frame(0, 1);
}
void plat_wait_till_us(unsigned int us_to)
{
unsigned int now;
now = plat_get_ticks_us();
while ((signed int)(us_to - now) > 512)
{
usleep(1024);
now = plat_get_ticks_us();
}
}

View file

@ -1,383 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../common/emu.h"
#include "../common/menu.h"
#include "../common/plat.h"
#include "../common/input.h"
#include "sndout_oss.h"
#include "version.h"
#include "log_io.h"
int current_keys;
unsigned char *PicoDraw2FB;
#ifdef FBDEV
#include "fbdev.h"
#else
#include <pthread.h>
#include <semaphore.h>
static int current_bpp = 16;
static int current_pal[256];
static const char *verstring = "PicoDrive " VERSION;
static int scr_changed = 0, scr_w = SCREEN_WIDTH, scr_h = SCREEN_HEIGHT;
/* faking GP2X pad */
enum { GP2X_UP=0x1, GP2X_LEFT=0x4, GP2X_DOWN=0x10, GP2X_RIGHT=0x40,
GP2X_START=1<<8, GP2X_SELECT=1<<9, GP2X_L=1<<10, GP2X_R=1<<11,
GP2X_A=1<<12, GP2X_B=1<<13, GP2X_X=1<<14, GP2X_Y=1<<15,
GP2X_VOL_UP=1<<23, GP2X_VOL_DOWN=1<<22, GP2X_PUSH=1<<27 };
static void key_press_event(int keycode)
{
switch (keycode)
{
case 111:
case 0x62: current_keys |= GP2X_UP; break;
case 116:
case 0x68: current_keys |= GP2X_DOWN; break;
case 113:
case 0x64: current_keys |= GP2X_LEFT; break;
case 114:
case 0x66: current_keys |= GP2X_RIGHT; break;
case 0x24: current_keys |= GP2X_START; break; // enter
case 0x23: current_keys |= GP2X_SELECT;break; // ]
case 0x34: current_keys |= GP2X_A; break; // z
case 0x35: current_keys |= GP2X_X; break; // x
case 0x36: current_keys |= GP2X_B; break; // c
case 0x37: current_keys |= GP2X_Y; break; // v
case 0x27: current_keys |= GP2X_L; break; // s
case 0x28: current_keys |= GP2X_R; break; // d
case 0x29: current_keys |= GP2X_PUSH; break; // f
case 0x18: current_keys |= GP2X_VOL_DOWN;break; // q
case 0x19: current_keys |= GP2X_VOL_UP;break; // w
case 0x2d: log_io_clear(); break; // k
case 0x2e: log_io_dump(); break; // l
case 0x17: { // tab
extern int PicoReset(void);
PicoReset();
break;
}
}
}
static void key_release_event(int keycode)
{
switch (keycode)
{
case 111:
case 0x62: current_keys &= ~GP2X_UP; break;
case 116:
case 0x68: current_keys &= ~GP2X_DOWN; break;
case 113:
case 0x64: current_keys &= ~GP2X_LEFT; break;
case 114:
case 0x66: current_keys &= ~GP2X_RIGHT; break;
case 0x24: current_keys &= ~GP2X_START; break; // enter
case 0x23: current_keys &= ~GP2X_SELECT;break; // ]
case 0x34: current_keys &= ~GP2X_A; break; // z
case 0x35: current_keys &= ~GP2X_X; break; // x
case 0x36: current_keys &= ~GP2X_B; break; // c
case 0x37: current_keys &= ~GP2X_Y; break; // v
case 0x27: current_keys &= ~GP2X_L; break; // s
case 0x28: current_keys &= ~GP2X_R; break; // d
case 0x29: current_keys &= ~GP2X_PUSH; break; // f
case 0x18: current_keys &= ~GP2X_VOL_DOWN;break; // q
case 0x19: current_keys &= ~GP2X_VOL_UP;break; // w
}
}
/* --- */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
static Display *xlib_display;
static Window xlib_window;
static XImage *ximage;
static void ximage_realloc(Display *display, Visual *visual)
{
void *xlib_screen;
XLockDisplay(xlib_display);
if (ximage != NULL)
XDestroyImage(ximage);
ximage = NULL;
xlib_screen = calloc(scr_w * scr_h, 4);
if (xlib_screen != NULL)
ximage = XCreateImage(display, visual, 24, ZPixmap, 0,
xlib_screen, scr_w, scr_h, 32, 0);
if (ximage == NULL)
fprintf(stderr, "failed to alloc ximage\n");
XUnlockDisplay(xlib_display);
}
static void xlib_update(void)
{
Status xstatus;
XLockDisplay(xlib_display);
xstatus = XPutImage(xlib_display, xlib_window, DefaultGC(xlib_display, 0), ximage,
0, 0, 0, 0, g_screen_width, g_screen_height);
if (xstatus != 0)
fprintf(stderr, "XPutImage %d\n", xstatus);
XUnlockDisplay(xlib_display);
}
static void *xlib_threadf(void *targ)
{
unsigned int width, height, display_width, display_height;
sem_t *sem = targ;
XTextProperty windowName;
Window win;
XEvent report;
Display *display;
Visual *visual;
int screen;
XInitThreads();
xlib_display = display = XOpenDisplay(NULL);
if (display == NULL)
{
fprintf(stderr, "cannot connect to X server %s\n",
XDisplayName(NULL));
sem_post(sem);
return NULL;
}
visual = DefaultVisual(display, 0);
if (visual->class != TrueColor)
{
fprintf(stderr, "cannot handle non true color visual\n");
XCloseDisplay(display);
sem_post(sem);
return NULL;
}
printf("X vendor: %s, rel: %d, display: %s, protocol ver: %d.%d\n", ServerVendor(display),
VendorRelease(display), DisplayString(display), ProtocolVersion(display),
ProtocolRevision(display));
screen = DefaultScreen(display);
ximage_realloc(display, visual);
sem_post(sem);
display_width = DisplayWidth(display, screen);
display_height = DisplayHeight(display, screen);
xlib_window = win = XCreateSimpleWindow(display,
RootWindow(display, screen),
display_width / 2 - scr_w / 2,
display_height / 2 - scr_h / 2,
scr_w + 2, scr_h + 2, 1,
BlackPixel(display, screen),
BlackPixel(display, screen));
XStringListToTextProperty((char **)&verstring, 1, &windowName);
XSetWMName(display, win, &windowName);
XSelectInput(display, win, ExposureMask |
KeyPressMask | KeyReleaseMask |
StructureNotifyMask);
XMapWindow(display, win);
while (1)
{
XNextEvent(display, &report);
switch (report.type)
{
case Expose:
while (XCheckTypedEvent(display, Expose, &report))
;
xlib_update();
break;
case ConfigureNotify:
width = report.xconfigure.width;
height = report.xconfigure.height;
if (scr_w != width - 2 || scr_h != height - 2) {
scr_w = width - 2;
scr_h = height - 2;
scr_changed = 1;
}
break;
case ButtonPress:
break;
case KeyPress:
key_press_event(report.xkey.keycode);
break;
case KeyRelease:
key_release_event(report.xkey.keycode);
break;
default:
break;
}
}
}
static void xlib_init(void)
{
pthread_t x_thread;
sem_t xlib_sem;
sem_init(&xlib_sem, 0, 0);
pthread_create(&x_thread, NULL, xlib_threadf, &xlib_sem);
pthread_detach(x_thread);
sem_wait(&xlib_sem);
sem_destroy(&xlib_sem);
}
/* --- */
static void realloc_screen(void)
{
int size = scr_w * scr_h * 2;
g_screen_width = g_menuscreen_w = scr_w;
g_screen_height = g_menuscreen_h = scr_h;
g_screen_ptr = realloc(g_screen_ptr, size);
g_menubg_ptr = realloc(g_menubg_ptr, size);
memset(g_screen_ptr, 0, size);
memset(g_menubg_ptr, 0, size);
PicoDraw2FB = g_menubg_ptr;
scr_changed = 0;
}
void plat_video_flip(void)
{
unsigned int *image;
int pixel_count, i;
if (ximage == NULL)
return;
pixel_count = g_screen_width * g_screen_height;
image = (void *)ximage->data;
if (current_bpp == 8)
{
unsigned char *pixels = g_screen_ptr;
int pix;
for (i = 0; i < pixel_count; i++)
{
pix = current_pal[pixels[i]];
image[i] = pix;
}
}
else
{
unsigned short *pixels = g_screen_ptr;
for (i = 0; i < pixel_count; i++)
{
/* in: rrrr rggg gggb bbbb */
/* out: rrrr r000 gggg gg00 bbbb b000 */
image[i] = (pixels[i] << 8) & 0xf80000;
image[i] |= (pixels[i] << 5) & 0x00fc00;
image[i] |= (pixels[i] << 3) & 0x0000f8;
}
}
xlib_update();
if (scr_changed) {
realloc_screen();
ximage_realloc(xlib_display, DefaultVisual(xlib_display, 0));
// propagate new ponters to renderers
plat_video_toggle_renderer(0, 0);
}
}
void plat_video_wait_vsync(void)
{
}
#endif // !FBDEV
void plat_early_init(void)
{
}
void plat_init(void)
{
#ifdef FBDEV
int ret, w, h;
ret = vout_fbdev_init(&w, &h);
if (ret != 0)
exit(1);
g_screen_width = g_menuscreen_w = w;
g_screen_height = g_menuscreen_h = h;
g_menubg_ptr = realloc(g_menubg_ptr, w * g_screen_height * 2);
PicoDraw2FB = g_menubg_ptr;
#else
realloc_screen();
memset(g_screen_ptr, 0, g_screen_width * g_screen_height * 2);
xlib_init();
#endif
// snd
sndout_oss_init();
}
void plat_finish(void)
{
#ifdef FBDEV
vout_fbdev_finish();
#else
free(g_screen_ptr);
#endif
sndout_oss_exit();
}
/* misc */
int mp3_get_bitrate(void *f, int size)
{
return 128;
}
void mp3_start_play(void *f, int pos)
{
}
void mp3_update(int *buffer, int length, int stereo)
{
}
#include <linux/input.h>
struct in_default_bind in_evdev_defbinds[] =
{
/* MXYZ SACB RLDU */
{ KEY_UP, IN_BINDTYPE_PLAYER12, 0 },
{ KEY_DOWN, IN_BINDTYPE_PLAYER12, 1 },
{ KEY_LEFT, IN_BINDTYPE_PLAYER12, 2 },
{ KEY_RIGHT, IN_BINDTYPE_PLAYER12, 3 },
{ KEY_S, IN_BINDTYPE_PLAYER12, 4 }, /* B */
{ KEY_D, IN_BINDTYPE_PLAYER12, 5 }, /* C */
{ KEY_A, IN_BINDTYPE_PLAYER12, 6 }, /* A */
{ KEY_ENTER, IN_BINDTYPE_PLAYER12, 7 },
{ KEY_BACKSLASH, IN_BINDTYPE_EMU, PEVB_MENU },
{ 0, 0, 0 }
};

View file

@ -1,81 +0,0 @@
#include <stdio.h>
typedef struct
{
unsigned int addr_min, addr_max;
int r8, r16, r32, w8, w16, w32;
} io_log_location;
static io_log_location io_locations[] =
{
{ 0x400000, 0x9FFFFF, 0, }, // unused
{ 0xa00000, 0xa03fff, 0, }, // z80 RAM
{ 0xa04000, 0xa05fff, 0, }, // ym2612
{ 0xa06000, 0xa060ff, 0, }, // bank reg
{ 0xa06100, 0xa07eff, 0, }, // unused
{ 0xa07f00, 0xa07fff, 0, }, // vdp
{ 0xa08000, 0xa0ffff, 0, }, // 0xa00000-0xa07fff mirror
{ 0xa10000, 0xa1001f, 0, }, // i/o
{ 0xa10020, 0xa10fff, 0, }, // expansion
{ 0xa11000, 0xa110ff, 0, }, // expansion
{ 0xa11100, 0xa11101, 0, }, // z80 busreq
{ 0xa11102, 0xa111ff, 0, }, // expansion
{ 0xa11200, 0xa11201, 0, }, // z80 reset
{ 0xa11202, 0xbfffff, 0, }, // expansion
{ 0xc00000, 0xc00003, 0, }, // vdp data port
{ 0xc00004, 0xc00007, 0, }, // vdp control
{ 0xc00009, 0xc0000f, 0, }, // hv counter
{ 0xc00010, 0xc00017, 0, }, // PSG
{ 0xc00018, 0xc0001f, 0, }, // unused
{ 0xc00020, 0xdfffff, 0, } // vdp mirrors
};
void log_io(unsigned int a, int bits, int is_write)
{
int i;
a &= 0x00ffffff;
if (bits > 8) a&=~1;
for (i = 0; i < sizeof(io_locations)/sizeof(io_locations[0]); i++)
{
if (a >= io_locations[i].addr_min && a <= io_locations[i].addr_max)
{
switch (bits|(is_write<<8)) {
case 0x008: io_locations[i].r8 ++; break;
case 0x010: io_locations[i].r16++; break;
case 0x020: io_locations[i].r32++; break;
case 0x108: io_locations[i].w8 ++; break;
case 0x110: io_locations[i].w16++; break;
case 0x120: io_locations[i].w32++; break;
default: printf("%06x %i %i\n", a, bits, is_write); break;
}
}
}
}
void log_io_clear(void)
{
int i;
for (i = 0; i < sizeof(io_locations)/sizeof(io_locations[0]); i++)
{
io_log_location *iol = &io_locations[i];
iol->r8 = iol->r16 = iol->r32 = iol->w8 = iol->w16 = iol->w32 = 0;
}
}
void log_io_dump(void)
{
int i;
printf(" range : r8 r16 r32 w8 w16 w32\n");
for (i = 0; i < sizeof(io_locations)/sizeof(io_locations[0]); i++)
{
io_log_location *iol = &io_locations[i];
if (iol->r8 == 0 && iol->r16 == 0 && iol->r32 == 0 && iol->w8 == 0 && iol->w16 == 0 && iol->w32 == 0)
continue;
printf("%06x - %06x : %8i %8i %8i %8i %8i %8i\n", iol->addr_min, iol->addr_max,
iol->r8, iol->r16, iol->r32, iol->w8, iol->w16, iol->w32);
}
printf("\n");
}

View file

@ -1,3 +0,0 @@
void log_io_clear(void);
void log_io_dump(void);

View file

@ -1,41 +0,0 @@
// port specific settings
#ifndef PORT_CONFIG_H
#define PORT_CONFIG_H
#define NO_SYNC
#define CASE_SENSITIVE_FS 1 // CS filesystem
#define DONT_OPEN_MANY_FILES 0
#define REDUCE_IO_CALLS 0
#define SCREEN_SIZE_FIXED 0
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define MSCREEN_SIZE_FIXED 0
#define MSCREEN_WIDTH SCREEN_WIDTH
#define MSCREEN_HEIGHT SCREEN_HEIGHT
// draw2.c
#define START_ROW 0 // which row of tiles to start rendering at?
#define END_ROW 28 // ..end
// pico.c
#define CAN_HANDLE_240_LINES 1
#define SIMPLE_WRITE_SOUND 0
#define mix_32_to_16l_stereo_lvl mix_32_to_16l_stereo
#define EL_LOGMASK (EL_STATUS|EL_ANOMALY|EL_UIO)
// EL_VDPDMA|EL_ASVDP|EL_SR | EL_IDLE | EL_BUSREQ|EL_Z80BNK | EL_32X)
//#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__)
#define dprintf(x...)
// platform
#define PATH_SEP "/"
#define PATH_SEP_C '/'
#define MENU_X2 0
#endif //PORT_CONFIG_H

View file

@ -1,126 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pico/pico_int.h>
struct pp_counters *pp_counters;
static int shmemid;
void pprof_init(void)
{
int this_is_new_shmem = 1;
key_t shmemkey;
void *shmem;
#ifndef PPROF_TOOL
unsigned int tmp = pprof_get_one();
printf("pprof: measured diff is %u\n", pprof_get_one() - tmp);
#endif
shmemkey = ftok(".", 0x02ABC32E);
if (shmemkey == -1)
{
perror("pprof: ftok failed");
return;
}
#ifndef PPROF_TOOL
shmemid = shmget(shmemkey, sizeof(*pp_counters),
IPC_CREAT | IPC_EXCL | 0644);
if (shmemid == -1)
#endif
{
shmemid = shmget(shmemkey, sizeof(*pp_counters),
0644);
if (shmemid == -1)
{
perror("pprof: shmget failed");
return;
}
this_is_new_shmem = 0;
}
shmem = shmat(shmemid, NULL, 0);
if (shmem == (void *)-1)
{
perror("pprof: shmat failed");
return;
}
pp_counters = shmem;
if (this_is_new_shmem) {
memset(pp_counters, 0, sizeof(*pp_counters));
printf("pprof: pp_counters cleared.\n");
}
}
void pprof_finish(void)
{
shmdt(pp_counters);
shmctl(shmemid, IPC_RMID, NULL);
}
#ifdef PPROF_TOOL
#define IT(n) { pp_##n, #n }
static const struct {
enum pprof_points pp;
const char *name;
} pp_tab[] = {
IT(main),
IT(frame),
IT(draw),
IT(sound),
IT(m68k),
IT(z80),
IT(msh2),
IT(ssh2),
IT(dummy),
};
int main(int argc, char *argv[])
{
unsigned long long old[pp_total_points], new[pp_total_points];
int base = 0;
int l, i;
pprof_init();
if (pp_counters == NULL)
return 1;
if (argc >= 2)
base = atoi(argv[1]);
memset(old, 0, sizeof(old));
for (l = 0; ; l++)
{
if ((l & 0x1f) == 0) {
for (i = 0; i < ARRAY_SIZE(pp_tab); i++)
printf("%6s ", pp_tab[i].name);
printf("\n");
}
memcpy(new, pp_counters->counter, sizeof(new));
for (i = 0; i < ARRAY_SIZE(pp_tab); i++)
{
unsigned long long idiff = new[i] - old[i];
unsigned long long bdiff = (new[base] - old[base]) | 1;
printf("%6.2f ", (double)idiff * 100.0 / bdiff);
}
printf("\n");
memcpy(old, new, sizeof(old));
if (argc < 3)
break;
usleep(atoi(argv[2]));
}
return 0;
}
#endif // PPROF_TOOL

View file

@ -1,67 +0,0 @@
#ifndef __PPROF_H__
#define __PPROF_H__
enum pprof_points {
pp_main,
pp_frame,
pp_draw,
pp_sound,
pp_m68k,
pp_z80,
pp_msh2,
pp_ssh2,
pp_dummy,
pp_total_points
};
struct pp_counters
{
unsigned long long counter[pp_total_points];
};
extern struct pp_counters *pp_counters;
#ifdef __i386__
static __attribute__((always_inline)) inline unsigned int pprof_get_one(void)
{
unsigned long long ret;
__asm__ __volatile__ ("rdtsc" : "=A" (ret));
return (unsigned int)ret;
}
#define unglitch_timer(x)
#elif defined(__GP2X__)
// XXX: MMSP2 only, timer sometimes seems to return lower vals?
extern volatile unsigned long *gp2x_memregl;
#define pprof_get_one() (unsigned int)gp2x_memregl[0x0a00 >> 2]
#define unglitch_timer(di) \
if ((signed int)(di) < 0) di = 0
#else
#error no timer
#endif
#define pprof_start(point) { \
unsigned int pp_start_##point = pprof_get_one()
#define pprof_end(point) \
{ \
unsigned int di = pprof_get_one() - pp_start_##point; \
unglitch_timer(di); \
pp_counters->counter[pp_##point] += di; \
} \
}
// subtract for recursive stuff
#define pprof_end_sub(point) \
{ \
unsigned int di = pprof_get_one() - pp_start_##point; \
unglitch_timer(di); \
pp_counters->counter[pp_##point] -= di; \
} \
}
extern void pprof_init(void);
extern void pprof_finish(void);
#endif // __PPROF_H__

View file

@ -1,2 +0,0 @@
#include "../gp2x/version.h"

View file

@ -1,107 +0,0 @@
#export CROSS = arm-none-linux-gnueabi-
CROSS ?= $(CROSS_COMPILE)
LIBROOT = /home/notaz/dev/pnd/libroot
PND_MAKE ?= $(HOME)/dev/pnd/src/pandora-libraries/testdata/scripts/pnd_make.sh
# settings
use_cyclone = 1
#use_musashi = 1
use_drz80 = 1
use_sh2drc = 1
#use_sh2mame = 1
asm_memory = 1
asm_render = 1
asm_ym2612 = 1
asm_misc = 1
asm_cdpico = 1
asm_cdmemory = 1
#profile = 1
#drc_debug = 3
-include Makefile.local
ifeq "$(use_musashi)" "1"
# due to CPU stop flag acces
asm_cdpico = 0
asm_cdmemory = 0
endif
ARCH = arm
DEFINES += ARM PANDORA IN_EVDEV
CFLAGS += -I../.. -I. -I$(LIBROOT)/include
CFLAGS += -Wall -Winline -mcpu=cortex-a8 -mtune=cortex-a8 -march=armv7-a
ifeq ($(DEBUG),)
CFLAGS += -O2 -fomit-frame-pointer -fstrict-aliasing -ffast-math
endif
LDFLAGS += -L$(LIBROOT)/lib -Wl,-Bstatic -lpng -Wl,-Bdynamic -lm -lpthread -ldl
ASFLAGS = -mcpu=cortex-a8
CC = $(CROSS)gcc
STRIP = $(CROSS)strip
AS = $(CROSS)as
LD = $(CROSS)ld
OBJCOPY = $(CROSS)objcopy
# frontend
OBJS += plat.o asm_utils.o
# common
OBJS += platform/common/emu.o platform/common/menu_pico.o platform/common/fonts.o platform/common/config.o \
platform/common/arm_utils.o platform/common/mp3_helix.o platform/common/arm_linux.o \
platform/common/readpng.o platform/common/input.o platform/common/main.o platform/common/mp3.o \
platform/linux/fbdev.o platform/linux/in_evdev.o platform/linux/sndout_oss.o \
platform/linux/plat.o platform/linux/xenv.o
# ARM stuff
OBJS += pico/carthw/svp/compiler.o pico/carthw/svp/stub_arm.o
OBJS += pico/sound/mix_arm.o
# zlib
OBJS += zlib/gzio.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o \
zlib/deflate.o zlib/crc32.o zlib/adler32.o zlib/zutil.o zlib/compress.o
# unzip
OBJS += unzip/unzip.o unzip/unzip_stream.o
vpath %.c = ../..
vpath %.s = ../..
vpath %.S = ../..
DIRS += platform/linux zlib unzip
all: mkdirs PicoDrive picorestore
include ../common/common.mak
include ../common/common_arm.mak
include ../common/revision.mak
CFLAGS += $(addprefix -D,$(DEFINES))
PicoDrive : $(OBJS) ../common/helix/$(CROSS)helix-mp3.a
@echo ">>>" $@
$(CC) -o $@ $(CFLAGS) $^ $(LDFLAGS) -Wl,-Map=PicoDrive.map
ifeq ($(DEBUG),)
$(STRIP) $@
endif
clean: tidy
$(RM) PicoDrive
tidy:
$(RM) $(OBJS)
readme.txt: ../../tools/textfilter ../base_readme.txt
../../tools/textfilter ../base_readme.txt $@ PANDORA
PicoDrive.pxml: PicoDrive.pxml.template
./make_pxml.sh PicoDrive.pxml.template PicoDrive.pxml
platform/common/menu_pico.o: platform/common/menu.c menu.c
# ----------- release -----------
VER ?= $(shell head -n 1 version.h | sed 's/.*"\(.*\)\.\(.*\)".*/\1\2/g')
rel: PicoDrive PicoDrive.run picorestore ../../pico/carthw.cfg readme.txt \
skin PicoDrive.png PicoDrive_p.png PicoDrive.pxml
rm -rf out
mkdir out
cp -r $^ out/
$(PND_MAKE) -p PicoDrive_$(VER).pnd -d out -x PicoDrive.pxml -i PicoDrive.png -c

View file

@ -1,3 +0,0 @@
void clut_line2x2(void *dest, const void *src, const unsigned short *pal, int pixels_mask);
void clut_line3x2(void *dest, const void *src, const unsigned short *pal, int pixels_mask);

View file

@ -1,108 +0,0 @@
@ vim:filetype=armasm
@ FIXME: handle dual issue
.global clut_line2x2 @ void *dest, void *src, unsigned short *pal, int pixels_mask
clut_line2x2:
stmfd sp!, {r4-r11,lr}
and lr, r3, #0xff0000
mov lr, lr, lsr #15 @ mask
mov r3, r3, lsr #3
and r3, r3, #0xff @ counter
add r11,r0, #800*2
clut_line_2x2_loop:
ldmia r1!, {r10,r12}
and r4, lr, r10, lsl #1
ldrh r4, [r2, r4]
and r5, lr, r10, lsr #7
ldrh r5, [r2, r5]
orr r4, r4, r4, lsl #16
and r6, lr, r10, lsr #15
ldrh r6, [r2, r6]
orr r5, r5, r5, lsl #16
and r7, lr, r10, lsr #23
ldrh r7, [r2, r7]
orr r6, r6, r6, lsl #16
and r8, lr, r12, lsl #1
ldrh r8, [r2, r8]
orr r7, r7, r7, lsl #16
and r9, lr, r12, lsr #7
ldrh r9, [r2, r9]
orr r8, r8, r8, lsl #16
and r10,lr, r12, lsr #15
ldrh r10,[r2, r10]
orr r9, r9, r9, lsl #16
and r12,lr, r12, lsr #23
ldrh r12,[r2, r12]
orr r10,r10,r10, lsl #16
subs r3, r3, #1
orr r12,r12,r12, lsl #16
stmia r0!, {r4-r10,r12}
stmia r11!,{r4-r10,r12}
bne clut_line_2x2_loop
ldmfd sp!, {r4-r11,pc}
@ 00 01 11 22 23 33
@ r4 r5 r6 r7 r8 r9
.macro do_4_to_12 rs
and r4, lr, \rs, lsl #1
and r6, lr, \rs, lsr #7
and r7, lr, \rs, lsr #15
and r9, lr, \rs, lsr #23
ldrh r4, [r2, r4]
ldrh r6, [r2, r6]
ldrh r7, [r2, r7]
ldrh r9, [r2, r9]
orr r5, r4, r6, lsl #16
orr r4, r4, r4, lsl #16
orr r6, r6, r6, lsl #16
orr r8, r7, r9, lsl #16
orr r7, r7, r7, lsl #16
orr r9, r9, r9, lsl #16
.endm
.global clut_line3x2 @ void *dest, void *src, unsigned short *pal, int pixels_mask
clut_line3x2:
stmfd sp!, {r4-r11,lr}
and lr, r3, #0xff0000
mov lr, lr, lsr #15 @ mask
mov r3, r3, lsr #3
and r3, r3, #0xff @ counter
add r11,r0, #800*2
clut_line3x2_loop:
ldmia r1!, {r10,r12}
do_4_to_12 r10
stmia r0!, {r4-r9}
stmia r11!,{r4-r9}
do_4_to_12 r12
subs r3, r3, #1
stmia r0!, {r4-r9}
stmia r11!,{r4-r9}
bne clut_line3x2_loop
ldmfd sp!, {r4-r11,pc}

View file

@ -1,10 +0,0 @@
#!/bin/sh
sed -i
major=`head -n 1 version.h | sed 's/.*"\([0-9]*\)\.\([0-9]*\).*/\1/g'`
minor=`head -n 1 version.h | sed 's/.*"\([0-9]*\)\.\([0-9]*\).*/\2/g'`
revision=`head -n 1 revision.h | sed 's/.*"\([0-9]*\)".*/\1/g'`
sed 's/@major@/'$major'/' "$1" > "$2"
sed -i 's/@minor@/'$minor'/' "$2"
sed -i 's/@revision@/'$revision'/' "$2"

View file

@ -1,148 +0,0 @@
#include "plat.h"
static const char *men_scaler[] = { "1x1, 1x1", "2x2, 3x2", "2x2, 2x2", "fullscreen", "custom", NULL };
static const char h_scaler[] = "Scalers for 40 and 32 column modes\n"
"(320 and 256 pixel wide horizontal)";
static const char h_cscaler[] = "Displays the scaler layer, you can resize it\n"
"using d-pad or move it using R+d-pad";
static const char *men_dummy[] = { NULL };
char **pnd_filter_list;
static int menu_loop_cscaler(int id, int keys)
{
unsigned int inp;
currentConfig.scaling = SCALE_CUSTOM;
pnd_setup_layer(1, g_layer_cx, g_layer_cy, g_layer_cw, g_layer_ch);
pnd_restore_layer_data();
for (;;)
{
menu_draw_begin(0);
memset(g_menuscreen_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2);
text_out16(2, 480 - 18, "%dx%d | d-pad to resize, R+d-pad to move", g_layer_cw, g_layer_ch);
menu_draw_end();
inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|PBTN_R|PBTN_MOK|PBTN_MBACK, 40);
if (inp & PBTN_UP) g_layer_cy--;
if (inp & PBTN_DOWN) g_layer_cy++;
if (inp & PBTN_LEFT) g_layer_cx--;
if (inp & PBTN_RIGHT) g_layer_cx++;
if (!(inp & PBTN_R)) {
if (inp & PBTN_UP) g_layer_ch += 2;
if (inp & PBTN_DOWN) g_layer_ch -= 2;
if (inp & PBTN_LEFT) g_layer_cw += 2;
if (inp & PBTN_RIGHT) g_layer_cw -= 2;
}
if (inp & (PBTN_MOK|PBTN_MBACK))
break;
if (inp & (PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT)) {
if (g_layer_cx < 0) g_layer_cx = 0;
if (g_layer_cx > 640) g_layer_cx = 640;
if (g_layer_cy < 0) g_layer_cy = 0;
if (g_layer_cy > 420) g_layer_cy = 420;
if (g_layer_cw < 160) g_layer_cw = 160;
if (g_layer_ch < 60) g_layer_ch = 60;
if (g_layer_cx + g_layer_cw > 800)
g_layer_cw = 800 - g_layer_cx;
if (g_layer_cy + g_layer_ch > 480)
g_layer_ch = 480 - g_layer_cy;
pnd_setup_layer(1, g_layer_cx, g_layer_cy, g_layer_cw, g_layer_ch);
}
}
pnd_setup_layer(0, g_layer_cx, g_layer_cy, g_layer_cw, g_layer_ch);
return 0;
}
#define MENU_OPTIONS_GFX \
mee_enum_h ("Scaler", MA_OPT_SCALING, currentConfig.scaling, \
men_scaler, h_scaler), \
mee_enum ("Filter", MA_OPT3_FILTERING, currentConfig.filter, men_dummy), \
mee_onoff ("Vsync", MA_OPT2_VSYNC, currentConfig.EmuOpt, EOPT_VSYNC), \
mee_cust_h ("Setup custom scaler", MA_NONE, menu_loop_cscaler, NULL, h_cscaler), \
mee_range_hide("layer_x", MA_OPT3_LAYER_X, g_layer_cx, 0, 640), \
mee_range_hide("layer_y", MA_OPT3_LAYER_Y, g_layer_cy, 0, 420), \
mee_range_hide("layer_w", MA_OPT3_LAYER_W, g_layer_cw, 160, 800), \
mee_range_hide("layer_h", MA_OPT3_LAYER_H, g_layer_ch, 60, 480), \
#define MENU_OPTIONS_ADV \
mee_onoff ("SVP dynarec", MA_OPT2_SVP_DYNAREC, PicoOpt, POPT_EN_SVP_DRC), \
mee_onoff ("Status line in main menu", MA_OPT2_STATUS_LINE, currentConfig.EmuOpt, EOPT_SHOW_RTC),
#define menu_main_plat_draw NULL
#include <dirent.h>
#include <errno.h>
static menu_entry e_menu_gfx_options[];
static menu_entry e_menu_options[];
static menu_entry e_menu_keyconfig[];
void pnd_menu_init(void)
{
struct dirent *ent;
int i, count = 0;
char **mfilters;
char buff[64], *p;
DIR *dir;
dir = opendir("/etc/pandora/conf/dss_fir");
if (dir == NULL) {
perror("filter opendir");
return;
}
while (1) {
errno = 0;
ent = readdir(dir);
if (ent == NULL) {
if (errno != 0)
perror("readdir");
break;
}
p = strstr(ent->d_name, "_up");
if (p != NULL && (p[3] == 0 || !strcmp(p + 3, "_h")))
count++;
}
if (count == 0)
return;
mfilters = calloc(count + 1, sizeof(mfilters[0]));
if (mfilters == NULL)
return;
rewinddir(dir);
for (i = 0; (ent = readdir(dir)); ) {
size_t len;
p = strstr(ent->d_name, "_up");
if (p == NULL || (p[3] != 0 && strcmp(p + 3, "_h")))
continue;
len = p - ent->d_name;
if (len > sizeof(buff) - 1)
continue;
strncpy(buff, ent->d_name, len);
buff[len] = 0;
mfilters[i] = strdup(buff);
if (mfilters[i] != NULL)
i++;
}
closedir(dir);
i = me_id2offset(e_menu_gfx_options, MA_OPT3_FILTERING);
e_menu_gfx_options[i].data = (void *)mfilters;
pnd_filter_list = mfilters;
i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS);
e_menu_options[i].name = "Max CPU clock";
me_enable(e_menu_keyconfig, MA_CTRL_DEADZONE, 0);
}

View file

@ -1,639 +0,0 @@
// (c) Copyright 2006-2009 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/fb.h>
#include <linux/omapfb.h>
#include "../common/emu.h"
#include "../common/menu.h"
#include "../common/plat.h"
#include "../common/arm_utils.h"
#include "../common/input.h"
#include "../linux/sndout_oss.h"
#include "../linux/fbdev.h"
#include "../linux/xenv.h"
#include "plat.h"
#include "asm_utils.h"
#include "version.h"
#include <pico/pico_int.h>
#include <linux/input.h>
static struct vout_fbdev *main_fb, *layer_fb;
// g_layer_* - in use, g_layer_c* - configured custom
int g_layer_cx, g_layer_cy, g_layer_cw, g_layer_ch;
static int g_layer_x, g_layer_y;
static int g_layer_w = 320, g_layer_h = 240;
static int g_osd_fps_x, g_osd_y, doing_bg_frame;
static const char pnd_script_base[] = "sudo -n /usr/pandora/scripts";
static short __attribute__((aligned(4))) sndBuffer[2*44100/50];
static unsigned char __attribute__((aligned(4))) fb_copy[g_screen_width * g_screen_height * 2];
static void *temp_frame;
unsigned char *PicoDraw2FB;
const char *renderer_names[] = { NULL };
const char *renderer_names32x[] = { NULL };
static const char * const pandora_gpio_keys[KEY_MAX + 1] = {
[0 ... KEY_MAX] = NULL,
[KEY_UP] = "Up",
[KEY_LEFT] = "Left",
[KEY_RIGHT] = "Right",
[KEY_DOWN] = "Down",
[KEY_HOME] = "A",
[KEY_PAGEDOWN] = "X",
[KEY_END] = "B",
[KEY_PAGEUP] = "Y",
[KEY_RIGHTSHIFT]= "L",
[KEY_RIGHTCTRL] = "R",
[KEY_LEFTALT] = "Start",
[KEY_LEFTCTRL] = "Select",
[KEY_MENU] = "Pandora",
};
struct in_default_bind in_evdev_defbinds[] =
{
/* MXYZ SACB RLDU */
{ KEY_UP, IN_BINDTYPE_PLAYER12, 0 },
{ KEY_DOWN, IN_BINDTYPE_PLAYER12, 1 },
{ KEY_LEFT, IN_BINDTYPE_PLAYER12, 2 },
{ KEY_RIGHT, IN_BINDTYPE_PLAYER12, 3 },
{ KEY_S, IN_BINDTYPE_PLAYER12, 4 }, /* B */
{ KEY_D, IN_BINDTYPE_PLAYER12, 5 }, /* C */
{ KEY_A, IN_BINDTYPE_PLAYER12, 6 }, /* A */
{ KEY_ENTER, IN_BINDTYPE_PLAYER12, 7 },
{ KEY_BACKSLASH, IN_BINDTYPE_EMU, PEVB_MENU },
{ KEY_SPACE, IN_BINDTYPE_EMU, PEVB_MENU },
/* Pandora */
{ KEY_PAGEDOWN, IN_BINDTYPE_PLAYER12, 4 },
{ KEY_END, IN_BINDTYPE_PLAYER12, 5 },
{ KEY_HOME, IN_BINDTYPE_PLAYER12, 6 },
{ KEY_LEFTALT, IN_BINDTYPE_PLAYER12, 7 },
{ KEY_RIGHTSHIFT,IN_BINDTYPE_EMU, PEVB_STATE_SAVE },
{ KEY_RIGHTCTRL, IN_BINDTYPE_EMU, PEVB_STATE_LOAD },
{ KEY_LEFTCTRL, IN_BINDTYPE_EMU, PEVB_MENU },
{ 0, 0, 0 }
};
static int get_cpu_clock(void)
{
FILE *f;
int ret = 0;
f = fopen("/proc/pandora/cpu_mhz_max", "r");
if (f) {
fscanf(f, "%d", &ret);
fclose(f);
}
return ret;
}
void pemu_prep_defconfig(void)
{
defaultConfig.EmuOpt |= EOPT_VSYNC|EOPT_16BPP;
defaultConfig.s_PicoOpt |= POPT_EN_MCD_GFX|POPT_EN_MCD_PSYNC;
defaultConfig.scaling = SCALE_2x2_3x2;
}
void pemu_validate_config(void)
{
currentConfig.CPUclock = get_cpu_clock();
}
static void osd_text(int x, int y, const char *text)
{
int len = strlen(text)*8;
int i, h;
len++;
for (h = 0; h < 8; h++) {
unsigned short *p;
p = (unsigned short *)g_screen_ptr + x + g_screen_width*(y + h);
for (i = len; i; i--, p++)
*p = (*p>>2) & 0x39e7;
}
emu_text_out16(x, y, text);
}
static void draw_cd_leds(void)
{
int old_reg;
old_reg = Pico_mcd->s68k_regs[0];
if (0) {
// 8-bit modes
unsigned int col_g = (old_reg & 2) ? 0xc0c0c0c0 : 0xe0e0e0e0;
unsigned int col_r = (old_reg & 1) ? 0xd0d0d0d0 : 0xe0e0e0e0;
*(unsigned int *)((char *)g_screen_ptr + g_screen_width*2+ 4) =
*(unsigned int *)((char *)g_screen_ptr + g_screen_width*3+ 4) =
*(unsigned int *)((char *)g_screen_ptr + g_screen_width*4+ 4) = col_g;
*(unsigned int *)((char *)g_screen_ptr + g_screen_width*2+12) =
*(unsigned int *)((char *)g_screen_ptr + g_screen_width*3+12) =
*(unsigned int *)((char *)g_screen_ptr + g_screen_width*4+12) = col_r;
} else {
// 16-bit modes
unsigned int *p = (unsigned int *)((short *)g_screen_ptr + g_screen_width*2+4);
unsigned int col_g = (old_reg & 2) ? 0x06000600 : 0;
unsigned int col_r = (old_reg & 1) ? 0xc000c000 : 0;
*p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += g_screen_width/2 - 12/2;
*p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += g_screen_width/2 - 12/2;
*p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r;
}
}
static int emuscan(unsigned int num)
{
DrawLineDest = (unsigned short *)g_screen_ptr + num * g_screen_width;
return 0;
}
void pemu_finalize_frame(const char *fps, const char *notice)
{
if (notice && notice[0])
osd_text(2, g_osd_y, notice);
if (fps && fps[0] && (currentConfig.EmuOpt & EOPT_SHOW_FPS))
osd_text(g_osd_fps_x, g_osd_y, fps);
if ((PicoAHW & PAHW_MCD) && (currentConfig.EmuOpt & EOPT_EN_CD_LEDS))
draw_cd_leds();
}
void plat_video_flip(void)
{
g_screen_ptr = vout_fbdev_flip(layer_fb);
// XXX: drain OS event queue here, maybe we'll actually use it someday..
int dummy;
xenv_update(&dummy);
}
void plat_video_toggle_renderer(int change, int is_menu)
{
}
void plat_video_menu_enter(int is_rom_loaded)
{
}
void plat_video_menu_begin(void)
{
}
void plat_video_menu_end(void)
{
g_menuscreen_ptr = vout_fbdev_flip(main_fb);
}
void plat_video_wait_vsync(void)
{
vout_fbdev_wait_vsync(main_fb);
}
void plat_status_msg_clear(void)
{
vout_fbdev_clear_lines(layer_fb, g_osd_y, 8);
}
void plat_status_msg_busy_next(const char *msg)
{
plat_status_msg_clear();
pemu_finalize_frame("", msg);
plat_video_flip();
emu_status_msg("");
reset_timing = 1;
}
void plat_status_msg_busy_first(const char *msg)
{
plat_status_msg_busy_next(msg);
}
void plat_update_volume(int has_changed, int is_up)
{
static int prev_frame = 0, wait_frames = 0;
int vol = currentConfig.volume;
if (has_changed)
{
if (is_up) {
if (vol < 99) vol++;
} else {
if (vol > 0) vol--;
}
wait_frames = 0;
sndout_oss_setvol(vol, vol);
currentConfig.volume = vol;
emu_status_msg("VOL: %02i", vol);
prev_frame = Pico.m.frame_count;
}
}
static void make_bg(int no_scale)
{
unsigned short *s = (void *)fb_copy;
int x, y;
memset32(g_menubg_src_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2 / 4);
if (!no_scale && g_menuscreen_w >= 640 && g_menuscreen_h >= 480) {
unsigned int t, *d = g_menubg_src_ptr;
d += (g_menuscreen_h / 2 - 480 / 2) * g_menuscreen_w / 2;
d += (g_menuscreen_w / 2 - 640 / 2) / 2;
for (y = 0; y < 240; y++, s += 320, d += g_menuscreen_w*2/2) {
for (x = 0; x < 320; x++) {
t = s[x];
t |= t << 16;
d[x] = d[x + g_menuscreen_w / 2] = t;
}
}
return;
}
if (g_menuscreen_w >= 320 && g_menuscreen_h >= 240) {
unsigned short *d = g_menubg_src_ptr;
d += (g_menuscreen_h / 2 - 240 / 2) * g_menuscreen_w;
d += (g_menuscreen_w / 2 - 320 / 2);
for (y = 0; y < 240; y++, s += 320, d += g_menuscreen_w)
memcpy(d, s, 320*2);
return;
}
}
void pemu_forced_frame(int no_scale, int do_emu)
{
doing_bg_frame = 1;
emu_cmn_forced_frame(no_scale, do_emu);
doing_bg_frame = 0;
// making a copy because enabling the layer clears it's mem
memcpy32((void *)fb_copy, g_screen_ptr, sizeof(fb_copy) / 4);
make_bg(no_scale);
}
static void oss_write_nonblocking(int len)
{
// sndout_oss_can_write() is not reliable, only use with no_frmlimit
if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && !sndout_oss_can_write(len))
return;
sndout_oss_write_nb(PsndOut, len);
}
void pemu_sound_start(void)
{
PsndOut = NULL;
if (currentConfig.EmuOpt & EOPT_EN_SOUND)
{
int is_stereo = (PicoOpt & POPT_EN_STEREO) ? 1 : 0;
PsndRerate(Pico.m.frame_count ? 1 : 0);
/*
* for 44k stereo, we do 1470 samples/emu_frame
* OMAP driver does power of 2 buffers, so we need at least 4K buffer.
* The most we can lag is 1K samples, size of OMAP's McBSP FIFO,
* with 2K sample buffer we might sometimes lag more than that,
* thus causing underflows.
*/
printf("starting audio: %i len: %i stereo: %i, pal: %i\n",
PsndRate, PsndLen, is_stereo, Pico.m.pal);
sndout_oss_start(PsndRate, is_stereo, 2);
//sndout_oss_setvol(currentConfig.volume, currentConfig.volume);
PicoWriteSound = oss_write_nonblocking;
plat_update_volume(0, 0);
memset(sndBuffer, 0, sizeof(sndBuffer));
PsndOut = sndBuffer;
}
}
void pemu_sound_stop(void)
{
sndout_oss_stop();
}
void pemu_sound_wait(void)
{
// don't need to do anything, writes will block by themselves
}
void plat_debug_cat(char *str)
{
}
static int pnd_setup_layer_(int fd, int enabled, int x, int y, int w, int h)
{
struct omapfb_plane_info pi;
struct omapfb_mem_info mi;
int ret;
ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi);
if (ret != 0) {
perror("QUERY_PLANE");
return -1;
}
ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi);
if (ret != 0) {
perror("QUERY_MEM");
return -1;
}
/* must disable when changing stuff */
if (pi.enabled) {
pi.enabled = 0;
ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
if (ret != 0)
perror("SETUP_PLANE");
}
mi.size = 320*240*2*4;
ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);
if (ret != 0) {
perror("SETUP_MEM");
return -1;
}
pi.pos_x = x;
pi.pos_y = y;
pi.out_width = w;
pi.out_height = h;
pi.enabled = enabled;
ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);
if (ret != 0) {
perror("SETUP_PLANE");
return -1;
}
return 0;
}
int pnd_setup_layer(int enabled, int x, int y, int w, int h)
{
return pnd_setup_layer_(vout_fbdev_get_fd(layer_fb), enabled, x, y, w, h);
}
void pnd_restore_layer_data(void)
{
short *t = (short *)fb_copy + 320*240 / 2 + 160;
// right now this is used by menu, which wants to preview something
// so try to get something on the layer.
if ((t[0] | t[5] | t[13]) == 0)
memset32((void *)fb_copy, 0x07000700, sizeof(fb_copy) / 4);
memcpy32(g_screen_ptr, (void *)fb_copy, 320*240*2 / 4);
plat_video_flip();
}
static void apply_filter(int which)
{
char buf[128];
int i;
if (pnd_filter_list == NULL)
return;
for (i = 0; i < which; i++)
if (pnd_filter_list[i] == NULL)
return;
if (pnd_filter_list[i] == NULL)
return;
snprintf(buf, sizeof(buf), "%s/op_videofir.sh %s", pnd_script_base, pnd_filter_list[i]);
system(buf);
}
void emu_video_mode_change(int start_line, int line_count, int is_32cols)
{
int fb_w = 320, fb_h = 240, fb_left = 0, fb_right = 0, fb_top = 0, fb_bottom = 0;
if (doing_bg_frame)
return;
PicoDrawSetOutFormat(PDF_RGB555, 1);
PicoDrawSetCallbacks(emuscan, NULL);
if (is_32cols) {
fb_w = 256;
fb_left = fb_right = 32;
}
switch (currentConfig.scaling) {
case SCALE_1x1:
g_layer_w = fb_w;
g_layer_h = fb_h;
break;
case SCALE_2x2_3x2:
g_layer_w = fb_w * (is_32cols ? 3 : 2);
g_layer_h = fb_h * 2;
break;
case SCALE_2x2_2x2:
g_layer_w = fb_w * 2;
g_layer_h = fb_h * 2;
break;
case SCALE_FULLSCREEN:
g_layer_w = 800;
g_layer_h = 480;
break;
case SCALE_CUSTOM:
g_layer_x = g_layer_cx;
g_layer_y = g_layer_cy;
g_layer_w = g_layer_cw;
g_layer_h = g_layer_ch;
break;
}
if (currentConfig.scaling != SCALE_CUSTOM) {
// center the layer
g_layer_x = 800 / 2 - g_layer_w / 2;
g_layer_y = 480 / 2 - g_layer_h / 2;
}
switch (currentConfig.scaling) {
case SCALE_FULLSCREEN:
case SCALE_CUSTOM:
fb_top = start_line;
fb_h = line_count;
break;
}
g_osd_fps_x = is_32cols ? 232 : 264;
g_osd_y = fb_top + fb_h - 8;
pnd_setup_layer(1, g_layer_x, g_layer_y, g_layer_w, g_layer_h);
vout_fbdev_clear(layer_fb);
vout_fbdev_resize(layer_fb, fb_w, fb_h, 16, fb_left, fb_right, fb_top, fb_bottom, 3);
plat_video_flip();
}
void pemu_loop_prep(void)
{
static int pal_old = -1;
static int filter_old = -1;
char buf[128];
if (currentConfig.CPUclock != get_cpu_clock()) {
snprintf(buf, sizeof(buf), "unset DISPLAY; echo y | %s/op_cpuspeed.sh %d",
pnd_script_base, currentConfig.CPUclock);
system(buf);
}
if (Pico.m.pal != pal_old) {
snprintf(buf, sizeof(buf), "%s/op_lcdrate.sh %d",
pnd_script_base, Pico.m.pal ? 50 : 60);
system(buf);
pal_old = Pico.m.pal;
}
if (currentConfig.filter != filter_old) {
apply_filter(currentConfig.filter);
filter_old = currentConfig.filter;
}
// make sure there is no junk left behind the layer
memset32(g_menuscreen_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2 / 4);
g_menuscreen_ptr = vout_fbdev_flip(main_fb);
// emu_video_mode_change will call pnd_setup_layer()
// dirty buffers better go now than during gameplay
sync();
sleep(0);
pemu_sound_start();
}
void pemu_loop_end(void)
{
pemu_sound_stop();
/* do one more frame for menu bg */
pemu_forced_frame(0, 1);
pnd_setup_layer(0, g_layer_x, g_layer_y, g_layer_w, g_layer_h);
}
void plat_wait_till_us(unsigned int us_to)
{
unsigned int now;
signed int diff;
now = plat_get_ticks_us();
// XXX: need to check NOHZ
diff = (signed int)(us_to - now);
if (diff > 10000) {
//printf("sleep %d\n", us_to - now);
usleep(diff * 15 / 16);
now = plat_get_ticks_us();
//printf(" wake %d\n", (signed)(us_to - now));
}
/*
while ((signed int)(us_to - now) > 512) {
spend_cycles(1024);
now = plat_get_ticks_us();
}
*/
}
void plat_early_init(void)
{
}
void plat_init(void)
{
const char *main_fb_name, *layer_fb_name;
int fd, ret, w, h;
main_fb_name = getenv("FBDEV_MAIN");
if (main_fb_name == NULL)
main_fb_name = "/dev/fb0";
layer_fb_name = getenv("FBDEV_LAYER");
if (layer_fb_name == NULL)
layer_fb_name = "/dev/fb1";
// must set the layer up first to be able to use it
fd = open(layer_fb_name, O_RDWR);
if (fd == -1) {
fprintf(stderr, "%s: ", layer_fb_name);
perror("open");
exit(1);
}
ret = pnd_setup_layer_(fd, 0, g_layer_x, g_layer_y, g_layer_w, g_layer_h);
close(fd);
if (ret != 0) {
fprintf(stderr, "failed to set up layer, exiting.\n");
exit(1);
}
xenv_init();
w = h = 0;
main_fb = vout_fbdev_init(main_fb_name, &w, &h, 16, 2);
if (main_fb == NULL) {
fprintf(stderr, "couldn't init fb: %s\n", main_fb_name);
exit(1);
}
g_menuscreen_w = w;
g_menuscreen_h = h;
g_menuscreen_ptr = vout_fbdev_flip(main_fb);
w = 320; h = 240;
layer_fb = vout_fbdev_init(layer_fb_name, &w, &h, 16, 3);
if (layer_fb == NULL) {
fprintf(stderr, "couldn't init fb: %s\n", layer_fb_name);
goto fail0;
}
if (w != g_screen_width || h != g_screen_height) {
fprintf(stderr, "%dx%d not supported on %s\n", w, h, layer_fb_name);
goto fail1;
}
g_screen_ptr = vout_fbdev_flip(layer_fb);
temp_frame = calloc(g_menuscreen_w * g_menuscreen_h * 2, 1);
if (temp_frame == NULL) {
fprintf(stderr, "OOM\n");
goto fail1;
}
g_menubg_ptr = temp_frame;
g_menubg_src_ptr = temp_frame;
PicoDraw2FB = temp_frame;
sndout_oss_init();
pnd_menu_init();
in_set_config(in_name_to_id("evdev:gpio-keys"), IN_CFG_KEY_NAMES,
pandora_gpio_keys, sizeof(pandora_gpio_keys));
return;
fail1:
vout_fbdev_finish(layer_fb);
fail0:
vout_fbdev_finish(main_fb);
exit(1);
}
void plat_finish(void)
{
sndout_oss_exit();
vout_fbdev_finish(main_fb);
xenv_finish();
printf("all done\n");
}

View file

@ -1,17 +0,0 @@
extern char **pnd_filter_list;
extern int g_layer_cx, g_layer_cy;
extern int g_layer_cw, g_layer_ch;
void pnd_menu_init(void);
int pnd_setup_layer(int enabled, int x, int y, int w, int h);
void pnd_restore_layer_data(void);
enum {
SCALE_1x1,
SCALE_2x2_3x2,
SCALE_2x2_2x2,
SCALE_FULLSCREEN,
SCALE_CUSTOM,
};

View file

@ -1,37 +0,0 @@
// port specific settings
#ifndef PORT_CONFIG_H
#define PORT_CONFIG_H
#define CASE_SENSITIVE_FS 1 // CS filesystem
#define DONT_OPEN_MANY_FILES 0
#define REDUCE_IO_CALLS 0
#define SCREEN_SIZE_FIXED 1
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define MSCREEN_SIZE_FIXED 0
#define MSCREEN_WIDTH SCREEN_WIDTH
#define MSCREEN_HEIGHT SCREEN_HEIGHT
// draw2.c
#define START_ROW 0 // which row of tiles to start rendering at?
#define END_ROW 28 // ..end
// pico.c
#define CAN_HANDLE_240_LINES 1
#define SIMPLE_WRITE_SOUND 0
// logging emu events
#define EL_LOGMASK (EL_STATUS|EL_IDLE) // (EL_STATUS|EL_ANOMALY|EL_UIO|EL_SRAMIO|EL_INTS|EL_CDPOLL) // xffff
//#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__)
#define dprintf(x...)
// platform
#define PATH_SEP "/"
#define PATH_SEP_C '/'
#define MENU_X2 1
#endif //PORT_CONFIG_H

View file

@ -1,13 +0,0 @@
@ vim:filetype=armasm
@ .equiv START_ROW, 1
@ .equiv END_ROW, 27
@ one row means 8 pixels. If above example was used, (27-1)*8=208 lines would be rendered.
.equiv START_ROW, 0
.equiv END_ROW, 28
.equiv UNALIGNED_DRAWLINEDEST, 0
@ this should be set to one only for GP2X port
.equiv EXTERNAL_YM2612, 1

View file

@ -1,2 +0,0 @@
#define VERSION "1.80"

View file

@ -1,205 +0,0 @@
# pspdev is expected to be in path
PSPSDK = $(shell psp-config --pspsdk-path)
# settings
#use_musashi = 1
#use_mz80 = 1
amalgamate = 0
for_15fw = 1
# :!touch platform/psp/psp.c
CFLAGS += -I../.. -I. -DNO_SYNC -D_ASM_DRAW_C_AMIPS
CFLAGS += -Wall -Winline -G0
#CFLAGS += -DLPRINTF_STDIO
#CFLAGS += -pg
ifeq ($(DEBUG),)
CFLAGS += -O2 -ftracer -fstrength-reduce -ffast-math
else
CFLAGS += -ggdb
endif
ifeq "$(for_15fw)" "1"
CFLAGS += -DFW15
endif
# frontend and stuff
OBJS += main.o emu.o mp3.o menu.o psp.o asm_utils.o
# common
OBJS += platform/common/emu.o platform/common/menu.o platform/common/fonts.o platform/common/config.o platform/common/readpng.o
# Pico
ifeq "$(amalgamate)" "1"
OBJS += ../../picoAll.o
else
OBJS += pico/area.o pico/cart.o pico/memory.o pico/misc.o pico/pico.o pico/sek.o pico/videoport.o \
pico/draw2.o pico/draw.o pico/z80if.o pico/patch.o pico/draw_amips.o pico/memory_amips.o \
pico/misc_amips.o pico/debug.o
# Pico - CD
OBJS += pico/cd/pico.o pico/cd/memory.o pico/cd/sek.o pico/cd/LC89510.o \
pico/cd/cd_sys.o pico/cd/cd_file.o pico/cd/cue.o pico/cd/gfx_cd.o \
pico/cd/area.o pico/cd/misc.o pico/cd/pcm.o pico/cd/buffering.o
# Pico - carthw
OBJS += pico/carthw/carthw.o pico/carthw/svp/svp.o pico/carthw/svp/memory.o \
pico/carthw/svp/ssp16.o
# Pico - Pico
OBJS += pico/pico/pico.o pico/pico/memory.o pico/pico/xpcm.o
endif
# Pico - sound
ifneq "$(amalgamate)" "1"
OBJS += pico/sound/sound.o
endif
OBJS += pico/sound/mix.o
OBJS += pico/sound/sn76496.o pico/sound/ym2612.o
# zlib (hacked)
OBJS += zlib/gzio.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o \
zlib/deflate.o zlib/crc32.o zlib/adler32.o zlib/zutil.o zlib/compress.o \
zlib/uncompr.o
# unzip
OBJS += unzip/unzip.o unzip/unzip_stream.o
# CPU cores
ifeq "$(use_musashi)" "1"
CFLAGS += -DEMU_M68K
OBJS += cpu/musashi/m68kops.o cpu/musashi/m68kcpu.o
else
CFLAGS += -DEMU_F68K
OBJS += cpu/fame/famec.o
endif
# z80
ifeq "$(use_mz80)" "1"
CFLAGS += -D_USE_MZ80
OBJS += cpu/mz80/mz80.o
else
CFLAGS += -D_USE_CZ80
OBJS += cpu/cz80/cz80.o
endif
# bg images
OBJS += data/bg32.o data/bg40.o
vpath %.c = ../..
vpath %.s = ../..
DIRS = platform platform/psp platform/common pico pico/cd pico/pico pico/sound pico/carthw/svp \
zlib unzip cpu cpu/musashi cpu/fame cpu/mz80 cpu/cz80
LIBS += -lpng -lm -lpspgu -lpsppower -lpspaudio -lpsprtc -lpspaudiocodec -lpspkubridge
#LIBS += -lpspprof
LDFLAGS += -Wl,-Map=PicoDrive.map
# target
TARGET = PicoDrive
EXTRA_TARGETS = mkdirs EBOOT.PBP
PSP_EBOOT_TITLE = PicoDrive
PSP_EBOOT_ICON = data/icon.png
#PSP_EBOOT_PIC1 = .png
ifneq "$(for_15fw)" "1"
BUILD_PRX = 1
endif
CUSTOM_CLEAN = myclean
include $(PSPSDK)/lib/build.mak
# some additional rules
mkdirs:
mkdir -p $(DIRS)
.c.o:
@echo ">>>" $<
$(CC) $(CFLAGS) -c $< -o $@
AS := psp-as
.s.o:
@echo ">>>" $<
$(AS) -march=allegrex -mtune=allegrex $< -o $@
../../cpu/musashi/m68kops.c :
make -C ../../cpu/musashi
cpu/fame/famec.o : ../../cpu/fame/famec.c
@echo ">>>" $<
$(CC) $(CFLAGS) -Wno-unused -c $< -o $@
pico/misc.o : ../../pico/misc.c
@echo ">>>" $<
$(CC) $(CFLAGS) -c $< -o $@ -D_ASM_MISC_C_AMIPS
pico/memory.o : ../../pico/memory.c
@echo ">>>" $<
$(CC) $(CFLAGS) -O2 -c $< -o $@ -D_ASM_MEMORY_C -D_ASM_MEMORY_C_AMIPS
pico/cd/memory.o : ../../pico/cd/memory.c
@echo ">>>" $<
$(CC) $(CFLAGS) -O2 -c $< -o $@
pico/cd/gfx_cd.o : ../../pico/cd/gfx_cd.c
@echo ">>>" $<
$(CC) $(CFLAGS) -O2 -c $< -o $@
readme.txt: ../../tools/textfilter ../base_readme.txt
../../tools/textfilter ../base_readme.txt $@ PSP
../../tools/textfilter: ../../tools/textfilter.c
make -C ../../tools/ textfilter
data/bg32.o: data/bg32.bin
bin2o -i $< $@ bgdatac32
data/bg40.o: data/bg40.bin
bin2o -i $< $@ bgdatac40
#
ifndef UPDIR
UPDIR = /media/disk/PSP/GAME/PicoDrive/
endif
up: EBOOT.PBP
@cp -v $^ $(UPDIR)
# cleanup
myclean:
#rm -rf $(DIRS)
$(RM) PicoDrive.map
make -C ../../cpu/musashi clean
clean_prof:
find ../.. -name '*.gcno' -delete
find ../.. -name '*.gcda' -delete
# ----------- release -----------
ifneq ($(findstring rel,$(MAKECMDGOALS)),)
ifeq ($(VER),)
$(error need VER)
endif
endif
# ?
rel: EBOOT.PBP readme.txt ../game_def.cfg
mkdir -p PicoDrive/skin/
cp $^ PicoDrive/
cp skin/* PicoDrive/skin/
zip -9 -r ../../PicoDrive_psp_$(VER).zip PicoDrive
rm -rf PicoDrive
mkdir bin_to_cso_mp3
cp ../../tools/bin_to_cso_mp3/* bin_to_cso_mp3/
zip -9 -r ../../PicoDrive_psp_$(VER).zip bin_to_cso_mp3
rm -rf bin_to_cso_mp3
rel_kxploit: readme.txt ../game_def.cfg
mkdir -p PicoDrive/skin/
cp $^ PicoDrive/
cp skin/* PicoDrive/skin/
zip -9 -r ../../PicoDrive_psp_$(VER)_kxploit.zip PicoDrive
zip -9 -r ../../PicoDrive_psp_$(VER)_kxploit.zip PicoDrive%
mkdir bin_to_cso_mp3
cp ../../tools/bin_to_cso_mp3/* bin_to_cso_mp3/
zip -9 -r ../../PicoDrive_psp_$(VER)_kxploit.zip bin_to_cso_mp3
rm -rf bin_to_cso_mp3

View file

@ -1,2 +0,0 @@
// pointers must be word aligned, gammaa_val = -4..16, black_lvl = {0,1,2}
void do_pal_convert(unsigned short *dest, unsigned short *src, int gammaa_val, int black_lvl);

View file

@ -1,135 +0,0 @@
# vim:filetype=mips
# some asm utils
# (c) Copyright 2007, Grazvydas "notaz" Ignotas
# All Rights Reserved
.set noreorder
.set noat
.data
.align 4
.byte 0, 1, 6, 11, 16, 21, 26, 31 # -4
.byte 0, 2, 7, 12, 16, 21, 26, 31 # -3
.byte 0, 3, 7, 12, 17, 22, 26, 31 # -2
.byte 0, 4, 8, 13, 17, 22, 26, 31 # -1
pal_gmtab:
.byte 0, 5, 10, 15, 16, 21, 26, 31 # 0
.byte 0, 6, 10, 15, 19, 23, 27, 31
.byte 0, 7, 11, 15, 19, 23, 27, 31
.byte 0, 8, 12, 16, 19, 23, 27, 31
.byte 0, 9, 12, 16, 20, 24, 27, 31
.byte 0, 10, 13, 17, 20, 24, 27, 31
.byte 0, 10, 14, 17, 21, 24, 28, 31
.byte 0, 11, 15, 18, 21, 24, 28, 31
.byte 0, 12, 15, 18, 22, 25, 28, 31
.byte 0, 13, 16, 19, 22, 25, 28, 31
.byte 0, 14, 17, 20, 22, 25, 28, 31 # 10
.byte 0, 15, 17, 20, 23, 26, 28, 31
.byte 0, 16, 18, 21, 23, 26, 28, 31
.byte 0, 16, 19, 21, 24, 26, 29, 31
.byte 0, 17, 20, 22, 24, 26, 29, 31
.byte 0, 18, 20, 22, 25, 27, 29, 31
.byte 0, 19, 21, 23, 25, 27, 29, 31 # 16
.text
.align 4
# bbbb bggg gggr rrrr
#.global pal_gmtab
.global do_pal_convert # dest, src, gammaa_val, black_lvl
do_pal_convert:
bnez $a2, dpc_gma
li $t0, 64/2
bnez $a3, dpc_gma
lui $t2, 0x00e
ori $t2, 0x00e
lui $t3, 0x006
ori $t3, 0x006
lui $t4, 0x0e0
ori $t4, 0x0e0
lui $t6, 0xe00
ori $t6, 0xe00
lui $t7, 0x600
ori $t7, 0x600
dpc_loop:
lw $v0, 0($a1)
addiu $a1, 4
and $v1, $v0, $t2 # r
sll $v1, 1
and $t9, $v0, $t3
srl $t9, 1
or $v1, $t9 # r
and $t9, $v0, $t4 # g
sll $t8, $t9, 3
or $v1, $t8
or $v1, $t9 # g
and $t9, $v0, $t6 # b
sll $t9, 4
or $v1, $t9
and $t9, $v0, $t7
sll $t9, 2
or $v1, $t9 # b
sw $v1, 0($a0)
addiu $t0, -1
bnez $t0, dpc_loop
addiu $a0, 4
jr $ra
nop
# non-zero gamma
dpc_gma:
slt $t2, $a2, $0
sll $a2, 3
lui $t1, %hi(pal_gmtab)
addiu $t1, %lo(pal_gmtab)
addu $a2, $t1
beqz $a3, dpc_gma_loop
sb $0, 0($a2) # black level 0
bnez $t2, dpc_gma_loop # gamma < 0, keep black at 0
addiu $a3, -2
slt $t2, $a3, $0 # t2 = a3_orig == 1 ? 1 : 0
lb $t1, 1($a2)
addiu $t1, -2
srlv $t1, $t1, $t2
sb $t1, 0($a2)
dpc_gma_loop:
lw $v0, 0($a1)
addiu $a1, 4
ext $v1, $v0, 1, 3
addu $v1, $a2
lb $v1, 0($v1)
ext $t1, $v0, 5, 3
addu $t1, $a2
lb $t1, 0($t1)
ext $t2, $v0, 9, 3
addu $t2, $a2
lb $t2, 0($t2)
ext $t3, $v0, 17, 3
addu $t3, $a2
lb $t3, 0($t3)
ext $t4, $v0, 21, 3
addu $t4, $a2
lb $t4, 0($t4)
ext $t5, $v0, 25, 3
addu $t5, $a2
lb $t5, 0($t5)
ins $v1, $t1, 6, 5
ins $v1, $t2, 11, 5
ins $v1, $t3, 16, 5
ins $v1, $t4, 22, 5
ins $v1, $t5, 27, 5
sw $v1, 0($a0)
addiu $t0, -1
bnez $t0, dpc_gma_loop
addiu $a0, 4
jr $ra
nop

1068
psp/emu.c

File diff suppressed because it is too large Load diff

View file

@ -1,15 +0,0 @@
// (c) Copyright 2006-2007 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
extern int engineStateSuspend;
void emu_HandleResume(void);
void emu_msg_cb(const char *msg);
// actually comes from Pico/Misc_amips.s
void memset32_uncached(int *dest, int c, int count);

View file

@ -1,121 +0,0 @@
// (c) Copyright 2007 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include <string.h>
#include "psp.h"
#include "emu.h"
#include "menu.h"
#include "mp3.h"
#include "../common/menu.h"
#include "../common/emu.h"
#include "../common/config.h"
#include "../common/lprintf.h"
#ifdef GPROF
#include <pspprof.h>
#endif
#ifdef GCOV
#include <stdio.h>
#include <stdlib.h>
void dummy(void)
{
engineState = atoi(rom_fname_reload);
setbuf(NULL, NULL);
getenv(NULL);
}
#endif
int pico_main(void)
{
psp_init();
emu_prepareDefaultConfig();
emu_ReadConfig(0, 0);
config_readlrom(PicoConfigFile);
emu_Init();
menu_init();
// moved to emu_Loop(), after CPU clock change..
//mp3_init();
engineState = PGS_Menu;
for (;;)
{
switch (engineState)
{
case PGS_Menu:
#ifndef GPROF
menu_loop();
#else
strcpy(rom_fname_reload, rom_fname_loaded);
engineState = PGS_ReloadRom;
#endif
break;
case PGS_ReloadRom:
if (emu_reload_rom(rom_fname_reload)) {
engineState = PGS_Running;
if (mp3_last_error != 0)
engineState = PGS_Menu; // send to menu to display mp3 error
} else {
lprintf("PGS_ReloadRom == 0\n");
engineState = PGS_Menu;
}
break;
case PGS_Suspending:
while (engineState == PGS_Suspending)
psp_wait_suspend();
break;
case PGS_SuspendWake:
psp_unhandled_suspend = 0;
psp_resume_suspend();
emu_HandleResume();
engineState = engineStateSuspend;
break;
case PGS_RestartRun:
engineState = PGS_Running;
case PGS_Running:
if (psp_unhandled_suspend) {
psp_unhandled_suspend = 0;
psp_resume_suspend();
emu_HandleResume();
break;
}
pemu_loop();
#ifdef GPROF
goto endloop;
#endif
break;
case PGS_Quit:
goto endloop;
default:
lprintf("engine got into unknown state (%i), exitting\n", engineState);
goto endloop;
}
}
endloop:
mp3_deinit();
emu_Deinit();
#ifdef GPROF
gprof_cleanup();
#endif
#ifndef GCOV
psp_finish();
#endif
return 0;
}

1786
psp/menu.c

File diff suppressed because it is too large Load diff

View file

@ -1,14 +0,0 @@
// (c) Copyright 2006,2007 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
void menu_loop(void);
int menu_loop_tray(void);
void menu_romload_prepare(const char *rom_name);
void menu_romload_end(void);
#define CONFIGURABLE_KEYS (PBTN_UP|PBTN_LEFT|PBTN_RIGHT|PBTN_DOWN|PBTN_L|PBTN_R|PBTN_TRIANGLE|PBTN_CIRCLE|PBTN_X|PBTN_SQUARE|PBTN_START| \
PBTN_NUB_UP|PBTN_NUB_RIGHT|PBTN_NUB_DOWN|PBTN_NUB_LEFT|PBTN_NOTE)

492
psp/mp3.c
View file

@ -1,492 +0,0 @@
// (c) Copyright 2007 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include <stdio.h>
#include <string.h>
#include <pspkernel.h>
#include <pspsdk.h>
#include <pspaudiocodec.h>
#include <kubridge.h>
#include "../../pico/pico_int.h"
#include "../../pico/sound/mix.h"
#include "../common/lprintf.h"
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;
// MPEG-1, layer 3
static int bitrates[] = { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 };
//static int samplerates[] = { 44100, 48000, 32000, 0 };
#define MIN_INFRAME_SIZE 96
#define IN_BUFFER_SIZE (2*1024)
static unsigned long mp3_codec_struct[65] __attribute__((aligned(64)));
static unsigned char mp3_src_buffer[2][IN_BUFFER_SIZE] __attribute__((aligned(64)));
static short mp3_mix_buffer[2][1152*2] __attribute__((aligned(64)));
static int working_buf = 0;
static const char *mp3_fname = NULL;
static SceUID mp3_handle = -1;
static int mp3_src_pos = 0, mp3_src_size = 0;
static int decode_thread(SceSize args, void *argp);
static void psp_sem_lock(SceUID sem)
{
int ret = sceKernelWaitSema(sem, 1, 0);
if (ret < 0) lprintf("sceKernelWaitSema(%08x) failed with %08x\n", sem, ret);
}
static void psp_sem_unlock(SceUID sem)
{
int ret = sceKernelSignalSema(sem, 1);
if (ret < 0) lprintf("sceKernelSignalSema(%08x) failed with %08x\n", sem, ret);
}
// only accepts MPEG-1, layer3
static int find_sync_word(unsigned char *data, int len)
{
int i;
for (i = 0; i < len-1; i++)
{
if ( data[i+0] != 0xff) continue;
if ((data[i+1] & 0xfe) == 0xfa) return i;
i++;
}
return -1;
}
static int read_next_frame(int which_buffer)
{
int i, bytes_read, frame_offset;
int bitrate, padding, frame_size = 0;
for (i = 0; i < 32; i++)
{
bytes_read = sceIoRead(mp3_handle, mp3_src_buffer[which_buffer], sizeof(mp3_src_buffer[which_buffer]));
mp3_src_pos += bytes_read;
if (bytes_read < MIN_INFRAME_SIZE) {
mp3_src_pos = mp3_src_size;
return 0; // EOF/IO failure
}
frame_offset = find_sync_word(mp3_src_buffer[which_buffer], bytes_read);
if (frame_offset < 0) {
lprintf("missing syncword, foffs=%i\n", mp3_src_pos - bytes_read);
mp3_src_pos--;
sceIoLseek32(mp3_handle, mp3_src_pos, PSP_SEEK_SET);
continue;
}
if (bytes_read - frame_offset < 4) {
lprintf("syncword @ EOB, foffs=%i\n", mp3_src_pos - bytes_read);
mp3_src_pos--;
sceIoLseek32(mp3_handle, mp3_src_pos, PSP_SEEK_SET);
continue;
}
bitrate = mp3_src_buffer[which_buffer][frame_offset+2] >> 4;
padding = (mp3_src_buffer[which_buffer][frame_offset+2] & 2) >> 1;
frame_size = 144000*bitrates[bitrate]/44100 + padding;
if (frame_size <= 0) {
lprintf("bad frame, foffs=%i\n", mp3_src_pos - bytes_read);
continue; // bad frame
}
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..
}
if (frame_offset) {
//lprintf("unaligned, foffs=%i, offs=%i\n", mp3_src_pos - bytes_read, frame_offset);
memmove(mp3_src_buffer[which_buffer], mp3_src_buffer[which_buffer] + frame_offset, frame_size);
}
// align for next frame read
mp3_src_pos -= bytes_read - (frame_offset + frame_size);
sceIoLseek32(mp3_handle, mp3_src_pos, PSP_SEEK_SET);
break;
}
return frame_size > 0 ? frame_size : -1;
}
static SceUID load_start_module(const char *prxname)
{
SceUID mod, mod1;
int status, ret;
mod = pspSdkLoadStartModule(prxname, PSP_MEMORY_PARTITION_KERNEL);
if (mod < 0) {
lprintf("failed to load %s (%08x), trying kuKernelLoadModule\n", prxname, mod);
mod1 = kuKernelLoadModule(prxname, 0, NULL);
if (mod1 < 0) lprintf("kuKernelLoadModule failed with %08x\n", mod1);
else {
ret = sceKernelStartModule(mod1, 0, NULL, &status, 0);
if (ret < 0) lprintf("sceKernelStartModule failed with %08x\n", ret);
else mod = mod1;
}
}
return mod;
}
int mp3_init(void)
{
SceUID thid, mod;
int ret;
/* load modules */
/* <= 1.5 (and probably some other, not sure which) fw need this to for audiocodec to work,
* so if it fails, assume we are just on new enough firmware and continue.. */
load_start_module("flash0:/kd/me_for_vsh.prx");
if (sceKernelDevkitVersion() < 0x02070010)
mod = load_start_module("flash0:/kd/audiocodec.prx");
else mod = load_start_module("flash0:/kd/avcodec.prx");
if (mod < 0) {
ret = mod;
mod = load_start_module("flash0:/kd/audiocodec_260.prx"); // last chance..
if (mod < 0) goto fail;
}
/* audiocodec init */
memset(mp3_codec_struct, 0, sizeof(mp3_codec_struct));
ret = sceAudiocodecCheckNeedMem(mp3_codec_struct, 0x1002);
if (ret < 0) {
lprintf("sceAudiocodecCheckNeedMem failed with %08x\n", ret);
goto fail;
}
ret = sceAudiocodecGetEDRAM(mp3_codec_struct, 0x1002);
if (ret < 0) {
lprintf("sceAudiocodecGetEDRAM failed with %08x\n", ret);
goto fail;
}
ret = sceAudiocodecInit(mp3_codec_struct, 0x1002);
if (ret < 0) {
lprintf("sceAudiocodecInit failed with %08x\n", ret);
goto fail1;
}
/* thread and stuff */
thread_job_sem = sceKernelCreateSema("p_mp3job_sem", 0, 0, 1, NULL);
if (thread_job_sem < 0) {
lprintf("sceKernelCreateSema() failed: %08x\n", thread_job_sem);
ret = thread_job_sem;
goto fail1;
}
thread_busy_sem = sceKernelCreateSema("p_mp3busy_sem", 0, 1, 1, NULL);
if (thread_busy_sem < 0) {
lprintf("sceKernelCreateSema() failed: %08x\n", thread_busy_sem);
ret = thread_busy_sem;
goto fail2;
}
/* use slightly higher prio then main */
thread_exit = 0;
thid = sceKernelCreateThread("mp3decode_thread", decode_thread, 30, 0x2000, 0, NULL);
if (thid < 0) {
lprintf("failed to create decode thread: %08x\n", thid);
ret = thid;
goto fail3;
}
ret = sceKernelStartThread(thid, 0, 0);
if (ret < 0) {
lprintf("failed to start decode thread: %08x\n", ret);
goto fail3;
}
mp3_last_error = 0;
initialized = 1;
return 0;
fail3:
sceKernelDeleteSema(thread_busy_sem);
thread_busy_sem = -1;
fail2:
sceKernelDeleteSema(thread_job_sem);
thread_job_sem = -1;
fail1:
sceAudiocodecReleaseEDRAM(mp3_codec_struct);
fail:
mp3_last_error = ret;
initialized = 0;
return 1;
}
void mp3_deinit(void)
{
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);
sceKernelSignalSema(thread_job_sem, 1);
sceKernelDelayThread(100*1000);
if (mp3_handle >= 0) sceIoClose(mp3_handle);
mp3_handle = -1;
mp3_fname = NULL;
sceKernelDeleteSema(thread_busy_sem);
thread_busy_sem = -1;
sceKernelDeleteSema(thread_job_sem);
thread_job_sem = -1;
sceAudiocodecReleaseEDRAM(mp3_codec_struct);
initialized = 0;
}
// may overflow stack?
static int decode_thread(SceSize args, void *argp)
{
int ret, frame_size;
lprintf("decode_thread started with id %08x, priority %i\n",
sceKernelGetThreadId(), sceKernelGetThreadCurrentPriority());
while (!thread_exit)
{
psp_sem_lock(thread_job_sem);
if (thread_exit) break;
psp_sem_lock(thread_busy_sem);
//lprintf("{ job\n");
frame_size = read_next_frame(working_buf);
if (frame_size > 0)
{
mp3_codec_struct[6] = (unsigned long)mp3_src_buffer[working_buf];
mp3_codec_struct[8] = (unsigned long)mp3_mix_buffer[working_buf];
mp3_codec_struct[7] = mp3_codec_struct[10] = frame_size;
mp3_codec_struct[9] = 1152 * 4;
ret = sceAudiocodecDecode(mp3_codec_struct, 0x1002);
if (ret < 0) lprintf("sceAudiocodecDecode failed with %08x\n", ret);
}
//lprintf("} job\n");
psp_sem_unlock(thread_busy_sem);
}
lprintf("leaving decode thread\n");
sceKernelExitDeleteThread(0);
return 0;
}
// might be called before initialization
int mp3_get_bitrate(void *f, int size)
{
int ret, retval = -1, sample_rate, bitrate;
// filenames are stored instead handles in PSP, due to stupid max open file limit
char *fname = f;
/* make sure thread is not busy.. */
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);
if (mp3_handle < 0) {
lprintf("sceIoOpen(%s) failed\n", fname);
goto end;
}
mp3_src_pos = 0;
ret = read_next_frame(0);
if (ret <= 0) {
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 (%s)\n", fname);
goto end; // only 44kHz supported..
}
bitrate = bitrates[bitrate];
if (bitrate == 0) {
lprintf("unsupported bitrate (%s)\n", fname);
goto end;
}
/* looking good.. */
retval = bitrate;
end:
if (mp3_handle >= 0) sceIoClose(mp3_handle);
mp3_handle = -1;
mp3_fname = NULL;
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;
}
static int mp3_job_started = 0, mp3_samples_ready = 0, mp3_buffer_offs = 0, mp3_play_bufsel = 0;
void mp3_start_play(void *f, int pos)
{
char *fname = f;
if (!initialized) return;
lprintf("mp3_start_play(%s) @ %i\n", fname, pos);
psp_sem_lock(thread_busy_sem);
if (mp3_fname != fname || mp3_handle < 0)
{
if (mp3_handle >= 0) sceIoClose(mp3_handle);
mp3_handle = sceIoOpen(fname, PSP_O_RDONLY, 0777);
if (mp3_handle < 0) {
lprintf("sceIoOpen(%s) failed\n", fname);
psp_sem_unlock(thread_busy_sem);
return;
}
mp3_src_size = sceIoLseek32(mp3_handle, 0, PSP_SEEK_END);
mp3_fname = fname;
}
// clear decoder state
sceAudiocodecInit(mp3_codec_struct, 0x1002);
// seek..
mp3_src_pos = (int) (((float)pos / 1023.0f) * (float)mp3_src_size);
sceIoLseek32(mp3_handle, mp3_src_pos, PSP_SEEK_SET);
lprintf("seek %i: %i/%i\n", pos, mp3_src_pos, mp3_src_size);
mp3_job_started = 1;
mp3_samples_ready = mp3_buffer_offs = mp3_play_bufsel = 0;
working_buf = 0;
/* send a request to decode first frame */
psp_sem_unlock(thread_busy_sem);
psp_sem_unlock(thread_job_sem);
sceKernelDelayThread(1); // reschedule
}
void mp3_update(int *buffer, int length, int stereo)
{
int length_mp3;
// playback was started, track not ended
if (mp3_handle < 0 || mp3_src_pos >= mp3_src_size) return;
length_mp3 = length;
if (PsndRate == 22050) length_mp3 <<= 1; // mp3s are locked to 44100Hz stereo
else if (PsndRate == 11025) length_mp3 <<= 2; // so make length 44100ish
/* do we have to wait? */
if (mp3_job_started && mp3_samples_ready < length_mp3)
{
psp_sem_lock(thread_busy_sem);
psp_sem_unlock(thread_busy_sem);
mp3_job_started = 0;
mp3_samples_ready += 1152;
}
/* mix mp3 data, only stereo */
if (mp3_samples_ready >= length_mp3)
{
int shr = 0;
void (*mix_samples)(int *dest_buf, short *mp3_buf, int count) = mix_16h_to_32;
if (PsndRate == 22050) { mix_samples = mix_16h_to_32_s1; shr = 1; }
else if (PsndRate == 11025) { mix_samples = mix_16h_to_32_s2; shr = 2; }
if (1152 - mp3_buffer_offs >= length_mp3) {
mix_samples(buffer, mp3_mix_buffer[mp3_play_bufsel] + mp3_buffer_offs*2, length<<1);
mp3_buffer_offs += length_mp3;
} else {
// collect samples from both buffers..
int left = 1152 - mp3_buffer_offs;
if (mp3_play_bufsel == 0)
{
mix_samples(buffer, mp3_mix_buffer[0] + mp3_buffer_offs*2, length<<1);
mp3_buffer_offs = length_mp3 - left;
mp3_play_bufsel = 1;
} else {
mix_samples(buffer, mp3_mix_buffer[1] + mp3_buffer_offs*2, (left>>shr)<<1);
mp3_buffer_offs = length_mp3 - left;
mix_samples(buffer + ((left>>shr)<<1),
mp3_mix_buffer[0], (mp3_buffer_offs>>shr)<<1);
mp3_play_bufsel = 0;
}
}
mp3_samples_ready -= length_mp3;
}
// ask to decode more if we already can
if (!mp3_job_started)
{
mp3_job_started = 1;
working_buf ^= 1;
/* next job.. */
psp_sem_lock(thread_busy_sem); // just in case
psp_sem_unlock(thread_busy_sem);
psp_sem_unlock(thread_job_sem);
sceKernelDelayThread(1);
}
}
int mp3_get_offset(void) // 0-1023
{
unsigned int offs1024 = 0;
int cdda_on;
cdda_on = (PicoAHW & PAHW_MCD) && (PicoOpt&0x800) && !(Pico_mcd->s68k_regs[0x36] & 1) &&
(Pico_mcd->scd.Status_CDC & 1) && mp3_handle >= 0;
if (cdda_on) {
offs1024 = mp3_src_pos << 7;
offs1024 /= mp3_src_size >> 3;
}
lprintf("offs1024=%u (%i/%i)\n", offs1024, mp3_src_pos, mp3_src_size);
return offs1024;
}
void mp3_reopen_file(void)
{
if (mp3_fname == NULL) return;
lprintf("mp3_reopen_file(%s)\n", mp3_fname);
// try closing, just in case
if (mp3_handle >= 0) sceIoClose(mp3_handle);
mp3_handle = sceIoOpen(mp3_fname, PSP_O_RDONLY, 0777);
if (mp3_handle >= 0)
sceIoLseek32(mp3_handle, mp3_src_pos, PSP_SEEK_SET);
lprintf("mp3_reopen_file %s\n", mp3_handle >= 0 ? "ok" : "failed");
}

View file

@ -1,8 +0,0 @@
// additional stuff for PSP mp3 decoder implementation
extern int mp3_last_error;
int mp3_init(void);
void mp3_deinit(void);
void mp3_reopen_file(void);

View file

@ -1,42 +0,0 @@
// port specific settings
#ifndef PORT_CONFIG_H
#define PORT_CONFIG_H
#define CASE_SENSITIVE_FS 0
#define DONT_OPEN_MANY_FILES 1 // work around the stupid PSP ~10 open file limit
#define REDUCE_IO_CALLS 1 // another workaround
#define SIMPLE_WRITE_SOUND 0
#define SCREEN_SIZE_FIXED 1
#define SCREEN_WIDTH 512
#define SCREEN_HEIGHT 272
#define MSCREEN_SIZE_FIXED 1
#define MSCREEN_WIDTH SCREEN_WIDTH
#define MSCREEN_HEIGHT SCREEN_HEIGHT
// draw.c
#define USE_BGR555 1
// draw2.c
#define START_ROW 0 // which row of tiles to start rendering at?
#define END_ROW 28 // ..end
#define DRAW2_OVERRIDE_LINE_WIDTH 512
// pico.c
extern void blit1(void);
#define DRAW_FINISH_FUNC blit1
#define CAN_HANDLE_240_LINES 1
// logging emu events
#define EL_LOGMASK (EL_STATUS|EL_IDLE) // (EL_STATUS|EL_ANOMALY|EL_UIO|EL_SRAMIO) // xffff
//#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__)
#define dprintf(x...)
// platform
#define PATH_SEP "/"
#define PATH_SEP_C '/'
#define MENU_X2 0
#endif //PORT_CONFIG_H

372
psp/psp.c
View file

@ -1,372 +0,0 @@
// (c) Copyright 2007 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <pspkernel.h>
#include <pspiofilemgr.h>
#include <pspdisplay.h>
#include <psppower.h>
#include <psprtc.h>
#include <pspgu.h>
#include <pspsdk.h>
#include "psp.h"
#include "emu.h"
#include "../common/lprintf.h"
#include "version.h"
extern int pico_main(void);
#ifndef FW15
PSP_MODULE_INFO("PicoDrive", 0, 1, 51);
PSP_HEAP_SIZE_MAX();
int main() { return pico_main(); } /* just a wrapper */
#else
PSP_MODULE_INFO("PicoDrive", 0x1000, 1, 51);
PSP_MAIN_THREAD_ATTR(0);
int main()
{
SceUID thid;
/* this is the thing we need the kernel mode for */
pspSdkInstallNoDeviceCheckPatch();
thid = sceKernelCreateThread("pico_main", (SceKernelThreadEntry) pico_main, 32, 0x2000, PSP_THREAD_ATTR_USER, NULL);
if (thid >= 0)
sceKernelStartThread(thid, 0, 0);
#ifndef GCOV
sceKernelExitDeleteThread(0);
#else
while (engineState != PGS_Quit)
sceKernelDelayThread(1024 * 1024);
#endif
return 0;
}
#endif
int psp_unhandled_suspend = 0;
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 */
static int exit_callback(int arg1, int arg2, void *common)
{
sceKernelExitGame();
return 0;
}
/* Power Callback */
static int power_callback(int unknown, int pwrflags, void *common)
{
lprintf("power_callback: flags: 0x%08X\n", pwrflags);
/* check for power switch and suspending as one is manual and the other automatic */
if (pwrflags & PSP_POWER_CB_POWER_SWITCH || pwrflags & PSP_POWER_CB_SUSPENDING || pwrflags & PSP_POWER_CB_STANDBY)
{
psp_unhandled_suspend = 1;
if (engineState != PGS_Suspending)
engineStateSuspend = engineState;
sceKernelDelayThread(100000); // ??
}
else if (pwrflags & PSP_POWER_CB_RESUME_COMPLETE)
{
engineState = PGS_SuspendWake;
}
//sceDisplayWaitVblankStart();
return 0;
}
/* Callback thread */
static int callback_thread(SceSize args, void *argp)
{
int cbid;
lprintf("callback_thread started with id %08x, priority %i\n",
sceKernelGetThreadId(), sceKernelGetThreadCurrentPriority());
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
cbid = sceKernelCreateCallback("Power Callback", power_callback, NULL);
scePowerRegisterCallback(0, cbid);
sceKernelSleepThreadCB();
return 0;
}
void psp_init(void)
{
SceUID thid;
char buff[128], *r;
/* fw 1.5 sometimes returns 8002032c, although getcwd works */
r = getcwd(buff, sizeof(buff));
if (r) sceIoChdir(buff);
main_thread_id = sceKernelGetThreadId();
lprintf("\n%s\n", "PicoDrive v" VERSION " " __DATE__ " " __TIME__);
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, NULL);
if (thid >= 0)
{
sceKernelStartThread(thid, 0, 0);
}
/* video */
sceDisplaySetMode(0, 480, 272);
sceDisplaySetFrameBuf(VRAM_FB1, 512, PSP_DISPLAY_PIXEL_FORMAT_565, PSP_DISPLAY_SETBUF_NEXTFRAME);
current_screen = 1;
psp_screen = VRAM_FB0;
/* gu */
sceGuInit();
sceGuStart(GU_DIRECT, guCmdList);
sceGuDrawBuffer(GU_PSM_5650, (void *)VRAMOFFS_FB0, 512);
sceGuDispBuffer(480, 272, (void *)VRAMOFFS_FB1, 512); // don't care
sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT);
sceGuDepthBuffer((void *)VRAMOFFS_DEPTH, 512);
sceGuOffset(2048 - (480 / 2), 2048 - (272 / 2));
sceGuViewport(2048, 2048, 480, 272);
sceGuDepthRange(0xc350, 0x2710);
sceGuScissor(0, 0, 480, 272);
sceGuEnable(GU_SCISSOR_TEST);
sceGuDepthMask(0xffff);
sceGuDisable(GU_DEPTH_TEST);
sceGuFrontFace(GU_CW);
sceGuEnable(GU_TEXTURE_2D);
sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB);
sceGuAmbientColor(0xffffffff);
sceGuColor(0xffffffff);
sceGuFinish();
sceGuSync(0, 0);
sceDisplayWaitVblankStart();
sceGuDisplay(GU_TRUE);
/* input */
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
}
void psp_finish(void)
{
lprintf("psp_finish..\n");
sceGuTerm();
//sceKernelSleepThread();
sceKernelExitGame();
}
void psp_video_flip(int wait_vsync)
{
if (wait_vsync) sceDisplayWaitVblankStart();
sceDisplaySetFrameBuf(psp_screen, 512, PSP_DISPLAY_PIXEL_FORMAT_565,
wait_vsync ? PSP_DISPLAY_SETBUF_IMMEDIATE : PSP_DISPLAY_SETBUF_NEXTFRAME);
current_screen ^= 1;
psp_screen = current_screen ? VRAM_FB0 : VRAM_FB1;
}
void *psp_video_get_active_fb(void)
{
return current_screen ? VRAM_FB1 : VRAM_FB0;
}
void psp_video_switch_to_single(void)
{
psp_screen = VRAM_FB0;
sceDisplaySetFrameBuf(psp_screen, 512, PSP_DISPLAY_PIXEL_FORMAT_565, PSP_DISPLAY_SETBUF_NEXTFRAME);
current_screen = 0;
}
void psp_msleep(int ms)
{
sceKernelDelayThread(ms * 1000);
}
unsigned int psp_pad_read(int blocking)
{
unsigned int buttons;
SceCtrlData pad;
if (blocking)
sceCtrlReadBufferPositive(&pad, 1);
else sceCtrlPeekBufferPositive(&pad, 1);
buttons = pad.Buttons;
// analog..
buttons &= ~(PBTN_NUB_UP|PBTN_NUB_DOWN|PBTN_NUB_LEFT|PBTN_NUB_RIGHT);
if (pad.Lx < 128 - ANALOG_DEADZONE) buttons |= PBTN_NUB_LEFT;
if (pad.Lx > 128 + ANALOG_DEADZONE) buttons |= PBTN_NUB_RIGHT;
if (pad.Ly < 128 - ANALOG_DEADZONE) buttons |= PBTN_NUB_UP;
if (pad.Ly > 128 + ANALOG_DEADZONE) buttons |= PBTN_NUB_DOWN;
return buttons;
}
int psp_get_cpu_clock(void)
{
return scePowerGetCpuClockFrequencyInt();
}
int psp_set_cpu_clock(int clock)
{
int ret = scePowerSetClockFrequency(clock, clock, clock/2);
if (ret != 0) lprintf("failed to set clock: %i\n", ret);
return ret;
}
char *psp_get_status_line(void)
{
static char buff[64];
int ret, bat_percent, bat_time;
pspTime time;
ret = sceRtcGetCurrentClockLocalTime(&time);
bat_percent = scePowerGetBatteryLifePercent();
bat_time = scePowerGetBatteryLifeTime();
if (ret < 0 || bat_percent < 0 || bat_time < 0) return NULL;
snprintf(buff, sizeof(buff), "%02i:%02i bat: %3i%%", time.hour, time.minutes, bat_percent);
if (!scePowerIsPowerOnline())
snprintf(buff+strlen(buff), sizeof(buff)-strlen(buff), " (%i:%02i)", bat_time/60, bat_time%60);
return buff;
}
void psp_wait_suspend(void)
{
// probably should do something smarter here?
sceDisplayWaitVblankStart();
}
void psp_resume_suspend(void)
{
// for some reason file IO doesn't seem to work
// after resume for some period of time, at least on 1.5
SceUID fd;
int i;
for (i = 0; i < 30; i++) {
fd = sceIoOpen("EBOOT.PBP", PSP_O_RDONLY, 0777);
if (fd >= 0) break;
sceKernelDelayThread(100 * 1024);
}
if (fd >= 0) sceIoClose(fd);
sceDisplayWaitVblankStart();
if (i < 30)
lprintf("io resumed after %i tries\n", i);
else {
lprintf("io resume failed with %08x\n", fd);
sceKernelDelayThread(500 * 1024);
}
}
/* alt logging */
#define LOG_FILE "log.txt"
#ifndef LPRINTF_STDIO
typedef struct _log_entry
{
char buff[256];
struct _log_entry *next;
} log_entry;
static log_entry *le_root = NULL;
#endif
/* strange: if this function leaks memory (before psp_init() call?),
* resume after suspend breaks on 3.90 */
void lprintf(const char *fmt, ...)
{
va_list vl;
#ifdef LPRINTF_STDIO
va_start(vl, fmt);
vprintf(fmt, vl);
va_end(vl);
#else
static SceUID logfd = -1;
static int msg_count = 0;
char buff[256];
log_entry *le, *le1;
if (logfd == -2) return; // disabled
va_start(vl, fmt);
vsnprintf(buff, sizeof(buff), fmt, vl);
va_end(vl);
// note: this is still unsafe code
if (main_thread_id != sceKernelGetThreadId())
{
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;
}
logfd = sceIoOpen(LOG_FILE, PSP_O_WRONLY|PSP_O_APPEND, 0777);
if (logfd < 0) {
if (msg_count == 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);
msg_count++;
}
}
sceIoWrite(logfd, buff, strlen(buff));
msg_count++;
// make sure it gets flushed
sceIoClose(logfd);
logfd = -1;
#endif
}

View file

@ -1,70 +0,0 @@
// (c) Copyright 2007 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include <pspctrl.h>
void psp_init(void);
void psp_finish(void);
void psp_msleep(int ms);
// vram usage map:
// 000000-044000 fb0
// 044000-088000 fb1
// 088000-0cc000 depth (?)
// 0cc000-126000 emu draw buffers: 512*240 + 512*240*2
#define VRAMOFFS_FB0 0x00000000
#define VRAMOFFS_FB1 0x00044000
#define VRAMOFFS_DEPTH 0x00088000
#define VRAMOFFS_STUFF 0x000cc000
#define VRAM_FB0 ((void *) (0x44000000+VRAMOFFS_FB0))
#define VRAM_FB1 ((void *) (0x44000000+VRAMOFFS_FB1))
#define VRAM_STUFF ((void *) (0x44000000+VRAMOFFS_STUFF))
#define VRAM_CACHED_STUFF ((void *) (0x04000000+VRAMOFFS_STUFF))
#define GU_CMDLIST_SIZE (16*1024)
extern unsigned int guCmdList[GU_CMDLIST_SIZE];
extern int psp_unhandled_suspend;
void *psp_video_get_active_fb(void);
void psp_video_switch_to_single(void);
void psp_video_flip(int wait_vsync);
extern void *psp_screen;
unsigned int psp_pad_read(int blocking);
int psp_get_cpu_clock(void);
int psp_set_cpu_clock(int clock);
char *psp_get_status_line(void);
void psp_wait_suspend(void);
void psp_resume_suspend(void);
/* shorter btn names */
#define PBTN_UP PSP_CTRL_UP
#define PBTN_LEFT PSP_CTRL_LEFT
#define PBTN_RIGHT PSP_CTRL_RIGHT
#define PBTN_DOWN PSP_CTRL_DOWN
#define PBTN_L PSP_CTRL_LTRIGGER
#define PBTN_R PSP_CTRL_RTRIGGER
#define PBTN_TRIANGLE PSP_CTRL_TRIANGLE
#define PBTN_CIRCLE PSP_CTRL_CIRCLE
#define PBTN_X PSP_CTRL_CROSS
#define PBTN_SQUARE PSP_CTRL_SQUARE
#define PBTN_SELECT PSP_CTRL_SELECT
#define PBTN_START PSP_CTRL_START
#define PBTN_NOTE PSP_CTRL_NOTE // doesn't seem to work?
/* fake 'nub' btns */
#define PBTN_NUB_UP (1 << 28)
#define PBTN_NUB_RIGHT (1 << 29)
#define PBTN_NUB_DOWN (1 << 30)
#define PBTN_NUB_LEFT (1 << 31)

View file

@ -1,2 +0,0 @@
#define VERSION "1.51b"

View file

@ -1,72 +0,0 @@
# settings
CROSS=i586-mingw32msvc-
#use_musashi = 1
use_fame = 1
use_cz80 = 1
use_sh2drc = 1
#use_sh2mame = 1
-include Makefile.local
ARCH ?= x86
CC = $(CROSS)gcc
CXX = $(CROSS)g++
LD = $(CROSS)ld
STRIP = $(CROSS)strip
DEFINES = _UNZIP_SUPPORT IN_VK
CFLAGS += -O2 -Wall -falign-functions=2 -ffast-math
CFLAGS += -I../.. -I. -I../../zlib/ -Idirectx/include/
LDFLAGS += -mwindows -L. -Ldirectx/lib/ -lgdi32 -lcomdlg32 -lddraw -ldsound -ldxguid
# frontend
OBJS += main.o plat.o direct.o dsnd.o in_vk.o
# common
OBJS += platform/common/emu.o platform/common/menu.o \
platform/common/config.o platform/common/fonts.o platform/common/readpng.o \
platform/common/input.o
OBJS += pico/carthw/svp/compiler.o
OBJS += pico/sound/mix.o
# zlib
OBJS += zlib/gzio.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o \
zlib/deflate.o zlib/crc32.o zlib/adler32.o zlib/zutil.o zlib/compress.o zlib/uncompr.o
# unzip
OBJS += unzip/unzip.o unzip/unzip_stream.o
CFLAGS += $(addprefix -D,$(DEFINES))
CXXFLAGS = $(CFLAGS)
vpath %.c = ../..
DIRS += zlib unzip
TARGET = PicoDrive.exe
all: mkdirs $(TARGET)
include ../common/common.mak
include ../common/revision.mak
clean: tidy
@$(RM) $(TARGET)
tidy:
$(RM) $(OBJS) $(TARGET).map
rm -rf $(DIRS)
$(TARGET) : $(OBJS)
@echo ">>>" $@
$(CC) $(CFLAGS) $^ $(LDFLAGS) -lm -lpng -Wl,-Map=$(TARGET).map -o $@
$(STRIP) $@
# ----------- release -----------
ifneq ($(findstring rel,$(MAKECMDGOALS)),)
ifeq ($(VER),)
$(error need VER)
endif
endif
rel: $(TARGET) readme.txt carthw.cfg
zip -9 -j ../../PicoDrive_win32_$(VER).zip $^

View file

@ -1,635 +0,0 @@
#include <windows.h>
#include <commdlg.h>
#include <stdio.h>
#include "../../pico/pico.h"
#include "../common/readpng.h"
#include "../common/config.h"
#include "../common/lprintf.h"
#include "../common/emu.h"
#include "../common/menu.h"
#include "../common/input.h"
#include "../common/plat.h"
#include "version.h"
#include "direct.h"
#include "in_vk.h"
char *romname=NULL;
HWND FrameWnd=NULL;
RECT FrameRectMy;
RECT EmuScreenRect = { 0, 0, 320, 224 };
int lock_to_1_1 = 1;
static HWND PicoSwWnd=NULL, PicoPadWnd=NULL;
static HMENU mmain = 0, mdisplay = 0, mpicohw = 0;
static HBITMAP ppad_bmp = 0;
static HBITMAP ppage_bmps[7] = { 0, };
static char rom_name[0x20*3+1];
static int main_wnd_as_pad = 0;
static HANDLE loop_enter_event, loop_end_event;
void error(char *text)
{
MessageBox(FrameWnd, text, "Error", 0);
}
static void UpdateRect(void)
{
WINDOWINFO wi;
memset(&wi, 0, sizeof(wi));
wi.cbSize = sizeof(wi);
GetWindowInfo(FrameWnd, &wi);
FrameRectMy = wi.rcClient;
}
static int extract_rom_name(char *dest, const unsigned char *src, int len)
{
char *p = dest, s_old = 0x20;
int i;
for (i = len - 1; i >= 0; i--)
{
if (src[i^1] != ' ') break;
}
len = i + 1;
for (i = 0; i < len; i++)
{
unsigned char s = src[i^1];
if (s == 0x20 && s_old == 0x20) continue;
else if (s >= 0x20 && s < 0x7f && s != '%')
{
*p++ = s;
}
else
{
sprintf(p, "%%%02x", s);
p += 3;
}
s_old = s;
}
*p = 0;
return p - dest;
}
static void check_name_alias(const char *afname)
{
char buff[256], *var, *val;
FILE *f;
int ret;
f = fopen(afname, "r");
if (f == NULL) return;
while (1)
{
ret = config_get_var_val(f, buff, sizeof(buff), &var, &val);
if (ret == 0) break;
if (ret == -1) continue;
if (strcmp(rom_name, var) == 0) {
lprintf("rom aliased: \"%s\" -> \"%s\"\n", rom_name, val);
strncpy(rom_name, val, sizeof(rom_name));
break;
}
}
fclose(f);
}
static HBITMAP png2hb(const char *fname, int is_480)
{
BITMAPINFOHEADER bih;
HBITMAP bmp;
void *bmem;
int ret;
bmem = calloc(1, is_480 ? 480*240*3 : 320*240*3);
if (bmem == NULL) return NULL;
ret = readpng(bmem, fname, READPNG_24, is_480 ? 480 : 320, 240);
if (ret != 0) {
free(bmem);
return NULL;
}
memset(&bih, 0, sizeof(bih));
bih.biSize = sizeof(bih);
bih.biWidth = is_480 ? 480 : 320;
bih.biHeight = -240;
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biCompression = BI_RGB;
bmp = CreateDIBitmap(GetDC(FrameWnd), &bih, CBM_INIT, bmem, (BITMAPINFO *)&bih, 0);
if (bmp == NULL)
lprintf("CreateDIBitmap failed with %i", GetLastError());
free(bmem);
return bmp;
}
static void PrepareForROM(void)
{
unsigned char *rom_data = NULL;
int i, ret, show = PicoAHW & PAHW_PICO;
PicoGetInternal(PI_ROM, (pint_ret_t *) &rom_data);
EnableMenuItem(mmain, 2, MF_BYPOSITION|(show ? MF_ENABLED : MF_GRAYED));
ShowWindow(PicoPadWnd, show ? SW_SHOWNA : SW_HIDE);
ShowWindow(PicoSwWnd, show ? SW_SHOWNA : SW_HIDE);
CheckMenuItem(mpicohw, 1210, show ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(mpicohw, 1211, show ? MF_CHECKED : MF_UNCHECKED);
PostMessage(FrameWnd, WM_COMMAND, 1220 + PicoPicohw.page, 0);
DrawMenuBar(FrameWnd);
InvalidateRect(PicoSwWnd, NULL, 1);
PicoPicohw.pen_pos[0] =
PicoPicohw.pen_pos[1] = 0x8000;
in_vk_add_pl12 = 0;
ret = extract_rom_name(rom_name, rom_data + 0x150, 0x20);
if (ret == 0)
extract_rom_name(rom_name, rom_data + 0x130, 0x20);
if (show)
{
char path[MAX_PATH], *p;
GetModuleFileName(NULL, path, sizeof(path) - 32);
p = strrchr(path, '\\');
if (p == NULL) p = path;
else p++;
if (ppad_bmp == NULL) {
strcpy(p, "pico\\pad.png");
ppad_bmp = png2hb(path, 0);
}
strcpy(p, "pico\\alias.txt");
check_name_alias(path);
for (i = 0; i < 7; i++) {
if (ppage_bmps[i] != NULL) DeleteObject(ppage_bmps[i]);
sprintf(p, "pico\\%s_%i.png", rom_name, i);
ppage_bmps[i] = png2hb(path, 1);
}
// games usually don't have page 6, so just duplicate page 5.
if (ppage_bmps[6] == NULL && ppage_bmps[5] != NULL) {
sprintf(p, "pico\\%s_5.png", rom_name);
ppage_bmps[6] = png2hb(path, 1);
}
}
}
static void LoadROM(const char *cmdpath)
{
char rompath[MAX_PATH];
int ret;
if (cmdpath != NULL && strlen(cmdpath)) {
strcpy(rompath, cmdpath + (cmdpath[0] == '\"' ? 1 : 0));
if (rompath[strlen(rompath)-1] == '\"')
rompath[strlen(rompath)-1] = 0;
}
else {
OPENFILENAME of; ZeroMemory(&of, sizeof(of));
rompath[sizeof(rompath) - 1] = 0;
strncpy(rompath, rom_fname_loaded, sizeof(rompath) - 1);
of.lStructSize = sizeof(of);
of.lpstrFilter = "ROMs, CD images\0*.smd;*.bin;*.gen;*.zip;*.32x;*.sms;*.iso;*.cso;*.cue\0"
"whatever\0*.*\0";
of.lpstrFile = rompath;
of.nMaxFile = MAX_PATH;
of.Flags = OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
of.hwndOwner = FrameWnd;
if (!GetOpenFileName(&of))
return;
}
if (engineState == PGS_Running) {
engineState = PGS_Paused;
WaitForSingleObject(loop_end_event, 5000);
}
ret = emu_reload_rom(rompath);
if (ret == 0) {
extern char menu_error_msg[]; // HACK..
error(menu_error_msg);
return;
}
PrepareForROM();
engineState = PGS_Running;
SetEvent(loop_enter_event);
}
static const int rect_widths[4] = { 320, 256, 640, 512 };
static const int rect_heights[4] = { 224, 224, 448, 448 };
// Window proc for the frame window:
static LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
POINT pt;
RECT rc;
int i;
switch (msg)
{
case WM_CLOSE:
PostQuitMessage(0);
return 0;
case WM_DESTROY:
FrameWnd = NULL; // Blank the handle
break;
case WM_SIZE:
case WM_MOVE:
case WM_SIZING:
UpdateRect();
if (lock_to_1_1 && FrameRectMy.right - FrameRectMy.left != 0 &&
(FrameRectMy.right - FrameRectMy.left != EmuScreenRect.right - EmuScreenRect.left ||
FrameRectMy.bottom - FrameRectMy.top != EmuScreenRect.bottom - EmuScreenRect.top)) {
lock_to_1_1 = 0;
CheckMenuItem(mdisplay, 1104, MF_UNCHECKED);
}
break;
case WM_COMMAND:
switch (LOWORD(wparam))
{
case 1000:
LoadROM(NULL);
break;
case 1001:
emu_reset_game();
return 0;
case 1002:
PostQuitMessage(0);
return 0;
case 1100:
case 1101:
case 1102:
case 1103:
// LoopWait=1; // another sync hack
// for (i = 0; !LoopWaiting && i < 10; i++) Sleep(10);
FrameRectMy.right = FrameRectMy.left + rect_widths[wparam&3];
FrameRectMy.bottom = FrameRectMy.top + rect_heights[wparam&3];
AdjustWindowRect(&FrameRectMy, WS_OVERLAPPEDWINDOW, 1);
MoveWindow(hwnd, FrameRectMy.left, FrameRectMy.top,
FrameRectMy.right-FrameRectMy.left, FrameRectMy.bottom-FrameRectMy.top, 1);
UpdateRect();
lock_to_1_1 = 0;
CheckMenuItem(mdisplay, 1104, MF_UNCHECKED);
// if (rom_loaded) LoopWait=0;
return 0;
case 1104:
lock_to_1_1 = !lock_to_1_1;
CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);
/* FALLTHROUGH */
case 2000: // EmuScreenRect/FrameRectMy sync request
if (!lock_to_1_1)
return 0;
FrameRectMy.right = FrameRectMy.left + (EmuScreenRect.right - EmuScreenRect.left);
FrameRectMy.bottom = FrameRectMy.top + (EmuScreenRect.bottom - EmuScreenRect.top);
AdjustWindowRect(&FrameRectMy, WS_OVERLAPPEDWINDOW, 1);
MoveWindow(hwnd, FrameRectMy.left, FrameRectMy.top,
FrameRectMy.right-FrameRectMy.left, FrameRectMy.bottom-FrameRectMy.top, 1);
UpdateRect();
return 0;
case 1210:
case 1211:
i = IsWindowVisible((LOWORD(wparam)&1) ? PicoPadWnd : PicoSwWnd);
i = !i;
ShowWindow((LOWORD(wparam)&1) ? PicoPadWnd : PicoSwWnd, i ? SW_SHOWNA : SW_HIDE);
CheckMenuItem(mpicohw, LOWORD(wparam), i ? MF_CHECKED : MF_UNCHECKED);
return 0;
case 1212:
main_wnd_as_pad = !main_wnd_as_pad;
CheckMenuItem(mpicohw, 1212, main_wnd_as_pad ? MF_CHECKED : MF_UNCHECKED);
return 0;
case 1220:
case 1221:
case 1222:
case 1223:
case 1224:
case 1225:
case 1226:
PicoPicohw.page = LOWORD(wparam) % 10;
for (i = 0; i < 7; i++)
CheckMenuItem(mpicohw, 1220 + i, MF_UNCHECKED);
CheckMenuItem(mpicohw, 1220 + PicoPicohw.page, MF_CHECKED);
InvalidateRect(PicoSwWnd, NULL, 1);
return 0;
case 1300:
MessageBox(FrameWnd, plat_get_credits(), "About", 0);
return 0;
}
break;
case WM_TIMER:
GetCursorPos(&pt);
GetWindowRect(PicoSwWnd, &rc);
if (PtInRect(&rc, pt)) break;
GetWindowRect(PicoPadWnd, &rc);
if (PtInRect(&rc, pt)) break;
PicoPicohw.pen_pos[0] |= 0x8000;
PicoPicohw.pen_pos[1] |= 0x8000;
in_vk_add_pl12 = 0;
break;
case WM_LBUTTONDOWN: in_vk_add_pl12 |= 0x20; return 0;
case WM_LBUTTONUP: in_vk_add_pl12 &= ~0x20; return 0;
case WM_MOUSEMOVE:
if (!main_wnd_as_pad) break;
PicoPicohw.pen_pos[0] = 0x03c + (320 * LOWORD(lparam) / (FrameRectMy.right - FrameRectMy.left));
PicoPicohw.pen_pos[1] = 0x1fc + (232 * HIWORD(lparam) / (FrameRectMy.bottom - FrameRectMy.top));
SetTimer(FrameWnd, 100, 1000, NULL);
break;
case WM_KEYDOWN:
if (wparam == VK_TAB) {
emu_reset_game();
break;
}
if (wparam == VK_ESCAPE) {
LoadROM(NULL);
break;
}
in_vk_keydown(wparam);
break;
case WM_KEYUP:
in_vk_keyup(wparam);
break;
}
return DefWindowProc(hwnd,msg,wparam,lparam);
}
static LRESULT CALLBACK PicoSwWndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
PAINTSTRUCT ps;
HDC hdc, hdc2;
switch (msg)
{
case WM_DESTROY: PicoSwWnd=NULL; break;
case WM_LBUTTONDOWN: in_vk_add_pl12 |= 0x20; return 0;
case WM_LBUTTONUP: in_vk_add_pl12 &= ~0x20; return 0;
case WM_MOUSEMOVE:
if (HIWORD(lparam) < 0x20) break;
PicoPicohw.pen_pos[0] = 0x03c + LOWORD(lparam) * 2/3;
PicoPicohw.pen_pos[1] = 0x2f8 + HIWORD(lparam) - 0x20;
SetTimer(FrameWnd, 100, 1000, NULL);
break;
case WM_KEYDOWN: in_vk_keydown(wparam); break;
case WM_KEYUP: in_vk_keyup(wparam); break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
if (ppage_bmps[PicoPicohw.page] == NULL)
{
SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
SetTextColor(hdc, RGB(255, 255, 255));
SetBkColor(hdc, RGB(0, 0, 0));
TextOut(hdc, 2, 2, "missing PNGs for", 16);
TextOut(hdc, 2, 18, rom_name, strlen(rom_name));
}
else
{
hdc2 = CreateCompatibleDC(GetDC(FrameWnd));
SelectObject(hdc2, ppage_bmps[PicoPicohw.page]);
BitBlt(hdc, 0, 0, 480, 240, hdc2, 0, 0, SRCCOPY);
DeleteDC(hdc2);
}
EndPaint(hwnd, &ps);
return 0;
case WM_CLOSE:
ShowWindow(hwnd, SW_HIDE);
CheckMenuItem(mpicohw, 1210, MF_UNCHECKED);
return 0;
}
return DefWindowProc(hwnd,msg,wparam,lparam);
}
static LRESULT CALLBACK PicoPadWndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
PAINTSTRUCT ps;
HDC hdc, hdc2;
switch (msg)
{
case WM_DESTROY: PicoPadWnd=NULL; break;
case WM_LBUTTONDOWN: in_vk_add_pl12 |= 0x20; return 0;
case WM_LBUTTONUP: in_vk_add_pl12 &= ~0x20; return 0;
case WM_MOUSEMOVE:
PicoPicohw.pen_pos[0] = 0x03c + LOWORD(lparam);
PicoPicohw.pen_pos[1] = 0x1fc + HIWORD(lparam);
SetTimer(FrameWnd, 100, 1000, NULL);
break;
case WM_KEYDOWN: in_vk_keydown(wparam); break;
case WM_KEYUP: in_vk_keyup(wparam); break;
case WM_PAINT:
if (ppad_bmp == NULL) break;
hdc = BeginPaint(hwnd, &ps);
hdc2 = CreateCompatibleDC(GetDC(FrameWnd));
SelectObject(hdc2, ppad_bmp);
BitBlt(hdc, 0, 0, 320, 240, hdc2, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);
DeleteDC(hdc2);
return 0;
case WM_CLOSE:
ShowWindow(hwnd, SW_HIDE);
CheckMenuItem(mpicohw, 1211, MF_UNCHECKED);
return 0;
}
return DefWindowProc(hwnd,msg,wparam,lparam);
}
static int FrameInit()
{
WNDCLASS wc;
RECT rect={0,0,0,0};
HMENU mfile;
int style=0;
int left=0,top=0,width=0,height=0;
memset(&wc,0,sizeof(wc));
// Register the window class:
wc.lpfnWndProc=WndProc;
wc.hInstance=GetModuleHandle(NULL);
wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=CreateSolidBrush(0);
wc.lpszClassName="PicoMainFrame";
RegisterClass(&wc);
wc.lpszClassName="PicoSwWnd";
wc.lpfnWndProc=PicoSwWndProc;
RegisterClass(&wc);
wc.lpszClassName="PicoPadWnd";
wc.lpfnWndProc=PicoPadWndProc;
RegisterClass(&wc);
rect.right =320;
rect.bottom=224;
// Adjust size of windows based on borders:
style=WS_OVERLAPPEDWINDOW;
AdjustWindowRect(&rect,style,1);
width =rect.right-rect.left;
height=rect.bottom-rect.top;
// Place window in the centre of the screen:
SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0);
left=rect.left+rect.right;
top=rect.top+rect.bottom;
left-=width; left>>=1;
top-=height; top>>=1;
// Create menu:
mfile = CreateMenu();
InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1000, "&Load ROM");
InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1001, "&Reset");
InsertMenu(mfile, -1, MF_BYPOSITION|MF_STRING, 1002, "E&xit");
mdisplay = CreateMenu();
InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1100, "320x224");
InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1101, "256x224");
InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1102, "640x448");
InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1103, "512x448");
InsertMenu(mdisplay, -1, MF_BYPOSITION|MF_STRING, 1104, "Lock to 1:1");
mpicohw = CreateMenu();
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1210, "Show &Storyware");
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1211, "Show &Drawing pad");
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1212, "&Main window as pad");
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1220, "Title page (&0)");
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1221, "Page &1");
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1222, "Page &2");
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1223, "Page &3");
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1224, "Page &4");
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1225, "Page &5");
InsertMenu(mpicohw, -1, MF_BYPOSITION|MF_STRING, 1226, "Page &6");
mmain = CreateMenu();
InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mfile, "&File");
InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mdisplay, "&Display");
InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR) mpicohw, "&Pico");
EnableMenuItem(mmain, 2, MF_BYPOSITION|MF_GRAYED);
// InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING|MF_POPUP, 1200, "&Config");
InsertMenu(mmain, -1, MF_BYPOSITION|MF_STRING, 1300, "&About");
// Create the window:
FrameWnd=CreateWindow("PicoMainFrame","PicoDrive " VERSION,style|WS_VISIBLE,
left,top,width,height,NULL,mmain,NULL,NULL);
CheckMenuItem(mdisplay, 1104, lock_to_1_1 ? MF_CHECKED : MF_UNCHECKED);
ShowWindow(FrameWnd, SW_NORMAL);
UpdateWindow(FrameWnd);
UpdateRect();
// create Pico windows
style = WS_OVERLAPPED|WS_CAPTION|WS_BORDER|WS_SYSMENU;
rect.left=rect.top=0;
rect.right =320;
rect.bottom=224;
AdjustWindowRect(&rect,style,1);
width =rect.right-rect.left;
height=rect.bottom-rect.top;
left += 326;
PicoSwWnd=CreateWindow("PicoSwWnd","Storyware",style,
left,top,width+160,height,FrameWnd,NULL,NULL,NULL);
top += 266;
PicoPadWnd=CreateWindow("PicoPadWnd","Drawing Pad",style,
left,top,width,height,FrameWnd,NULL,NULL,NULL);
return 0;
}
// --------------------
static DWORD WINAPI work_thread(void *x)
{
while (engineState != PGS_Quit) {
WaitForSingleObject(loop_enter_event, INFINITE);
if (engineState != PGS_Running)
continue;
printf("loop..\n");
emu_loop();
SetEvent(loop_end_event);
}
return 0;
}
// XXX: use main.c
void xxinit(void)
{
/* in_init() must go before config, config accesses in_ fwk */
in_init();
emu_prep_defconfig();
emu_read_config(NULL, 0);
config_readlrom(PicoConfigFile);
plat_init();
in_probe();
emu_init();
menu_init();
}
int WINAPI WinMain(HINSTANCE p1, HINSTANCE p2, LPSTR cmdline, int p4)
{
MSG msg;
DWORD tid = 0;
HANDLE thread;
int ret;
xxinit();
FrameInit();
ret = DirectInit();
if (ret)
goto end0;
loop_enter_event = CreateEvent(NULL, 0, 0, NULL);
if (loop_enter_event == NULL)
goto end0;
loop_end_event = CreateEvent(NULL, 0, 0, NULL);
if (loop_end_event == NULL)
goto end0;
thread = CreateThread(NULL, 0, work_thread, NULL, 0, &tid);
if (thread == NULL)
goto end0;
LoadROM(cmdline);
// Main window loop:
for (;;)
{
GetMessage(&msg,NULL,0,0);
if (msg.message==WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Signal thread to quit and wait for it to exit:
if (engineState == PGS_Running) {
engineState = PGS_Quit;
WaitForSingleObject(loop_end_event, 5000);
}
CloseHandle(thread); thread=NULL;
emu_write_config(0);
emu_finish();
//plat_finish();
end0:
DirectExit();
DestroyWindow(FrameWnd);
// _CrtDumpMemoryLeaks();
return 0;
}

View file

@ -1,11 +0,0 @@
#ifdef __cplusplus
extern "C" {
#endif
extern HWND FrameWnd;
extern RECT FrameRectMy;
extern RECT EmuScreenRect;
#ifdef __cplusplus
}
#endif

View file

@ -1,249 +0,0 @@
#include <windows.h>
#include <stdio.h>
#include "../common/lprintf.h"
#include "../common/plat.h"
#include "../common/emu.h"
#include "../../pico/pico.h"
#include "version.h"
#include "direct.h"
#include "dsnd.h"
#include "main.h"
static unsigned short screen_buff[320 * 240];
static unsigned char PicoDraw2FB_[(8+320) * (8+240+8)];
unsigned char *PicoDraw2FB = PicoDraw2FB_;
const char *renderer_names[] = { NULL };
const char *renderer_names32x[] = { NULL };
void plat_init(void)
{
g_screen_ptr = (void *)screen_buff;
}
int plat_is_dir(const char *path)
{
return (GetFileAttributes(path) & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
}
unsigned int plat_get_ticks_ms(void)
{
return GetTickCount();
}
unsigned int plat_get_ticks_us(void)
{
// XXX: maybe performance counters?
return GetTickCount() * 1000;
}
void plat_wait_till_us(unsigned int us)
{
int msdiff = (int)(us - plat_get_ticks_us()) / 1000;
if (msdiff > 6)
Sleep(msdiff - 6);
while (plat_get_ticks_us() < us)
;
}
void plat_sleep_ms(int ms)
{
Sleep(ms);
}
int plat_wait_event(int *fds_hnds, int count, int timeout_ms)
{
return -1;
}
void pemu_prep_defconfig(void)
{
memset(&defaultConfig, 0, sizeof(defaultConfig));
defaultConfig.s_PicoOpt|= POPT_6BTN_PAD; // for xmen proto
defaultConfig.s_PicoCDBuffers = 0;
defaultConfig.Frameskip = 0;
}
void pemu_validate_config(void)
{
}
void pemu_loop_prep(void)
{
PicoDrawSetOutFormat(PDF_RGB555, 1);
PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
pemu_sound_start();
}
void pemu_loop_end(void)
{
pemu_sound_stop();
}
void pemu_forced_frame(int no_scale, int do_emu)
{
}
void pemu_finalize_frame(const char *fps, const char *notice_msg)
{
}
void plat_video_flip(void)
{
DirectScreen(g_screen_ptr);
DirectPresent();
}
void plat_video_wait_vsync(void)
{
}
void plat_video_toggle_renderer(int change, int is_menu)
{
// this will auto-select SMS/32X renderers
PicoDrawSetOutFormat(PDF_RGB555, 1);
}
void emu_video_mode_change(int start_line, int line_count, int is_32cols)
{
EmuScreenRect.left = is_32cols ? 32 : 0;
EmuScreenRect.right = is_32cols ? 256+32 : 320;
EmuScreenRect.top = start_line;
EmuScreenRect.bottom = start_line + line_count;
PostMessage(FrameWnd, WM_COMMAND, 0x20000 | 2000, 0);
}
static int sndbuff[2*44100/50/2 + 4];
static void update_sound(int len)
{
/* avoid writing audio when lagging behind to prevent audio lag */
if (PicoSkipFrame != 2)
DSoundUpdate(sndbuff, (currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) ? 0 : 1);
}
void pemu_sound_start(void)
{
int ret;
PsndOut = NULL;
currentConfig.EmuOpt &= ~EOPT_EXT_FRMLIMIT;
// prepare sound stuff
if (currentConfig.EmuOpt & EOPT_EN_SOUND)
{
PsndRerate(0);
ret = DSoundInit(FrameWnd, PsndRate, (PicoOpt & POPT_EN_STEREO) ? 1 : 0, PsndLen);
if (ret != 0) {
lprintf("dsound init failed\n");
return;
}
PsndOut = (void *)sndbuff;
PicoWriteSound = update_sound;
currentConfig.EmuOpt |= EOPT_EXT_FRMLIMIT;
}
}
void pemu_sound_stop(void)
{
DSoundExit();
}
void pemu_sound_wait(void)
{
}
int plat_get_root_dir(char *dst, int len)
{
int ml;
ml = GetModuleFileName(NULL, dst, len);
while (ml > 0 && dst[ml] != '\\')
ml--;
if (ml != 0)
ml++;
dst[ml] = 0;
return ml;
}
void plat_status_msg_busy_first(const char *msg)
{
}
void plat_status_msg_busy_next(const char *msg)
{
}
void plat_status_msg_clear(void)
{
}
void plat_video_menu_enter(int is_rom_loaded)
{
}
void plat_video_menu_begin(void)
{
}
void plat_video_menu_end(void)
{
}
void plat_update_volume(int has_changed, int is_up)
{
}
const char *plat_get_credits(void)
{
return "PicoDrive v" VERSION " minibeta (c) notaz, 2006-2009\n\n"
"Credits:\n"
"fDave: base code of PicoDrive\n"
"Chui: Fame/C\n"
"NJ: CZ80\n"
"MAME devs: YM2612, SN76496 and SH2 cores\n"
"Stéphane Dallongeville: base of Fame/C (C68K), CZ80\n\n"
"Special thanks (ideas, valuable information and stuff):\n"
"Charles MacDonald, Eke, Exophase, Haze, Lordus, Nemesis,\n"
"Pierpaolo Prazzoli, Rokas, Steve Snake, Tasco Deluxe.\n";
}
void plat_debug_cat(char *str)
{
}
// required by pico
int mp3_get_bitrate(void *f, int size)
{
return 128;
}
void mp3_start_play(void *f, int pos)
{
}
void mp3_update(int *buffer, int length, int stereo)
{
}
// other
void lprintf(const char *fmt, ...)
{
char buf[512];
va_list val;
va_start(val, fmt);
vsnprintf(buf, sizeof(buf), fmt, val);
va_end(val);
OutputDebugString(buf);
printf("%s", buf);
}
// fake
int alphasort() { return 0; }
int scandir() { return 0; }

View file

@ -1,40 +0,0 @@
// port specific settings
#ifndef PORT_CONFIG_H
#define PORT_CONFIG_H
#define NO_SYNC
#define CASE_SENSITIVE_FS 0 // CS filesystem
#define DONT_OPEN_MANY_FILES 0
#define REDUCE_IO_CALLS 0
#define SCREEN_SIZE_FIXED 0
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define MSCREEN_SIZE_FIXED 0
#define MSCREEN_WIDTH SCREEN_WIDTH
#define MSCREEN_HEIGHT SCREEN_HEIGHT
// draw2.c
#define START_ROW 0 // which row of tiles to start rendering at?
#define END_ROW 28 // ..end
// pico.c
#define CAN_HANDLE_240_LINES 1
#define SIMPLE_WRITE_SOUND 1
#define mix_32_to_16l_stereo_lvl mix_32_to_16l_stereo
#define EL_LOGMASK (EL_STATUS)
//#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__)
#define dprintf(x...)
// platform
#define PATH_SEP "\\"
#define PATH_SEP_C '\\'
#define MENU_X2 0
#endif //PORT_CONFIG_H

View file

@ -1,70 +0,0 @@
About
-----
This is a quick windows port of PicoDrive, a Megadrive / Genesis emulator for
handheld devices. It was originally coded having ARM CPU based devices in mind
(most work was done on GP2X version), but there is also a PSP port.
The reason I'm sometimes doing windows versions is to show certain emulation
possibilities, first release was to demonstrate SVP emulation (Virtua Racing),
later Pico toy and X-Men 32X prototype. It is not to compete with other
emulators like Kega Fusion and the likes.
For more info, visit http://notaz.gp2x.de/svp.php
Releases
--------
1.70 - preliminary 32X emulation, runs X-Men proto.
1.45a - Few bugfixes and additions.
1.45 - Added preliminary Sega Pico emulation.
1.40b - Perspective fix thanks to Pierpaolo Prazzoli's info.
1.40a - Tasco Deluxe's dithering fix.
1.40 - first release.
Controls
--------
These are currently hardcoded, keyboard only:
PC Gen/MD Sega Pico
-------+-----------+---------
Enter: Start
A: A
S: B red button
D: C pen push
Q,W,E: X,Y,Z
TAB: (reset)
Esc: (load ROM)
Arrows: D-pad
It is possible to change some things in config.cfg (it is created on exit),
but possibilities are limited.
Credits
-------
Vast majority of code written by notaz (notasasatgmailcom).
A lot of work on making SVP emulation happen was done by Tasco Deluxe, my
stuff is a continuation of his. Pierpaolo Prazzoli's information and his
SSP1610 disassembler in MAME code helped a lot too.
The original PicoDrive was written by fDave from finalburn.com
This PicoDrive version uses bits and pieces of from other projects:
68k: FAME/C core, by Chui and Stéphane Dallongeville (as C68K).
z80: CZ80 by Stéphane Dallongeville and modified by NJ.
YM2612, SN76496 and SH2 cores: MAME devs.
Special thanks (ideas, valuable information and stuff):
Charles MacDonald, Eke, Exophase, Haze, Lordus, Nemesis,
Pierpaolo Prazzoli, Rokas, Steve Snake, Tasco Deluxe.
Greets to all the sceners and emu authors out there!

View file

@ -1,2 +0,0 @@
#define VERSION "1.70"