[Scummvm-cvs-logs] CVS: scummvm/backends/dc cache.S,NONE,1.1 dcloader.cpp,NONE,1.1 dcloader.h,NONE,1.1 plugin.syms,NONE,1.1 plugin.x,NONE,1.1 .cvsignore,1.9,1.10 Makefile,1.23,1.24
Marcus Comstedt
marcus_c at users.sourceforge.net
Sun Aug 22 14:48:00 CEST 2004
- Previous message: [Scummvm-cvs-logs] CVS: scummvm/base plugins.cpp,1.33,1.34
- Next message: [Scummvm-cvs-logs] CVS: scummvm/scumm cursor.cpp,2.9,2.10 intern.h,2.177,2.178 object.cpp,1.176,1.177 resource_v7he.cpp,1.6,1.7 script_v5.cpp,1.258,1.259 script_v6.cpp,1.381,1.382 script_v7he.cpp,2.34,2.35 script_v8.cpp,2.268,2.269 scumm.cpp,1.131,1.132 scumm.h,1.445,1.446
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/scummvm/scummvm/backends/dc
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12463
Modified Files:
.cvsignore Makefile
Added Files:
cache.S dcloader.cpp dcloader.h plugin.syms plugin.x
Log Message:
Support dynamic plugins on Dreamcast.
--- NEW FILE: cache.S ---
.globl _flush_instruction_cache
.align 2
! Flush the SH instruction cache
_flush_instruction_cache:
mova fcc,r0
mov.l p2_mask,r1
or r1,r0
jmp @r0
nop
nop
fcc:
mov.l ccr_addr,r0
mov.l ccr_data,r1
mov.l r1, at r0
nop
nop
nop
nop
nop
nop
nop
nop
rts
nop
.align 2
p2_mask:
.long 0xa0000000
ccr_addr:
.long 0xff00001c
ccr_data:
.word 0x0905
--- NEW FILE: dcloader.cpp ---
/* ScummVM - Scumm Interpreter
* Dreamcast port
* Copyright (C) 2002-2004 Marcus Comstedt
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/backends/dc/dcloader.cpp,v 1.1 2004/08/22 21:47:20 marcus_c Exp $
*
*/
#include <stdafx.h>
#include <ronin/ronin.h>
#include <string.h>
#include <stdarg.h>
#include "dcloader.h"
#ifdef DL_DEBUG
#define DBG(...) reportf(__VA_ARGS__)
#else
#define DBG(...) 0
#endif
/* ELF stuff */
typedef unsigned short Elf32_Half, Elf32_Section;
typedef unsigned long Elf32_Word, Elf32_Addr, Elf32_Off;
typedef signed long Elf32_Sword;
typedef Elf32_Half Elf32_Versym;
#define EI_NIDENT (16)
#define ELFMAG "\177ELF\1\1"
#define SELFMAG 6
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;
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;
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;
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;
typedef struct
{
Elf32_Addr r_offset; /* Address */
Elf32_Word r_info; /* Relocation type and symbol index */
Elf32_Sword r_addend; /* Addend */
} Elf32_Rela;
extern "C" void flush_instruction_cache();
static void purge_copyback()
{
int i;
for(i=0; i!=(1<<14); i+=(1<<5))
*(volatile unsigned int *)(0xf4000000+i) &= ~3;
}
void DLObject::seterror(const char *fmt, ...)
{
if(errbuf) {
va_list va;
va_start(va, fmt);
vsnprintf(errbuf, MAXDLERRLEN, fmt, va);
va_end(va);
}
}
void DLObject::discard_symtab()
{
free(symtab);
free(strtab);
symtab = NULL;
strtab = NULL;
symbol_cnt = 0;
}
void DLObject::unload()
{
discard_symtab();
free(segment);
segment = NULL;
}
bool DLObject::relocate(int fd, unsigned long offset, unsigned long size)
{
Elf32_Rela *rela;
if(!(rela = (Elf32_Rela *)malloc(size))) {
seterror("Out of memory.");
return false;
}
if(lseek(fd, offset, SEEK_SET)<0 ||
read(fd, rela, size) != size) {
seterror("Relocation table load failed.");
free(rela);
return false;
}
int cnt = size / sizeof(*rela);
for(int i=0; i<cnt; i++) {
Elf32_Sym *sym = (Elf32_Sym *)(((char *)symtab)+(rela[i].r_info>>4));
void *target = ((char *)segment)+rela[i].r_offset;
switch(rela[i].r_info & 0xf) {
case 1: /* DIR32 */
if(sym->st_shndx < 0xff00)
*(unsigned long *)target += (unsigned long)segment;
break;
default:
seterror("Unknown relocation type %d.", rela[i].r_info & 0xf);
free(rela);
return false;
}
}
free(rela);
return true;
}
bool DLObject::load(int fd)
{
Elf32_Ehdr ehdr;
Elf32_Phdr phdr;
Elf32_Shdr *shdr;
int symtab_sect = -1;
if(read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr) ||
memcmp(ehdr.e_ident, ELFMAG, SELFMAG) ||
ehdr.e_type != 2 || ehdr.e_machine != 42 ||
ehdr.e_phentsize < sizeof(phdr) || ehdr.e_shentsize != sizeof(*shdr) ||
ehdr.e_phnum != 1) {
seterror("Invalid file type.");
return false;
}
DBG("phoff = %d, phentsz = %d, phnum = %d\n",
ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_phnum);
if(lseek(fd, ehdr.e_phoff, SEEK_SET)<0 ||
read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) {
seterror("Program header load failed.");
return false;
}
if(phdr.p_type != 1 || phdr.p_vaddr != 0 || phdr.p_paddr != 0 ||
phdr.p_filesz > phdr.p_memsz) {
seterror("Invalid program header.");
return false;
}
DBG("offs = %d, filesz = %d, memsz = %d, align = %d\n",
phdr.p_offset, phdr.p_filesz, phdr.p_memsz, phdr.p_align);
if(!(segment = memalign(phdr.p_align, phdr.p_memsz))) {
seterror("Out of memory.");
return false;
}
DBG("segment @ %p\n", segment);
if(lseek(fd, phdr.p_offset, SEEK_SET)<0 ||
read(fd, segment, phdr.p_filesz) != phdr.p_filesz) {
seterror("Segment load failed.");
return false;
}
DBG("shoff = %d, shentsz = %d, shnum = %d\n",
ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shnum);
if(!(shdr = (Elf32_Shdr *)malloc(ehdr.e_shnum * sizeof(*shdr)))) {
seterror("Out of memory.");
return false;
}
if(lseek(fd, ehdr.e_shoff, SEEK_SET)<0 ||
read(fd, shdr, ehdr.e_shnum * sizeof(*shdr)) !=
ehdr.e_shnum * sizeof(*shdr)) {
seterror("Section headers load failed.");
free(shdr);
return false;
}
for(int i=0; i<ehdr.e_shnum; i++) {
DBG("Section %d: type = %d, size = %d, entsize = %d, link = %d\n",
i, shdr[i].sh_type, shdr[i].sh_size, shdr[i].sh_entsize, shdr[i].sh_link);
if(shdr[i].sh_type == 2 && shdr[i].sh_entsize == sizeof(Elf32_Sym) &&
shdr[i].sh_link < ehdr.e_shnum && shdr[shdr[i].sh_link].sh_type == 3 &&
symtab_sect < 0)
symtab_sect = i;
}
if(symtab_sect < 0) {
seterror("No symbol table.");
free(shdr);
return false;
}
if(!(symtab = malloc(shdr[symtab_sect].sh_size))) {
seterror("Out of memory.");
free(shdr);
return false;
}
if(lseek(fd, shdr[symtab_sect].sh_offset, SEEK_SET)<0 ||
read(fd, symtab, shdr[symtab_sect].sh_size) != shdr[symtab_sect].sh_size){
seterror("Symbol table load failed.");
free(shdr);
return false;
}
if(!(strtab = (char *)malloc(shdr[shdr[symtab_sect].sh_link].sh_size))) {
seterror("Out of memory.");
free(shdr);
return false;
}
if(lseek(fd, shdr[shdr[symtab_sect].sh_link].sh_offset, SEEK_SET)<0 ||
read(fd, strtab, shdr[shdr[symtab_sect].sh_link].sh_size) !=
shdr[shdr[symtab_sect].sh_link].sh_size){
seterror("Symbol table strings load failed.");
free(shdr);
return false;
}
symbol_cnt = shdr[symtab_sect].sh_size / sizeof(Elf32_Sym);
DBG("Loaded %d symbols.\n", symbol_cnt);
Elf32_Sym *s = (Elf32_Sym *)symtab;
for(int c = symbol_cnt; c--; s++)
if(s->st_shndx < 0xff00)
s->st_value += (Elf32_Addr)segment;
for(int i=0; i<ehdr.e_shnum; i++)
if(shdr[i].sh_type == 4 && shdr[i].sh_entsize == sizeof(Elf32_Rela) &&
shdr[i].sh_link == symtab_sect)
if(!relocate(fd, shdr[i].sh_offset, shdr[i].sh_size)) {
free(shdr);
return false;
}
free(shdr);
return true;
}
bool DLObject::open(const char *path)
{
int fd;
void *ctors_start, *ctors_end;
DBG("open(\"%s\")\n", path);
if((fd = ::open(path, O_RDONLY))<0) {
seterror("%s not found.", path);
return false;
}
if(!load(fd)) {
::close(fd);
unload();
return false;
}
::close(fd);
purge_copyback();
flush_instruction_cache();
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++)
if((s->st_info>>4 == 1 || s->st_info>>4 == 2) &&
strtab[s->st_name] == '_' && !strcmp(name, strtab+s->st_name+1)) {
DBG("=> %p\n", (void*)s->st_value);
return (void*)s->st_value;
}
seterror("Symbol \"%s\" not found.", name);
return NULL;
}
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();
}
--- NEW FILE: dcloader.h ---
/* ScummVM - Scumm Interpreter
* Dreamcast port
* Copyright (C) 2002-2004 Marcus Comstedt
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: /cvsroot/scummvm/scummvm/backends/dc/dcloader.h,v 1.1 2004/08/22 21:47:20 marcus_c Exp $
*
*/
#ifndef DC_DCLOADER_H
#define DC_DCLOADER_H
#include "dc.h"
#define MAXDLERRLEN 80
class DLObject {
private:
char *errbuf; /* For error messages, at least MAXDLERRLEN in size */
void *segment, *symtab;
char *strtab;
int symbol_cnt;
void *dtors_start, *dtors_end;
void seterror(const char *fmt, ...);
void unload();
bool relocate(int fd, unsigned long offset, unsigned long size);
bool load(int fd);
public:
bool open(const char *path);
bool close();
void *symbol(const char *name);
void discard_symtab();
DLObject(char *_errbuf = NULL) : errbuf(_errbuf), segment(NULL),symtab(NULL),
strtab(NULL), symbol_cnt(0), dtors_start(NULL), dtors_end(NULL) {}
};
#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
--- NEW FILE: plugin.syms ---
_PLUGIN_createEngine
_PLUGIN_detectGames
_PLUGIN_getSupportedGames
_PLUGIN_name
___plugin_ctors
___plugin_ctors_end
___plugin_dtors
___plugin_dtors_end
--- NEW FILE: plugin.x ---
OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl")
OUTPUT_ARCH(sh)
SECTIONS
{
. = 0;
.text :
{
*(.text .stub .text.* .gnu.linkonce.t.*)
*(.gnu.warning)
} =0
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) }
.sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
.data :
{
*(.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) }
.ctors :
{
___plugin_ctors = .;
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
___plugin_ctors_end = .;
}
.dtors :
{
___plugin_dtors = .;
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
___plugin_dtors_end = .;
}
.sdata :
{
*(.sdata .sdata.* .gnu.linkonce.s.*)
}
.sbss :
{
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
}
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
}
}
Index: .cvsignore
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/dc/.cvsignore,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- .cvsignore 20 Aug 2004 21:44:07 -0000 1.9
+++ .cvsignore 22 Aug 2004 21:47:20 -0000 1.10
@@ -14,3 +14,4 @@
base
backends
scummvm.elf
+*.plg
Index: Makefile
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/dc/Makefile,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- Makefile 14 Mar 2004 22:16:22 -0000 1.23
+++ Makefile 22 Aug 2004 21:47:20 -0000 1.24
@@ -2,9 +2,12 @@
ronindir = /usr/local/ronin
+# BUILD_PLUGINS = 1
+
srcdir = ../..
VPATH = $(srcdir)
+CC = sh-elf-gcc -ml -m4-single-only
CXX = sh-elf-g++ -ml -m4-single-only
CXXFLAGS= -O3 -Wno-multichar -funroll-loops -fschedule-insns2 -fomit-frame-pointer -fdelete-null-pointer-checks -fno-exceptions
DEFINES = -D__DC__ -DNONSTANDARD_PORT
@@ -12,6 +15,10 @@
INCLUDES= -I./ -I$(srcdir) -I$(srcdir)/common -I$(ronindir)/include/
LIBS = -L$(ronindir)/lib -lronin-netcd -lz -lm
EXECUTABLE = scummvm.elf
+PLUGIN_PREFIX =
+PLUGIN_SUFFIX = .plg
+PLUGIN_EXTRA_DEPS = plugin.x plugin.syms scummvm.elf
+PLUGIN_LDFLAGS = -nostartfiles -Wl,-q,-Tplugin.x,--just-symbols,scummvm.elf,--retain-symbols-file,plugin.syms -L$(ronindir)/lib
MKDIR = mkdir -p
RM = rm -f
RM_REC = rm -rf
@@ -19,10 +26,17 @@
RANLIB = sh-elf-ranlib
HAVE_GCC3 = true
+ifdef BUILD_PLUGINS
+DEFINES += -DDYNAMIC_MODULES
+endif
+
OBJS := dcmain.o time.o display.o audio.o input.o selector.o icon.o \
- label.o vmsave.o softkbd.o
+ label.o vmsave.o softkbd.o dcloader.o cache.o
MODULE_DIRS += .
include $(srcdir)/Makefile.common
+scummvm.bin : scummvm.elf
+ sh-elf-objcopy -S -R .stack -O binary $< $@
+
- Previous message: [Scummvm-cvs-logs] CVS: scummvm/base plugins.cpp,1.33,1.34
- Next message: [Scummvm-cvs-logs] CVS: scummvm/scumm cursor.cpp,2.9,2.10 intern.h,2.177,2.178 object.cpp,1.176,1.177 resource_v7he.cpp,1.6,1.7 script_v5.cpp,1.258,1.259 script_v6.cpp,1.381,1.382 script_v7he.cpp,2.34,2.35 script_v8.cpp,2.268,2.269 scumm.cpp,1.131,1.132 scumm.h,1.445,1.446
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Scummvm-git-logs
mailing list