mirror of
https://github.com/RaySollium99/libpicofe.git
synced 2025-10-26 09:09:40 -04:00
remove PicoDrive-specific stuff, add readme
This commit is contained in:
parent
ca69c3e5a0
commit
f506842df2
73 changed files with 13 additions and 16178 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
*.o
|
||||||
|
*.swp
|
||||||
11
README
Normal file
11
README
Normal 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
|
||||||
1159
base_readme.txt
1159
base_readme.txt
File diff suppressed because it is too large
Load diff
|
|
@ -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);
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
840
common/config.c
840
common/config.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
1636
common/emu.c
1636
common/emu.c
File diff suppressed because it is too large
Load diff
155
common/emu.h
155
common/emu.h
|
|
@ -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
|
|
||||||
|
|
||||||
148
common/main.c
148
common/main.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
1080
common/menu_pico.c
1080
common/menu_pico.c
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
|
||||||
|
|
||||||
29
common/mp3.c
29
common/mp3.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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:
|
|
||||||
|
|
||||||
166
game_def.cfg
166
game_def.cfg
|
|
@ -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
|
|
||||||
|
|
||||||
529
gp2x/940ctl.c
529
gp2x/940ctl.c
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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);
|
|
||||||
128
gp2x/Makefile
128
gp2x/Makefile
|
|
@ -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/
|
|
||||||
|
|
||||||
915
gp2x/emu.c
915
gp2x/emu.c
|
|
@ -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 = ¤tConfig.renderer32x;
|
|
||||||
else
|
|
||||||
r = ¤tConfig.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
128
gp2x/menu.c
128
gp2x/menu.c
|
|
@ -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(<ime);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
233
gp2x/plat.c
233
gp2x/plat.c
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
37
gp2x/test.c
37
gp2x/test.c
|
|
@ -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++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
#define VERSION "1.80"
|
|
||||||
|
|
||||||
254
gp2x/warm.c
254
gp2x/warm.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
100
gp2x/warm.h
100
gp2x/warm.h
|
|
@ -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__ */
|
|
||||||
|
|
@ -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 $@
|
|
||||||
|
|
||||||
|
|
@ -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.).
|
|
||||||
|
|
||||||
83
linux/blit.c
83
linux/blit.c
|
|
@ -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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
300
linux/emu.c
300
linux/emu.c
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
383
linux/io.c
383
linux/io.c
|
|
@ -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 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -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");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
void log_io_clear(void);
|
|
||||||
void log_io_dump(void);
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
126
linux/pprof.c
126
linux/pprof.c
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
@ -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__
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
#include "../gp2x/version.h"
|
|
||||||
|
|
||||||
107
pandora/Makefile
107
pandora/Makefile
|
|
@ -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
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
@ -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}
|
|
||||||
|
|
||||||
|
|
@ -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"
|
|
||||||
148
pandora/menu.c
148
pandora/menu.c
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
639
pandora/plat.c
639
pandora/plat.c
|
|
@ -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");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
#define VERSION "1.80"
|
|
||||||
|
|
||||||
205
psp/Makefile
205
psp/Makefile
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
@ -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);
|
|
||||||
135
psp/asm_utils.s
135
psp/asm_utils.s
|
|
@ -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
|
|
||||||
|
|
||||||
15
psp/emu.h
15
psp/emu.h
|
|
@ -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);
|
|
||||||
|
|
||||||
121
psp/main.c
121
psp/main.c
|
|
@ -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
1786
psp/menu.c
File diff suppressed because it is too large
Load diff
14
psp/menu.h
14
psp/menu.h
|
|
@ -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
492
psp/mp3.c
|
|
@ -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");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
||||||
|
|
@ -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
372
psp/psp.c
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
70
psp/psp.h
70
psp/psp.h
|
|
@ -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)
|
|
||||||
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
#define VERSION "1.51b"
|
|
||||||
|
|
||||||
|
|
@ -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 $^
|
|
||||||
|
|
||||||
635
win32/main.c
635
win32/main.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
11
win32/main.h
11
win32/main.h
|
|
@ -1,11 +0,0 @@
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern HWND FrameWnd;
|
|
||||||
extern RECT FrameRectMy;
|
|
||||||
extern RECT EmuScreenRect;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
249
win32/plat.c
249
win32/plat.c
|
|
@ -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; }
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
@ -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!
|
|
||||||
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
#define VERSION "1.70"
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue