diff options
Diffstat (limited to 'backends/platform')
35 files changed, 1502 insertions, 1092 deletions
diff --git a/backends/platform/ds/arm7/source/main.cpp b/backends/platform/ds/arm7/source/main.cpp index a4cde02ba6..7029d96405 100644 --- a/backends/platform/ds/arm7/source/main.cpp +++ b/backends/platform/ds/arm7/source/main.cpp @@ -38,7 +38,7 @@ #include <system.h> #include <stdlib.h> #include <string.h> -#include <registers_alt.h> // Needed for SOUND_CR +//#include <registers_alt.h> // not needed in current libnds #include <NDS/scummvm_ipc.h> ////////////////////////////////////////////////////////////////////// #ifdef USE_DEBUGGER @@ -590,7 +590,7 @@ int main(int argc, char ** argv) { IPC->reset = false; - //fifoInit(); + fifoInit(); for (int r = 0; r < 8; r++) { IPC->adpcm.arm7Buffer[r] = (u8 *) malloc(512); diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile index 7f03f4c310..eca170ef96 100644 --- a/backends/platform/ds/arm9/makefile +++ b/backends/platform/ds/arm9/makefile @@ -75,7 +75,7 @@ else ifdef DS_BUILD_K else - # USE_MAD = 1 + USE_MAD = 1 endif endif endif diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp index 5a63e5f08f..7eb02f9070 100644 --- a/backends/platform/ds/arm9/source/dsmain.cpp +++ b/backends/platform/ds/arm9/source/dsmain.cpp @@ -702,7 +702,7 @@ void displayMode8Bit() { - consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 2, 0, true, true); + consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 2, 0, true); // Set this again because consoleinit resets it videoSetMode(MODE_5_2D | (consoleEnable? DISPLAY_BG0_ACTIVE: 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); @@ -940,7 +940,7 @@ void displayMode16Bit() { SUB_BG0_CR = BG_MAP_BASE(4) | BG_TILE_BASE(0); SUB_BG0_Y0 = 0; - consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 4, 0, false, true); + consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 4, 0, false); // consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(4), (u16*)CHAR_BASE_BLOCK_SUB(0), 16); for (int r = 0; r < 32 * 32; r++) { diff --git a/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h b/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h index f41548f400..9344be68f9 100644 --- a/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h +++ b/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h @@ -33,18 +33,6 @@ ////////////////////////////////////////////////////////////////////// -typedef struct sTransferSoundData { -//--------------------------------------------------------------------------------- - const void *data; - u32 len; - u32 rate; - u8 vol; - u8 pan; - u8 format; - u8 PADDING; -} TransferSoundData, * pTransferSoundData; - - //--------------------------------------------------------------------------------- diff --git a/backends/platform/gp2x/graphics.cpp b/backends/platform/gp2x/graphics.cpp index 4a3c668c52..1888cbe47c 100644 --- a/backends/platform/gp2x/graphics.cpp +++ b/backends/platform/gp2x/graphics.cpp @@ -1405,6 +1405,7 @@ void OSystem_GP2X::drawMouse() { SDL_Rect zoomdst; SDL_Rect dst; int scale; + int width, height; int hotX, hotY; int tmpScreenWidth, tmpScreenHeight; @@ -1425,12 +1426,16 @@ void OSystem_GP2X::drawMouse() { if (!_overlayVisible) { scale = _videoMode.scaleFactor; + width = _videoMode.screenWidth; + height = _videoMode.screenHeight; dst.w = _mouseCurState.vW; dst.h = _mouseCurState.vH; hotX = _mouseCurState.vHotX; hotY = _mouseCurState.vHotY; } else { scale = 1; + width = _videoMode.overlayWidth; + height = _videoMode.overlayHeight; dst.w = _mouseCurState.rW; dst.h = _mouseCurState.rH; hotX = _mouseCurState.rHotX; diff --git a/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp b/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp index 6abddd52f3..ff3bd725be 100644 --- a/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp +++ b/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp @@ -149,6 +149,7 @@ void OSystem_GP2XWIZ::drawMouse() { SDL_Rect dst; int scale; + int width, height; int hotX, hotY; if (_videoMode.mode == GFX_HALF && !_overlayVisible){ @@ -161,12 +162,16 @@ void OSystem_GP2XWIZ::drawMouse() { if (!_overlayVisible) { scale = _videoMode.scaleFactor; + width = _videoMode.screenWidth; + height = _videoMode.screenHeight; dst.w = _mouseCurState.vW; dst.h = _mouseCurState.vH; hotX = _mouseCurState.vHotX; hotY = _mouseCurState.vHotY; } else { scale = 1; + width = _videoMode.overlayWidth; + height = _videoMode.overlayHeight; dst.w = _mouseCurState.rW; dst.h = _mouseCurState.rH; hotX = _mouseCurState.rHotX; diff --git a/backends/platform/linuxmoto/linuxmoto-graphics.cpp b/backends/platform/linuxmoto/linuxmoto-graphics.cpp index a39416ebc4..d66d41dfab 100644 --- a/backends/platform/linuxmoto/linuxmoto-graphics.cpp +++ b/backends/platform/linuxmoto/linuxmoto-graphics.cpp @@ -168,6 +168,7 @@ void OSystem_LINUXMOTO::drawMouse() { SDL_Rect dst; int scale; + int width, height; int hotX, hotY; if (_videoMode.mode == GFX_HALF && !_overlayVisible) { @@ -180,12 +181,16 @@ void OSystem_LINUXMOTO::drawMouse() { if (!_overlayVisible) { scale = _videoMode.scaleFactor; + width = _videoMode.screenWidth; + height = _videoMode.screenHeight; dst.w = _mouseCurState.vW; dst.h = _mouseCurState.vH; hotX = _mouseCurState.vHotX; hotY = _mouseCurState.vHotY; } else { scale = 1; + width = _videoMode.overlayWidth; + height = _videoMode.overlayHeight; dst.w = _mouseCurState.rW; dst.h = _mouseCurState.rH; hotX = _mouseCurState.rHotX; diff --git a/backends/platform/ps2/Makefile.ps2 b/backends/platform/ps2/Makefile.ps2 index bf7ac0aca0..d6ebc9bfc8 100644 --- a/backends/platform/ps2/Makefile.ps2 +++ b/backends/platform/ps2/Makefile.ps2 @@ -1,39 +1,52 @@ # $Header: Exp $ include $(PS2SDK)/Defs.make -PS2_EXTRA = /works/devel/ps2/sdk-extra +PS2_EXTRA = /home/tony/GSOC/ps2/sdk-extra PS2_EXTRA_INCS = /zlib/include /libmad/ee/include /SjPcm/ee/src /tremor -PS2_EXTRA_LIBS = /zlib/lib /libmad/ee/lib /SjPcm/ee/lib /tremor/tremor +PS2_EXTRA_LIBS = /zlib/lib /libmad/ee/lib /SjPcm/ee/lib /vorbis /tremor/tremor -ENABLED=STATIC_PLUGIN +# Set to 1 to enable, 0 to disable dynamic modules +DYNAMIC_MODULES = 1 + +VERBOSE_BUILD=0 + +# Test for dynamic plugins +ifeq ($(DYNAMIC_MODULES),1) +ENABLED = DYNAMIC_PLUGIN +DEFINES += -DDYNAMIC_MODULES +PRE_OBJS_FLAGS = -Wl,--whole-archive +POST_OBJS_FLAGS = -Wl,--no-whole-archive +else +ENABLED = STATIC_PLUGIN +endif ENABLE_SCUMM = $(ENABLED) -ENABLE_SCUMM_7_8 = $(ENABLED) -ENABLE_HE = $(ENABLED) +#ENABLE_SCUMM_7_8 = $(ENABLED) +#ENABLE_HE = $(ENABLED) ENABLE_AGI = $(ENABLED) -ENABLE_AGOS = $(ENABLED) -ENABLE_CINE = $(ENABLED) -ENABLE_CRUISE = $(ENABLED) -ENABLE_DRASCULA = $(ENABLED) -ENABLE_GOB = $(ENABLED) -ENABLE_KYRA = $(ENABLED) -ENABLE_LURE = $(ENABLED) +#ENABLE_AGOS = $(ENABLED) +#ENABLE_CINE = $(ENABLED) +#ENABLE_CRUISE = $(ENABLED) +#ENABLE_DRASCULA = $(ENABLED) +#ENABLE_GOB = $(ENABLED) +#ENABLE_KYRA = $(ENABLED) +#ENABLE_LURE = $(ENABLED) # ENABLE_M4 = $(ENABLED) -ENABLE_MADE = $(ENABLED) -ENABLE_PARALLACTION = $(ENABLED) -ENABLE_QUEEN = $(ENABLED) -ENABLE_SAGA = $(ENABLED) -ENABLE_SAGA2 = $(ENABLED) -ENABLE_IHNM = $(ENABLED) -ENABLE_SKY = $(ENABLED) -ENABLE_SWORD1 = $(ENABLED) -ENABLE_SWORD2 = $(ENABLED) +#ENABLE_MADE = $(ENABLED) +#ENABLE_PARALLACTION = $(ENABLED) +#ENABLE_QUEEN = $(ENABLED) +#ENABLE_SAGA = $(ENABLED) +#ENABLE_SAGA2 = $(ENABLED) +#ENABLE_IHNM = $(ENABLED) +#ENABLE_SKY = $(ENABLED) +#ENABLE_SWORD1 = $(ENABLED) +#ENABLE_SWORD2 = $(ENABLED) # ENABLE_TINSEL = $(ENABLED) -ENABLE_TOUCHE = $(ENABLED) +#ENABLE_TOUCHE = $(ENABLED) HAVE_GCC3 = true -CC = ee-gcc +CC = ee-gcc CXX = ee-g++ AS = ee-gcc LD = ee-gcc @@ -46,15 +59,21 @@ RM = rm -f srcdir = ../../.. VPATH = $(srcdir) INCDIR = ../../../ -# DEPDIR = .deps +DEPDIR = .deps +CXX_UPDATE_DEP_FLAG = -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP -DEFINES = -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_ZLIB -DFORCE_RTL -D_EE -D__PLAYSTATION2__ -O2 -Wall -Wno-multichar +# Variables for dynamic plugin building +PLUGIN_PREFIX = +PLUGIN_SUFFIX = .plg +PLUGIN_EXTRA_DEPS = plugin.syms elf/scummvm.elf +PLUGIN_LDFLAGS = -nostartfiles -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -Wl,-q,--just-symbols=elf/scummvm.org.elf,-Tlinkfile,--retain-symbols-file,plugin.syms -lstdc++ -lc +DEFINES = -DUSE_VORBIS -DUSE_MAD -DUSE_TREMOR -DUSE_ZLIB -DFORCE_RTL -D_EE -D__PLAYSTATION2__ -O2 -Wall -Wno-multichar -fno-exceptions -fno-rtti -INCLUDES = $(addprefix -I$(PS2_EXTRA),$(PS2_EXTRA_INCS)) +INCLUDES = $(addprefix -I$(PS2_EXTRA),$(PS2_EXTRA_INCS)) INCLUDES += -I $(PS2SDK)/ee/include -I $(PS2SDK)/common/include -I ./common -I . -I $(srcdir) -I $(srcdir)/engines -TARGET = elf/scummvm.elf +TARGET = elf/scummvm OBJS := backends/platform/ps2/DmaPipe.o \ backends/platform/ps2/Gs2dScreen.o \ @@ -71,20 +90,20 @@ OBJS := backends/platform/ps2/DmaPipe.o \ backends/platform/ps2/systemps2.o \ backends/platform/ps2/ps2mutex.o \ backends/platform/ps2/ps2time.o \ - backends/platform/ps2/ps2debug.o + backends/platform/ps2/ps2debug.o \ + backends/platform/ps2/ps2loader.o MODULE_DIRS += . include $(srcdir)/Makefile.common -LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T $(PS2SDK)/ee/startup/linkfile -LDFLAGS += -L $(PS2SDK)/ee/lib -L . +LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T main_prog.ld #$(PS2SDK)/ee/startup/linkfile +LDFLAGS += -G 0 -L $(PS2SDK)/ee/lib -L . LDFLAGS += $(addprefix -L$(PS2_EXTRA),$(PS2_EXTRA_LIBS)) -LDFLAGS += -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lmad -ltremor -lz -lm -lc -lfileXio -lkernel -lstdc++ -LDFLAGS += -s - -all: $(TARGET) +LDFLAGS += -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lmad -ltremor -lz -lm -lc -lfileXio -lkernel -lstdc++ +LDFLAGS += -$(TARGET): $(OBJS) - $(LD) $^ $(LDFLAGS) -o $@ +all: $(TARGET).elf +$(TARGET).elf: $(OBJS) + $(LD) $(PRE_OBJS_FLAGS) $(OBJS) $(POST_OBJS_FLAGS) $(LDFLAGS) -o $@ diff --git a/backends/platform/ps2/elf32.h b/backends/platform/ps2/elf32.h new file mode 100644 index 0000000000..616cc4b4d2 --- /dev/null +++ b/backends/platform/ps2/elf32.h @@ -0,0 +1,209 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef BACKENDS_ELF_H +#define BACKENDS_ELF_H + +/* ELF stuff */ + +typedef unsigned short Elf32_Half, Elf32_Section; +typedef unsigned int Elf32_Word, Elf32_Addr, Elf32_Off; +typedef signed int Elf32_Sword; +typedef Elf32_Half Elf32_Versym; + +#define EI_NIDENT (16) +#define SELFMAG 6 + +/* ELF File format structures. Look up ELF structure for more details */ + +// ELF header (contains info about the file) +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +// Should be in e_ident +#define ELFMAG "\177ELF\1\1" /* ELF Magic number */ + +// e_type values +#define ET_NONE 0 /* no file type */ +#define ET_REL 1 /* relocatable */ +#define ET_EXEC 2 /* executable */ +#define ET_DYN 3 /* shared object */ +#define ET_CORE 4 /* core file */ + +// e_machine values +#define EM_MIPS 8 + + +// Program header (contains info about segment) +typedef struct { + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +// p_type values +#define PT_NULL 0 /* ignored */ +#define PT_LOAD 1 /* loadable segment */ +#define PT_DYNAMIC 2 /* dynamic linking info */ +#define PT_INTERP 3 /* info about interpreter */ +#define PT_NOTE 4 /* note segment */ +#define PT_SHLIB 5 /* reserved */ +#define PT_PHDR 6 /* Program header table */ +#define PT_MIPS_REGINFO 0x70000000 /* register usage info */ + +// p_flags value +#define PF_X 1 /* execute */ +#define PF_W 2 /* write */ +#define PF_R 4 /* read */ + +// Section header (contains info about section) +typedef struct { + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +// sh_type values +#define SHT_NULL 0 /* Inactive section */ +#define SHT_PROGBITS 1 /* Proprietary */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addend */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Info for dynamic linking */ +#define SHT_NOTE 7 /* Note section */ +#define SHT_NOBITS 8 /* Occupies no space */ +#define SHT_REL 9 /* Relocation entries without addend */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Minimal set of dynamic linking symbols */ +#define SHT_MIPS_LIBLSIT 0x70000000 /* Info about dynamic shared object libs */ +#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicts btw executables and shared objects */ +#define SHT_MIPS_GPTAB 0x70000003 /* Global pointer table */ + +// sh_flags values +#define SHF_WRITE 0 /* writable section */ +#define SHF_ALLOC 2 /* section occupies memory */ +#define SHF_EXECINSTR 4 /* machine instructions */ +#define SHF_MIPS_GPREL 0x10000000 /* Must be made part of global data area */ + + +// Symbol entry (contain info about a symbol) +typedef struct { + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +// Extract from the st_info +#define SYM_TYPE(x) ((x)&0xF) +#define SYM_BIND(x) ((x)>>4) + + +// Symbol binding values from st_info +#define STB_LOCAL 0 /* Symbol not visible outside object */ +#define STB_GLOBAL 1 /* Symbol visible to all object files */ +#define STB_WEAK 2 /* Similar to STB_GLOBAL */ + +// Symbol type values from st_info +#define STT_NOTYPE 0 /* Not specified */ +#define STT_OBJECT 1 /* Data object e.g. variable */ +#define STT_FUNC 2 /* Function */ +#define STT_SECTION 3 /* Section */ +#define STT_FILE 4 /* Source file associated with object file */ + +// Special section header index values from st_shndex +#define SHN_UNDEF 0 +#define SHN_LOPROC 0xFF00 /* Extended values */ +#define SHN_ABS 0xFFF1 /* Absolute value: don't relocate */ +#define SHN_COMMON 0xFFF2 /* Common block. Not allocated yet */ +#define SHN_HIPROC 0xFF1F +#define SHN_HIRESERVE 0xFFFF + +// Relocation entry (info about how to relocate) +typedef struct { + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +// Access macros for the relocation info +#define REL_TYPE(x) ((x)&0xFF) /* Extract relocation type */ +#define REL_INDEX(x) ((x)>>8) /* Extract relocation index into symbol table */ + +// MIPS relocation types +#define R_MIPS_NONE 0 +#define R_MIPS_16 1 +#define R_MIPS_32 2 +#define R_MIPS_REL32 3 +#define R_MIPS_26 4 +#define R_MIPS_HI16 5 +#define R_MIPS_LO16 6 +#define R_MIPS_GPREL16 7 +#define R_MIPS_LITERAL 8 +#define R_MIPS_GOT16 9 +#define R_MIPS_PC16 10 +#define R_MIPS_CALL16 11 +#define R_MIPS_GPREL32 12 +#define R_MIPS_GOTHI16 13 +#define R_MIPS_GOTLO16 14 +#define R_MIPS_CALLHI16 15 +#define R_MIPS_CALLLO16 16 + +// Mock function to get value of global pointer +#define getGP() ({ \ + unsigned int __valgp; \ + __asm__ ("add %0, $gp, $0" : "=r"(__valgp) : ); \ + __valgp; \ +}) + +#endif /* BACKENDS_ELF_H */ diff --git a/backends/platform/ps2/main_prog.ld b/backends/platform/ps2/main_prog.ld new file mode 100644 index 0000000000..de4b534135 --- /dev/null +++ b/backends/platform/ps2/main_prog.ld @@ -0,0 +1,97 @@ +ENTRY(_start); + +SECTIONS { + .text 0x00100000: { + _ftext = . ; + *(.text) + *(.text.*) + *(.gnu.linkonce.t*) + KEEP(*(.init)) + KEEP(*(.fini)) + QUAD(0) + } + + PROVIDE(_etext = .); + PROVIDE(etext = .); + + .reginfo : { *(.reginfo) } + + /* Global/static constructors and deconstructors. */ + .ctors ALIGN(16): { + KEEP(*crtbegin*.o(.ctors)) + KEEP(*(EXCLUDE_FILE(*crtend*.o) .ctors)) + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + } + .dtors ALIGN(16): { + KEEP(*crtbegin*.o(.dtors)) + KEEP(*(EXCLUDE_FILE(*crtend*.o) .dtors)) + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + } + + /* Static data. */ + .rodata ALIGN(128): { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } + + .data ALIGN(128): { + _fdata = . ; + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } + + .rdata ALIGN(128): { *(.rdata) } + .gcc_except_table ALIGN(128): { *(.gcc_except_table) } + + _gp = ALIGN(128) + 0x7ff0; + .lit4 ALIGN(128): { *(.lit4) } + .lit8 ALIGN(128): { *(.lit8) } + + .sdata ALIGN(128): { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s*) + } + + _edata = .; + PROVIDE(edata = .); + + /* Uninitialized data. */ + .sbss ALIGN(128) : { + _fbss = . ; + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb*) + *(.scommon) + } + + __plugin_hole_start = .; + . = _gp + 0x7ff0; + __plugin_hole_end = .; + + COMMON : + { + *(COMMON) + } + . = ALIGN(128); + + .bss ALIGN(128) : { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + } + _end_bss = .; + + _end = . ; + PROVIDE(end = .); + + /* Symbols needed by crt0.s. */ + PROVIDE(_heap_size = -1); + PROVIDE(_stack = -1); + PROVIDE(_stack_size = 128 * 1024); +} diff --git a/backends/platform/ps2/module.mk b/backends/platform/ps2/module.mk index 86b12cb668..69a28b93c4 100644 --- a/backends/platform/ps2/module.mk +++ b/backends/platform/ps2/module.mk @@ -16,7 +16,8 @@ MODULE_OBJS := \ systemps2.o \ ps2mutex.o \ ps2time.o \ - ps2debug.o + ps2debug.o \ + ps2loader.o MODULE_DIRS += \ backends/platform/ps2/ diff --git a/backends/platform/ps2/plugin.ld b/backends/platform/ps2/plugin.ld new file mode 100644 index 0000000000..d6ca6dcfe6 --- /dev/null +++ b/backends/platform/ps2/plugin.ld @@ -0,0 +1,214 @@ +/* Script for -z combreloc: combine and sort reloc sections */ +OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips", + "elf32-littlemips") +OUTPUT_ARCH(mips:5900) +SEARCH_DIR("/home/tony/GSOC/ps2/tools/ee/ee/lib"); +PHDRS +{ + plugin PT_LOAD ; + shorts PT_LOAD ; +} +/* Do we need any of these for elf? + __DYNAMIC = 0; +_DYNAMIC_LINK = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0x100000; + .interp : { *(.interp) } : plugin + .reginfo : { *(.reginfo) } : plugin + .dynamic : { *(.dynamic) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0 + .plt : { *(.plt) } + .text : + { + _ftext = . ; + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.mips16.fn.*) *(.mips16.call.*) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(128) + (. & (128 - 1)); + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } + PROVIDE (__fini_array_end = .); + .data : + { + _fdata = . ; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table) } + .dynamic : { *(.dynamic) } + .ctors : + { + ___plugin_ctors = .; + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __plugin_ctors_end = .; + } + .dtors : + { + ___plugin_dtors = .; + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + ___plugin_dtors_end = .; + } + .jcr : { KEEP (*(.jcr)) } + + . = __plugin_hole_start; + + .got : { *(.got.plt) *(.got) } : shorts + .lit8 : { *(.lit8) } + .lit4 : { *(.lit4) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + _fbss = .; + .sbss : + { + PROVIDE (__sbss_start = .); + PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); + PROVIDE (___sbss_end = .); + } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + } + . = ALIGN(32 / 8); + _end = .; + PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } + + /* Symbols needed by crt0.s */ + PROVIDE(_heap_size = -1); + PROVIDE(_stack = -1); + PROVIDE(_stack_size = 128 * 1024); +} diff --git a/backends/platform/ps2/plugin.syms b/backends/platform/ps2/plugin.syms new file mode 100644 index 0000000000..24ee1a19dc --- /dev/null +++ b/backends/platform/ps2/plugin.syms @@ -0,0 +1,8 @@ +PLUGIN_getVersion +PLUGIN_getType +PLUGIN_getTypeVersion +PLUGIN_getObject +___plugin_ctors +___plugin_ctors_end +___plugin_dtors +___plugin_dtors_end diff --git a/backends/platform/ps2/ps2loader.cpp b/backends/platform/ps2/ps2loader.cpp new file mode 100644 index 0000000000..bea697bf07 --- /dev/null +++ b/backends/platform/ps2/ps2loader.cpp @@ -0,0 +1,721 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#if defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__) + +#include <string.h> +#include <stdarg.h> +#include <stdio.h> +#include <malloc.h> +#include <unistd.h> +#include <sys/_default_fcntl.h> + +#include <ps2utils.h> + +#include "backends/platform/ps2/ps2loader.h" +//#include "backends/platform/ps2/powerman.h" //TODO + +//#define __PS2_DEBUG_PLUGINS__ + +#ifdef __PS2_DEBUG_PLUGINS__ +#define DBG(x,...) fprintf(stderr,x, ## __VA_ARGS__) +#else +#define DBG(x,...) +#endif + +#define seterror(x,...) fprintf(stderr,x, ## __VA_ARGS__) + +extern char __plugin_hole_start; // Indicates start of hole in program file for shorts +extern char __plugin_hole_end; // Indicates end of hole in program file +extern char _gp[]; // Value of gp register + +DECLARE_SINGLETON(ShortSegmentManager) // For singleton + +// Get rid of symbol table in memory +void DLObject::discard_symtab() { + free(_symtab); + free(_strtab); + _symtab = NULL; + _strtab = NULL; + _symbol_cnt = 0; +} + +// Unload all objects from memory +void DLObject::unload() { + discard_symtab(); + free(_segment); + _segment = NULL; + + if (_shortsSegment) { + ShortsMan.deleteSegment(_shortsSegment); + _shortsSegment = NULL; + } +} + +/** + * Follow the instruction of a relocation section. + * + * @param fd File Descriptor + * @param offset Offset into the File + * @param size Size of relocation section + * @param relSegment Base address of relocated segment in memory (memory offset) + * + */ +bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *relSegment) { + Elf32_Rel *rel = NULL; // relocation entry + + // Allocate memory for relocation table + if (!(rel = (Elf32_Rel *)malloc(size))) { + seterror("Out of memory."); + return false; + } + + // Read in our relocation table + if (lseek(fd, offset, SEEK_SET) < 0 || + read(fd, rel, size) != (ssize_t)size) { + seterror("Relocation table load failed."); + free(rel); + return false; + } + + // Treat each relocation entry. Loop over all of them + int cnt = size / sizeof(*rel); + + DBG("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment); + + bool seenHi16 = false; // For treating HI/LO16 commands + int firstHi16 = -1; // Mark the point of the first hi16 seen + Elf32_Addr ahl = 0; // Calculated addend + int a = 0; // Addend: taken from the target + + unsigned int *lastTarget = 0; // For processing hi16 when lo16 arrives + unsigned int relocation = 0; + int debugRelocs[10] = {0}; // For debugging + int extendedHi16 = 0; // Count extended hi16 treatments + Elf32_Addr lastHiSymVal = 0; + bool hi16InShorts = false; + +#define DEBUG_NUM 2 + + // Loop over relocation entries + for (int i = 0; i < cnt; i++) { + // Get the symbol this relocation entry is referring to + Elf32_Sym *sym = (Elf32_Sym *)(_symtab) + (REL_INDEX(rel[i].r_info)); + + // Get the target instruction in the code + unsigned int *target = (unsigned int *)((char *)relSegment + rel[i].r_offset); + + unsigned int origTarget = *target; // Save for debugging + + // Act differently based on the type of relocation + switch (REL_TYPE(rel[i].r_info)) { + + case R_MIPS_HI16: // Absolute addressing. + if (sym->st_shndx < SHN_LOPROC && // Only shift for plugin section (ie. has a real section index) + firstHi16 < 0) { // Only process first in block of HI16s + firstHi16 = i; // Keep the first Hi16 we saw + seenHi16 = true; + ahl = (*target & 0xffff) << 16; // Take lower 16 bits shifted up + + lastHiSymVal = sym->st_value; + hi16InShorts = (ShortsMan.inGeneralSegment((char *)sym->st_value)); // Fix for problem with switching btw segments + if (debugRelocs[0]++ < DEBUG_NUM) // Print only a set number + DBG("R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x\n", + i, rel[i].r_offset, ahl, *target); + } + break; + + case R_MIPS_LO16: // Absolute addressing. Needs a HI16 to come before it + if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section. (ie. has a real section index) + if (!seenHi16) { // We MUST have seen HI16 first + seterror("R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!\n", i); + free(rel); + return false; + } + + // Fix: bug in gcc makes LO16s connect to wrong HI16s sometimes (shorts and regular segment) + // Note that we can check the entire shorts segment because the executable's shorts don't belong to this plugin section + // and will be screened out above + bool lo16InShorts = ShortsMan.inGeneralSegment((char *)sym->st_value); + + // Correct the bug by getting the proper value in ahl (taken from the current symbol) + if ((hi16InShorts && !lo16InShorts) || (!hi16InShorts && lo16InShorts)) { + ahl -= (lastHiSymVal & 0xffff0000); // We assume gcc meant the same offset + ahl += (sym->st_value & 0xffff0000); + } + + ahl &= 0xffff0000; // Clean lower 16 bits for repeated LO16s + a = *target & 0xffff; // Take lower 16 bits of the target + a = (a << 16) >> 16; // Sign extend them + ahl += a; // Add lower 16 bits. AHL is now complete + + // Fix: we can have LO16 access to the short segment sometimes + if (lo16InShorts) { + relocation = ahl + _shortsSegment->getOffset(); // Add in the short segment offset + } else // It's in the regular segment + relocation = ahl + (Elf32_Addr)_segment; // Add in the new offset for the segment + + if (firstHi16 >= 0) { // We haven't treated the HI16s yet so do it now + for (int j = firstHi16; j < i; j++) { + if (REL_TYPE(rel[j].r_info) != R_MIPS_HI16) continue; // Skip over non-Hi16s + + lastTarget = (unsigned int *)((char *)relSegment + rel[j].r_offset); // get hi16 target + *lastTarget &= 0xffff0000; // Clear the lower 16 bits of the last target + *lastTarget |= (relocation >> 16) & 0xffff; // Take the upper 16 bits of the relocation + if (relocation & 0x8000)(*lastTarget)++; // Subtle: we need to add 1 to the HI16 in this case + } + firstHi16 = -1; // Reset so we'll know we treated it + } else { + extendedHi16++; + } + + *target &= 0xffff0000; // Clear the lower 16 bits of current target + *target |= relocation & 0xffff; // Take the lower 16 bits of the relocation + + if (debugRelocs[1]++ < DEBUG_NUM) + DBG("R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n", + i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target); + if (lo16InShorts && debugRelocs[2]++ < DEBUG_NUM) + DBG("R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n", + i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target); + } + break; + + case R_MIPS_26: // Absolute addressing (for jumps and branches only) + if (sym->st_shndx < SHN_LOPROC) { // Only relocate for main segment + a = *target & 0x03ffffff; // Get 26 bits' worth of the addend + a = (a << 6) >> 6; // Sign extend a + relocation = ((a << 2) + (Elf32_Addr)_segment) >> 2; // a already points to the target. Subtract our offset + *target &= 0xfc000000; // Clean lower 26 target bits + *target |= (relocation & 0x03ffffff); + + if (debugRelocs[3]++ < DEBUG_NUM) + DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n", + i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target); + } else { + if (debugRelocs[4]++ < DEBUG_NUM) + DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n", + i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target); + } + break; + + case R_MIPS_GPREL16: // GP Relative addressing + if (_shortsSegment->getOffset() != 0 && // Only relocate if we shift the shorts section + ShortsMan.inGeneralSegment((char *)sym->st_value)) { // Only relocate things in the plugin hole + a = *target & 0xffff; // Get 16 bits' worth of the addend + a = (a << 16) >> 16; // Sign extend it + + relocation = a + _shortsSegment->getOffset(); + + *target &= 0xffff0000; // Clear the lower 16 bits of the target + *target |= relocation & 0xffff; + + if (debugRelocs[5]++ < DEBUG_NUM) + DBG("R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x\n", + i, a, _gpVal, origTarget, *target, _shortsSegment->getOffset()); + } + + break; + + case R_MIPS_32: // Absolute addressing + if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section. + a = *target; // Get full 32 bits of addend + + if (ShortsMan.inGeneralSegment((char *)sym->st_value)) // Check if we're in the shorts segment + relocation = a + _shortsSegment->getOffset(); // Shift by shorts offset + else // We're in the main section + relocation = a + (Elf32_Addr)_segment; // Shift by main offset + *target = relocation; + + if (debugRelocs[6]++ < DEBUG_NUM) + DBG("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target); + } + break; + + default: + seterror("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i); + free(rel); + return false; + } + } + + DBG("Done with relocation. extendedHi16=%d\n\n", extendedHi16); + + free(rel); + return true; +} + +bool DLObject::readElfHeader(int fd, Elf32_Ehdr *ehdr) { + // Start reading the elf header. Check for errors + if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr) || + memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || // Check MAGIC + ehdr->e_type != ET_EXEC || // Check for executable + ehdr->e_machine != EM_MIPS || // Check for MIPS machine type + ehdr->e_phentsize < sizeof(Elf32_Phdr) || // Check for size of program header + ehdr->e_shentsize != sizeof(Elf32_Shdr)) { // Check for size of section header + seterror("Invalid file type."); + return false; + } + + DBG("phoff = %d, phentsz = %d, phnum = %d\n", + ehdr->e_phoff, ehdr->e_phentsize, ehdr->e_phnum); + + return true; +} + +bool DLObject::readProgramHeaders(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, int num) { + // Read program header + if (lseek(fd, ehdr->e_phoff + sizeof(*phdr)*num, SEEK_SET) < 0 || + read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr)) { + seterror("Program header load failed."); + return false; + } + + // Check program header values + if (phdr->p_type != PT_LOAD || phdr->p_filesz > phdr->p_memsz) { + seterror("Invalid program header."); + return false; + } + + DBG("offs = %x, filesz = %x, memsz = %x, align = %x\n", + phdr->p_offset, phdr->p_filesz, phdr->p_memsz, phdr->p_align); + + return true; + +} + +bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) { + + char *baseAddress = 0; + + // We need to take account of non-allocated segment for shorts + if (phdr->p_flags & PF_X) { // This is a relocated segment + + // Attempt to allocate memory for segment + int extra = phdr->p_vaddr % phdr->p_align; // Get extra length TODO: check logic here + DBG("extra mem is %x\n", extra); + + if (phdr->p_align < 0x10000) phdr->p_align = 0x10000; // Fix for wrong alignment on e.g. AGI + + if (!(_segment = (char *)memalign(phdr->p_align, phdr->p_memsz + extra))) { + seterror("Out of memory.\n"); + return false; + } + DBG("allocated segment @ %p\n", _segment); + + // Get offset to load segment into + baseAddress = (char *)_segment + phdr->p_vaddr; + _segmentSize = phdr->p_memsz + extra; + } else { // This is a shorts section. + _shortsSegment = ShortsMan.newSegment(phdr->p_memsz, (char *)phdr->p_vaddr); + + baseAddress = _shortsSegment->getStart(); + DBG("shorts segment @ %p to %p. Segment wants to be at %x. Offset=%x\n", + _shortsSegment->getStart(), _shortsSegment->getEnd(), phdr->p_vaddr, _shortsSegment->getOffset()); + + } + + // Set bss segment to 0 if necessary (assumes bss is at the end) + if (phdr->p_memsz > phdr->p_filesz) { + DBG("Setting %p to %p to 0 for bss\n", baseAddress + phdr->p_filesz, baseAddress + phdr->p_memsz); + memset(baseAddress + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); + } + // Read the segment into memory + if (lseek(fd, phdr->p_offset, SEEK_SET) < 0 || + read(fd, baseAddress, phdr->p_filesz) != (ssize_t)phdr->p_filesz) { + seterror("Segment load failed."); + return false; + } + + return true; +} + + +Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) { + + Elf32_Shdr *shdr = NULL; + + // Allocate memory for section headers + if (!(shdr = (Elf32_Shdr *)malloc(ehdr->e_shnum * sizeof(*shdr)))) { + seterror("Out of memory."); + return NULL; + } + + // Read from file into section headers + if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0 || + read(fd, shdr, ehdr->e_shnum * sizeof(*shdr)) != + (ssize_t)(ehdr->e_shnum * sizeof(*shdr))) { + seterror("Section headers load failed."); + return NULL; + } + + return shdr; +} + +int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { + + // Loop over sections, looking for symbol table linked to a string table + for (int i = 0; i < ehdr->e_shnum; i++) { + //DBG("Section %d: type = %x, size = %x, entsize = %x, link = %x\n", + // i, shdr[i].sh_type, shdr[i].sh_size, shdr[i].sh_entsize, shdr[i].sh_link); + + if (shdr[i].sh_type == SHT_SYMTAB && + shdr[i].sh_entsize == sizeof(Elf32_Sym) && + shdr[i].sh_link < ehdr->e_shnum && + shdr[shdr[i].sh_link].sh_type == SHT_STRTAB && + _symtab_sect < 0) { + _symtab_sect = i; + } + } + + // Check for no symbol table + if (_symtab_sect < 0) { + seterror("No symbol table."); + return -1; + } + + DBG("Symbol section at section %d, size %x\n", _symtab_sect, shdr[_symtab_sect].sh_size); + + // Allocate memory for symbol table + if (!(_symtab = malloc(shdr[_symtab_sect].sh_size))) { + seterror("Out of memory."); + return -1; + } + + // Read symbol table into memory + if (lseek(fd, shdr[_symtab_sect].sh_offset, SEEK_SET) < 0 || + read(fd, _symtab, shdr[_symtab_sect].sh_size) != + (ssize_t)shdr[_symtab_sect].sh_size) { + seterror("Symbol table load failed."); + return -1; + } + + // Set number of symbols + _symbol_cnt = shdr[_symtab_sect].sh_size / sizeof(Elf32_Sym); + DBG("Loaded %d symbols.\n", _symbol_cnt); + + return _symtab_sect; + +} + +bool DLObject::loadStringTable(int fd, Elf32_Shdr *shdr) { + + int string_sect = shdr[_symtab_sect].sh_link; + + // Allocate memory for string table + if (!(_strtab = (char *)malloc(shdr[string_sect].sh_size))) { + seterror("Out of memory."); + return false; + } + + // Read string table into memory + if (lseek(fd, shdr[string_sect].sh_offset, SEEK_SET) < 0 || + read(fd, _strtab, shdr[string_sect].sh_size) != + (ssize_t)shdr[string_sect].sh_size) { + seterror("Symbol table strings load failed."); + return false; + } + return true; +} + +void DLObject::relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset) { + + int shortsCount = 0, othersCount = 0; + DBG("Relocating symbols by %x. Shorts offset=%x\n", offset, shortsOffset); + + // Loop over symbols, add relocation offset + Elf32_Sym *s = (Elf32_Sym *)_symtab; + for (int c = _symbol_cnt; c--; s++) { + // Make sure we don't relocate special valued symbols + if (s->st_shndx < SHN_LOPROC) { + if (!ShortsMan.inGeneralSegment((char *)s->st_value)) { + othersCount++; + s->st_value += offset; + if (s->st_value < (Elf32_Addr)_segment || s->st_value > (Elf32_Addr)_segment + _segmentSize) + seterror("Symbol out of bounds! st_value = %x\n", s->st_value); + } else { // shorts section + shortsCount++; + s->st_value += shortsOffset; + if (!_shortsSegment->inSegment((char *)s->st_value)) + seterror("Symbol out of bounds! st_value = %x\n", s->st_value); + } + + } + + } + + DBG("Relocated %d short symbols, %d others.\n", shortsCount, othersCount); +} + +bool DLObject::relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { + + // Loop over sections, finding relocation sections + for (int i = 0; i < ehdr->e_shnum; i++) { + + Elf32_Shdr *curShdr = &(shdr[i]); + //Elf32_Shdr *linkShdr = &(shdr[curShdr->sh_info]); + + if (curShdr->sh_type == SHT_REL && // Check for a relocation section + curShdr->sh_entsize == sizeof(Elf32_Rel) && // Check for proper relocation size + (int)curShdr->sh_link == _symtab_sect && // Check that the sh_link connects to our symbol table + curShdr->sh_info < ehdr->e_shnum && // Check that the relocated section exists + (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) { // Check if relocated section resides in memory + if (!ShortsMan.inGeneralSegment((char *)shdr[curShdr->sh_info].sh_addr)) { // regular segment + if (!relocate(fd, curShdr->sh_offset, curShdr->sh_size, _segment)) { + return false; + } + } else { // In Shorts segment + if (!relocate(fd, curShdr->sh_offset, curShdr->sh_size, (void *)_shortsSegment->getOffset())) { + return false; + } + } + + } + } + + return true; +} + + +bool DLObject::load(int fd) { + fprintf(stderr, "In DLObject::load\n"); + + Elf32_Ehdr ehdr; // ELF header + Elf32_Phdr phdr; // Program header + Elf32_Shdr *shdr; // Section header + bool ret = true; + + if (readElfHeader(fd, &ehdr) == false) { + return false; + } + + for (int i = 0; i < ehdr.e_phnum; i++) { // Load our 2 segments + + fprintf(stderr, "Loading segment %d\n", i); + + if (readProgramHeaders(fd, &ehdr, &phdr, i) == false) + return false; + + if (!loadSegment(fd, &phdr)) + return false; + } + + if ((shdr = loadSectionHeaders(fd, &ehdr)) == NULL) + ret = false; + + if (ret && ((_symtab_sect = loadSymbolTable(fd, &ehdr, shdr)) < 0)) + ret = false; + + if (ret && (loadStringTable(fd, shdr) == false)) + ret = false; + + if (ret) + relocateSymbols((Elf32_Addr)_segment, _shortsSegment->getOffset()); // Offset by our segment allocated address + + if (ret && (relocateRels(fd, &ehdr, shdr) == false)) + ret = false; + + free(shdr); + + return ret; +} + +bool DLObject::open(const char *path) { + int fd; + void *ctors_start, *ctors_end; + + DBG("open(\"%s\")\n", path); + + // Get the address of the global pointer + _gpVal = (unsigned int) & _gp; + DBG("_gpVal is %x\n", _gpVal); + + PowerMan.beginCriticalSection(); + + if ((fd = ::open(path, O_RDONLY)) < 0) { + seterror("%s not found.", path); + return false; + } + + // Try to load and relocate + if (!load(fd)) { + ::close(fd); + unload(); + return false; + } + + ::close(fd); + + PowerMan.endCriticalSection(); + + // flush data cache + sceKernelDcacheWritebackAll(); + + // Get the symbols for the global constructors and destructors + ctors_start = symbol("___plugin_ctors"); + ctors_end = symbol("___plugin_ctors_end"); + _dtors_start = symbol("___plugin_dtors"); + _dtors_end = symbol("___plugin_dtors_end"); + + if (ctors_start == NULL || ctors_end == NULL || _dtors_start == NULL || + _dtors_end == NULL) { + seterror("Missing ctors/dtors."); + _dtors_start = _dtors_end = NULL; + unload(); + return false; + } + + DBG("Calling constructors.\n"); + for (void (**f)(void) = (void (**)(void))ctors_start; f != ctors_end; f++) + (**f)(); + + DBG("%s opened ok.\n", path); + return true; +} + +bool DLObject::close() { + if (_dtors_start != NULL && _dtors_end != NULL) + for (void (**f)(void) = (void (**)(void))_dtors_start; f != _dtors_end; f++) + (**f)(); + _dtors_start = _dtors_end = NULL; + unload(); + return true; +} + +void *DLObject::symbol(const char *name) { + DBG("symbol(\"%s\")\n", name); + + if (_symtab == NULL || _strtab == NULL || _symbol_cnt < 1) { + seterror("No symbol table loaded."); + return NULL; + } + + Elf32_Sym *s = (Elf32_Sym *)_symtab; + for (int c = _symbol_cnt; c--; s++) { + + // We can only import symbols that are global or weak in the plugin + if ((SYM_BIND(s->st_info) == STB_GLOBAL || SYM_BIND(s->st_info) == STB_WEAK) && + /*_strtab[s->st_name] == '_' && */ // Try to make this more efficient + !strcmp(name, _strtab + s->st_name)) { + + // We found the symbol + DBG("=> %p\n", (void*)s->st_value); + return (void*)s->st_value; + } + } + + seterror("Symbol \"%s\" not found.", name); + return NULL; +} + + + +ShortSegmentManager::ShortSegmentManager() { + _shortsStart = &__plugin_hole_start ; + _shortsEnd = &__plugin_hole_end; +} + +ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *origAddr) { + char *lastAddress = origAddr; + Common::List<Segment *>::iterator i; + + // Find a block that fits, starting from the beginning + for (i = _list.begin(); i != _list.end(); ++i) { + char *currAddress = (*i)->getStart(); + + if ((int)(currAddress - lastAddress) >= size) break; + + lastAddress = (*i)->getEnd(); + } + + if ((Elf32_Addr)lastAddress & 3) + lastAddress += 4 - ((Elf32_Addr)lastAddress & 3); // Round up to multiple of 4 + + if (lastAddress + size > _shortsEnd) { + seterror("Error. No space in shorts segment for %x bytes. Last address is %p, max address is %p.\n", + size, lastAddress, _shortsEnd); + return NULL; + } + + Segment *seg = new Segment(lastAddress, size, origAddr); // Create a new segment + + if (lastAddress + size > _highestAddress) _highestAddress = lastAddress + size; // Keep track of maximum + + _list.insert(i, seg); + + DBG("Shorts segment size %x allocated. End = %p. Remaining space = %x. Highest so far is %p.\n", + size, lastAddress + size, _shortsEnd - _list.back()->getEnd(), _highestAddress); + + return seg; +} + +void ShortSegmentManager::deleteSegment(ShortSegmentManager::Segment *seg) { + DBG("Deleting shorts segment from %p to %p.\n\n", seg->getStart(), seg->getEnd()); + _list.remove(seg); + delete seg; +} + +static char dlerr[MAXDLERRLEN]; + +void *dlopen(const char *filename, int flags) { + DLObject *obj = new DLObject(dlerr); + if (obj->open(filename)) + return (void *)obj; + delete obj; + return NULL; +} + +int dlclose(void *handle) { + DLObject *obj = (DLObject *)handle; + if (obj == NULL) { + strcpy(dlerr, "Handle is NULL."); + return -1; + } + if (obj->close()) { + delete obj; + return 0; + } + return -1; +} + +void *dlsym(void *handle, const char *symbol) { + if (handle == NULL) { + strcpy(dlerr, "Handle is NULL."); + return NULL; + } + return ((DLObject *)handle)->symbol(symbol); +} + +const char *dlerror() { + return dlerr; +} + +void dlforgetsyms(void *handle) { + if (handle != NULL) + ((DLObject *)handle)->discard_symtab(); +} + + +#endif /* DYNAMIC_MODULES && __PLAYSTATION2__ */ diff --git a/backends/platform/ps2/ps2loader.h b/backends/platform/ps2/ps2loader.h new file mode 100644 index 0000000000..7c412e7b05 --- /dev/null +++ b/backends/platform/ps2/ps2loader.h @@ -0,0 +1,137 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef PS2LOADER_H +#define PS2LOADER_H + +#include "elf32.h" +#include "common/list.h" +#include "common/singleton.h" + +#define MAXDLERRLEN 80 + +#define ShortsMan ShortSegmentManager::instance() + +class ShortSegmentManager : public Common::Singleton<ShortSegmentManager> { +private: + char *_shortsStart; + char *_shortsEnd; + +public: + char *getShortsStart() { + return _shortsStart; + } + bool inGeneralSegment(char *addr) { + return ((char *)addr >= _shortsStart && (char *)addr < _shortsEnd); + } + + class Segment { + private: + friend class ShortSegmentManager; + Segment(char *start, int size, char *origAddr) : _startAddress(start), _size(size), _origAddress(origAddr) {} + ~Segment() {} + char *_startAddress; // Start of shorts segment in memory + int _size; // Size of shorts segment + char *_origAddress; // Original address this segment was supposed to be at + public: + char *getStart() { + return _startAddress; + } + char *getEnd() { + return (_startAddress + _size); + } + Elf32_Addr getOffset() { + return (Elf32_Addr)(_startAddress - _origAddress); + } + bool inSegment(char *addr) { + return ((char *)addr >= _startAddress && (char *)addr <= _startAddress + _size); + } + }; + + Segment *newSegment(int size, char *origAddr); + void deleteSegment(Segment *); + +private: + ShortSegmentManager(); + friend class Common::Singleton<ShortSegmentManager>; + Common::List<Segment *> _list; + char *_highestAddress; +}; + + + + +class DLObject { +protected: + char *_errbuf; /* For error messages, at least MAXDLERRLEN in size */ + + ShortSegmentManager::Segment *_shortsSegment; // For assigning shorts ranges + void *_segment, *_symtab; + char *_strtab; + int _symbol_cnt; + int _symtab_sect; + void *_dtors_start, *_dtors_end; + + unsigned int _gpVal; // Value of Global Pointer + int _segmentSize; + + void seterror(const char *fmt, ...); + void unload(); + bool relocate(int fd, unsigned long offset, unsigned long size, void *); + bool load(int fd); + + bool readElfHeader(int fd, Elf32_Ehdr *ehdr); + bool readProgramHeaders(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, int num); + bool loadSegment(int fd, Elf32_Phdr *phdr); + Elf32_Shdr *loadSectionHeaders(int fd, Elf32_Ehdr *ehdr); + int loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr); + bool loadStringTable(int fd, Elf32_Shdr *shdr); + void relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset); + bool relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr); + +public: + bool open(const char *path); + bool close(); + void *symbol(const char *name); + void discard_symtab(); + + DLObject(char *errbuf = NULL) : _errbuf(_errbuf), _shortsSegment(NULL), _segment(NULL), _symtab(NULL), + _strtab(NULL), _symbol_cnt(0), _symtab_sect(-1), _dtors_start(NULL), _dtors_end(NULL), _gpVal(0) , + _segmentSize(0) {} +}; + + + +#define RTLD_LAZY 0 + +extern "C" { + void *dlopen(const char *filename, int flags); + int dlclose(void *handle); + void *dlsym(void *handle, const char *symbol); + const char *dlerror(); + void dlforgetsyms(void *handle); +} + +#endif /* PS2LOADER_H */ diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp index 7659d5194d..120f6ee157 100644 --- a/backends/platform/ps2/systemps2.cpp +++ b/backends/platform/ps2/systemps2.cpp @@ -59,6 +59,8 @@ #include "backends/platform/ps2/ps2debug.h" #include "backends/fs/ps2/ps2-fs-factory.h" +#include "backends/plugins/ps2/ps2-provider.h" + #include "backends/saves/default/default-saves.h" #include "common/config-manager.h" @@ -132,6 +134,10 @@ extern "C" int main(int argc, char *argv[]) { g_systemPs2->init(); +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new PS2PluginProvider()); +#endif + sioprintf("init done. starting ScummVM.\n"); int res = scummvm_main(argc, argv); sioprintf("scummvm_main terminated: %d\n", res); diff --git a/backends/platform/psp/Makefile b/backends/platform/psp/Makefile index 7f8bb63b0a..8e83563d10 100644 --- a/backends/platform/psp/Makefile +++ b/backends/platform/psp/Makefile @@ -129,8 +129,7 @@ SDLFLAGS := $(shell $(PSPBIN)/sdl-config --cflags) SDLLIBS := $(shell $(PSPBIN)/sdl-config --libs) # PSP LIBS PSPLIBS = -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk \ - -lpsputility -lpspuser -lpsppower -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lpspaudiocodec \ - -lpspkernel + -lpsputility -lpspuser -lpsppower -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lpspkernel # Add in PSPSDK includes and libraries. CXXFLAGS += $(SDLFLAGS) @@ -148,10 +147,8 @@ OBJS := powerman.o \ cursor.o \ trace.o \ psploader.o \ - pspkeyboard.o \ - audio.o \ - thread.o \ - mp3.o + pspkeyboard.o + # Include common Scummvm makefile include $(srcdir)/Makefile.common diff --git a/backends/platform/psp/audio.cpp b/backends/platform/psp/audio.cpp deleted file mode 100644 index bf1fb9ab41..0000000000 --- a/backends/platform/psp/audio.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ - * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ - * - */ - -#include <pspthreadman.h> -#include <pspaudio.h> - -#include "common/scummsys.h" -#include "backends/platform/psp/audio.h" -#include "backends/platform/psp/thread.h" - -//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */ -//#define __PSP_DEBUG_PRINT__ /* For debug printouts */ - -#include "backends/platform/psp/trace.h" - -bool PspAudio::open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, callbackFunc callback, void *userData) { - DEBUG_ENTER_FUNC(); - if (_init) { - PSP_ERROR("audio device already initialized\n"); - return true; - } - - PSP_DEBUG_PRINT("freq[%d], numOfChannels[%d], numOfSamples[%d], callback[%p], userData[%x]\n", - freq, numOfChannels, numOfSamples, callback, (uint32)userData); - - numOfSamples = PSP_AUDIO_SAMPLE_ALIGN(numOfSamples); - uint32 bufLen = numOfSamples * numOfChannels * NUM_BUFFERS * sizeof(uint16); - - PSP_DEBUG_PRINT("total buffer size[%d]\n", bufLen); - - _buffers[0] = (byte *)memalign(64, bufLen); - if (!_buffers[0]) { - PSP_ERROR("failed to allocate memory for audio buffers\n"); - return false; - } - memset(_buffers[0], 0, bufLen); // clean the buffer - - // Fill in the rest of the buffer pointers - byte *pBuffer = _buffers[0]; - for (int i = 1; i < NUM_BUFFERS; i++) { - pBuffer += numOfSamples * numOfChannels * sizeof(uint16); - _buffers[i] = pBuffer; - } - - // Reserve a HW channel for our audio - _pspChannel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, numOfSamples, numOfChannels == 2 ? PSP_AUDIO_FORMAT_STEREO : PSP_AUDIO_FORMAT_MONO); - if (_pspChannel < 0) { - PSP_ERROR("failed to reserve audio channel\n"); - return false; - } - - PSP_DEBUG_PRINT("reserved channel[%d] for audio\n", _pspChannel); - - // Save our data - _numOfChannels = numOfChannels; - _numOfSamples = numOfSamples; - _bufferSize = numOfSamples * numOfChannels * sizeof(uint16); // should be the right size to send the app - _callback = callback; - _userData = userData; - _bufferToFill = 0; - _bufferToPlay = 0; - - _init = true; - _paused = true; // start in paused mode - - createThread(); - - return true; -} - -bool PspAudio::createThread() { - DEBUG_ENTER_FUNC(); - int threadId = sceKernelCreateThread("audioThread", thread, PRIORITY_AUDIO_THREAD, STACK_AUDIO_THREAD, THREAD_ATTR_USER, 0); - - if (threadId < 0) { // error - PSP_ERROR("failed to create audio thread. Error code %d\n", threadId); - return false; - } - - PspAudio *_this = this; // trick to get into context when the thread starts - - if (sceKernelStartThread(threadId, sizeof(uint32 *), &_this) < 0) { - PSP_ERROR("failed to start thread %d\n", threadId); - return false; - } - - PSP_DEBUG_PRINT("created audio thread[%x]\n", threadId); - - return true; -} - -// Static function to be called upon thread startup. Will call a non-static function -int PspAudio::thread(SceSize, void *__this) { - DEBUG_ENTER_FUNC(); - PspAudio *_this = *(PspAudio **)__this; // get our this for the context - - _this->audioThread(); - return 0; -}; - -// The real thread function -void PspAudio::audioThread() { - assert(_callback); - PSP_DEBUG_PRINT_FUNC("audio thread started\n"); - - while (_init) { // Keep looping so long as we haven't been told to stop - if (_paused) - PSP_DEBUG_PRINT("audio thread paused\n"); - while (_paused) { // delay until we stop pausing - sceKernelDelayThread(100000); // 100ms - if (!_paused) - PSP_DEBUG_PRINT("audio thread unpaused\n"); - } - - PSP_DEBUG_PRINT("remaining samples[%d]\n", remainingSamples); - - PSP_DEBUG_PRINT("filling buffer[%d]\n", _bufferToFill); - _callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in - nextBuffer(_bufferToFill); - - PSP_DEBUG_PRINT("playing buffer[%d].\n", _bufferToPlay); - playBuffer(); - nextBuffer(_bufferToPlay); - } // while _init - - // destroy everything - free(_buffers[0]); - sceAudioChRelease(_pspChannel); - PSP_DEBUG_PRINT("audio thread exiting. ****************************\n"); -} - -// Much faster than using % -inline void PspAudio::nextBuffer(int &bufferIdx) { - DEBUG_ENTER_FUNC(); - bufferIdx++; - if (bufferIdx >= NUM_BUFFERS) - bufferIdx = 0; -} - -// Don't do it with blocking -inline bool PspAudio::playBuffer() { - DEBUG_ENTER_FUNC(); - int ret; - if (_numOfChannels == 1) - ret = sceAudioOutputBlocking(_pspChannel, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]); - else - ret = sceAudioOutputPannedBlocking(_pspChannel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]); - - if (ret < 0) { - PSP_ERROR("failed to output audio. Error[%d]\n", ret); - return false; - } - return true; -} - -void PspAudio::close() { - PSP_DEBUG_PRINT("close had been called ***************\n"); - _init = false; -} diff --git a/backends/platform/psp/audio.h b/backends/platform/psp/audio.h deleted file mode 100644 index 603f8f6bfc..0000000000 --- a/backends/platform/psp/audio.h +++ /dev/null @@ -1,69 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ - * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ - * - */ - -#ifndef PSP_AUDIO_H -#define PSP_AUDIO_H - -class PspAudio { -public: - enum { - NUM_BUFFERS = 2, - FREQUENCY = 44100 /* only frequency we allow */ - }; - typedef void (* callbackFunc)(void *userData, byte *samples, int len); - PspAudio() : _pspChannel(0), - _numOfChannels(0), _numOfSamples(0), _callback(0), - _bufferToPlay(0), _bufferToFill(0), - _init(false), _paused(true) { - for (int i=0; i<NUM_BUFFERS; i++) - _buffers[i] = 0; - } - ~PspAudio() { close(); } - bool playBuffer(); - void nextBuffer(int &bufferIdx); - static int thread(SceSize, void *); - void audioThread(); - bool open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, callbackFunc callback, void *userData); - bool createThread(); - void close(); - uint32 getFrequency() { return FREQUENCY; } - void pause() { _paused = true; } - void unpause() { _paused = false; } - -private: - int _pspChannel; // chosen hardware output channel - uint32 _numOfChannels; // 1 for mono; 2 for stereo - uint32 _numOfSamples; - callbackFunc _callback; // the callback to call between outputting audio - void *_userData; // userData to send with callback - byte *_buffers[NUM_BUFFERS]; - int _bufferToPlay; // the next buffer to output - int _bufferToFill; - int _bufferSize; - bool _init; // flag for initialization - bool _paused; -}; - -#endif /* PSP_AUDIO_H */ diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp index c5a6250188..90c41e796d 100644 --- a/backends/platform/psp/display_client.cpp +++ b/backends/platform/psp/display_client.cpp @@ -686,18 +686,17 @@ void GuRenderer::fillVertices(Vertex *vertices) { uint32 gapX = _useGlobalScaler ? (PSP_SCREEN_WIDTH - outputWidth) >> 1 : 0; uint32 gapY = _useGlobalScaler ? (PSP_SCREEN_HEIGHT - outputHeight) >> 1 : 0; - // Save scaled offset on screen - float scaledOffsetOnScreenX = scaleSourceToOutputX(_offsetOnScreen.x); - float scaledOffsetOnScreenY = scaleSourceToOutputY(_offsetOnScreen.y); - float imageStartX, imageStartY, imageEndX, imageEndY; - imageStartX = gapX + scaledOffsetOnScreenX + (scaleSourceToOutputX(_maxTextureOffset.x)); - imageStartY = gapY + scaledOffsetOnScreenY; + imageStartX = gapX + (scaleSourceToOutputX(_maxTextureOffset.x)); + imageStartY = gapY; + + imageStartX += scaleSourceToOutputX(_offsetOnScreen.x); + imageStartY += scaleSourceToOutputY(_offsetOnScreen.y); if (_fullScreen) { // shortcut - imageEndX = PSP_SCREEN_WIDTH - gapX + scaledOffsetOnScreenX; - imageEndY = PSP_SCREEN_HEIGHT - gapY + scaledOffsetOnScreenY; // needed for screen shake + imageEndX = PSP_SCREEN_WIDTH - gapX; + imageEndY = PSP_SCREEN_HEIGHT - gapY; } else { /* !fullScreen */ imageEndX = imageStartX + scaleSourceToOutputX(_drawSize.width); imageEndY = imageStartY + scaleSourceToOutputY(_drawSize.height); diff --git a/backends/platform/psp/display_manager.cpp b/backends/platform/psp/display_manager.cpp index c2f21e084b..0982512a86 100644 --- a/backends/platform/psp/display_manager.cpp +++ b/backends/platform/psp/display_manager.cpp @@ -34,7 +34,6 @@ #include "backends/platform/psp/default_display_client.h" #include "backends/platform/psp/cursor.h" #include "backends/platform/psp/pspkeyboard.h" -#include "backends/platform/psp/thread.h" #define USE_DISPLAY_CALLBACK // to use callback for finishing the render #include "backends/platform/psp/display_manager.h" @@ -65,7 +64,7 @@ const OSystem::GraphicsMode DisplayManager::_supportedModes[] = { void MasterGuRenderer::setupCallbackThread() { DEBUG_ENTER_FUNC(); - int thid = sceKernelCreateThread("displayCbThread", guCallbackThread, PRIORITY_DISPLAY_THREAD, STACK_DISPLAY_THREAD, THREAD_ATTR_USER, 0); + int thid = sceKernelCreateThread("displayCbThread", guCallbackThread, 0x11, 4*1024, THREAD_ATTR_USER, 0); PSP_DEBUG_PRINT("Display CB thread id is %x\n", thid); diff --git a/backends/platform/psp/module.mk b/backends/platform/psp/module.mk index 99170ce7fb..f7191fe14f 100644 --- a/backends/platform/psp/module.mk +++ b/backends/platform/psp/module.mk @@ -12,10 +12,7 @@ MODULE_OBJS := powerman.o \ cursor.o \ trace.o \ psploader.o \ - pspkeyboard.o \ - audio.o \ - thread.o \ - mp3.o + pspkeyboard.o MODULE_DIRS += \ backends/platform/psp/ diff --git a/backends/platform/psp/mp3.cpp b/backends/platform/psp/mp3.cpp deleted file mode 100644 index 972c5a8ba8..0000000000 --- a/backends/platform/psp/mp3.cpp +++ /dev/null @@ -1,487 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - - -#include "common/debug.h" -#include "common/stream.h" -#include "common/util.h" -#include "common/singleton.h" -#include "common/mutex.h" - -#include "sound/audiostream.h" - -#include <pspaudiocodec.h> -#include <psputility_modules.h> -#include <pspthreadman.h> -#include <pspsysmem.h> -#include <pspmodulemgr.h> -#include <psputility_avmodules.h> -#include <mad.h> -#include "backends/platform/psp/mp3.h" - -//#define DISABLE_PSP_MP3 // to make us use the regular MAD decoder instead - -//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ -//#define __PSP_DEBUG_PRINT__ -#include "backends/platform/psp/trace.h" - -//#define PRINT_BUFFERS /* to debug MP3 buffers */ - -namespace Audio { - -class Mp3PspStream; - -bool Mp3PspStream::_decoderInit = false; // has the decoder been initialized -#ifdef DISABLE_PSP_MP3 -bool Mp3PspStream::_decoderFail = true; // pretend the decoder failed -#else -bool Mp3PspStream::_decoderFail = false; // has the decoder failed to load -#endif - -bool Mp3PspStream::initDecoder() { - DEBUG_ENTER_FUNC(); - - if (_decoderInit) { - PSP_ERROR("Already initialized!"); - return true; - } - - // Based on PSP firmware version, we need to do different things to do Media Engine processing - uint32 firmware = sceKernelDevkitVersion(); - PSP_DEBUG_PRINT("Firmware version 0x%x\n", firmware); - if (firmware == 0x01050001){ - if (!loadStartAudioModule((char *)(void *)"flash0:/kd/me_for_vsh.prx", - PSP_MEMORY_PARTITION_KERNEL)) { - PSP_ERROR("failed to load me_for_vsh.prx. ME cannot start.\n"); - _decoderFail = true; - return false; - } - if (!loadStartAudioModule((char *)(void *)"flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL)) { - PSP_ERROR("failed to load audiocodec.prx. ME cannot start.\n"); - _decoderFail = true; - return false; - } - } else { - if (sceUtilityLoadAvModule(PSP_AV_MODULE_AVCODEC) < 0) { - PSP_ERROR("failed to load AVCODEC module.\n"); - _decoderFail = true; - return false; - } - } - - PSP_INFO_PRINT("Using PSP's ME for MP3\n"); // important to know this is happening - - _decoderInit = true; - return true; -} - -bool Mp3PspStream::stopDecoder() { - DEBUG_ENTER_FUNC(); - - if (!_decoderInit) - return true; - - // Based on PSP firmware version, we need to do different things to do Media Engine processing - if (sceKernelDevkitVersion() == 0x01050001){ -/* if (!unloadAudioModule("flash0:/kd/me_for_vsh.prx", PSP_MEMORY_PARTITION_KERNEL) || - !unloadAudioModule("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL) { - PSP_ERROR("failed to unload audio module\n"); - return false; - } -*/ - }else{ - if (sceUtilityUnloadModule(PSP_MODULE_AV_AVCODEC) < 0) { - PSP_ERROR("failed to unload avcodec module\n"); - return false; - } - } - - _decoderInit = false; - return true; -} - -//Load a PSP audio module -bool Mp3PspStream::loadStartAudioModule(const char *modname, int partition){ - DEBUG_ENTER_FUNC(); - - SceKernelLMOption option; - SceUID modid; - - memset(&option, 0, sizeof(option)); - option.size = sizeof(option); - option.mpidtext = partition; - option.mpiddata = partition; - option.position = 0; - option.access = 1; - - modid = sceKernelLoadModule(modname, 0, &option); - if (modid < 0) { - PSP_ERROR("Failed to load module %s. Got error 0x%x\n", modname, modid); - return false; - } - - int ret = sceKernelStartModule(modid, 0, NULL, NULL, NULL); - if (ret < 0) { - PSP_ERROR("Failed to start module %s. Got error 0x%x\n", modname, ret); - return false; - } - return true; -} - -// TODO: make parallel function for unloading the 1.50 modules - -Mp3PspStream::Mp3PspStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) : - _inStream(inStream), - _disposeAfterUse(dispose), - _pcmLength(0), - _posInFrame(0), - _state(MP3_STATE_INIT), - _length(0, 1000), - _sampleRate(0), - _totalTime(mad_timer_zero) { - - DEBUG_ENTER_FUNC(); - - assert(_decoderInit); // must be initialized by now - - // let's leave the buffer guard -- who knows, it may be good? - memset(_buf, 0, sizeof(_buf)); - memset(_codecInBuffer, 0, sizeof(_codecInBuffer)); - - initStream(); // init needed stuff for the stream - - while (_state != MP3_STATE_EOS) - findValidHeader(); // get a first header so we can read basic stuff - - _sampleRate = _header.samplerate; // copy it before it gets destroyed - - _length = Timestamp(mad_timer_count(_totalTime, MAD_UNITS_MILLISECONDS), getRate()); - - //initStreamME(); // init the stuff needed for the ME to work - - deinitStream(); - //releaseStreamME(); - - _state = MP3_STATE_INIT; -} - -int Mp3PspStream::initStream() { - DEBUG_ENTER_FUNC(); - - if (_state != MP3_STATE_INIT) - deinitStream(); - - // Init MAD - mad_stream_init(&_stream); - mad_header_init(&_header); - - // Reset the stream data - _inStream->seek(0, SEEK_SET); - _totalTime = mad_timer_zero; - _posInFrame = 0; - - // Update state - _state = MP3_STATE_READY; - - // Read the first few sample bytes into the buffer - readMP3DataIntoBuffer(); - - return true; -} - -bool Mp3PspStream::initStreamME() { - // The following will eventually go into the thread - sceAudiocodecReleaseEDRAM(_codecParams); // do we need this? - - memset(_codecParams, 0, sizeof(_codecParams)); - - // Init the MP3 hardware - int ret = 0; - ret = sceAudiocodecCheckNeedMem(_codecParams, 0x1002); - if (ret < 0) { - PSP_ERROR("failed to init MP3 ME module. sceAudiocodecCheckNeedMem returned 0x%x.\n", ret); - return false; - } - PSP_DEBUG_PRINT("sceAudiocodecCheckNeedMem returned %d\n", ret); - ret = sceAudiocodecGetEDRAM(_codecParams, 0x1002); - if (ret < 0) { - PSP_ERROR("failed to init MP3 ME module. sceAudiocodecGetEDRAM returned 0x%x.\n", ret); - return false; - } - PSP_DEBUG_PRINT("sceAudioCodecGetEDRAM returned %d\n", ret); - - PSP_DEBUG_PRINT("samplerate[%d]\n", _sampleRate); - _codecParams[10] = _sampleRate; - - ret = sceAudiocodecInit(_codecParams, 0x1002); - if (ret < 0) { - PSP_ERROR("failed to init MP3 ME module. sceAudiocodecInit returned 0x%x.\n", ret); - return false; - } - - return true; -} - -Mp3PspStream::~Mp3PspStream() { - DEBUG_ENTER_FUNC(); - - deinitStream(); - releaseStreamME(); // free the memory used for this stream - - if (_disposeAfterUse == DisposeAfterUse::YES) - delete _inStream; -} - -void Mp3PspStream::deinitStream() { - DEBUG_ENTER_FUNC(); - - if (_state == MP3_STATE_INIT) - return; - - // Deinit MAD - mad_header_finish(&_header); - mad_stream_finish(&_stream); - - _state = MP3_STATE_EOS; -} - -void Mp3PspStream::releaseStreamME() { - sceAudiocodecReleaseEDRAM(_codecParams); -} - -void Mp3PspStream::decodeMP3Data() { - DEBUG_ENTER_FUNC(); - - do { - if (_state == MP3_STATE_INIT) { - initStream(); - initStreamME(); - } - - if (_state == MP3_STATE_EOS) - return; - - findValidHeader(); // seach for next valid header - - while (_state == MP3_STATE_READY) { - _stream.error = MAD_ERROR_NONE; - - uint32 frame_size = _stream.next_frame - _stream.this_frame; - uint32 samplesPerFrame = _header.layer == MAD_LAYER_III ? 576 : 1152; // Varies by layer - // calculate frame size -- try - //uint32 calc_frame_size = ((144 * _header.bitrate) / 22050) + (_header.flags & MAD_FLAG_PADDING ? 1 : 0); - - // Get stereo/mono - uint32 multFactor = 1; - if (_header.mode != MAD_MODE_SINGLE_CHANNEL) // mono - x2 for 16bit - multFactor *= 2; // stereo - x4 for 16bit - - PSP_DEBUG_PRINT("MP3 frame size[%d]. Samples[%d]. Multfactor[%d] pad[%d]\n", frame_size, samplesPerFrame, multFactor, _header.flags & MAD_FLAG_PADDING); - memcpy(_codecInBuffer, _stream.this_frame, frame_size); // we need it aligned - - // set up parameters for ME - _codecParams[6] = (unsigned long)_codecInBuffer; - _codecParams[8] = (unsigned long)_pcmSamples; - _codecParams[7] = frame_size; - _codecParams[9] = samplesPerFrame * multFactor; // x2 for stereo - - // debug -#ifdef PRINT_BUFFERS - PSP_DEBUG_PRINT("mp3 frame:\n"); - for (int i=0; i < (int)frame_size; i++) { - PSP_DEBUG_PRINT_SAMELN("%x ", _codecInBuffer[i]); - } - PSP_DEBUG_PRINT("\n"); -#endif - // Decode the next frame - // This function blocks. We'll want to put it in a thread - int ret = sceAudiocodecDecode(_codecParams, 0x1002); - if (ret < 0) { - PSP_ERROR("failed to decode MP3 data in ME. sceAudiocodecDecode returned 0x%x\n", ret); - // handle error here - } - -#ifdef PRINT_BUFFERS - PSP_DEBUG_PRINT("PCM frame:\n"); - for (int i=0; i < (int)_codecParams[9]; i+=2) { // changed from i+=2 - PSP_DEBUG_PRINT_SAMELN("%d ", (int16)_pcmSamples[i]); - } - PSP_DEBUG_PRINT("\n"); -#endif - _pcmLength = samplesPerFrame; - _posInFrame = 0; - break; - } - } while (_state != MP3_STATE_EOS && _stream.error == MAD_ERROR_BUFLEN); - - if (_stream.error != MAD_ERROR_NONE) // catch EOS - _state = MP3_STATE_EOS; -} - -void Mp3PspStream::readMP3DataIntoBuffer() { - DEBUG_ENTER_FUNC(); - - uint32 remaining = 0; - - // Give up immediately if we already used up all data in the stream - if (_inStream->eos()) { - _state = MP3_STATE_EOS; - return; - } - - if (_stream.next_frame) { - // If there is still data in the MAD stream, we need to preserve it. - // Note that we use memmove, as we are reusing the same buffer, - // and hence the data regions we copy from and to may overlap. - remaining = _stream.bufend - _stream.next_frame; - assert(remaining < BUFFER_SIZE); // Paranoia check - memmove(_buf, _stream.next_frame, remaining); // TODO: may want another buffer - } - - // Try to read the next block - uint32 size = _inStream->read(_buf + remaining, BUFFER_SIZE - remaining); - if (size <= 0) { - _state = MP3_STATE_EOS; - return; - } - - // Feed the data we just read into the stream decoder - _stream.error = MAD_ERROR_NONE; - mad_stream_buffer(&_stream, _buf, size + remaining); // just setup the pointers -} - -bool Mp3PspStream::seek(const Timestamp &where) { - DEBUG_ENTER_FUNC(); - - if (where == _length) { - _state = MP3_STATE_EOS; - return true; - } else if (where > _length) { - return false; - } - - const uint32 time = where.msecs(); - - mad_timer_t destination; - mad_timer_set(&destination, time / 1000, time % 1000, 1000); - - // Check if we need to rewind - if (_state != MP3_STATE_READY || mad_timer_compare(destination, _totalTime) < 0) { - initStream(); - initStreamME(); - } - - // The ME will need clear data no matter what once we seek? - //if (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS) - // initStreamME(); - - // Skip ahead - while (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS) - findValidHeader(); - - return (_state != MP3_STATE_EOS); -} - -// Seek in the stream, finding the next valid header -void Mp3PspStream::findValidHeader() { - DEBUG_ENTER_FUNC(); - - if (_state != MP3_STATE_READY) - return; - - // If necessary, load more data into the stream decoder - if (_stream.error == MAD_ERROR_BUFLEN) - readMP3DataIntoBuffer(); - - while (_state != MP3_STATE_EOS) { - _stream.error = MAD_ERROR_NONE; - - // Decode the next header. - if (mad_header_decode(&_header, &_stream) == -1) { - if (_stream.error == MAD_ERROR_BUFLEN) { - readMP3DataIntoBuffer(); // Read more data - continue; - } else if (MAD_RECOVERABLE(_stream.error)) { - debug(6, "MP3PSPStream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream)); - continue; - } else { - warning("MP3PSPStream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream)); - break; - } - } - - // Sum up the total playback time so far - mad_timer_add(&_totalTime, _header.duration); - break; - } - - if (_stream.error != MAD_ERROR_NONE) - _state = MP3_STATE_EOS; -} - -int Mp3PspStream::readBuffer(int16 *buffer, const int numSamples) { - DEBUG_ENTER_FUNC(); - - int samples = 0; -#ifdef PRINT_BUFFERS - int16 *debugBuffer = buffer; -#endif - - // Keep going as long as we have input available - while (samples < numSamples && _state != MP3_STATE_EOS) { - const int len = MIN(numSamples, samples + (int)(_pcmLength - _posInFrame) * MAD_NCHANNELS(&_header)); - - while (samples < len) { - *buffer++ = _pcmSamples[_posInFrame << 1]; - samples++; - if (MAD_NCHANNELS(&_header) == 2) { - *buffer++ = _pcmSamples[(_posInFrame << 1) + 1]; - samples++; - } - _posInFrame++; // always skip an extra sample since ME always outputs stereo - } - - //memcpy(buffer, &_pcmSamples[_posInFrame], len << 1); // 16 bits - //_posInFrame += len; // next time we start from the middle - - if (_posInFrame >= _pcmLength) { - // We used up all PCM data in the current frame -- read & decode more - decodeMP3Data(); - } - } - -#ifdef PRINT_BUFFERS - PSP_INFO_PRINT("buffer:\n"); - for (int i = 0; i<numSamples; i++) - PSP_INFO_PRINT("%d ", debugBuffer[i]); - PSP_INFO_PRINT("\n\n"); -#endif - - return samples; -} - -} // End of namespace Audio - - diff --git a/backends/platform/psp/mp3.h b/backends/platform/psp/mp3.h deleted file mode 100644 index f8802f930c..0000000000 --- a/backends/platform/psp/mp3.h +++ /dev/null @@ -1,121 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef SOUND_MP3_PSP_H -#define SOUND_MP3_PSP_H - -#include "common/types.h" -#include "common/scummsys.h" - -namespace Common { - class SeekableReadStream; -} - -namespace Audio { - -class AudioStream; -class SeekableAudioStream; - -class Mp3PspStream : public SeekableAudioStream { -protected: - enum State { - MP3_STATE_INIT, // Need to init the decoder - MP3_STATE_READY, // ready for processing data - MP3_STATE_EOS // end of data reached (may need to loop) - }; - - #define MAX_SAMPLES_PER_FRAME 2048 * 2 - int16 _pcmSamples[MAX_SAMPLES_PER_FRAME] __attribute__((aligned(64))); // samples to output PCM data into - byte _codecInBuffer[3072] __attribute__((aligned(64))); // the codec always needs alignment - unsigned long _codecParams[65]__attribute__((aligned(64))); // TODO: change to struct - - Common::SeekableReadStream *_inStream; - DisposeAfterUse::Flag _disposeAfterUse; - - uint32 _pcmLength; // how many pcm samples we have (/2 for mono) - - uint _posInFrame; // position in frame - State _state; // what state the stream is in - - Timestamp _length; - uint32 _sampleRate; - - mad_timer_t _totalTime; - mad_stream _stream; // - mad_header _header; // This is all we need from libmad - - static bool _decoderInit; // has the decoder been initialized - static bool _decoderFail; // has the decoder failed to load - - enum { - BUFFER_SIZE = 5 * 8192 - }; - - // This buffer contains a slab of input data - byte _buf[BUFFER_SIZE + MAD_BUFFER_GUARD]; - - void decodeMP3Data(); - void readMP3DataIntoBuffer(); - - static bool loadStartAudioModule(const char *modname, int partition); - int initStream(); - void findValidHeader(); - void deinitStream(); - - // to init and uninit ME decoder - static bool initDecoder(); - static bool stopDecoder(); - - // ME functions for stream - bool initStreamME(); - void releaseStreamME(); - -public: - Mp3PspStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose); - ~Mp3PspStream(); - - // This function avoids having to create streams when it's not possible - static inline bool isOkToCreateStream() { - if (_decoderFail) // fatal failure - return false; - if (!_decoderInit) // if we're not initialized - if (!initDecoder()) // check if we failed init - return false; - return true; - } - - int readBuffer(int16 *buffer, const int numSamples); - - bool endOfData() const { return _state == MP3_STATE_EOS; } - bool isStereo() const { return MAD_NCHANNELS(&_header) == 2; } - int getRate() const { return _header.samplerate; } - - bool seek(const Timestamp &where); - Timestamp getLength() const { return _length; } -}; - -} // End of namespace Audio - -#endif // #ifndef SOUND_MP3_PSP_H diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp index a36ae1847f..58d98bc219 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -37,7 +37,6 @@ #include "backends/platform/psp/psppixelformat.h" #include "backends/platform/psp/osys_psp.h" #include "backends/platform/psp/powerman.h" -#include "backends/platform/psp/thread.h" #include "backends/saves/psp/psp-saves.h" #include "backends/timer/default/default-timer.h" @@ -49,7 +48,6 @@ #include "backends/platform/psp/trace.h" -#define USE_PSP_AUDIO #define SAMPLES_PER_SEC 44100 @@ -60,11 +58,7 @@ static int timer_handler(int t) { } void OSystem_PSP::initSDL() { -#ifdef USE_PSP_AUDIO - SDL_Init(0); -#else - SDL_Init(SDL_INIT_AUDIO); -#endif + SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER); } OSystem_PSP::~OSystem_PSP() {} @@ -91,7 +85,7 @@ void OSystem_PSP::initBackend() { _inputHandler.init(); initSDL(); - + _savefile = new PSPSaveFileManager; _timer = new DefaultTimerManager(); @@ -299,18 +293,17 @@ bool OSystem_PSP::pollEvent(Common::Event &event) { return _inputHandler.getAllInputs(event); } + uint32 OSystem_PSP::getMillis() { - return PspThread::getMillis(); + return SDL_GetTicks(); } void OSystem_PSP::delayMillis(uint msecs) { - PspThread::delayMillis(msecs); + SDL_Delay(msecs); } void OSystem_PSP::setTimerCallback(TimerProc callback, int interval) { - _pspTimer.setCallback((PspTimer::CallbackFunc)callback); - _pspTimer.setIntervalMs(interval); - _pspTimer.start(); + SDL_SetTimer(interval, (SDL_TimerCallback)callback); } OSystem::MutexRef OSystem_PSP::createMutex(void) { @@ -338,6 +331,8 @@ void OSystem_PSP::mixCallback(void *sys, byte *samples, int len) { } void OSystem_PSP::setupMixer(void) { + SDL_AudioSpec desired; + SDL_AudioSpec obtained; // Determine the desired output sampling frequency. uint32 samplesPerSec = 0; @@ -354,22 +349,6 @@ void OSystem_PSP::setupMixer(void) { while (samples * 16 > samplesPerSec * 2) samples >>= 1; - assert(!_mixer); - -#ifdef USE_PSP_AUDIO - if (!_audio.open(samplesPerSec, 2, samples, mixCallback, this)) { - PSP_ERROR("failed to open audio\n"); - return; - } - samplesPerSec = _audio.getFrequency(); // may have been changed by audio system - _mixer = new Audio::MixerImpl(this, samplesPerSec); - assert(_mixer); - _mixer->setReady(true); - _audio.unpause(); -#else - SDL_AudioSpec obtained; - SDL_AudioSpec desired; - memset(&desired, 0, sizeof(desired)); desired.freq = samplesPerSec; desired.format = AUDIO_S16SYS; @@ -377,7 +356,8 @@ void OSystem_PSP::setupMixer(void) { desired.samples = samples; desired.callback = mixCallback; desired.userdata = this; - + + assert(!_mixer); if (SDL_OpenAudio(&desired, &obtained) != 0) { warning("Could not open audio: %s", SDL_GetError()); _mixer = new Audio::MixerImpl(this, samplesPerSec); @@ -396,15 +376,10 @@ void OSystem_PSP::setupMixer(void) { SDL_PauseAudio(0); } -#endif /* USE_PSP_AUDIO */ } void OSystem_PSP::quit() { -#ifdef USE_PSP_AUDIO - _audio.close(); -#else SDL_CloseAudio(); -#endif SDL_Quit(); sceKernelExitGame(); } diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h index 3f075d0139..8c5b40dcdf 100644 --- a/backends/platform/psp/osys_psp.h +++ b/backends/platform/psp/osys_psp.h @@ -38,8 +38,6 @@ #include "backends/platform/psp/pspkeyboard.h" #include "backends/platform/psp/display_manager.h" #include "backends/platform/psp/input.h" -#include "backends/platform/psp/audio.h" -#include "backends/timer/psp/timer.h" #include <SDL.h> @@ -57,8 +55,6 @@ private: DisplayManager _displayManager; PSPKeyboard _keyboard; InputHandler _inputHandler; - PspAudio _audio; - PspTimer _pspTimer; void initSDL(); diff --git a/backends/platform/psp/psp.spec b/backends/platform/psp/psp.spec index ac325b7fd6..debdab3208 100644 --- a/backends/platform/psp/psp.spec +++ b/backends/platform/psp/psp.spec @@ -1,3 +1,3 @@ %rename lib old_lib *lib: -%(old_lib) -lz -lstdc++ -lc -lm -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk -lpsputility -lpspuser -lpsppower -lpsphprm -lpsprtc -lpspaudio -lpspaudiocodec -lpspkernel +%(old_lib) -lz -lstdc++ -lc -lm -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk -lpsputility -lpspuser -lpsppower -lpsphprm -lpsprtc -lpspaudio -lpspkernel diff --git a/backends/platform/psp/psp_main.cpp b/backends/platform/psp/psp_main.cpp index e6940eba13..e568184990 100644 --- a/backends/platform/psp/psp_main.cpp +++ b/backends/platform/psp/psp_main.cpp @@ -39,7 +39,6 @@ #include <base/main.h> #include <base/plugins.h> #include "backends/platform/psp/powerman.h" -#include "backends/platform/psp/thread.h" #include "backends/plugins/psp/psp-provider.h" #include "backends/platform/psp/psppixelformat.h" @@ -141,7 +140,7 @@ int CallbackThread(SceSize /*size*/, void *arg) { /* Sets up the callback thread and returns its thread id */ int SetupCallbacks(void) { - int thid = sceKernelCreateThread("power_thread", CallbackThread, PRIORITY_POWER_THREAD, STACK_POWER_THREAD, THREAD_ATTR_USER, 0); + int thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, THREAD_ATTR_USER, 0); if (thid >= 0) { sceKernelStartThread(thid, 0, 0); } diff --git a/backends/platform/psp/thread.cpp b/backends/platform/psp/thread.cpp deleted file mode 100644 index 88e7b6fe38..0000000000 --- a/backends/platform/psp/thread.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.h $ - * $Id: osys_psp.h 49173 2010-05-24 03:05:17Z bluddy $ - * - */ - -#include <time.h> -#include <psptypes.h> -#include <psprtc.h> -#include <pspthreadman.h> - -#include "backends/platform/psp/thread.h" - -void PspThread::delayMillis(uint32 ms) { - sceKernelDelayThread(ms * 1000); -} - -void PspThread::delayMicros(uint32 us) { - sceKernelDelayThread(us); -} - -uint32 PspThread::getMillis() { - uint32 ticks[2]; - sceRtcGetCurrentTick((u64 *)ticks); - return (ticks[0]/1000); -} - -uint32 PspThread::getMicros() { - uint32 ticks[2]; - sceRtcGetCurrentTick((u64 *)ticks); - return ticks[0]; -} - diff --git a/backends/platform/psp/thread.h b/backends/platform/psp/thread.h deleted file mode 100644 index e83eead68e..0000000000 --- a/backends/platform/psp/thread.h +++ /dev/null @@ -1,56 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/portdefs.h $ - * $Id: portdefs.h 38687 2009-02-21 12:08:52Z joostp $ - * - */ - -#ifndef PSP_THREAD_H -#define PSP_THREAD_H - -#include "common/scummsys.h" - -class PspThread { -public: - static void delayMillis(uint32 ms); - static void delayMicros(uint32 us); - static uint32 getMillis(); - static uint32 getMicros(); -}; - -enum ThreadPriority { - PRIORITY_MAIN_THREAD = 36, - PRIORITY_TIMER_THREAD = 30, - PRIORITY_AUDIO_THREAD = 25, // must be higher than timer or we get stuttering - PRIORITY_POWER_THREAD = 20, // quite a light thread - PRIORITY_DISPLAY_THREAD = 17 // very light thread for callbacks only -}; - -enum StackSizes { - STACK_AUDIO_THREAD = 16 * 1024, - STACK_TIMER_THREAD = 32 * 1024, - STACK_DISPLAY_THREAD = 2 * 1024, - STACK_POWER_THREAD = 4 * 1024 -}; - -#endif /* PSP_THREADS_H */ - - diff --git a/backends/platform/samsungtv/main.cpp b/backends/platform/samsungtv/main.cpp index 2c025b750c..a6b8376912 100644 --- a/backends/platform/samsungtv/main.cpp +++ b/backends/platform/samsungtv/main.cpp @@ -43,7 +43,7 @@ extern "C" int Game_Main(char *path, char *) { // Invoke the actual ScummVM main entry point: int res = scummvm_main(0, 0); - ((OSystem_SDL *)g_system)->deinit(); + g_system->quit(); // TODO: Consider removing / replacing this! return res; } diff --git a/backends/platform/sdl/graphics.cpp b/backends/platform/sdl/graphics.cpp index 82670cfcb7..9d0d872c3d 100644 --- a/backends/platform/sdl/graphics.cpp +++ b/backends/platform/sdl/graphics.cpp @@ -1673,6 +1673,7 @@ void OSystem_SDL::drawMouse() { SDL_Rect dst; int scale; + int width, height; int hotX, hotY; dst.x = _mouseCurState.x; @@ -1680,12 +1681,16 @@ void OSystem_SDL::drawMouse() { if (!_overlayVisible) { scale = _videoMode.scaleFactor; + width = _videoMode.screenWidth; + height = _videoMode.screenHeight; dst.w = _mouseCurState.vW; dst.h = _mouseCurState.vH; hotX = _mouseCurState.vHotX; hotY = _mouseCurState.vHotY; } else { scale = 1; + width = _videoMode.overlayWidth; + height = _videoMode.overlayHeight; dst.w = _mouseCurState.rW; dst.h = _mouseCurState.rH; hotX = _mouseCurState.rHotX; diff --git a/backends/platform/sdl/main.cpp b/backends/platform/sdl/main.cpp index 13e614a4a2..b38b815438 100644 --- a/backends/platform/sdl/main.cpp +++ b/backends/platform/sdl/main.cpp @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) { // Invoke the actual ScummVM main entry point: int res = scummvm_main(argc, argv); - ((OSystem_SDL *)g_system)->deinit(); + g_system->quit(); // TODO: Consider removing / replacing this! return res; } diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index f8ae824acf..e54d70e8b2 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -482,7 +482,7 @@ bool OSystem_SDL::getFeatureState(Feature f) { } } -void OSystem_SDL::deinit() { +void OSystem_SDL::quit() { if (_cdrom) { SDL_CDStop(_cdrom); SDL_CDClose(_cdrom); @@ -504,14 +504,10 @@ void OSystem_SDL::deinit() { SDL_Quit(); - // Event Manager requires save manager for storing + // Even Manager requires save manager for storing // recorded events delete getEventManager(); delete _savefile; -} - -void OSystem_SDL::quit() { - deinit(); #if !defined(SAMSUNGTV) exit(0); diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index 341a59c8cf..b6baa52391 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -202,8 +202,6 @@ public: // Quit virtual void quit(); // overloaded by CE backend - void deinit(); - virtual void getTimeAndDate(TimeDate &t) const; virtual Common::TimerManager *getTimerManager(); |