Initial commit
This commit is contained in:
26
backends/platform/dc/DCLauncherDialog.h
Normal file
26
backends/platform/dc/DCLauncherDialog.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
class DCLauncherDialog {
|
||||
public:
|
||||
DCLauncherDialog() {}
|
||||
int runModal();
|
||||
};
|
||||
95
backends/platform/dc/Makefile
Normal file
95
backends/platform/dc/Makefile
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
ronindir = /usr/local/ronin
|
||||
|
||||
DYNAMIC_MODULES = 1
|
||||
|
||||
srcdir = ../../..
|
||||
VPATH = $(srcdir)
|
||||
|
||||
CC = sh-elf-gcc -ml -m4-single-only
|
||||
CXX = sh-elf-g++ -ml -m4-single-only
|
||||
LD = $(CXX)
|
||||
CXXFLAGS= -O3 -Wno-multichar -funroll-loops -fschedule-insns2 -fomit-frame-pointer -fdelete-null-pointer-checks -fno-exceptions
|
||||
DEFINES = -D__DC__ -DNONSTANDARD_PORT -DUSE_MAD -DUSE_ZLIB -DDISABLE_DEFAULT_SAVEFILEMANAGER -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DUSE_RGB_COLOR
|
||||
# For release builds:
|
||||
#DEFINES += -DNOSERIAL
|
||||
LDFLAGS = -Wl,-Ttext,0x8c010000 -nostartfiles $(ronindir)/lib/crt0.o
|
||||
INCLUDES= -I./ -I$(srcdir) -I$(ronindir)/include/ -I$(srcdir)/engines
|
||||
LIBS = -L$(ronindir)/lib -lmad -lronin -lz -lm
|
||||
# For release builds:
|
||||
#LIBS = -L$(ronindir)/lib -lmad -lronin-noserial -lz -lm
|
||||
EXECUTABLE = scummvm.elf
|
||||
DEPDIR = .deps
|
||||
CXX_UPDATE_DEP_FLAG = -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP
|
||||
PLUGIN_PREFIX =
|
||||
PLUGIN_SUFFIX = .plg
|
||||
PLUGIN_EXTRA_DEPS = plugin.x plugin.syms scummvm.elf plugin_head.o
|
||||
PLUGIN_LDFLAGS = -nostartfiles -Wl,-q,-Tplugin.x,--just-symbols,scummvm.elf,--retain-symbols-file,plugin.syms -L$(ronindir)/lib plugin_head.o
|
||||
MKDIR = mkdir -p
|
||||
RM = rm -f
|
||||
RM_REC = rm -rf
|
||||
AR = sh-elf-ar cru
|
||||
RANLIB = sh-elf-ranlib
|
||||
USE_RGB_COLOR = true
|
||||
|
||||
ifdef DYNAMIC_MODULES
|
||||
DEFINES += -DDYNAMIC_MODULES
|
||||
PRE_OBJS_FLAGS = -Wl,--whole-archive
|
||||
POST_OBJS_FLAGS = -Wl,--no-whole-archive
|
||||
ENABLED=DYNAMIC_PLUGIN
|
||||
else
|
||||
ENABLED=STATIC_PLUGIN
|
||||
endif
|
||||
|
||||
ENABLE_SCUMM = $(ENABLED)
|
||||
# Not meaningful anymore (bug #6008)
|
||||
#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_GROOVIE = $(ENABLED)
|
||||
ENABLE_IHNM = $(ENABLED)
|
||||
ENABLE_KYRA = $(ENABLED)
|
||||
ENABLE_LURE = $(ENABLED)
|
||||
ENABLE_M4 = $(ENABLED)
|
||||
ENABLE_MADE = $(ENABLED)
|
||||
ENABLE_PARALLACTION = $(ENABLED)
|
||||
ENABLE_QUEEN = $(ENABLED)
|
||||
ENABLE_SAGA = $(ENABLED)
|
||||
ENABLE_SKY = $(ENABLED)
|
||||
ENABLE_SWORD1 = $(ENABLED)
|
||||
ENABLE_SWORD2 = $(ENABLED)
|
||||
ENABLE_TOUCHE = $(ENABLED)
|
||||
ENABLE_TUCKER = $(ENABLED)
|
||||
|
||||
OBJS := dcmain.o time.o display.o audio.o input.o selector.o icon.o \
|
||||
label.o vmsave.o softkbd.o dcloader.o cache.o dc-fs.o plugins.o \
|
||||
dcutils.o
|
||||
|
||||
MODULE_DIRS += ./
|
||||
|
||||
BACKEND := dc
|
||||
|
||||
include $(srcdir)/Makefile.common
|
||||
|
||||
scummvm.bin : scummvm.elf
|
||||
sh-elf-objcopy -S -R .stack -O binary $< $@
|
||||
|
||||
SCUMMVM.BIN : scummvm.bin
|
||||
scramble $< $@
|
||||
|
||||
plugin_dist : plugins
|
||||
for p in $(PLUGINS); do \
|
||||
t="`basename \"$$p\" | LC_CTYPE=C tr '[:lower:]' '[:upper:]'`"; \
|
||||
sh-elf-strip -g -o "$$t" "$$p"; \
|
||||
./check_plugin_symbols "$$t"; \
|
||||
done
|
||||
|
||||
dist : SCUMMVM.BIN plugin_dist
|
||||
|
||||
spotless : distclean
|
||||
$(RM) SCUMMVM.BIN scummvm.bin *.PLG
|
||||
25
backends/platform/dc/README
Normal file
25
backends/platform/dc/README
Normal file
@@ -0,0 +1,25 @@
|
||||
Compiling ScummVM for SEGA Dreamcast
|
||||
====================================
|
||||
|
||||
If you want to compile ScummVM for your Dreamcast,
|
||||
you'll need the following:
|
||||
|
||||
* gcc-4.6.3 configured as a cross-compiler for `sh-elf'
|
||||
|
||||
* binutils-2.18 configured likewise
|
||||
|
||||
* newlib for sh-elf : <URL:http://mc.pp.se/dc/files/newlib-1.19.0.tar.gz>
|
||||
|
||||
* libronin-0.7 : <URL:http://peter.bortas.org/scumm/libronin-0.7.tar.gz>
|
||||
|
||||
* libmad : <URL:http://mc.pp.se/dc/files/libmad-0.15.1b.tar.gz>
|
||||
|
||||
* GNU make
|
||||
|
||||
|
||||
Edit the Makefile to contain the path to libronin if you installed it
|
||||
somewhere other than /usr/local/ronin, then run `make dist', and you
|
||||
should get a scrambled binary SCUMMVM.BIN and some plugins *.PLG.
|
||||
|
||||
For serial/IP upload, remove the "DYNAMIC_MODULES" line and just run `make',
|
||||
to get a static binary with the name `scummvm.elf'.
|
||||
75
backends/platform/dc/audio.cpp
Normal file
75
backends/platform/dc/audio.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common/scummsys.h>
|
||||
#include "engines/engine.h"
|
||||
#include "audio/mixer_intern.h"
|
||||
#include "dc.h"
|
||||
|
||||
EXTERN_C void *memcpy4s(void *s1, const void *s2, unsigned int n);
|
||||
|
||||
uint OSystem_Dreamcast::initSound()
|
||||
{
|
||||
stop_sound();
|
||||
do_sound_command(CMD_SET_FREQ_EXP(FREQ_22050_EXP));
|
||||
do_sound_command(CMD_SET_STEREO(1));
|
||||
do_sound_command(CMD_SET_BUFFER(SOUND_BUFFER_SHIFT));
|
||||
return read_sound_int(&SOUNDSTATUS->freq);
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::checkSound()
|
||||
{
|
||||
int n;
|
||||
int curr_ring_buffer_samples;
|
||||
|
||||
if (!_mixer)
|
||||
return;
|
||||
|
||||
if (read_sound_int(&SOUNDSTATUS->mode) != MODE_PLAY)
|
||||
start_sound();
|
||||
|
||||
curr_ring_buffer_samples = read_sound_int(&SOUNDSTATUS->ring_length);
|
||||
|
||||
n = read_sound_int(&SOUNDSTATUS->samplepos);
|
||||
|
||||
if ((n-=fillpos)<0)
|
||||
n += curr_ring_buffer_samples;
|
||||
|
||||
n = ADJUST_BUFFER_SIZE(n-10);
|
||||
|
||||
if (n<100)
|
||||
return;
|
||||
|
||||
_mixer->mixCallback((byte *)temp_sound_buffer,
|
||||
2*SAMPLES_TO_BYTES(n));
|
||||
|
||||
if (fillpos+n > curr_ring_buffer_samples) {
|
||||
int r = curr_ring_buffer_samples - fillpos;
|
||||
memcpy4s(RING_BUF+fillpos, temp_sound_buffer, SAMPLES_TO_BYTES(r));
|
||||
fillpos = 0;
|
||||
n -= r;
|
||||
memcpy4s(RING_BUF, temp_sound_buffer+r, SAMPLES_TO_BYTES(n));
|
||||
} else {
|
||||
memcpy4s(RING_BUF+fillpos, temp_sound_buffer, SAMPLES_TO_BYTES(n));
|
||||
}
|
||||
if ((fillpos += n) >= curr_ring_buffer_samples)
|
||||
fillpos = 0;
|
||||
}
|
||||
37
backends/platform/dc/cache.S
Normal file
37
backends/platform/dc/cache.S
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
.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,@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
|
||||
15
backends/platform/dc/check_plugin_symbols
Normal file
15
backends/platform/dc/check_plugin_symbols
Normal file
@@ -0,0 +1,15 @@
|
||||
#! /bin/sh
|
||||
case "$0" in
|
||||
*/*) dir=`dirname "$0"`/;;
|
||||
*) dir="";;
|
||||
esac
|
||||
exec < "$dir"plugin.syms
|
||||
while read sym; do
|
||||
if sh-elf-nm "$1" | grep >/dev/null " $sym"'$'; then
|
||||
:
|
||||
else
|
||||
echo >&2 "ERROR: Symbol $sym missing from $1"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
172
backends/platform/dc/dc-fs.cpp
Normal file
172
backends/platform/dc/dc-fs.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
|
||||
#include "dc.h"
|
||||
#include "backends/fs/abstract-fs.h"
|
||||
#include "backends/fs/stdiostream.h"
|
||||
|
||||
#include <ronin/cdfs.h>
|
||||
#include <stdio.h>
|
||||
#define usleep usleep_unistd
|
||||
#include <unistd.h>
|
||||
#undef usleep
|
||||
|
||||
/**
|
||||
* Implementation of the ScummVM file system API based on Ronin.
|
||||
*
|
||||
* Parts of this class are documented in the base interface class, AbstractFSNode.
|
||||
*/
|
||||
class RoninCDFileNode : public AbstractFSNode {
|
||||
protected:
|
||||
Common::String _path;
|
||||
|
||||
public:
|
||||
RoninCDFileNode(const Common::String &path) : _path(path) {}
|
||||
|
||||
bool exists() const override { return true; }
|
||||
Common::String getName() const override { return lastPathComponent(_path, '/'); }
|
||||
Common::U32String getDisplayName() const override { return getName(); }
|
||||
Common::String getPath() const override { return _path; }
|
||||
bool isDirectory() const override { return false; }
|
||||
bool isReadable() const override { return true; }
|
||||
bool isWritable() const override { return false; }
|
||||
|
||||
AbstractFSNode *getChild(const Common::String &n) const override { return NULL; }
|
||||
bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const override { return false; }
|
||||
AbstractFSNode *getParent() const override;
|
||||
|
||||
Common::SeekableReadStream *createReadStream() override;
|
||||
Common::SeekableWriteStream *createWriteStream(bool atomic) override { return 0; }
|
||||
bool createDirectory() override { return false; }
|
||||
|
||||
static AbstractFSNode *makeFileNodePath(const Common::String &path);
|
||||
};
|
||||
|
||||
/* A directory */
|
||||
class RoninCDDirectoryNode final : public RoninCDFileNode {
|
||||
public:
|
||||
RoninCDDirectoryNode(const Common::String &path) : RoninCDFileNode(path) {}
|
||||
|
||||
bool isDirectory() const override { return true; }
|
||||
AbstractFSNode *getChild(const Common::String &n) const override;
|
||||
bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const override;
|
||||
Common::SeekableReadStream *createReadStream() override { return 0; }
|
||||
bool createDirectory() override { return true; }
|
||||
};
|
||||
|
||||
/* A file/directory which does not exist */
|
||||
class RoninCDNonexistingNode final : public RoninCDFileNode {
|
||||
public:
|
||||
RoninCDNonexistingNode(const Common::String &path) : RoninCDFileNode(path) {}
|
||||
|
||||
bool exists() const override { return false; }
|
||||
bool isReadable() const override { return false; }
|
||||
Common::SeekableReadStream *createReadStream() override { return 0; }
|
||||
};
|
||||
|
||||
AbstractFSNode *RoninCDFileNode::makeFileNodePath(const Common::String &path) {
|
||||
assert(path.size() > 0);
|
||||
|
||||
int fd;
|
||||
|
||||
if ((fd = open(path.c_str(), O_RDONLY)) >= 0) {
|
||||
close(fd);
|
||||
return new RoninCDFileNode(path);
|
||||
} else if ((fd = open(path.c_str(), O_DIR|O_RDONLY)) >= 0) {
|
||||
close(fd);
|
||||
return new RoninCDDirectoryNode(path);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
AbstractFSNode *RoninCDDirectoryNode::getChild(const Common::String &n) const {
|
||||
Common::String newPath(_path);
|
||||
if (_path.lastChar() != '/')
|
||||
newPath += '/';
|
||||
newPath += n;
|
||||
|
||||
return makeFileNodePath(newPath);
|
||||
}
|
||||
|
||||
bool RoninCDDirectoryNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
|
||||
|
||||
DIR *dirp = opendir(_path.c_str());
|
||||
struct dirent *dp;
|
||||
|
||||
if (dirp == NULL)
|
||||
return false;
|
||||
|
||||
// ... loop over dir entries using readdir
|
||||
while ((dp = readdir(dirp)) != NULL) {
|
||||
Common::String newPath(_path);
|
||||
if (newPath.lastChar() != '/')
|
||||
newPath += '/';
|
||||
newPath += dp->d_name;
|
||||
|
||||
if (dp->d_size < 0) {
|
||||
// Honor the chosen mode
|
||||
if (mode == Common::FSNode::kListFilesOnly)
|
||||
continue;
|
||||
|
||||
myList.push_back(new RoninCDDirectoryNode(newPath));
|
||||
} else {
|
||||
// Honor the chosen mode
|
||||
if (mode == Common::FSNode::kListDirectoriesOnly)
|
||||
continue;
|
||||
|
||||
myList.push_back(new RoninCDFileNode(newPath));
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AbstractFSNode *RoninCDFileNode::getParent() const {
|
||||
if (_path == "/")
|
||||
return 0;
|
||||
|
||||
const char *start = _path.c_str();
|
||||
const char *end = lastPathComponent(_path, '/');
|
||||
|
||||
return new RoninCDDirectoryNode(Common::String(start, end - start));
|
||||
}
|
||||
|
||||
|
||||
Common::SeekableReadStream *RoninCDFileNode::createReadStream() {
|
||||
return StdioStream::makeFromPath(getPath().c_str(), StdioStream::WriteMode_Read);
|
||||
}
|
||||
|
||||
AbstractFSNode *OSystem_Dreamcast::makeRootFileNode() const {
|
||||
return new RoninCDDirectoryNode("/");
|
||||
}
|
||||
|
||||
AbstractFSNode *OSystem_Dreamcast::makeCurrentDirectoryFileNode() const {
|
||||
return makeRootFileNode();
|
||||
}
|
||||
|
||||
AbstractFSNode *OSystem_Dreamcast::makeFileNodePath(const Common::String &path) const {
|
||||
AbstractFSNode *node = RoninCDFileNode::makeFileNodePath(path);
|
||||
return (node ? node : new RoninCDNonexistingNode(path));
|
||||
}
|
||||
254
backends/platform/dc/dc.h
Normal file
254
backends/platform/dc/dc.h
Normal file
@@ -0,0 +1,254 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "backends/base-backend.h"
|
||||
#include <graphics/surface.h>
|
||||
#include <graphics/paletteman.h>
|
||||
#include <ronin/soundcommon.h>
|
||||
#include "backends/timer/default/default-timer.h"
|
||||
#include "backends/audiocd/default/default-audiocd.h"
|
||||
#include "backends/fs/fs-factory.h"
|
||||
#include "audio/mixer_intern.h"
|
||||
#include "common/language.h"
|
||||
#include "common/platform.h"
|
||||
#ifdef DYNAMIC_MODULES
|
||||
#include "backends/plugins/dynamic-plugin.h"
|
||||
#endif
|
||||
|
||||
#define NUM_BUFFERS 4
|
||||
#define SOUND_BUFFER_SHIFT 3
|
||||
|
||||
class Interactive
|
||||
{
|
||||
public:
|
||||
virtual int key(int k, byte &shiftFlags) = 0;
|
||||
virtual void mouse(int x, int y) = 0;
|
||||
virtual ~Interactive() = 0;
|
||||
};
|
||||
inline Interactive::~Interactive() { }
|
||||
|
||||
#include "softkbd.h"
|
||||
|
||||
class DCHardware {
|
||||
private:
|
||||
static void dc_init_hardware();
|
||||
protected:
|
||||
DCHardware() { dc_init_hardware(); }
|
||||
};
|
||||
|
||||
class DCCDManager : public DefaultAudioCDManager {
|
||||
public:
|
||||
// Poll cdrom status
|
||||
// Returns true if cd audio is playing
|
||||
bool isPlaying() const override;
|
||||
|
||||
// Play cdrom audio track
|
||||
bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false,
|
||||
Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType) override;
|
||||
|
||||
// Stop cdrom audio track
|
||||
void stop() override;
|
||||
};
|
||||
|
||||
class OSystem_Dreamcast : private DCHardware, public EventsBaseBackend, public PaletteManager, public FilesystemFactory
|
||||
#ifdef DYNAMIC_MODULES
|
||||
, public FilePluginProvider
|
||||
#endif
|
||||
{
|
||||
|
||||
public:
|
||||
OSystem_Dreamcast();
|
||||
|
||||
virtual void initBackend();
|
||||
|
||||
// Determine whether the backend supports the specified feature.
|
||||
bool hasFeature(Feature f);
|
||||
|
||||
// En-/disable the specified feature.
|
||||
void setFeatureState(Feature f, bool enable);
|
||||
|
||||
// Query the state of the specified feature.
|
||||
bool getFeatureState(Feature f);
|
||||
|
||||
// Set colors of the palette
|
||||
PaletteManager *getPaletteManager() { return this; }
|
||||
protected:
|
||||
// PaletteManager API
|
||||
void setPalette(const byte *colors, uint start, uint num);
|
||||
void grabPalette(byte *colors, uint start, uint num) const;
|
||||
|
||||
public:
|
||||
|
||||
// Determine the pixel format currently in use for screen rendering.
|
||||
Graphics::PixelFormat getScreenFormat() const;
|
||||
|
||||
// Returns a list of all pixel formats supported by the backend.
|
||||
Common::List<Graphics::PixelFormat> getSupportedFormats() const;
|
||||
|
||||
// Set the size of the video bitmap.
|
||||
// Typically, 320x200
|
||||
void initSize(uint w, uint h, const Graphics::PixelFormat *format);
|
||||
int16 getHeight() { return _screen_h; }
|
||||
int16 getWidth() { return _screen_w; }
|
||||
|
||||
// Draw a bitmap to screen.
|
||||
// The screen will not be updated to reflect the new bitmap
|
||||
void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h);
|
||||
|
||||
virtual Graphics::Surface *lockScreen();
|
||||
virtual void unlockScreen();
|
||||
|
||||
// Update the dirty areas of the screen
|
||||
void updateScreen();
|
||||
|
||||
// Either show or hide the mouse cursor
|
||||
bool showMouse(bool visible);
|
||||
|
||||
// Move ("warp") the mouse cursor to the specified position.
|
||||
void warpMouse(int x, int y);
|
||||
|
||||
// Set the bitmap that's used when drawing the cursor.
|
||||
void setMouseCursor(const void *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format, const byte *mask);
|
||||
|
||||
// Replace the specified range of cursor the palette with new colors.
|
||||
void setCursorPalette(const byte *colors, uint start, uint num);
|
||||
|
||||
// Shaking is used in SCUMM. Set current shake position.
|
||||
void setShakePos(int shake_x_pos, int shake_y_pos);
|
||||
|
||||
// Get the number of milliseconds since the program was started.
|
||||
uint32 getMillis(bool skipRecord = false);
|
||||
|
||||
// Delay for a specified amount of milliseconds
|
||||
void delayMillis(uint msecs);
|
||||
|
||||
// Get the current time and date. Correspond to time()+localtime().
|
||||
void getTimeAndDate(TimeDate &td, bool skipRecord = false) const;
|
||||
|
||||
// Get the next event.
|
||||
// Returns true if an event was retrieved.
|
||||
bool pollEvent(Common::Event &event);
|
||||
|
||||
// Quit
|
||||
void quit();
|
||||
|
||||
// Overlay
|
||||
int16 getOverlayHeight() const;
|
||||
int16 getOverlayWidth() const;
|
||||
bool isOverlayVisible() const { return _overlay_visible; }
|
||||
void showOverlay(bool inGUI);
|
||||
void hideOverlay();
|
||||
void clearOverlay();
|
||||
void grabOverlay(Graphics::Surface &surface);
|
||||
void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h);
|
||||
virtual Graphics::PixelFormat getOverlayFormat() const { return Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12); }
|
||||
|
||||
// Mutex handling
|
||||
Common::MutexInternal *createMutex();
|
||||
|
||||
// Set a window caption or any other comparable status display to the
|
||||
// given value.
|
||||
void setWindowCaption(const Common::U32String &caption);
|
||||
|
||||
// Modulatized backend
|
||||
Audio::Mixer *getMixer() { return _mixer; }
|
||||
|
||||
// Extra SoftKbd support
|
||||
void mouseToSoftKbd(int x, int y, int &rx, int &ry) const;
|
||||
|
||||
// Filesystem
|
||||
AbstractFSNode *makeRootFileNode() const override;
|
||||
AbstractFSNode *makeCurrentDirectoryFileNode() const override;
|
||||
AbstractFSNode *makeFileNodePath(const Common::String &path) const override;
|
||||
|
||||
private:
|
||||
|
||||
Audio::MixerImpl *_mixer;
|
||||
SoftKeyboard _softkbd;
|
||||
|
||||
int _ms_cur_x, _ms_cur_y, _ms_cur_w, _ms_cur_h, _ms_old_x, _ms_old_y;
|
||||
int _ms_hotspot_x, _ms_hotspot_y, _ms_visible, _devpoll, _last_screen_refresh;
|
||||
int _current_shake_x_pos, _current_shake_y_pos, _screen_w, _screen_h;
|
||||
int _overlay_x, _overlay_y;
|
||||
unsigned char *_ms_buf;
|
||||
uint32 _ms_keycolor;
|
||||
bool _overlay_visible, _overlay_dirty, _screen_dirty;
|
||||
int _screen_buffer, _overlay_buffer, _mouse_buffer;
|
||||
bool _aspect_stretch, _softkbd_on, _enable_cursor_palette;
|
||||
bool _overlay_in_gui;
|
||||
float _overlay_fade, _xscale, _yscale, _top_offset;
|
||||
int _softkbd_motion;
|
||||
|
||||
unsigned char *screen;
|
||||
unsigned short *mouse;
|
||||
unsigned short *overlay;
|
||||
void *screen_tx[NUM_BUFFERS];
|
||||
void *mouse_tx[NUM_BUFFERS];
|
||||
void *ovl_tx[NUM_BUFFERS];
|
||||
unsigned short palette[256], cursor_palette[256];
|
||||
|
||||
Graphics::Surface _framebuffer;
|
||||
int _screenFormat, _mouseFormat;
|
||||
|
||||
int temp_sound_buffer[RING_BUFFER_SAMPLES>>SOUND_BUFFER_SHIFT];
|
||||
|
||||
uint initSound();
|
||||
void checkSound();
|
||||
|
||||
void updateScreenTextures(void);
|
||||
void updateScreenPolygons(void);
|
||||
void maybeRefreshScreen(void);
|
||||
void drawMouse(int xdraw, int ydraw, int w, int h,
|
||||
unsigned char *buf, bool visible);
|
||||
|
||||
void setScaling();
|
||||
|
||||
|
||||
Common::SaveFileManager *createSavefileManager();
|
||||
|
||||
Common::SeekableReadStream *createConfigReadStream();
|
||||
Common::WriteStream *createConfigWriteStream();
|
||||
|
||||
void logMessage(LogMessageType::Type type, const char *message);
|
||||
Common::String getSystemLanguage() const;
|
||||
|
||||
#ifdef DYNAMIC_MODULES
|
||||
class DCPlugin;
|
||||
|
||||
protected:
|
||||
Plugin* createPlugin(const Common::FSNode &node) const;
|
||||
bool isPluginFilename(const Common::FSNode &node) const;
|
||||
void addCustomDirectories(Common::FSList &dirs) const;
|
||||
public:
|
||||
PluginList getPlugins();
|
||||
private:
|
||||
const char *pluginCustomDirectory;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
extern int handleInput(struct mapledev *pad,
|
||||
int &mouse_x, int &mouse_y,
|
||||
byte &shiftFlags, Interactive *inter = NULL);
|
||||
extern bool selectGame(char *&, char *&, char *&, Common::Language &, Common::Platform &, class Icon &);
|
||||
#ifdef DYNAMIC_MODULES
|
||||
extern bool selectPluginDir(Common::String &selection, const Common::FSNode &base);
|
||||
#endif
|
||||
446
backends/platform/dc/dcloader.cpp
Normal file
446
backends/platform/dc/dcloader.cpp
Normal file
@@ -0,0 +1,446 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ronin/ronin.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "dcloader.h"
|
||||
|
||||
#include <cxxabi.h>
|
||||
|
||||
#ifdef DL_DEBUG
|
||||
#define DBG(x) reportf x
|
||||
#else
|
||||
#define DBG(x) do{}while(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) != (ssize_t)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 *)(void *)(((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 (phdr.p_memsz > phdr.p_filesz)
|
||||
memset(((char *)segment) + phdr.p_filesz, 0, phdr.p_memsz - phdr.p_filesz);
|
||||
|
||||
if (lseek(fd, phdr.p_offset, SEEK_SET)<0 ||
|
||||
read(fd, segment, phdr.p_filesz) != (ssize_t)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)) !=
|
||||
(ssize_t)(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) !=
|
||||
(ssize_t)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) !=
|
||||
(ssize_t)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) &&
|
||||
(int)shdr[i].sh_link == symtab_sect && shdr[i].sh_info < ehdr.e_shnum &&
|
||||
(shdr[shdr[i].sh_info].sh_flags & 2))
|
||||
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);
|
||||
|
||||
int oldmask = getimask();
|
||||
setimask(15);
|
||||
purge_copyback();
|
||||
flush_instruction_cache();
|
||||
setimask(oldmask);
|
||||
|
||||
ctors_start = symbol("__plugin_ctors");
|
||||
ctors_end = symbol("__plugin_ctors_end");
|
||||
dtors_start = symbol("__plugin_dtors");
|
||||
dtors_end = symbol("__plugin_dtors_end");
|
||||
dso_handle = symbol("__dso_handle");
|
||||
|
||||
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 (dso_handle != NULL) {
|
||||
__cxxabiv1::__cxa_finalize(dso_handle);
|
||||
dso_handle = NULL;
|
||||
}
|
||||
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) {
|
||||
Common::strcpy_s(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) {
|
||||
Common::strcpy_s(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();
|
||||
}
|
||||
63
backends/platform/dc/dcloader.h
Normal file
63
backends/platform/dc/dcloader.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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, *dso_handle;
|
||||
|
||||
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
|
||||
315
backends/platform/dc/dcmain.cpp
Normal file
315
backends/platform/dc/dcmain.cpp
Normal file
@@ -0,0 +1,315 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
|
||||
#include <common/scummsys.h>
|
||||
#include <engines/engine.h>
|
||||
#include <base/main.h>
|
||||
#include <base/plugins.h>
|
||||
#include "dc.h"
|
||||
#include "dcutils.h"
|
||||
#include "icon.h"
|
||||
#include "DCLauncherDialog.h"
|
||||
#include "backends/mutex/null/null-mutex.h"
|
||||
#include <common/config-manager.h>
|
||||
#include <common/memstream.h>
|
||||
#include <common/endian.h>
|
||||
|
||||
#include "audio/mixer_intern.h"
|
||||
|
||||
|
||||
Icon icon;
|
||||
char gGameName[32];
|
||||
|
||||
|
||||
OSystem_Dreamcast::OSystem_Dreamcast()
|
||||
: _devpoll(0), screen(NULL), mouse(NULL), overlay(NULL), _softkbd(this),
|
||||
_ms_buf(NULL), _mixer(NULL),
|
||||
_current_shake_x_pos(0), _current_shake_y_pos(0), _aspect_stretch(false), _softkbd_on(false),
|
||||
_softkbd_motion(0), _enable_cursor_palette(false), _overlay_in_gui(false), _screenFormat(0)
|
||||
{
|
||||
memset(screen_tx, 0, sizeof(screen_tx));
|
||||
memset(mouse_tx, 0, sizeof(mouse_tx));
|
||||
memset(ovl_tx, 0, sizeof(ovl_tx));
|
||||
_fsFactory = this;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::initBackend()
|
||||
{
|
||||
ConfMan.setInt("autosave_period", 0);
|
||||
_savefileManager = createSavefileManager();
|
||||
_timerManager = new DefaultTimerManager();
|
||||
|
||||
uint sampleRate = initSound();
|
||||
_mixer = new Audio::MixerImpl(sampleRate);
|
||||
_mixer->setReady(true);
|
||||
|
||||
_audiocdManager = new DCCDManager();
|
||||
|
||||
EventsBaseBackend::initBackend();
|
||||
}
|
||||
|
||||
|
||||
/* CD Audio */
|
||||
static bool find_track(int track, int &first_sec, int &last_sec)
|
||||
{
|
||||
struct TOC *toc = cdfs_gettoc();
|
||||
if (!toc)
|
||||
return false;
|
||||
int i, first, last;
|
||||
first = TOC_TRACK(toc->first);
|
||||
last = TOC_TRACK(toc->last);
|
||||
if (first < 1 || last > 99 || first > last)
|
||||
return false;
|
||||
for (i=first; i<=last; i++)
|
||||
if (!(TOC_CTRL(toc->entry[i-1])&4)) {
|
||||
if (track==1) {
|
||||
first_sec = TOC_LBA(toc->entry[i-1]);
|
||||
last_sec = TOC_LBA(toc->entry[i]);
|
||||
return true;
|
||||
} else
|
||||
--track;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DCCDManager::play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate,
|
||||
Audio::Mixer::SoundType soundType) {
|
||||
// Prefer emulation
|
||||
if (DefaultAudioCDManager::play(track, numLoops, startFrame, duration, onlyEmulate, soundType))
|
||||
return true;
|
||||
|
||||
// If we're playing now return here
|
||||
if (isPlaying()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we should only play emulated tracks stop here.
|
||||
if (onlyEmulate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int firstSec, lastSec;
|
||||
#if 1
|
||||
if (numLoops)
|
||||
--numLoops;
|
||||
#endif
|
||||
|
||||
if (numLoops > 14)
|
||||
numLoops = 14;
|
||||
else if (numLoops < 0)
|
||||
numLoops = 15; // infinity
|
||||
|
||||
if (!find_track(track, firstSec, lastSec))
|
||||
return false;
|
||||
|
||||
if (duration)
|
||||
lastSec = firstSec + startFrame + duration;
|
||||
|
||||
firstSec += startFrame;
|
||||
play_cdda_sectors(firstSec, lastSec, numLoops);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DCCDManager::stop() {
|
||||
DefaultAudioCDManager::stop();
|
||||
stop_cdda();
|
||||
}
|
||||
|
||||
bool DCCDManager::isPlaying() const {
|
||||
if (DefaultAudioCDManager::isPlaying())
|
||||
return true;
|
||||
|
||||
return getCdState() == 3;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::setWindowCaption(const Common::U32String &caption)
|
||||
{
|
||||
Common::strlcpy(gGameName, caption.encode(Common::kISO8859_1).c_str(), 32);
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::quit() {
|
||||
(*(void(**)(int))0x8c0000e0)(0);
|
||||
}
|
||||
|
||||
/* Mutex handling */
|
||||
Common::MutexInternal *OSystem_Dreamcast::createMutex()
|
||||
{
|
||||
return new NullMutexInternal();
|
||||
}
|
||||
|
||||
/* Features */
|
||||
bool OSystem_Dreamcast::hasFeature(Feature f)
|
||||
{
|
||||
switch(f) {
|
||||
case kFeatureAspectRatioCorrection:
|
||||
case kFeatureVirtualKeyboard:
|
||||
case kFeatureOverlaySupportsAlpha:
|
||||
case kFeatureCursorPalette:
|
||||
case kFeatureCursorAlpha:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::setFeatureState(Feature f, bool enable)
|
||||
{
|
||||
switch(f) {
|
||||
case kFeatureAspectRatioCorrection:
|
||||
_aspect_stretch = enable;
|
||||
if (screen)
|
||||
setScaling();
|
||||
break;
|
||||
case kFeatureVirtualKeyboard:
|
||||
_softkbd_on = enable;
|
||||
break;
|
||||
case kFeatureCursorPalette:
|
||||
_enable_cursor_palette = enable;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool OSystem_Dreamcast::getFeatureState(Feature f)
|
||||
{
|
||||
switch(f) {
|
||||
case kFeatureAspectRatioCorrection:
|
||||
return _aspect_stretch;
|
||||
case kFeatureVirtualKeyboard:
|
||||
return _softkbd_on;
|
||||
case kFeatureCursorPalette:
|
||||
return _enable_cursor_palette;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::getTimeAndDate(TimeDate &td, bool skipRecord) const {
|
||||
time_t curTime;
|
||||
time(&curTime);
|
||||
struct tm t = *localtime(&curTime);
|
||||
td.tm_sec = t.tm_sec;
|
||||
td.tm_min = t.tm_min;
|
||||
td.tm_hour = t.tm_hour;
|
||||
td.tm_mday = t.tm_mday;
|
||||
td.tm_mon = t.tm_mon;
|
||||
td.tm_year = t.tm_year;
|
||||
td.tm_wday = t.tm_wday;
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *OSystem_Dreamcast::createConfigReadStream() {
|
||||
Common::FSNode file("/scummvm.ini");
|
||||
Common::SeekableReadStream *s = file.createReadStream();
|
||||
return s? s : new Common::MemoryReadStream((const byte *)"", 0);
|
||||
}
|
||||
|
||||
Common::WriteStream *OSystem_Dreamcast::createConfigWriteStream() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::logMessage(LogMessageType::Type type, const char *message) {
|
||||
#ifndef NOSERIAL
|
||||
report(message);
|
||||
#endif
|
||||
}
|
||||
|
||||
Common::String OSystem_Dreamcast::getSystemLanguage() const {
|
||||
static const char *languages[] = {
|
||||
"ja_JP",
|
||||
"en_US",
|
||||
"de_DE",
|
||||
"fr_FR",
|
||||
"es_ES",
|
||||
"it_IT"
|
||||
};
|
||||
int l = DC_Flash::get_locale_setting();
|
||||
if (l<0 || ((unsigned)l)>=sizeof(languages)/sizeof(languages[0]))
|
||||
l = 1;
|
||||
return Common::String(languages[l]);
|
||||
}
|
||||
|
||||
|
||||
void DCHardware::dc_init_hardware()
|
||||
{
|
||||
#ifndef NOSERIAL
|
||||
serial_init(57600);
|
||||
usleep(2000000);
|
||||
printf("Serial OK\r\n");
|
||||
#endif
|
||||
|
||||
cdfs_init();
|
||||
maple_init();
|
||||
dc_setup_ta();
|
||||
init_arm();
|
||||
}
|
||||
|
||||
static OSystem_Dreamcast osys_dc;
|
||||
|
||||
int main()
|
||||
{
|
||||
static const char *argv[] = { "scummvm", NULL, };
|
||||
static int argc = 1;
|
||||
|
||||
g_system = &osys_dc;
|
||||
|
||||
#ifdef DYNAMIC_MODULES
|
||||
PluginManager::instance().addPluginProvider(&osys_dc);
|
||||
#endif
|
||||
|
||||
scummvm_main(argc, argv);
|
||||
|
||||
g_system->quit();
|
||||
}
|
||||
|
||||
int DCLauncherDialog::runModal()
|
||||
{
|
||||
char *engineId = NULL, *gameId = NULL, *dir = NULL;
|
||||
Common::Language language = Common::UNK_LANG;
|
||||
Common::Platform platform = Common::kPlatformUnknown;
|
||||
|
||||
if (!selectGame(engineId, gameId, dir, language, platform, icon))
|
||||
g_system->quit();
|
||||
|
||||
// Set the game path.
|
||||
ConfMan.addGameDomain(gameId);
|
||||
ConfMan.set("engineid", engineId, gameId);
|
||||
ConfMan.set("gameid", gameId, gameId);
|
||||
|
||||
if (dir != NULL)
|
||||
ConfMan.setPath("path", dir, gameId);
|
||||
|
||||
// Set the game language.
|
||||
if (language != Common::UNK_LANG)
|
||||
ConfMan.set("language", Common::getLanguageCode(language), gameId);
|
||||
|
||||
// Set the game platform.
|
||||
if (platform != Common::kPlatformUnknown)
|
||||
ConfMan.set("platform", Common::getPlatformCode(platform), gameId);
|
||||
|
||||
// Set the target.
|
||||
ConfMan.setActiveDomain(gameId);
|
||||
|
||||
return 0;
|
||||
}
|
||||
250
backends/platform/dc/dcutils.cpp
Normal file
250
backends/platform/dc/dcutils.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_chdir
|
||||
|
||||
#include "dc.h"
|
||||
#include "dcutils.h"
|
||||
#include <ronin/gddrive.h>
|
||||
|
||||
|
||||
int getCdState()
|
||||
{
|
||||
unsigned int param[4];
|
||||
gdGdcGetDrvStat(param);
|
||||
return param[0];
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
int dummy_cdfs_get_volume_id(char *, unsigned int) {
|
||||
return -1;
|
||||
}
|
||||
int cdfs_get_volume_id(char *, unsigned int) __attribute__ ((weak, alias ("dummy_cdfs_get_volume_id")));
|
||||
}
|
||||
|
||||
DiscLabel::DiscLabel() {
|
||||
if (cdfs_get_volume_id(buf, 32) < 0)
|
||||
memset(buf, '*', 32);
|
||||
}
|
||||
|
||||
bool DiscLabel::operator==(const DiscLabel &other) const {
|
||||
return !memcmp(buf, other.buf, 32);
|
||||
}
|
||||
|
||||
void DiscLabel::get(char *p) const {
|
||||
memcpy(p, buf, 32);
|
||||
p[32] = 0;
|
||||
}
|
||||
|
||||
|
||||
void draw_solid_quad(float x1, float y1, float x2, float y2,
|
||||
int c0, int c1, int c2, int c3)
|
||||
{
|
||||
struct polygon_list mypoly;
|
||||
struct packed_colour_vertex_list myvertex;
|
||||
|
||||
mypoly.cmd =
|
||||
TA_CMD_POLYGON|TA_CMD_POLYGON_TYPE_OPAQUE|TA_CMD_POLYGON_SUBLIST|
|
||||
TA_CMD_POLYGON_STRIPLENGTH_2|TA_CMD_POLYGON_PACKED_COLOUR|
|
||||
TA_CMD_POLYGON_GOURAUD_SHADING;
|
||||
mypoly.mode1 = TA_POLYMODE1_Z_ALWAYS|TA_POLYMODE1_NO_Z_UPDATE;
|
||||
mypoly.mode2 =
|
||||
TA_POLYMODE2_BLEND_SRC|TA_POLYMODE2_FOG_DISABLED;
|
||||
mypoly.texture = 0;
|
||||
|
||||
mypoly.red = mypoly.green = mypoly.blue = mypoly.alpha = 0;
|
||||
|
||||
ta_commit_list(&mypoly);
|
||||
|
||||
myvertex.cmd = TA_CMD_VERTEX;
|
||||
myvertex.ocolour = 0;
|
||||
myvertex.z = 0.5;
|
||||
myvertex.u = 0.0;
|
||||
myvertex.v = 0.0;
|
||||
|
||||
myvertex.colour = c0;
|
||||
myvertex.x = x1;
|
||||
myvertex.y = y1;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.colour = c1;
|
||||
myvertex.x = x2;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.colour = c2;
|
||||
myvertex.x = x1;
|
||||
myvertex.y = y2;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.colour = c3;
|
||||
myvertex.x = x2;
|
||||
myvertex.cmd |= TA_CMD_VERTEX_EOS;
|
||||
ta_commit_list(&myvertex);
|
||||
}
|
||||
|
||||
void draw_trans_quad(float x1, float y1, float x2, float y2,
|
||||
int c0, int c1, int c2, int c3)
|
||||
{
|
||||
struct polygon_list mypoly;
|
||||
struct packed_colour_vertex_list myvertex;
|
||||
|
||||
mypoly.cmd =
|
||||
TA_CMD_POLYGON|TA_CMD_POLYGON_TYPE_TRANSPARENT|TA_CMD_POLYGON_SUBLIST|
|
||||
TA_CMD_POLYGON_STRIPLENGTH_2|TA_CMD_POLYGON_PACKED_COLOUR|
|
||||
TA_CMD_POLYGON_GOURAUD_SHADING;
|
||||
mypoly.mode1 = TA_POLYMODE1_Z_ALWAYS|TA_POLYMODE1_NO_Z_UPDATE;
|
||||
mypoly.mode2 =
|
||||
TA_POLYMODE2_BLEND_SRC_ALPHA|TA_POLYMODE2_BLEND_DST_INVALPHA|
|
||||
TA_POLYMODE2_FOG_DISABLED|TA_POLYMODE2_ENABLE_ALPHA;
|
||||
mypoly.texture = 0;
|
||||
|
||||
mypoly.red = mypoly.green = mypoly.blue = mypoly.alpha = 0;
|
||||
|
||||
ta_commit_list(&mypoly);
|
||||
|
||||
myvertex.cmd = TA_CMD_VERTEX;
|
||||
myvertex.ocolour = 0;
|
||||
myvertex.z = 0.5;
|
||||
myvertex.u = 0.0;
|
||||
myvertex.v = 0.0;
|
||||
|
||||
myvertex.colour = c0;
|
||||
myvertex.x = x1;
|
||||
myvertex.y = y1;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.colour = c1;
|
||||
myvertex.x = x2;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.colour = c2;
|
||||
myvertex.x = x1;
|
||||
myvertex.y = y2;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.colour = c3;
|
||||
myvertex.x = x2;
|
||||
myvertex.cmd |= TA_CMD_VERTEX_EOS;
|
||||
ta_commit_list(&myvertex);
|
||||
}
|
||||
|
||||
DiscSwap::DiscSwap(const char *label, unsigned int argb_) : argb(argb_) {
|
||||
x = 320 - 7 * strlen(label);
|
||||
lab.create_texture(label);
|
||||
}
|
||||
|
||||
void DiscSwap::run()
|
||||
{
|
||||
int wasopen = 0;
|
||||
for (;;) {
|
||||
int s = getCdState();
|
||||
if (s >= 6)
|
||||
wasopen = 1;
|
||||
if (s > 0 && s < 6 && wasopen) {
|
||||
cdfs_reinit();
|
||||
chdir("/"); // Expect this one to fail with ERR_DISKCHG
|
||||
chdir("/"); // but this one to succeed
|
||||
return;
|
||||
}
|
||||
|
||||
ta_begin_frame();
|
||||
background();
|
||||
ta_commit_end();
|
||||
lab.draw(x, 200.0, argb);
|
||||
ta_commit_frame();
|
||||
|
||||
interact();
|
||||
}
|
||||
}
|
||||
|
||||
namespace DC_Flash {
|
||||
|
||||
static int syscall_info_flash(int sect, int *info)
|
||||
{
|
||||
return (*(int (**)(int, void*, int, int))0x8c0000b8)(sect,info,0,0);
|
||||
}
|
||||
|
||||
static int syscall_read_flash(int offs, void *buf, int cnt)
|
||||
{
|
||||
return (*(int (**)(int, void*, int, int))0x8c0000b8)(offs,buf,cnt,1);
|
||||
}
|
||||
|
||||
static int flash_crc(const char *buf, int size)
|
||||
{
|
||||
int i, c, n = -1;
|
||||
for(i=0; i<size; i++) {
|
||||
n ^= (buf[i]<<8);
|
||||
for(c=0; c<8; c++)
|
||||
if(n & 0x8000)
|
||||
n = (n << 1) ^ 4129;
|
||||
else
|
||||
n <<= 1;
|
||||
}
|
||||
return (unsigned short)~n;
|
||||
}
|
||||
|
||||
int flash_read_sector(int partition, int sec, unsigned char *dst)
|
||||
{
|
||||
int s, r, n, b, bmb, got=0;
|
||||
int info[2];
|
||||
char buf[64];
|
||||
char bm[64];
|
||||
|
||||
if((r = syscall_info_flash(partition, info))<0)
|
||||
return r;
|
||||
|
||||
if((r = syscall_read_flash(info[0], buf, 64))<0)
|
||||
return r;
|
||||
|
||||
if(memcmp(buf, "KATANA_FLASH", 12) ||
|
||||
buf[16] != partition || buf[17] != 0)
|
||||
return -2;
|
||||
|
||||
n = (info[1]>>6)-1-((info[1] + 0x7fff)>>15);
|
||||
bmb = n+1;
|
||||
for(b = 0; b < n; b++) {
|
||||
if(!(b&511)) {
|
||||
if((r = syscall_read_flash(info[0] + (bmb++ << 6), bm, 64))<0)
|
||||
return r;
|
||||
}
|
||||
if(!(bm[(b>>3)&63] & (0x80>>(b&7)))) {
|
||||
if((r = syscall_read_flash(info[0] + ((b+1) << 6), buf, 64))<0)
|
||||
return r;
|
||||
else if((s=READ_LE_UINT16(buf+0)) == sec &&
|
||||
flash_crc(buf, 62) == READ_LE_UINT16(buf+62)) {
|
||||
memcpy(dst+(s-sec)*60, buf+2, 60);
|
||||
got=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return got;
|
||||
}
|
||||
|
||||
int get_locale_setting()
|
||||
{
|
||||
unsigned char data[60];
|
||||
if (flash_read_sector(2,5,data) == 1)
|
||||
return data[5];
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // End of namespace DC_Flash
|
||||
75
backends/platform/dc/dcutils.h
Normal file
75
backends/platform/dc/dcutils.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DC_DCUTILS_H
|
||||
#define DC_DCUTILS_H
|
||||
|
||||
extern int getCdState();
|
||||
|
||||
class TextureStack {
|
||||
private:
|
||||
void *mark;
|
||||
public:
|
||||
TextureStack() {
|
||||
ta_sync();
|
||||
mark = ta_txmark();
|
||||
}
|
||||
~TextureStack() {
|
||||
ta_sync();
|
||||
ta_txrelease(mark);
|
||||
}
|
||||
};
|
||||
|
||||
class DiscLabel {
|
||||
private:
|
||||
char buf[32];
|
||||
public:
|
||||
DiscLabel();
|
||||
bool operator==(const DiscLabel &other) const;
|
||||
void get(char *p) const;
|
||||
};
|
||||
|
||||
class DiscSwap : TextureStack {
|
||||
private:
|
||||
unsigned int argb;
|
||||
float x;
|
||||
Label lab;
|
||||
protected:
|
||||
virtual void background() {}
|
||||
virtual void interact() {}
|
||||
public:
|
||||
DiscSwap(const char *label, unsigned int argb);
|
||||
virtual ~DiscSwap() {}
|
||||
void run();
|
||||
};
|
||||
|
||||
extern void draw_solid_quad(float x1, float y1, float x2, float y2,
|
||||
int c0, int c1, int c2, int c3);
|
||||
extern void draw_trans_quad(float x1, float y1, float x2, float y2,
|
||||
int c0, int c1, int c2, int c3);
|
||||
|
||||
namespace DC_Flash {
|
||||
int flash_read_sector(int partition, int sec, unsigned char *dst);
|
||||
int get_locale_setting();
|
||||
} // End of namespace DC_Flash
|
||||
|
||||
|
||||
#endif /* DC_DCUTILS_H */
|
||||
66
backends/platform/dc/deficon.h
Normal file
66
backends/platform/dc/deficon.h
Normal file
@@ -0,0 +1,66 @@
|
||||
static const unsigned char scummvm_icon[] = {
|
||||
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x01, 0x00,
|
||||
0x04, 0x00, 0xe8, 0x02, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x28, 0x00,
|
||||
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x12, 0x0b,
|
||||
0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
|
||||
0x00, 0x00, 0x33, 0x33, 0x33, 0x00, 0x33, 0x55, 0x22, 0x00, 0x33, 0x33,
|
||||
0x33, 0x00, 0x33, 0x99, 0x00, 0x00, 0x33, 0xcc, 0x00, 0x00, 0x33, 0x33,
|
||||
0x33, 0x00, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
0x65, 0x52, 0x52, 0x56, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x22, 0x00, 0x00, 0x00, 0x00, 0x22, 0x56, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x20, 0x00, 0x00, 0x00, 0x10, 0x01,
|
||||
0x00, 0x02, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x62, 0x00, 0x01,
|
||||
0x11, 0x31, 0x11, 0x11, 0x10, 0x00, 0x25, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x00, 0x01, 0x13, 0x34, 0x44, 0x44, 0x43, 0x31, 0x00, 0x00, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x60, 0x00, 0x11, 0x33, 0x44, 0x44, 0x44, 0x44,
|
||||
0x43, 0x31, 0x00, 0x26, 0x66, 0x66, 0x66, 0x66, 0x20, 0x01, 0x34, 0x44,
|
||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x43, 0x00, 0x05, 0x66, 0x66, 0x66, 0x66,
|
||||
0x00, 0x13, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x43, 0x30, 0x02,
|
||||
0x66, 0x66, 0x66, 0x66, 0x00, 0x14, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x44, 0x41, 0x00, 0x66, 0x66, 0x66, 0x66, 0x20, 0x14, 0x44, 0x44,
|
||||
0x43, 0x31, 0x13, 0x44, 0x44, 0x44, 0x41, 0x00, 0x66, 0x66, 0x66, 0x66,
|
||||
0x50, 0x01, 0x44, 0x43, 0x10, 0x00, 0x03, 0x44, 0x44, 0x44, 0x41, 0x00,
|
||||
0x66, 0x66, 0x66, 0x66, 0x65, 0x00, 0x14, 0x30, 0x00, 0x00, 0x13, 0x44,
|
||||
0x44, 0x44, 0x43, 0x00, 0x56, 0x66, 0x66, 0x66, 0x66, 0x50, 0x01, 0x10,
|
||||
0x00, 0x03, 0x34, 0x44, 0x44, 0x44, 0x43, 0x00, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x65, 0x00, 0x00, 0x11, 0x34, 0x44, 0x44, 0x44, 0x44, 0x41, 0x02,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x01, 0x13, 0x44, 0x44, 0x44,
|
||||
0x44, 0x44, 0x40, 0x05, 0x66, 0x66, 0x66, 0x66, 0x66, 0x62, 0x00, 0x13,
|
||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x30, 0x06, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x50, 0x01, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x43, 0x00, 0x56,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x13, 0x44, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x40, 0x02, 0x66, 0x66, 0x66, 0x66, 0x66, 0x65, 0x00, 0x34, 0x44,
|
||||
0x44, 0x44, 0x44, 0x44, 0x43, 0x00, 0x26, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
0x62, 0x01, 0x44, 0x44, 0x44, 0x44, 0x44, 0x43, 0x10, 0x00, 0x05, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x60, 0x01, 0x44, 0x44, 0x44, 0x44, 0x43, 0x10,
|
||||
0x01, 0x10, 0x02, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x01, 0x44, 0x44,
|
||||
0x44, 0x44, 0x30, 0x00, 0x01, 0x31, 0x00, 0x26, 0x66, 0x66, 0x66, 0x66,
|
||||
0x60, 0x01, 0x44, 0x44, 0x44, 0x43, 0x00, 0x01, 0x14, 0x44, 0x10, 0x05,
|
||||
0x66, 0x66, 0x66, 0x66, 0x60, 0x01, 0x44, 0x44, 0x44, 0x43, 0x31, 0x34,
|
||||
0x44, 0x44, 0x30, 0x02, 0x66, 0x66, 0x66, 0x66, 0x62, 0x01, 0x44, 0x44,
|
||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x41, 0x00, 0x66, 0x66, 0x66, 0x66,
|
||||
0x65, 0x00, 0x14, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x02,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x20, 0x03, 0x44, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x43, 0x00, 0x06, 0x66, 0x66, 0x66, 0x66, 0x66, 0x50, 0x01, 0x34,
|
||||
0x44, 0x44, 0x44, 0x44, 0x43, 0x00, 0x02, 0x56, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x65, 0x00, 0x01, 0x34, 0x44, 0x44, 0x33, 0x10, 0x00, 0x26, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x05, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x52,
|
||||
0x00, 0x00, 0x00, 0x00, 0x25, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x65, 0x55, 0x55, 0x56, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x66, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0x00,
|
||||
0x00, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x3f, 0xf8, 0x00,
|
||||
0x00, 0x1f, 0xf0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xf0, 0x00,
|
||||
0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xf8, 0x00,
|
||||
0x00, 0x07, 0xfc, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x0f, 0xff, 0x00,
|
||||
0x00, 0x0f, 0xfe, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x1f, 0xfc, 0x00,
|
||||
0x00, 0x3f, 0xf8, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00, 0x3f, 0xf8, 0x00,
|
||||
0x00, 0x3f, 0xf8, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x0f, 0xf8, 0x00,
|
||||
0x00, 0x0f, 0xf8, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x0f, 0xfc, 0x00,
|
||||
0x00, 0x1f, 0xfc, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0x00,
|
||||
0x00, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xf8, 0x1f, 0xff
|
||||
};
|
||||
713
backends/platform/dc/display.cpp
Normal file
713
backends/platform/dc/display.cpp
Normal file
@@ -0,0 +1,713 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define RONIN_TIMER_ACCESS
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "graphics/blit.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "dc.h"
|
||||
|
||||
#define SCREEN_W 640
|
||||
#define SCREEN_H 480
|
||||
#define MOUSE_W 128
|
||||
#define MOUSE_H 128
|
||||
|
||||
#define OVL_W 320
|
||||
#define OVL_H 200
|
||||
#define OVL_TXSTRIDE 512
|
||||
|
||||
#define LEFT_OFFSET (_xscale*_current_shake_x_pos)
|
||||
#define TOP_OFFSET (_top_offset+_yscale*_current_shake_y_pos)
|
||||
|
||||
static const struct {
|
||||
Graphics::PixelFormat pixelFormat;
|
||||
unsigned int textureFormat;
|
||||
operator const Graphics::PixelFormat&() const { return pixelFormat; }
|
||||
} screenFormats[] = {
|
||||
/* Note: These are ordered by _increasing_ preference, so that
|
||||
CLUT8 appears at index 0. getSupportedFormats() will return
|
||||
them in reversed order. */
|
||||
{ Graphics::PixelFormat::createFormatCLUT8(), TA_TEXTUREMODE_ARGB1555 },
|
||||
{ Graphics::PixelFormat(2,4,4,4,4,8,4,0,12), TA_TEXTUREMODE_ARGB4444 },
|
||||
{ Graphics::PixelFormat(2,5,5,5,1,10,5,0,15), TA_TEXTUREMODE_ARGB1555 },
|
||||
{ Graphics::PixelFormat(2,5,6,5,0,11,5,0,0), TA_TEXTUREMODE_RGB565 },
|
||||
};
|
||||
#define NUM_FORMATS (sizeof(screenFormats)/sizeof(screenFormats[0]))
|
||||
|
||||
|
||||
#define QACR0 (*(volatile unsigned int *)(void *)0xff000038)
|
||||
#define QACR1 (*(volatile unsigned int *)(void *)0xff00003c)
|
||||
|
||||
|
||||
#define COPYPIXEL(n) do { \
|
||||
unsigned short _tmp = pal[*s++]; \
|
||||
d[n] = _tmp|(pal[*s++]<<16); \
|
||||
} while (0)
|
||||
|
||||
static void texture_memcpy64_pal(void *dest, void *src, int cnt, unsigned short *pal)
|
||||
{
|
||||
unsigned char *s = (unsigned char *)src;
|
||||
unsigned int *d = (unsigned int *)(void *)
|
||||
(0xe0000000 | (((unsigned long)dest) & 0x03ffffc0));
|
||||
QACR0 = ((0xa4000000>>26)<<2)&0x1c;
|
||||
QACR1 = ((0xa4000000>>26)<<2)&0x1c;
|
||||
while (cnt--) {
|
||||
COPYPIXEL(0);
|
||||
COPYPIXEL(1);
|
||||
COPYPIXEL(2);
|
||||
COPYPIXEL(3);
|
||||
asm("pref @%0" : : "r" (s+4*16));
|
||||
COPYPIXEL(4);
|
||||
COPYPIXEL(5);
|
||||
COPYPIXEL(6);
|
||||
COPYPIXEL(7);
|
||||
asm("pref @%0" : : "r" (d));
|
||||
d += 8;
|
||||
COPYPIXEL(0);
|
||||
COPYPIXEL(1);
|
||||
COPYPIXEL(2);
|
||||
COPYPIXEL(3);
|
||||
asm("pref @%0" : : "r" (s+4*16));
|
||||
COPYPIXEL(4);
|
||||
COPYPIXEL(5);
|
||||
COPYPIXEL(6);
|
||||
COPYPIXEL(7);
|
||||
asm("pref @%0" : : "r" (d));
|
||||
d += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void texture_memcpy64(void *dest, void *src, int cnt)
|
||||
{
|
||||
unsigned int *s = (unsigned int *)src;
|
||||
unsigned int *d = (unsigned int *)(void *)
|
||||
(0xe0000000 | (((unsigned long)dest) & 0x03ffffc0));
|
||||
QACR0 = ((0xa4000000>>26)<<2)&0x1c;
|
||||
QACR1 = ((0xa4000000>>26)<<2)&0x1c;
|
||||
while (cnt--) {
|
||||
d[0] = *s++;
|
||||
d[1] = *s++;
|
||||
d[2] = *s++;
|
||||
d[3] = *s++;
|
||||
asm("pref @%0" : : "r" (s+16));
|
||||
d[4] = *s++;
|
||||
d[5] = *s++;
|
||||
d[6] = *s++;
|
||||
d[7] = *s++;
|
||||
asm("pref @%0" : : "r" (d));
|
||||
d += 8;
|
||||
d[0] = *s++;
|
||||
d[1] = *s++;
|
||||
d[2] = *s++;
|
||||
d[3] = *s++;
|
||||
asm("pref @%0" : : "r" (s+16));
|
||||
d[4] = *s++;
|
||||
d[5] = *s++;
|
||||
d[6] = *s++;
|
||||
d[7] = *s++;
|
||||
asm("pref @%0" : : "r" (d));
|
||||
d += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void commit_dummy_transpoly()
|
||||
{
|
||||
struct polygon_list mypoly;
|
||||
|
||||
mypoly.cmd =
|
||||
TA_CMD_POLYGON|TA_CMD_POLYGON_TYPE_TRANSPARENT|TA_CMD_POLYGON_SUBLIST|
|
||||
TA_CMD_POLYGON_STRIPLENGTH_2|TA_CMD_POLYGON_PACKED_COLOUR;
|
||||
mypoly.mode1 = TA_POLYMODE1_Z_ALWAYS|TA_POLYMODE1_NO_Z_UPDATE;
|
||||
mypoly.mode2 =
|
||||
TA_POLYMODE2_BLEND_SRC_ALPHA|TA_POLYMODE2_BLEND_DST_INVALPHA|
|
||||
TA_POLYMODE2_FOG_DISABLED|TA_POLYMODE2_ENABLE_ALPHA;
|
||||
mypoly.texture = 0;
|
||||
mypoly.red = mypoly.green = mypoly.blue = mypoly.alpha = 0;
|
||||
ta_commit_list(&mypoly);
|
||||
}
|
||||
|
||||
|
||||
void OSystem_Dreamcast::setPalette(const byte *colors, uint start, uint num)
|
||||
{
|
||||
unsigned short *dst = palette + start;
|
||||
if (num>0)
|
||||
while ( num-- ) {
|
||||
*dst++ = ((colors[0]<<7)&0x7c00)|
|
||||
((colors[1]<<2)&0x03e0)|
|
||||
((colors[2]>>3)&0x001f);
|
||||
colors += 3;
|
||||
}
|
||||
_screen_dirty = true;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::setCursorPalette(const byte *colors, uint start, uint num)
|
||||
{
|
||||
unsigned short *dst = cursor_palette + start;
|
||||
if (num>0)
|
||||
while ( num-- ) {
|
||||
*dst++ = ((colors[0]<<7)&0x7c00)|
|
||||
((colors[1]<<2)&0x03e0)|
|
||||
((colors[2]>>3)&0x001f);
|
||||
colors += 3;
|
||||
}
|
||||
_enable_cursor_palette = true;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::grabPalette(byte *colors, uint start, uint num) const
|
||||
{
|
||||
const unsigned short *src = palette + start;
|
||||
if (num>0)
|
||||
while ( num-- ) {
|
||||
unsigned short p = *src++;
|
||||
colors[0] = ((p&0x7c00)>>7)|((p&0x7000)>>12);
|
||||
colors[1] = ((p&0x03e0)>>2)|((p&0x0380)>>7);
|
||||
colors[2] = ((p&0x001f)<<3)|((p&0x001c)>>2);
|
||||
colors += 3;
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::PixelFormat OSystem_Dreamcast::getScreenFormat() const
|
||||
{
|
||||
return screenFormats[_screenFormat];
|
||||
}
|
||||
|
||||
Common::List<Graphics::PixelFormat> OSystem_Dreamcast::getSupportedFormats() const
|
||||
{
|
||||
Common::List<Graphics::PixelFormat> list;
|
||||
unsigned i;
|
||||
for (i=0; i<NUM_FORMATS; i++)
|
||||
list.push_front(screenFormats[i]);
|
||||
return list;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::setScaling()
|
||||
{
|
||||
if (_screen_w > 400) {
|
||||
_xscale = _yscale = 1.0;
|
||||
_top_offset = (SCREEN_H-_screen_h)>>1;
|
||||
} else if (_aspect_stretch && _screen_w == 320 && _screen_h == 200) {
|
||||
_xscale = SCREEN_W/320.0;
|
||||
_yscale = SCREEN_H/200.0;
|
||||
_top_offset = 0;
|
||||
} else {
|
||||
_xscale = _yscale = 2.0;
|
||||
_top_offset = (SCREEN_H>>1)-_screen_h;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::initSize(uint w, uint h, const Graphics::PixelFormat *format)
|
||||
{
|
||||
assert(w <= SCREEN_W && h <= SCREEN_H);
|
||||
|
||||
int i = 0;
|
||||
if (format != NULL)
|
||||
for (i=NUM_FORMATS-1; i>0; --i)
|
||||
if (*format == screenFormats[i])
|
||||
break;
|
||||
_screenFormat = i;
|
||||
|
||||
_overlay_visible = false;
|
||||
_overlay_fade = 0.0;
|
||||
_screen_w = w;
|
||||
_screen_h = h;
|
||||
_overlay_x = (w-OVL_W)/2;
|
||||
_overlay_y = (h-OVL_H)/2;
|
||||
if (_overlay_x<0) _overlay_x = 0;
|
||||
if (_overlay_y<0) _overlay_y = 0;
|
||||
setScaling();
|
||||
ta_sync();
|
||||
if (!screen)
|
||||
screen = new unsigned char[SCREEN_W*SCREEN_H*2];
|
||||
if (!overlay)
|
||||
overlay = new unsigned short[OVL_W*OVL_H];
|
||||
for (i=0; i<NUM_BUFFERS; i++)
|
||||
if (!screen_tx[i])
|
||||
screen_tx[i] = ta_txalloc(SCREEN_W*SCREEN_H*2);
|
||||
for (i=0; i<NUM_BUFFERS; i++)
|
||||
if (!mouse_tx[i])
|
||||
mouse_tx[i] = ta_txalloc(MOUSE_W*MOUSE_H*2);
|
||||
for (i=0; i<NUM_BUFFERS; i++)
|
||||
if (!ovl_tx[i])
|
||||
ovl_tx[i] = ta_txalloc(OVL_TXSTRIDE*OVL_H*2);
|
||||
_screen_buffer = 0;
|
||||
_mouse_buffer = 0;
|
||||
_overlay_buffer = 0;
|
||||
_screen_dirty = true;
|
||||
_overlay_dirty = true;
|
||||
*(volatile unsigned int *)(0xa05f80e4) = SCREEN_W/32; //stride
|
||||
// dc_reset_screen(0, 0);
|
||||
memset(screen, 0, SCREEN_W*SCREEN_H*2);
|
||||
memset(overlay, 0, OVL_W*OVL_H*sizeof(unsigned short));
|
||||
|
||||
_devpoll = Timer();
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::copyRectToScreen(const void *buf, int pitch, int x, int y,
|
||||
int w, int h)
|
||||
{
|
||||
if (w<1 || h<1)
|
||||
return;
|
||||
if (_screenFormat != 0) {
|
||||
x<<=1; w<<=1;
|
||||
}
|
||||
unsigned char *dst = screen + y*SCREEN_W*2 + x;
|
||||
const byte *src = (const byte *)buf;
|
||||
do {
|
||||
memcpy(dst, src, w);
|
||||
dst += SCREEN_W*2;
|
||||
src += pitch;
|
||||
} while (--h);
|
||||
_screen_dirty = true;
|
||||
}
|
||||
|
||||
bool OSystem_Dreamcast::showMouse(bool visible)
|
||||
{
|
||||
bool last = _ms_visible;
|
||||
_ms_visible = visible;
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::warpMouse(int x, int y)
|
||||
{
|
||||
_ms_cur_x = x;
|
||||
_ms_cur_y = y;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::setMouseCursor(const void *buf, uint w, uint h,
|
||||
int hotspot_x, int hotspot_y,
|
||||
uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format, const byte *mask) {
|
||||
if (mask)
|
||||
warning("OSystem_Dreamcast::setMouseCursor: Masks are not supported");
|
||||
|
||||
_ms_cur_w = w;
|
||||
_ms_cur_h = h;
|
||||
|
||||
_ms_hotspot_x = hotspot_x;
|
||||
_ms_hotspot_y = hotspot_y;
|
||||
|
||||
_ms_keycolor = keycolor;
|
||||
|
||||
int i = 0;
|
||||
if (format != NULL)
|
||||
for (i=NUM_FORMATS-1; i>0; --i)
|
||||
if (*format == screenFormats[i])
|
||||
break;
|
||||
_mouseFormat = i;
|
||||
|
||||
free(_ms_buf);
|
||||
|
||||
if (_mouseFormat != 0)
|
||||
w <<= 1;
|
||||
|
||||
_ms_buf = (byte *)malloc(w * h);
|
||||
memcpy(_ms_buf, buf, w * h);
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::setShakePos(int shake_x_pos, int shake_y_pos)
|
||||
{
|
||||
_current_shake_x_pos = shake_x_pos;
|
||||
_current_shake_y_pos = shake_y_pos;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::updateScreenTextures(void)
|
||||
{
|
||||
if (_screen_dirty) {
|
||||
|
||||
_screen_buffer++;
|
||||
_screen_buffer &= NUM_BUFFERS-1;
|
||||
|
||||
unsigned short *dst = (unsigned short *)screen_tx[_screen_buffer];
|
||||
unsigned char *src = screen;
|
||||
|
||||
// while ((*((volatile unsigned int *)(void *)0xa05f810c) & 0x3ff) != 200);
|
||||
// *((volatile unsigned int *)(void *)0xa05f8040) = 0xff0000;
|
||||
|
||||
if (_screenFormat == 0)
|
||||
for ( int y = 0; y<_screen_h; y++ )
|
||||
{
|
||||
texture_memcpy64_pal( dst, src, _screen_w>>5, palette );
|
||||
src += SCREEN_W*2;
|
||||
dst += SCREEN_W;
|
||||
}
|
||||
else
|
||||
for ( int y = 0; y<_screen_h; y++ )
|
||||
{
|
||||
texture_memcpy64( dst, src, _screen_w>>5 );
|
||||
src += SCREEN_W*2;
|
||||
dst += SCREEN_W;
|
||||
}
|
||||
|
||||
_screen_dirty = false;
|
||||
}
|
||||
|
||||
if ( _overlay_visible && _overlay_dirty ) {
|
||||
|
||||
_overlay_buffer++;
|
||||
_overlay_buffer &= NUM_BUFFERS-1;
|
||||
|
||||
unsigned short *dst = (unsigned short *)ovl_tx[_overlay_buffer];
|
||||
unsigned short *src = overlay;
|
||||
|
||||
for ( int y = 0; y<OVL_H; y++ )
|
||||
{
|
||||
texture_memcpy64( dst, src, OVL_W>>5 );
|
||||
src += OVL_W;
|
||||
dst += OVL_TXSTRIDE;
|
||||
}
|
||||
|
||||
_overlay_dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::updateScreenPolygons(void)
|
||||
{
|
||||
struct polygon_list mypoly;
|
||||
struct packed_colour_vertex_list myvertex;
|
||||
|
||||
// *((volatile unsigned int *)(void *)0xa05f8040) = 0x00ff00;
|
||||
|
||||
mypoly.cmd =
|
||||
TA_CMD_POLYGON|TA_CMD_POLYGON_TYPE_OPAQUE|TA_CMD_POLYGON_SUBLIST|
|
||||
TA_CMD_POLYGON_STRIPLENGTH_2|TA_CMD_POLYGON_PACKED_COLOUR|TA_CMD_POLYGON_TEXTURED;
|
||||
mypoly.mode1 = TA_POLYMODE1_Z_ALWAYS|TA_POLYMODE1_NO_Z_UPDATE;
|
||||
mypoly.mode2 =
|
||||
TA_POLYMODE2_BLEND_SRC|TA_POLYMODE2_FOG_DISABLED|TA_POLYMODE2_TEXTURE_REPLACE|
|
||||
TA_POLYMODE2_U_SIZE_1024|TA_POLYMODE2_V_SIZE_1024;
|
||||
mypoly.texture = screenFormats[_screenFormat].textureFormat|
|
||||
TA_TEXTUREMODE_NON_TWIDDLED|TA_TEXTUREMODE_STRIDE|
|
||||
TA_TEXTUREMODE_ADDRESS(screen_tx[_screen_buffer]);
|
||||
|
||||
mypoly.red = mypoly.green = mypoly.blue = mypoly.alpha = 0;
|
||||
|
||||
ta_begin_frame();
|
||||
// *((volatile unsigned int *)(void *)0xa05f8040) = 0x0000ff;
|
||||
ta_commit_list(&mypoly);
|
||||
|
||||
myvertex.cmd = TA_CMD_VERTEX;
|
||||
myvertex.ocolour = 0;
|
||||
myvertex.colour = 0;
|
||||
myvertex.z = 0.5;
|
||||
myvertex.u = 0.0;
|
||||
myvertex.v = 0.0;
|
||||
|
||||
myvertex.x = LEFT_OFFSET;
|
||||
myvertex.y = TOP_OFFSET;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x = _screen_w*_xscale;
|
||||
myvertex.u = _screen_w*(1/1024.0);
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x = 0.0;
|
||||
myvertex.y += _screen_h*_yscale;
|
||||
myvertex.u = 0.0;
|
||||
myvertex.v = _screen_h*(1/1024.0);
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x = _screen_w*_xscale;
|
||||
myvertex.u = _screen_w*(1/1024.0);
|
||||
myvertex.cmd |= TA_CMD_VERTEX_EOS;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
ta_commit_end();
|
||||
|
||||
if (_overlay_visible) {
|
||||
if (_overlay_fade < 1.0)
|
||||
_overlay_fade += 0.125;
|
||||
} else {
|
||||
if (_overlay_fade > 0)
|
||||
_overlay_fade -= 0.125;
|
||||
}
|
||||
|
||||
if (_overlay_fade > 0.0) {
|
||||
|
||||
mypoly.cmd =
|
||||
TA_CMD_POLYGON|TA_CMD_POLYGON_TYPE_TRANSPARENT|TA_CMD_POLYGON_SUBLIST|
|
||||
TA_CMD_POLYGON_STRIPLENGTH_2|TA_CMD_POLYGON_PACKED_COLOUR|TA_CMD_POLYGON_TEXTURED;
|
||||
mypoly.mode1 = TA_POLYMODE1_Z_ALWAYS|TA_POLYMODE1_NO_Z_UPDATE;
|
||||
mypoly.mode2 =
|
||||
TA_POLYMODE2_BLEND_SRC/*_ALPHA*/|TA_POLYMODE2_BLEND_DST_INVALPHA|
|
||||
TA_POLYMODE2_ENABLE_ALPHA|
|
||||
TA_POLYMODE2_FOG_DISABLED|TA_POLYMODE2_TEXTURE_MODULATE_ALPHA|
|
||||
TA_POLYMODE2_U_SIZE_512|TA_POLYMODE2_V_SIZE_512;
|
||||
mypoly.texture = TA_TEXTUREMODE_ARGB4444|TA_TEXTUREMODE_NON_TWIDDLED|
|
||||
TA_TEXTUREMODE_ADDRESS(ovl_tx[_overlay_buffer]);
|
||||
|
||||
mypoly.red = mypoly.green = mypoly.blue = mypoly.alpha = 0.0;
|
||||
|
||||
ta_commit_list(&mypoly);
|
||||
|
||||
myvertex.cmd = TA_CMD_VERTEX;
|
||||
myvertex.ocolour = 0;
|
||||
myvertex.colour = 0xffffff|(((int)(255*_overlay_fade))<<24);
|
||||
|
||||
myvertex.z = 0.5;
|
||||
myvertex.u = 0.0;
|
||||
myvertex.v = 0.0;
|
||||
|
||||
myvertex.x = _overlay_x*_xscale+LEFT_OFFSET;
|
||||
myvertex.y = _overlay_y*_yscale+TOP_OFFSET;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x += OVL_W*_xscale;
|
||||
myvertex.u = OVL_W*(1.0/512.0);
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x = _overlay_x*_xscale;
|
||||
myvertex.y += OVL_H*_yscale;
|
||||
myvertex.u = 0.0;
|
||||
myvertex.v = OVL_H*(1.0/512.0);
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x += OVL_W*_xscale;
|
||||
myvertex.u = OVL_W*(1.0/512.0);
|
||||
myvertex.cmd |= TA_CMD_VERTEX_EOS;
|
||||
ta_commit_list(&myvertex);
|
||||
}
|
||||
|
||||
if (_softkbd_on)
|
||||
if (_softkbd_motion < 120)
|
||||
_softkbd_motion += 10;
|
||||
else
|
||||
;
|
||||
else
|
||||
if (_softkbd_motion > 0)
|
||||
_softkbd_motion -= 10;
|
||||
|
||||
if (_softkbd_motion)
|
||||
_softkbd.draw(330.0*sin(0.013*_softkbd_motion) - 320.0, 200.0,
|
||||
120-_softkbd_motion);
|
||||
|
||||
// *((volatile unsigned int *)(void *)0xa05f8040) = 0xffff00;
|
||||
drawMouse(_ms_cur_x, _ms_cur_y, _ms_cur_w, _ms_cur_h, _ms_buf, _ms_visible);
|
||||
// *((volatile unsigned int *)(void *)0xa05f8040) = 0xff00ff;
|
||||
ta_commit_frame();
|
||||
|
||||
// *((volatile unsigned int *)(void *)0xa05f8040) = 0x0;
|
||||
|
||||
_last_screen_refresh = Timer();
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::updateScreen(void)
|
||||
{
|
||||
updateScreenTextures();
|
||||
updateScreenPolygons();
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::maybeRefreshScreen(void)
|
||||
{
|
||||
unsigned int t = Timer();
|
||||
if((int)(t-_last_screen_refresh) > USEC_TO_TIMER(30000))
|
||||
updateScreenPolygons();
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::drawMouse(int xdraw, int ydraw, int w, int h,
|
||||
unsigned char *buf, bool visible)
|
||||
{
|
||||
if (!visible || buf == NULL || !w || !h || w>MOUSE_W || h>MOUSE_H) {
|
||||
commit_dummy_transpoly();
|
||||
return;
|
||||
}
|
||||
|
||||
struct polygon_list mypoly;
|
||||
struct packed_colour_vertex_list myvertex;
|
||||
|
||||
_mouse_buffer++;
|
||||
_mouse_buffer &= NUM_BUFFERS-1;
|
||||
|
||||
unsigned short *dst = (unsigned short *)mouse_tx[_mouse_buffer];
|
||||
unsigned int texturemode = screenFormats[_mouseFormat].textureFormat;
|
||||
|
||||
if (_mouseFormat == 0) {
|
||||
unsigned short *pal = _enable_cursor_palette? cursor_palette : palette;
|
||||
for (int y=0; y<h; y++) {
|
||||
int x;
|
||||
for (x=0; x<w; x++)
|
||||
if (*buf == _ms_keycolor) {
|
||||
*dst++ = 0;
|
||||
buf++;
|
||||
} else
|
||||
*dst++ = pal[*buf++]|0x8000;
|
||||
dst += MOUSE_W-x;
|
||||
}
|
||||
} else if(texturemode == TA_TEXTUREMODE_RGB565 &&
|
||||
_ms_keycolor<=0xffff) {
|
||||
/* Special handling when doing colorkey on RGB565; we need
|
||||
to convert to ARGB1555 to get an alpha channel... */
|
||||
texturemode = TA_TEXTUREMODE_ARGB1555;
|
||||
unsigned short *bufs = (unsigned short *)buf;
|
||||
for (int y=0; y<h; y++) {
|
||||
int x;
|
||||
for (x=0; x<w; x++)
|
||||
if (*bufs == _ms_keycolor) {
|
||||
*dst++ = 0;
|
||||
bufs++;
|
||||
} else {
|
||||
unsigned short p = *bufs++;
|
||||
*dst++ = (p&0x1f)|((p&0xffc0)>>1)|0x8000;
|
||||
}
|
||||
dst += MOUSE_W-x;
|
||||
}
|
||||
} else {
|
||||
unsigned short *bufs = (unsigned short *)buf;
|
||||
for (int y=0; y<h; y++) {
|
||||
int x;
|
||||
for (x=0; x<w; x++)
|
||||
if (*bufs == _ms_keycolor) {
|
||||
*dst++ = 0;
|
||||
bufs++;
|
||||
} else
|
||||
*dst++ = *bufs++;
|
||||
dst += MOUSE_W-x;
|
||||
}
|
||||
}
|
||||
|
||||
mypoly.cmd =
|
||||
TA_CMD_POLYGON|TA_CMD_POLYGON_TYPE_TRANSPARENT|TA_CMD_POLYGON_SUBLIST|
|
||||
TA_CMD_POLYGON_STRIPLENGTH_2|TA_CMD_POLYGON_PACKED_COLOUR|TA_CMD_POLYGON_TEXTURED;
|
||||
mypoly.mode1 = TA_POLYMODE1_Z_ALWAYS|TA_POLYMODE1_NO_Z_UPDATE;
|
||||
mypoly.mode2 =
|
||||
TA_POLYMODE2_BLEND_SRC_ALPHA|TA_POLYMODE2_BLEND_DST_INVALPHA|
|
||||
TA_POLYMODE2_FOG_DISABLED|TA_POLYMODE2_TEXTURE_REPLACE|
|
||||
TA_POLYMODE2_U_SIZE_128|TA_POLYMODE2_V_SIZE_128;
|
||||
mypoly.texture = texturemode|TA_TEXTUREMODE_NON_TWIDDLED|
|
||||
TA_TEXTUREMODE_ADDRESS(mouse_tx[_mouse_buffer]);
|
||||
|
||||
mypoly.red = mypoly.green = mypoly.blue = mypoly.alpha = 0;
|
||||
|
||||
ta_commit_list(&mypoly);
|
||||
|
||||
myvertex.cmd = TA_CMD_VERTEX;
|
||||
myvertex.ocolour = 0;
|
||||
myvertex.colour = 0xffff00;
|
||||
myvertex.z = 0.25;
|
||||
myvertex.u = 0.0;
|
||||
myvertex.v = 0.0;
|
||||
|
||||
myvertex.x = (xdraw-_ms_hotspot_x)*_xscale + LEFT_OFFSET;
|
||||
myvertex.y = (ydraw-_ms_hotspot_y)*_yscale + TOP_OFFSET;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x += w*_xscale;
|
||||
myvertex.u = w*(1.0/MOUSE_W);
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x -= w*_xscale;
|
||||
myvertex.y += h*_yscale;
|
||||
myvertex.u = 0.0;
|
||||
myvertex.v = h*(1.0/MOUSE_H);
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x += w*_xscale;
|
||||
myvertex.u = w*(1.0/MOUSE_W);
|
||||
myvertex.cmd |= TA_CMD_VERTEX_EOS;
|
||||
ta_commit_list(&myvertex);
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::mouseToSoftKbd(int x, int y, int &rx, int &ry) const
|
||||
{
|
||||
if (_softkbd_motion) {
|
||||
rx = (int)(x*_xscale - (330.0*sin(0.013*_softkbd_motion) + LEFT_OFFSET - 320.0));
|
||||
ry = (int)(y*_yscale + TOP_OFFSET - 200.0);
|
||||
} else {
|
||||
rx = -1;
|
||||
ry = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OSystem_Dreamcast::showOverlay(bool inGUI)
|
||||
{
|
||||
_overlay_in_gui = inGUI;
|
||||
_overlay_visible = true;
|
||||
clearOverlay();
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::hideOverlay()
|
||||
{
|
||||
_overlay_in_gui = false;
|
||||
_overlay_visible = false;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::clearOverlay()
|
||||
{
|
||||
if (!_overlay_visible)
|
||||
return;
|
||||
|
||||
memset(overlay, 0, OVL_W*OVL_H*sizeof(unsigned short));
|
||||
|
||||
_overlay_dirty = true;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::grabOverlay(Graphics::Surface &surface)
|
||||
{
|
||||
assert(surface.w >= OVL_W);
|
||||
assert(surface.h >= OVL_H);
|
||||
assert(surface.format.bytesPerPixel == sizeof(unsigned short));
|
||||
|
||||
byte *src = (byte *)overlay;
|
||||
byte *dst = (byte *)surface.getPixels();
|
||||
Graphics::copyBlit(dst, src, surface.pitch, OVL_W * sizeof(unsigned short),
|
||||
OVL_W, OVL_H, sizeof(unsigned short));
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::copyRectToOverlay(const void *buf, int pitch,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
if (w<1 || h<1)
|
||||
return;
|
||||
unsigned short *dst = overlay + y*OVL_W + x;
|
||||
const unsigned char *src = (const unsigned char *)buf;
|
||||
do {
|
||||
memcpy(dst, src, w*sizeof(int16));
|
||||
dst += OVL_W;
|
||||
src += pitch;
|
||||
} while (--h);
|
||||
_overlay_dirty = true;
|
||||
}
|
||||
|
||||
Graphics::Surface *OSystem_Dreamcast::lockScreen()
|
||||
{
|
||||
if (!screen)
|
||||
return 0;
|
||||
|
||||
_framebuffer.init(_screen_w, _screen_h, SCREEN_W*2, screen, screenFormats[_screenFormat]);
|
||||
|
||||
return &_framebuffer;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::unlockScreen()
|
||||
{
|
||||
// Force screen update
|
||||
_screen_dirty = true;
|
||||
}
|
||||
|
||||
int16 OSystem_Dreamcast::getOverlayHeight() const
|
||||
{
|
||||
return OVL_H;
|
||||
}
|
||||
|
||||
int16 OSystem_Dreamcast::getOverlayWidth() const
|
||||
{
|
||||
return OVL_W;
|
||||
}
|
||||
46
backends/platform/dc/dreamcast.mk
Normal file
46
backends/platform/dc/dreamcast.mk
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
CC := $(CXX)
|
||||
ASFLAGS := $(CXXFLAGS)
|
||||
|
||||
dist : SCUMMVM.BIN IP.BIN plugin_dist
|
||||
|
||||
clean : dcclean
|
||||
|
||||
plugin_dist : plugins
|
||||
@[ -z "$(PLUGINS)" ] || for p in $(or $(PLUGINS),none); do \
|
||||
t="`basename \"$$p\" | LC_CTYPE=C tr '[:lower:]' '[:upper:]'`"; \
|
||||
if /usr/bin/test "$$p" -ot "$$t"; then :; else \
|
||||
echo sh-elf-strip -g -o "$$t" "$$p"; \
|
||||
sh-elf-strip -g -o "$$t" "$$p"; \
|
||||
$(srcdir)/backends/platform/dc/check_plugin_symbols "$$t"; \
|
||||
fi;\
|
||||
done
|
||||
|
||||
SCUMMVM.BIN : scummvm.bin
|
||||
scramble $< $@
|
||||
|
||||
scummvm.bin : scummvm.elf
|
||||
sh-elf-objcopy -S -R .stack -O binary $< $@
|
||||
|
||||
IP.BIN : ip.txt
|
||||
makeip $< $@
|
||||
|
||||
ip.txt : $(srcdir)/backends/platform/dc/ip.txt.in
|
||||
if [ x"$(VER_EXTRA)" = xgit ]; then \
|
||||
ver="GIT"; \
|
||||
else ver="V$(VERSION)"; fi; \
|
||||
if expr "$$ver" : V...... >/dev/null; then \
|
||||
ver="$$(printf "V%02d%02d%d" $$(($(VER_MAJOR) - 2000)) $(VER_MINOR) $(VER_PATCH))"; fi; \
|
||||
sed -e 's/[@]VERSION[@]/'"$$ver"/ -e 's/[@]DATE[@]/$(shell date '+%Y%m%d')/' < $< > $@
|
||||
|
||||
|
||||
dcdist : dist
|
||||
mkdir -p dcdist/scummvm
|
||||
cp scummvm.elf SCUMMVM.BIN IP.BIN *.PLG dcdist/scummvm/
|
||||
|
||||
dcclean :
|
||||
$(RM) backends/platform/dc/plugin_head.o
|
||||
$(RM) scummvm.bin SCUMMVM.BIN ip.txt IP.BIN *.PLG
|
||||
$(RM_REC) dcdist
|
||||
|
||||
.PHONY: dcclean
|
||||
237
backends/platform/dc/icon.cpp
Normal file
237
backends/platform/dc/icon.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ronin/ronin.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "icon.h"
|
||||
|
||||
void Icon::create_vmicon(void *buffer)
|
||||
{
|
||||
unsigned short *pal = (unsigned short *)buffer;
|
||||
unsigned char *pix = ((unsigned char *)buffer)+32;
|
||||
|
||||
for (int n = 0; n<16; n++) {
|
||||
int p = palette[n];
|
||||
pal[n] =
|
||||
((p>>16)&0xf000)|
|
||||
((p>>12)&0x0f00)|
|
||||
((p>> 8)&0x00f0)|
|
||||
((p>> 4)&0x000f);
|
||||
}
|
||||
|
||||
for (int line = 0; line < 32; line++) {
|
||||
memcpy(pix, &bitmap[32/2*(31-line)], 32/2);
|
||||
pix += 32/2;
|
||||
}
|
||||
}
|
||||
|
||||
void Icon::create_texture()
|
||||
{
|
||||
static unsigned char tt[16] = { 0, 1, 4, 5, 16, 17, 20, 21,
|
||||
64, 65, 68, 69, 80, 81, 84, 85 };
|
||||
unsigned short *tex = (unsigned short *)ta_txalloc(512);
|
||||
unsigned short *linebase;
|
||||
unsigned char *src = bitmap+sizeof(bitmap)-17;
|
||||
for (int y=0; y<16; y++) {
|
||||
linebase = tex + (tt[y]<<1);
|
||||
for (int x=0; x<16; x++, --src)
|
||||
linebase[tt[x]] = src[16]|(src[0]<<8);
|
||||
src -= 16;
|
||||
}
|
||||
texture = tex;
|
||||
}
|
||||
|
||||
void Icon::setPalette(int pal)
|
||||
{
|
||||
unsigned int (*hwpal)[64][16] = (unsigned int (*)[64][16])0xa05f9000;
|
||||
for (int n = 0; n<16; n++)
|
||||
(*hwpal)[pal][n] = palette[n];
|
||||
}
|
||||
|
||||
void Icon::draw(float x1, float y1, float x2, float y2, int pal,
|
||||
unsigned int argb)
|
||||
{
|
||||
struct polygon_list mypoly;
|
||||
struct packed_colour_vertex_list myvertex;
|
||||
|
||||
mypoly.cmd =
|
||||
TA_CMD_POLYGON|TA_CMD_POLYGON_TYPE_TRANSPARENT|TA_CMD_POLYGON_SUBLIST|
|
||||
TA_CMD_POLYGON_STRIPLENGTH_2|TA_CMD_POLYGON_PACKED_COLOUR|TA_CMD_POLYGON_TEXTURED;
|
||||
mypoly.mode1 = TA_POLYMODE1_Z_ALWAYS|TA_POLYMODE1_NO_Z_UPDATE;
|
||||
mypoly.mode2 =
|
||||
TA_POLYMODE2_BLEND_SRC_ALPHA|TA_POLYMODE2_BLEND_DST_INVALPHA|
|
||||
TA_POLYMODE2_FOG_DISABLED|TA_POLYMODE2_ENABLE_ALPHA|
|
||||
TA_POLYMODE2_TEXTURE_MODULATE_ALPHA|TA_POLYMODE2_U_SIZE_32|
|
||||
TA_POLYMODE2_V_SIZE_32;
|
||||
mypoly.texture = TA_TEXTUREMODE_CLUT4|TA_TEXTUREMODE_CLUTBANK4(pal)|
|
||||
TA_TEXTUREMODE_ADDRESS(texture);
|
||||
|
||||
mypoly.red = mypoly.green = mypoly.blue = mypoly.alpha = 0;
|
||||
|
||||
ta_commit_list(&mypoly);
|
||||
|
||||
myvertex.cmd = TA_CMD_VERTEX;
|
||||
myvertex.ocolour = 0;
|
||||
myvertex.colour = argb;
|
||||
myvertex.z = 0.5;
|
||||
myvertex.u = 0.0;
|
||||
myvertex.v = 1.0;
|
||||
|
||||
myvertex.x = x1;
|
||||
myvertex.y = y1;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x = x2;
|
||||
myvertex.v = 0.0;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x = x1;
|
||||
myvertex.y = y2;
|
||||
myvertex.u = 1.0;
|
||||
myvertex.v = 1.0;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x = x2;
|
||||
myvertex.v = 0.0;
|
||||
myvertex.cmd |= TA_CMD_VERTEX_EOS;
|
||||
ta_commit_list(&myvertex);
|
||||
}
|
||||
|
||||
int Icon::find_unused_pixel(const unsigned char *mask)
|
||||
{
|
||||
int use[16];
|
||||
memset(use, 0, sizeof(use));
|
||||
unsigned char *p = bitmap;
|
||||
for (int n=0; n<32*32/2/4; n++) {
|
||||
unsigned char mbits = ~*mask++;
|
||||
for (int i=0; i<4; i++) {
|
||||
unsigned char pix = *p++;
|
||||
if(mbits & 64)
|
||||
use[pix&0xf]++;
|
||||
if(mbits & 128)
|
||||
use[pix>>4]++;
|
||||
mbits <<= 2;
|
||||
}
|
||||
}
|
||||
for (int i=0; i<16; i++)
|
||||
if (!use[i])
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Icon::load_image2(const void *data, int len)
|
||||
{
|
||||
struct {
|
||||
int size, w, h;
|
||||
short pla, bitcnt;
|
||||
int comp, sizeimg, xres, yres, used, imp;
|
||||
} hdr;
|
||||
if (len < 40)
|
||||
return false;
|
||||
memcpy(&hdr, data, 40);
|
||||
if (hdr.size != 40 || /* hdr.sizeimg<=0 || */ hdr.w<0 || hdr.h<0 ||
|
||||
hdr.bitcnt<0 || hdr.used<0)
|
||||
return false;
|
||||
if (!hdr.used)
|
||||
hdr.used = 1<<hdr.bitcnt;
|
||||
hdr.h >>= 1;
|
||||
/* Fix incorrect sizeimg (The Dig) */
|
||||
if (hdr.sizeimg < ((hdr.w*hdr.h*(1+hdr.bitcnt)+7)>>3))
|
||||
hdr.sizeimg = ((hdr.w*hdr.h*(1+hdr.bitcnt)+7)>>3);
|
||||
if (hdr.size + (hdr.used<<2) + hdr.sizeimg > len /* ||
|
||||
hdr.sizeimg < ((hdr.w*hdr.h*(1+hdr.bitcnt)+7)>>3) */)
|
||||
return false;
|
||||
if (hdr.w != 32 || hdr.h != 32 || hdr.bitcnt != 4 || hdr.used > 16)
|
||||
return false;
|
||||
memcpy(palette, ((const char *)data)+hdr.size, hdr.used<<2);
|
||||
memcpy(bitmap, ((const char *)data)+hdr.size+(hdr.used<<2), 32*32/2);
|
||||
for (int i=0; i<16; i++)
|
||||
palette[i] |= 0xff000000;
|
||||
for (int i=hdr.used; i<16; i++)
|
||||
palette[i] = 0;
|
||||
const unsigned char *mask =
|
||||
((const unsigned char *)data)+hdr.size+(hdr.used<<2)+32*32/2;
|
||||
int unused = find_unused_pixel(mask);
|
||||
if (unused >= 0) {
|
||||
unsigned char *pix = bitmap;
|
||||
for (int y=0; y<32; y++)
|
||||
for (int x=0; x<32/8; x++) {
|
||||
unsigned char mbits = *mask++;
|
||||
for (int z=0; z<4; z++) {
|
||||
unsigned char pbits = *pix;
|
||||
if (mbits & 64) pbits = (pbits & ~0xf) | unused;
|
||||
if (mbits & 128) pbits = (pbits & 0xf) | (unused << 4);
|
||||
*pix++ = pbits;
|
||||
mbits <<= 2;
|
||||
}
|
||||
}
|
||||
palette[unused] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Icon::load_image1(const void *data, int len, int offs)
|
||||
{
|
||||
struct {
|
||||
char w, h, colors, rsrv;
|
||||
short pla, bitcnt;
|
||||
int bytes, offs;
|
||||
} hdr;
|
||||
if (len < offs+16)
|
||||
return false;
|
||||
memcpy(&hdr, ((const char *)data)+offs, 16);
|
||||
if (hdr.bytes > 0 && hdr.offs >= 0 && hdr.offs+hdr.bytes <= len)
|
||||
return load_image2(((const char *)data)+hdr.offs, hdr.bytes);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Icon::load(const void *data, int len, int offs)
|
||||
{
|
||||
struct { short rsrv, type, cnt; } hdr;
|
||||
memset(bitmap, 0, sizeof(bitmap));
|
||||
memset(palette, 0, sizeof(palette));
|
||||
texture = NULL;
|
||||
if (len < offs+6)
|
||||
return false;
|
||||
memcpy(&hdr, ((const char *)data)+offs, 6);
|
||||
if (hdr.type != 1 || hdr.cnt < 1 || offs+6+(hdr.cnt<<4) > len)
|
||||
return false;
|
||||
for (int i=0; i<hdr.cnt; i++)
|
||||
if (load_image1(data, len, offs+6+(i<<4)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Icon::load(const char *filename)
|
||||
{
|
||||
char buf[2048];
|
||||
int fd;
|
||||
if ((fd = open(filename, O_RDONLY))>=0) {
|
||||
int sz;
|
||||
sz = read(fd, buf, sizeof(buf));
|
||||
close(fd);
|
||||
if (sz>0)
|
||||
return load(buf, sz);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
46
backends/platform/dc/icon.h
Normal file
46
backends/platform/dc/icon.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DC_ICON_H
|
||||
#define DC_ICON_H
|
||||
|
||||
class Icon
|
||||
{
|
||||
private:
|
||||
unsigned char bitmap[32*32/2];
|
||||
unsigned int palette[16];
|
||||
void *texture;
|
||||
|
||||
int find_unused_pixel(const unsigned char *);
|
||||
bool load_image1(const void *data, int len, int offs);
|
||||
bool load_image2(const void *data, int len);
|
||||
|
||||
public:
|
||||
bool load(const void *data, int len, int offs = 0);
|
||||
bool load(const char *filename);
|
||||
void create_texture();
|
||||
void setPalette(int pal);
|
||||
void draw(float x1, float y1, float x2, float y2, int pal,
|
||||
unsigned argb = 0xffffffff);
|
||||
void create_vmicon(void *buffer);
|
||||
};
|
||||
|
||||
#endif /* DC_ICON_H */
|
||||
251
backends/platform/dc/input.cpp
Normal file
251
backends/platform/dc/input.cpp
Normal file
@@ -0,0 +1,251 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
|
||||
#define RONIN_TIMER_ACCESS
|
||||
|
||||
#include <common/scummsys.h>
|
||||
#include <common/events.h>
|
||||
#include "dc.h"
|
||||
|
||||
int handleInput(struct mapledev *pad, int &mouse_x, int &mouse_y,
|
||||
byte &shiftFlags, Interactive *inter)
|
||||
{
|
||||
static const char numpadmap[] = "0000039601740285";
|
||||
int lmb=0, rmb=0, newkey=0;
|
||||
static int lastkey = 0;
|
||||
static byte lastlmb = 0, lastrmb = 0;
|
||||
static int8 mouse_wheel = 0, lastwheel = 0;
|
||||
shiftFlags = 0;
|
||||
for (int i=0; i<4; i++, pad++)
|
||||
if (pad->func & MAPLE_FUNC_CONTROLLER) {
|
||||
int buttons = pad->cond.controller.buttons;
|
||||
|
||||
if (!(buttons & 0x060e)) exit(0);
|
||||
|
||||
if (!(buttons & 4)) lmb++;
|
||||
if (!(buttons & 2)) rmb++;
|
||||
|
||||
if (!(buttons & 8)) newkey = Common::KEYCODE_F5;
|
||||
else if (!(buttons & 512)) newkey = ' ';
|
||||
else if (!(buttons & 1024)) newkey = numpadmap[(buttons>>4)&15];
|
||||
|
||||
if (!(buttons & 128)) { if (inter) newkey = 1001; else mouse_x++; }
|
||||
if (!(buttons & 64)) { if (inter) newkey = 1002; else mouse_x--; }
|
||||
if (!(buttons & 32)) { if (inter) newkey = 1003; else mouse_y++; }
|
||||
if (!(buttons & 16)) { if (inter) newkey = 1004; else mouse_y--; }
|
||||
|
||||
mouse_x += ((int)pad->cond.controller.joyx-128)>>4;
|
||||
mouse_y += ((int)pad->cond.controller.joyy-128)>>4;
|
||||
|
||||
if (pad->cond.controller.ltrigger > 200) newkey = 1005;
|
||||
else if (pad->cond.controller.rtrigger > 200) newkey = 1006;
|
||||
|
||||
} else if (pad->func & MAPLE_FUNC_MOUSE) {
|
||||
int buttons = pad->cond.mouse.buttons;
|
||||
|
||||
if (!(buttons & 4)) lmb++;
|
||||
if (!(buttons & 2)) rmb++;
|
||||
|
||||
if (!(buttons & 8)) newkey = Common::KEYCODE_F5;
|
||||
|
||||
mouse_x += pad->cond.mouse.axis1;
|
||||
mouse_y += pad->cond.mouse.axis2;
|
||||
mouse_wheel += pad->cond.mouse.axis3;
|
||||
|
||||
if (inter)
|
||||
inter->mouse(mouse_x, mouse_y);
|
||||
|
||||
pad->cond.mouse.axis1 = 0;
|
||||
pad->cond.mouse.axis2 = 0;
|
||||
pad->cond.mouse.axis3 = 0;
|
||||
} else if (pad->func & MAPLE_FUNC_KEYBOARD) {
|
||||
for (int p=0; p<6; p++) {
|
||||
int shift = pad->cond.kbd.shift;
|
||||
int key = pad->cond.kbd.key[p];
|
||||
if (shift & 0x08) lmb++;
|
||||
if (shift & 0x80) rmb++;
|
||||
if (shift & 0x11) shiftFlags |= Common::KBD_CTRL;
|
||||
if (shift & 0x44) shiftFlags |= Common::KBD_ALT;
|
||||
if (shift & 0x22) shiftFlags |= Common::KBD_SHIFT;
|
||||
if (key >= 4 && key <= 0x1d)
|
||||
newkey = key+('a'-4);
|
||||
else if (key >= 0x1e && key <= 0x26)
|
||||
newkey = key+((shift & 0x22)? ('!'-0x1e) : ('1'-0x1e));
|
||||
else if (key >= 0x59 && key <= 0x61)
|
||||
newkey = key+('1'-0x59);
|
||||
else if (key >= 0x2d && key <= 0x38 && key != 0x31)
|
||||
newkey = ((shift & 0x22)?
|
||||
"=?`{ }+*?<>?" :
|
||||
"-^@[ ];:?,./")[key - 0x2d];
|
||||
else if (key >= 0x3a && key <= 0x43)
|
||||
newkey = key+(Common::KEYCODE_F1-0x3a);
|
||||
else if (key >= 0x54 && key <= 0x57)
|
||||
newkey = "/*-+"[key-0x54];
|
||||
else switch(key) {
|
||||
case 0x27: case 0x62:
|
||||
newkey = ((shift & 0x22)? '~' : '0'); break;
|
||||
case 0x28: case 0x58:
|
||||
newkey = Common::KEYCODE_RETURN; break;
|
||||
case 0x29:
|
||||
newkey = Common::KEYCODE_ESCAPE; break;
|
||||
case 0x2a:
|
||||
newkey = Common::KEYCODE_BACKSPACE; break;
|
||||
case 0x2b:
|
||||
newkey = Common::KEYCODE_TAB; break;
|
||||
case 0x2c:
|
||||
newkey = Common::KEYCODE_SPACE; break;
|
||||
case 0x4c:
|
||||
if ((shift & 0x11) && (shift & 0x44))
|
||||
exit(0);
|
||||
break;
|
||||
case 0x4f:
|
||||
if (inter) newkey = 1001; else mouse_x++; break;
|
||||
case 0x50:
|
||||
if (inter) newkey = 1002; else mouse_x--; break;
|
||||
case 0x51:
|
||||
if (inter) newkey = 1003; else mouse_y++; break;
|
||||
case 0x52:
|
||||
if (inter) newkey = 1004; else mouse_y--; break;
|
||||
case 0x63:
|
||||
newkey = '.'; break;
|
||||
case 0x64: case 0x87:
|
||||
newkey = ((shift & 0x22)? '_' : '\\'); break;
|
||||
case 0x89:
|
||||
newkey = ((shift & 0x22)? '|' : '?'); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lmb && inter && !lastlmb) {
|
||||
newkey = 1000;
|
||||
lmb = 0;
|
||||
}
|
||||
|
||||
if (lmb && !lastlmb) {
|
||||
lastlmb = 1;
|
||||
return -Common::EVENT_LBUTTONDOWN;
|
||||
} else if (lastlmb && !lmb) {
|
||||
lastlmb = 0;
|
||||
return -Common::EVENT_LBUTTONUP;
|
||||
}
|
||||
if (rmb && !lastrmb) {
|
||||
lastrmb = 1;
|
||||
return -Common::EVENT_RBUTTONDOWN;
|
||||
} else if (lastrmb && !rmb) {
|
||||
lastrmb = 0;
|
||||
return -Common::EVENT_RBUTTONUP;
|
||||
}
|
||||
|
||||
if (mouse_wheel != lastwheel) {
|
||||
if (((int8)(mouse_wheel - lastwheel)) > 0) {
|
||||
lastwheel++;
|
||||
return -Common::EVENT_WHEELDOWN;
|
||||
} else {
|
||||
--lastwheel;
|
||||
return -Common::EVENT_WHEELUP;
|
||||
}
|
||||
}
|
||||
|
||||
if (newkey && inter && newkey != lastkey) {
|
||||
int transkey = inter->key(newkey, shiftFlags);
|
||||
if (transkey) {
|
||||
newkey = transkey;
|
||||
inter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!newkey || (lastkey && newkey != lastkey)) {
|
||||
int upkey = lastkey;
|
||||
lastkey = 0;
|
||||
if (upkey)
|
||||
return upkey | (1<<30);
|
||||
} else if (!lastkey) {
|
||||
lastkey = newkey;
|
||||
if (newkey >= 1000 || !inter)
|
||||
return newkey;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool OSystem_Dreamcast::pollEvent(Common::Event &event)
|
||||
{
|
||||
unsigned int t = Timer();
|
||||
|
||||
if (_timerManager != NULL)
|
||||
((DefaultTimerManager *)_timerManager)->handler();
|
||||
|
||||
if (((int)(t-_devpoll))<0)
|
||||
return false;
|
||||
_devpoll += USEC_TO_TIMER(17000);
|
||||
if (((int)(t-_devpoll))>=0)
|
||||
_devpoll = t + USEC_TO_TIMER(17000);
|
||||
|
||||
maybeRefreshScreen();
|
||||
|
||||
int mask = getimask();
|
||||
setimask(15);
|
||||
checkSound();
|
||||
int e = handleInput(locked_get_pads(), _ms_cur_x, _ms_cur_y,
|
||||
event.kbd.flags, (_softkbd_on? &_softkbd : NULL));
|
||||
setimask(mask);
|
||||
if (_ms_cur_x<0) _ms_cur_x=0;
|
||||
if (_ms_cur_x>=_screen_w) _ms_cur_x=_screen_w-1;
|
||||
if (_ms_cur_y<0) _ms_cur_y=0;
|
||||
if (_ms_cur_y>=_screen_h) _ms_cur_y=_screen_h-1;
|
||||
event.mouse.x = _ms_cur_x;
|
||||
event.mouse.y = _ms_cur_y;
|
||||
if (_overlay_in_gui) {
|
||||
event.mouse.x -= _overlay_x;
|
||||
event.mouse.y -= _overlay_y;
|
||||
}
|
||||
event.kbd.ascii = 0;
|
||||
event.kbd.keycode = Common::KEYCODE_INVALID;
|
||||
if (e<0) {
|
||||
event.type = (Common::EventType)-e;
|
||||
return true;
|
||||
} else if (e>0) {
|
||||
bool processed = false, down = !(e&(1<<30));
|
||||
e &= ~(1<<30);
|
||||
if (e < 1000) {
|
||||
event.type = (down? Common::EVENT_KEYDOWN : Common::EVENT_KEYUP);
|
||||
event.kbd.keycode = (Common::KeyCode)e;
|
||||
event.kbd.ascii = (e>='a' && e<='z' && (event.kbd.flags & Common::KBD_SHIFT)?
|
||||
e &~ 0x20 : e);
|
||||
processed = true;
|
||||
} else if (down) {
|
||||
if (e == 1005)
|
||||
setFeatureState(kFeatureVirtualKeyboard,
|
||||
!getFeatureState(kFeatureVirtualKeyboard));
|
||||
}
|
||||
return processed;
|
||||
} else if (_ms_cur_x != _ms_old_x || _ms_cur_y != _ms_old_y) {
|
||||
event.type = Common::EVENT_MOUSEMOVE;
|
||||
_ms_old_x = _ms_cur_x;
|
||||
_ms_old_y = _ms_cur_y;
|
||||
return true;
|
||||
} else {
|
||||
event.type = (Common::EventType)0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
11
backends/platform/dc/ip.txt.in
Normal file
11
backends/platform/dc/ip.txt.in
Normal file
@@ -0,0 +1,11 @@
|
||||
Hardware ID : SEGA SEGAKATANA
|
||||
Maker ID : SEGA ENTERPRISES
|
||||
Device Info : 0000 CD-ROM1/1
|
||||
Area Symbols : JUE
|
||||
Peripherals : E000F10
|
||||
Product No : T0000
|
||||
Version : @VERSION@
|
||||
Release Date : @DATE@
|
||||
Boot Filename : SCUMMVM.BIN
|
||||
SW Maker Name : The ScummVM Team
|
||||
Game Title : ScummVM
|
||||
135
backends/platform/dc/label.cpp
Normal file
135
backends/platform/dc/label.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ronin/ronin.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "label.h"
|
||||
|
||||
|
||||
void *get_romfont_address() __asm__(".get_romfont_address");
|
||||
__asm__("\
|
||||
\n\
|
||||
.get_romfont_address: \n\
|
||||
mov.l 1f,r0 \n\
|
||||
mov.l @r0,r0 \n\
|
||||
jmp @r0 \n\
|
||||
mov #0,r1 \n\
|
||||
.align 2 \n\
|
||||
1: .long 0x8c0000b4 \n\
|
||||
\n\
|
||||
");
|
||||
|
||||
|
||||
static void draw_char(unsigned short *dst, int mod, int c, void *font_base)
|
||||
{
|
||||
unsigned char *src;
|
||||
int i, j;
|
||||
if (c<=32 || c>255 || (c>=127 && c<160)) c=160;
|
||||
if (c<128) c -= 32; else c -= 64;
|
||||
src = c*36 + (unsigned char *)font_base;
|
||||
for (i=0; i<12; i++) {
|
||||
int n = (src[0]<<16)|(src[1]<<8)|src[2];
|
||||
for (j=0; j<12; j++, n<<=1)
|
||||
if (n & (1<<23)) {
|
||||
dst[j] = 0xffff;
|
||||
dst[j+1] = 0xffff;
|
||||
dst[j+2] = 0xa108;
|
||||
dst[j+mod] = 0xa108;
|
||||
dst[j+mod+1] = 0xa108;
|
||||
}
|
||||
dst += mod;
|
||||
for (j=0; j<12; j++, n<<=1)
|
||||
if (n & (1<<23)) {
|
||||
dst[j] = 0xffff;
|
||||
dst[j+1] = 0xffff;
|
||||
dst[j+2] = 0xa108;
|
||||
dst[j+mod] = 0xa108;
|
||||
dst[j+mod+1] = 0xa108;
|
||||
}
|
||||
dst += mod;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void Label::create_texture(const char *text)
|
||||
{
|
||||
void *font = get_romfont_address();
|
||||
int l = strlen(text);
|
||||
if (l>64) l=64;
|
||||
int w = 14*l;
|
||||
for (tex_u=TA_POLYMODE2_U_SIZE_8, u=8; u<w; u<<=1, tex_u += 1<<3);
|
||||
int tsz = u*32;
|
||||
unsigned short *tex = (unsigned short *)ta_txalloc(tsz*2);
|
||||
for (int i=0; i<tsz; i++)
|
||||
tex[i] = 0;
|
||||
int p=l*14;
|
||||
while (l>0)
|
||||
draw_char(tex+(p-=14), u, text[--l], font);
|
||||
texture = tex;
|
||||
}
|
||||
|
||||
void Label::draw(float x, float y, unsigned int argb, float scale)
|
||||
{
|
||||
struct polygon_list mypoly;
|
||||
struct packed_colour_vertex_list myvertex;
|
||||
|
||||
mypoly.cmd =
|
||||
TA_CMD_POLYGON|TA_CMD_POLYGON_TYPE_TRANSPARENT|TA_CMD_POLYGON_SUBLIST|
|
||||
TA_CMD_POLYGON_STRIPLENGTH_2|TA_CMD_POLYGON_PACKED_COLOUR|TA_CMD_POLYGON_TEXTURED;
|
||||
mypoly.mode1 = TA_POLYMODE1_Z_ALWAYS|TA_POLYMODE1_NO_Z_UPDATE;
|
||||
mypoly.mode2 =
|
||||
TA_POLYMODE2_BLEND_SRC_ALPHA|TA_POLYMODE2_BLEND_DST_INVALPHA|
|
||||
TA_POLYMODE2_FOG_DISABLED|TA_POLYMODE2_ENABLE_ALPHA|
|
||||
TA_POLYMODE2_TEXTURE_MODULATE_ALPHA|TA_POLYMODE2_V_SIZE_32|tex_u;
|
||||
mypoly.texture = TA_TEXTUREMODE_ARGB1555|TA_TEXTUREMODE_NON_TWIDDLED|
|
||||
TA_TEXTUREMODE_ADDRESS(texture);
|
||||
|
||||
mypoly.red = mypoly.green = mypoly.blue = mypoly.alpha = 0;
|
||||
|
||||
ta_commit_list(&mypoly);
|
||||
|
||||
myvertex.cmd = TA_CMD_VERTEX;
|
||||
myvertex.ocolour = 0;
|
||||
myvertex.colour = argb;
|
||||
myvertex.z = 0.5;
|
||||
myvertex.u = 0.0;
|
||||
myvertex.v = 0.0;
|
||||
|
||||
myvertex.x = x;
|
||||
myvertex.y = y;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x = x+u*scale;
|
||||
myvertex.u = 1.0;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x = x;
|
||||
myvertex.y = y+25.0*scale;
|
||||
myvertex.u = 0.0;
|
||||
myvertex.v = 25.0/32.0;
|
||||
ta_commit_list(&myvertex);
|
||||
|
||||
myvertex.x = x+u*scale;
|
||||
myvertex.u = 1.0;
|
||||
myvertex.cmd |= TA_CMD_VERTEX_EOS;
|
||||
ta_commit_list(&myvertex);
|
||||
}
|
||||
37
backends/platform/dc/label.h
Normal file
37
backends/platform/dc/label.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DC_LABEL_H
|
||||
#define DC_LABEL_H
|
||||
|
||||
class Label
|
||||
{
|
||||
private:
|
||||
void *texture;
|
||||
int tex_u, u;
|
||||
|
||||
public:
|
||||
void create_texture(const char *text);
|
||||
void draw(float x, float y, unsigned int argb = 0xffffffff,
|
||||
float scale = 1.0);
|
||||
};
|
||||
|
||||
#endif /* DC_LABEL_H */
|
||||
10
backends/platform/dc/module.mk
Normal file
10
backends/platform/dc/module.mk
Normal file
@@ -0,0 +1,10 @@
|
||||
MODULE := backends/platform/dc
|
||||
|
||||
MODULE_OBJS := dcmain.o time.o display.o audio.o input.o selector.o icon.o \
|
||||
label.o vmsave.o softkbd.o dcloader.o cache.o dc-fs.o plugins.o \
|
||||
dcutils.o
|
||||
|
||||
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
|
||||
MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
|
||||
OBJS := $(MODULE_OBJS) $(OBJS)
|
||||
MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
|
||||
9
backends/platform/dc/plugin.syms
Normal file
9
backends/platform/dc/plugin.syms
Normal file
@@ -0,0 +1,9 @@
|
||||
_PLUGIN_getVersion
|
||||
_PLUGIN_getType
|
||||
_PLUGIN_getTypeVersion
|
||||
_PLUGIN_getObject
|
||||
___plugin_ctors
|
||||
___plugin_ctors_end
|
||||
___plugin_dtors
|
||||
___plugin_dtors_end
|
||||
___dso_handle
|
||||
60
backends/platform/dc/plugin.x
Normal file
60
backends/platform/dc/plugin.x
Normal file
@@ -0,0 +1,60 @@
|
||||
OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl")
|
||||
OUTPUT_ARCH(sh)
|
||||
PHDRS
|
||||
{
|
||||
plugin PT_LOAD ;
|
||||
}
|
||||
SECTIONS
|
||||
{
|
||||
. = 0;
|
||||
.text :
|
||||
{
|
||||
___dso_handle = .;
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
*(.gnu.warning)
|
||||
} :plugin =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)
|
||||
}
|
||||
}
|
||||
5
backends/platform/dc/plugin_head.S
Normal file
5
backends/platform/dc/plugin_head.S
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
.section .ctors,"aw",@progbits
|
||||
.section .dtors,"aw",@progbits
|
||||
|
||||
.end
|
||||
172
backends/platform/dc/plugins.cpp
Normal file
172
backends/platform/dc/plugins.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#if defined(DYNAMIC_MODULES)
|
||||
|
||||
#include "backends/plugins/dynamic-plugin.h"
|
||||
#include "common/fs.h"
|
||||
|
||||
#include "dcloader.h"
|
||||
#include "dcutils.h"
|
||||
|
||||
static void drawPluginProgress(const Common::String &filename)
|
||||
{
|
||||
TextureStack txstack;
|
||||
const char *fn = filename.c_str();
|
||||
Label lab1, lab2, lab3;
|
||||
char buf[32];
|
||||
unsigned memleft = 0x8cf00000-((unsigned)sbrk(0));
|
||||
float ffree = memleft*(1.0/(16<<20));
|
||||
int fcol = (memleft < (1<<20)? 0xffff0000:
|
||||
(memleft < (4<<20)? 0xffffff00: 0xff00ff00));
|
||||
snprintf(buf, sizeof(buf), "%dK free memory", memleft>>10);
|
||||
if (fn[0] == '/') fn++;
|
||||
lab1.create_texture("Loading plugins, please wait...");
|
||||
lab2.create_texture(fn);
|
||||
lab3.create_texture(buf);
|
||||
ta_begin_frame();
|
||||
draw_solid_quad(80.0, 270.0, 560.0, 300.0,
|
||||
0xff808080, 0xff808080, 0xff808080, 0xff808080);
|
||||
draw_solid_quad(85.0, 275.0, 555.0, 295.0,
|
||||
0xff202020, 0xff202020, 0xff202020, 0xff202020);
|
||||
draw_solid_quad(85.0, 275.0, 85.0+470.0*ffree, 295.0,
|
||||
fcol, fcol, fcol, fcol);
|
||||
ta_commit_end();
|
||||
lab1.draw(100.0, 150.0, 0xffffffff);
|
||||
lab2.draw(100.0, 190.0, 0xffaaffaa);
|
||||
lab3.draw(100.0, 230.0, 0xffffffff);
|
||||
ta_commit_frame();
|
||||
}
|
||||
|
||||
class OSystem_Dreamcast::DCPlugin : public DynamicPlugin {
|
||||
protected:
|
||||
void *_dlHandle;
|
||||
DiscLabel _label;
|
||||
|
||||
virtual VoidFunc findSymbol(const char *symbol) {
|
||||
void *func = dlsym(_dlHandle, symbol);
|
||||
if (!func)
|
||||
warning("Failed loading symbol '%s' from plugin '%s' (%s)", symbol, _filename.toString(Common::Path::kNativeSeparator).c_str(), dlerror());
|
||||
|
||||
// FIXME HACK: This is a HACK to circumvent a clash between the ISO C++
|
||||
// standard and POSIX: ISO C++ disallows casting between function pointers
|
||||
// and data pointers, but dlsym always returns a void pointer. For details,
|
||||
// see e.g. <https://web.archive.org/web/20061205092618/http://www.trilithium.com/johan/2004/12/problem-with-dlsym/>.
|
||||
assert(sizeof(VoidFunc) == sizeof(func));
|
||||
VoidFunc tmp;
|
||||
memcpy(&tmp, &func, sizeof(VoidFunc));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void checkDisc(const DiscLabel &);
|
||||
|
||||
public:
|
||||
DCPlugin(const Common::Path &filename)
|
||||
: DynamicPlugin(filename), _dlHandle(0) {}
|
||||
|
||||
bool loadPlugin() {
|
||||
assert(!_dlHandle);
|
||||
DiscLabel original;
|
||||
checkDisc(_label);
|
||||
drawPluginProgress(_filename.toString(Common::Path::kNativeSeparator));
|
||||
_dlHandle = dlopen(_filename.toString(Common::Path::kNativeSeparator).c_str(), RTLD_LAZY);
|
||||
|
||||
if (!_dlHandle) {
|
||||
checkDisc(original);
|
||||
warning("Failed loading plugin '%s' (%s)", _filename.toString(Common::Path::kNativeSeparator).c_str(), dlerror());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = DynamicPlugin::loadPlugin();
|
||||
|
||||
if (ret)
|
||||
dlforgetsyms(_dlHandle);
|
||||
|
||||
checkDisc(original);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void unloadPlugin() {
|
||||
DynamicPlugin::unloadPlugin();
|
||||
if (_dlHandle) {
|
||||
if (dlclose(_dlHandle) != 0)
|
||||
warning("Failed unloading plugin '%s' (%s)", _filename.toString(Common::Path::kNativeSeparator).c_str(), dlerror());
|
||||
_dlHandle = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void OSystem_Dreamcast::DCPlugin::checkDisc(const DiscLabel &target)
|
||||
{
|
||||
for (;;) {
|
||||
DiscLabel current;
|
||||
if (current == target)
|
||||
return;
|
||||
|
||||
char buf[32+24];
|
||||
Common::strcpy_s(buf, "Please insert disc '");
|
||||
target.get(buf+strlen(buf));
|
||||
Common::strcat_s(buf, "'");
|
||||
DiscSwap(buf, 0xffffffff).run();
|
||||
}
|
||||
}
|
||||
|
||||
Plugin* OSystem_Dreamcast::createPlugin(const Common::FSNode &node) const {
|
||||
return new DCPlugin(node.getPath());
|
||||
}
|
||||
|
||||
bool OSystem_Dreamcast::isPluginFilename(const Common::FSNode &node) const {
|
||||
// Check the plugin suffix
|
||||
Common::String filename = node.getName();
|
||||
if (!filename.hasSuffix(".PLG"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::addCustomDirectories(Common::FSList &dirs) const
|
||||
{
|
||||
FilePluginProvider::addCustomDirectories(dirs);
|
||||
if (pluginCustomDirectory != NULL)
|
||||
dirs.push_back(Common::FSNode(pluginCustomDirectory));
|
||||
}
|
||||
|
||||
PluginList OSystem_Dreamcast::getPlugins()
|
||||
{
|
||||
pluginCustomDirectory = NULL;
|
||||
PluginList list = FilePluginProvider::getPlugins();
|
||||
if (list.empty()) {
|
||||
Common::String selection;
|
||||
if (selectPluginDir(selection, Common::FSNode("plugins"))) {
|
||||
pluginCustomDirectory = selection.c_str();
|
||||
list = FilePluginProvider::getPlugins();
|
||||
pluginCustomDirectory = NULL;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
#endif // defined(DYNAMIC_MODULES)
|
||||
47
backends/platform/dc/portdefs.h
Normal file
47
backends/platform/dc/portdefs.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <new>
|
||||
#include <limits>
|
||||
|
||||
#ifndef RONIN_TIMER_ACCESS
|
||||
#define Timer ronin_Timer
|
||||
#endif
|
||||
#include <ronin/ronin.h>
|
||||
#ifdef Timer
|
||||
#undef Timer
|
||||
#endif
|
||||
/* newlib ctype.h defines _X for hex digit flag.
|
||||
This conflicts with the use of _X as a variable name. */
|
||||
#undef _X
|
||||
459
backends/platform/dc/selector.cpp
Normal file
459
backends/platform/dc/selector.cpp
Normal file
@@ -0,0 +1,459 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
|
||||
#include <common/scummsys.h>
|
||||
#include <engines/engine.h>
|
||||
#include <engines/metaengine.h>
|
||||
#include <engines/game.h>
|
||||
#include <base/plugins.h>
|
||||
#include <common/fs.h>
|
||||
#include <common/events.h>
|
||||
#include <common/config-manager.h>
|
||||
#include "dc.h"
|
||||
#include "icon.h"
|
||||
#include "label.h"
|
||||
#include "dcutils.h"
|
||||
|
||||
#include <ronin/gddrive.h>
|
||||
|
||||
|
||||
#define MAX_GAMES 100
|
||||
#define MAX_DIR 100
|
||||
#define MAX_PLUGIN_DIRS 100
|
||||
|
||||
|
||||
struct Game
|
||||
{
|
||||
char dir[256];
|
||||
char engine_id[256];
|
||||
char filename_base[256];
|
||||
char text[256];
|
||||
Common::Language language;
|
||||
Common::Platform platform;
|
||||
Icon icon;
|
||||
Label label;
|
||||
};
|
||||
|
||||
struct Dir
|
||||
{
|
||||
char name[252];
|
||||
char deficon[256];
|
||||
Common::FSNode node;
|
||||
};
|
||||
|
||||
static Game the_game;
|
||||
|
||||
static bool isIcon(const Common::FSNode &entry)
|
||||
{
|
||||
return entry.getName().hasSuffixIgnoreCase(".ICO");
|
||||
}
|
||||
|
||||
static bool loadIcon(Game &game, Dir *dirs, int num_dirs)
|
||||
{
|
||||
char icofn[520];
|
||||
Common::sprintf_s(icofn, "%s%s.ICO", game.dir, game.filename_base);
|
||||
if (game.icon.load(icofn))
|
||||
return true;
|
||||
for (int i=0; i<num_dirs; i++)
|
||||
if (!strcmp(dirs[i].name, game.dir) &&
|
||||
dirs[i].deficon[0]) {
|
||||
Common::sprintf_s(icofn, "%s%s", game.dir, dirs[i].deficon);
|
||||
if (game.icon.load(icofn))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void makeDefIcon(Icon &icon)
|
||||
{
|
||||
#include "deficon.h"
|
||||
icon.load(scummvm_icon, sizeof(scummvm_icon));
|
||||
}
|
||||
|
||||
static bool sameOrSubdir(const char *dir1, const char *dir2)
|
||||
{
|
||||
int l1 = strlen(dir1), l2 = strlen(dir2);
|
||||
if (l1<=l2)
|
||||
return !strcmp(dir1, dir2);
|
||||
else
|
||||
return !memcmp(dir1, dir2, l2);
|
||||
}
|
||||
|
||||
static bool uniqueGame(const char *base, const char *dir,
|
||||
Common::Language lang, Common::Platform plf,
|
||||
Game *games, int cnt)
|
||||
{
|
||||
while (cnt--)
|
||||
if (/*Don't detect the same game in a subdir,
|
||||
this is a workaround for the detector bug in toon... */
|
||||
sameOrSubdir(dir, games->dir) &&
|
||||
/*!strcmp(dir, games->dir) &&*/
|
||||
!scumm_stricmp(base, games->filename_base) &&
|
||||
lang == games->language &&
|
||||
plf == games->platform)
|
||||
return false;
|
||||
else
|
||||
games++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int findGames(Game *games, int max, bool use_ini)
|
||||
{
|
||||
Dir *dirs = new Dir[MAX_DIR];
|
||||
int curr_game = 0, curr_dir = 0, num_dirs = 0;
|
||||
|
||||
if (use_ini) {
|
||||
Common::ConfigManager::Domain *appDomain =
|
||||
ConfMan.getDomain(Common::ConfigManager::kApplicationDomain);
|
||||
Common::ConfigManager::Domain savedAppDomain = *appDomain;
|
||||
ConfMan.loadDefaultConfigFile("");
|
||||
*appDomain = savedAppDomain;
|
||||
const Common::ConfigManager::DomainMap &game_domains = ConfMan.getGameDomains();
|
||||
for(Common::ConfigManager::DomainMap::const_iterator i =
|
||||
game_domains.begin(); curr_game < max && i != game_domains.end(); i++) {
|
||||
Common::Path path(Common::Path::fromConfig((*i)._value["path"]));
|
||||
int j;
|
||||
for (j=0; j<num_dirs; j++)
|
||||
if (path.equals(dirs[j].node.getPath()))
|
||||
break;
|
||||
if (j >= num_dirs) {
|
||||
if (num_dirs >= MAX_DIR)
|
||||
continue;
|
||||
dirs[j = num_dirs++].node = Common::FSNode(path);
|
||||
}
|
||||
if (curr_game < max) {
|
||||
Common::strcpy_s(games[curr_game].filename_base, (*i)._key.c_str());
|
||||
strncpy(games[curr_game].engine_id, (*i)._value["engineid"].c_str(), 256);
|
||||
games[curr_game].engine_id[255] = '\0';
|
||||
strncpy(games[curr_game].dir, dirs[j].node.getPath().toString().c_str(), 256);
|
||||
games[curr_game].dir[255] = '\0';
|
||||
games[curr_game].language = Common::UNK_LANG;
|
||||
games[curr_game].platform = Common::kPlatformUnknown;
|
||||
Common::strcpy_s(games[curr_game].text, (*i)._value["description"].c_str());
|
||||
curr_game++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dirs[num_dirs++].node = Common::FSNode("");
|
||||
}
|
||||
|
||||
while ((curr_game < max || use_ini) && curr_dir < num_dirs) {
|
||||
strncpy(dirs[curr_dir].name, dirs[curr_dir].node.getPath().toString().c_str(), 251);
|
||||
dirs[curr_dir].name[250] = '\0';
|
||||
if (!dirs[curr_dir].name[0] ||
|
||||
dirs[curr_dir].name[strlen(dirs[curr_dir].name)-1] != '/')
|
||||
Common::strcat_s(dirs[curr_dir].name, "/");
|
||||
dirs[curr_dir].deficon[0] = '\0';
|
||||
Common::FSList files, fslist;
|
||||
dirs[curr_dir++].node.getChildren(fslist, Common::FSNode::kListAll);
|
||||
for (Common::FSList::const_iterator entry = fslist.begin(); entry != fslist.end();
|
||||
++entry) {
|
||||
if (entry->isDirectory()) {
|
||||
if (!use_ini && num_dirs < MAX_DIR) {
|
||||
dirs[num_dirs].node = *entry;
|
||||
num_dirs++;
|
||||
}
|
||||
/* Toonstruck detector needs directories to be present too */
|
||||
if(!use_ini)
|
||||
files.push_back(*entry);
|
||||
} else
|
||||
if (isIcon(*entry))
|
||||
Common::strcpy_s(dirs[curr_dir-1].deficon, entry->getName().c_str());
|
||||
else if(!use_ini)
|
||||
files.push_back(*entry);
|
||||
}
|
||||
|
||||
if (!use_ini) {
|
||||
DetectionResults detectionResults = EngineMan.detectGames(files);
|
||||
DetectedGames candidates = detectionResults.listRecognizedGames();
|
||||
|
||||
for (DetectedGames::const_iterator ge = candidates.begin();
|
||||
ge != candidates.end(); ++ge)
|
||||
if (curr_game < max) {
|
||||
Common::strcpy_s(games[curr_game].engine_id, ge->engineId.c_str());
|
||||
Common::strcpy_s(games[curr_game].filename_base, ge->gameId.c_str());
|
||||
Common::strcpy_s(games[curr_game].dir, dirs[curr_dir-1].name);
|
||||
games[curr_game].language = ge->language;
|
||||
games[curr_game].platform = ge->platform;
|
||||
if (uniqueGame(games[curr_game].filename_base,
|
||||
games[curr_game].dir,
|
||||
games[curr_game].language,
|
||||
games[curr_game].platform, games, curr_game)) {
|
||||
|
||||
Common::strcpy_s(games[curr_game].text, ge->description.c_str());
|
||||
#if 0
|
||||
printf("Registered game <%s> (l:%d p:%d) in <%s> <%s> because of <%s> <*>\n",
|
||||
games[curr_game].text,
|
||||
(int)games[curr_game].language,
|
||||
(int)games[curr_game].platform,
|
||||
games[curr_game].dir, games[curr_game].filename_base,
|
||||
dirs[curr_dir-1].name);
|
||||
#endif
|
||||
curr_game++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<curr_game; i++)
|
||||
if (!loadIcon(games[i], dirs, num_dirs))
|
||||
makeDefIcon(games[i].icon);
|
||||
delete[] dirs;
|
||||
return curr_game;
|
||||
}
|
||||
|
||||
static void drawBackground()
|
||||
{
|
||||
draw_solid_quad(20.0, 20.0, 620.0, 460.0,
|
||||
0xff0000, 0x00ff00, 0x0000ff, 0xffffff);
|
||||
}
|
||||
|
||||
namespace {
|
||||
class SelectorDiscSwap : public DiscSwap {
|
||||
using DiscSwap::DiscSwap;
|
||||
protected:
|
||||
void background() override {
|
||||
drawBackground();
|
||||
}
|
||||
void interact() override {
|
||||
int mousex = 0, mousey = 0;
|
||||
byte shiftFlags;
|
||||
|
||||
int mask = getimask();
|
||||
setimask(15);
|
||||
handleInput(locked_get_pads(), mousex, mousey, shiftFlags);
|
||||
setimask(mask);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void waitForDisk()
|
||||
{
|
||||
//printf("waitForDisk, cdstate = %d\n", getCdState());
|
||||
SelectorDiscSwap("Please insert game CD.", 0xffff2020).run();
|
||||
}
|
||||
|
||||
static void drawGameLabel(Game &game, int pal, float x, float y,
|
||||
unsigned int argb, int fade = 0, float scale = 1.0)
|
||||
{
|
||||
unsigned int fade_alpha = (255-fade)<<24;
|
||||
|
||||
game.icon.draw(x, y, x+32.0*scale, y+32.0*scale, pal, 0xffffff|fade_alpha);
|
||||
game.label.draw(x+54.0*scale, y+4.0*scale, argb|fade_alpha, scale);
|
||||
}
|
||||
|
||||
int gameMenu(Game *games, int num_games)
|
||||
{
|
||||
int top_game = 0, selector_pos = 0;
|
||||
int mousex = 0, mousey = 0;
|
||||
float y;
|
||||
|
||||
if (!num_games)
|
||||
return -1;
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (getCdState()>=6)
|
||||
return -1;
|
||||
|
||||
ta_begin_frame();
|
||||
|
||||
drawBackground();
|
||||
|
||||
ta_commit_end();
|
||||
|
||||
y = 40.0;
|
||||
for (int i=top_game, cnt=0; cnt<10 && i<num_games; i++, cnt++) {
|
||||
int pal = 48+(i&15);
|
||||
|
||||
if (cnt == selector_pos)
|
||||
draw_trans_quad(100.0, y, 590.0, y+32.0,
|
||||
0x7000ff00, 0x7000ff00, 0x7000ff00, 0x7000ff00);
|
||||
|
||||
games[i].icon.setPalette(pal);
|
||||
drawGameLabel(games[i], pal, 50.0, y, (cnt == selector_pos?
|
||||
0xffff00 : 0xffffff));
|
||||
y += 40.0;
|
||||
}
|
||||
|
||||
ta_commit_frame();
|
||||
|
||||
byte shiftFlags;
|
||||
int event;
|
||||
|
||||
int mask = getimask();
|
||||
setimask(15);
|
||||
event = handleInput(locked_get_pads(), mousex, mousey, shiftFlags);
|
||||
setimask(mask);
|
||||
|
||||
if (event==-Common::EVENT_LBUTTONDOWN || event==Common::KEYCODE_RETURN || event==Common::KEYCODE_F5) {
|
||||
int selected_game = top_game + selector_pos;
|
||||
|
||||
for (int fade=0; fade<=256; fade+=4) {
|
||||
|
||||
ta_begin_frame();
|
||||
|
||||
drawBackground();
|
||||
|
||||
ta_commit_end();
|
||||
|
||||
y = 40.0;
|
||||
|
||||
if (fade < 256)
|
||||
for (int i=top_game, cnt=0; cnt<10 && i<num_games;
|
||||
i++, cnt++, y += 40.0)
|
||||
if (cnt != selector_pos)
|
||||
drawGameLabel(games[i], 48+(i&15), 50.0, y, 0xffffff, fade);
|
||||
|
||||
y = (40.0/256.0 * (selector_pos + 1))*(256-fade) + 80.0/256.0*fade;
|
||||
float x = 50.0/256.0*(256-fade) + 160.0/256.0*fade;
|
||||
float scale = 1.0+9.0/256.0*fade;
|
||||
|
||||
drawGameLabel(games[selected_game], 48+(selected_game&15), x, y,
|
||||
0xffff00, 0, scale);
|
||||
|
||||
ta_commit_frame();
|
||||
}
|
||||
return selected_game;
|
||||
}
|
||||
|
||||
if (mousey>=16) {
|
||||
if (selector_pos + top_game + 1 < num_games)
|
||||
if (++selector_pos >= 10) {
|
||||
--selector_pos;
|
||||
++top_game;
|
||||
}
|
||||
mousey -= 16;
|
||||
} else if (mousey<=-16) {
|
||||
if (selector_pos + top_game > 0)
|
||||
if (--selector_pos < 0) {
|
||||
++selector_pos;
|
||||
--top_game;
|
||||
}
|
||||
mousey += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool selectGame(char *&engineId, char *&ret, char *&dir_ret, Common::Language &lang_ret, Common::Platform &plf_ret, Icon &icon)
|
||||
{
|
||||
Game *games = new Game[MAX_GAMES];
|
||||
int selected, num_games;
|
||||
|
||||
for (;;) {
|
||||
num_games = findGames(games, MAX_GAMES, true);
|
||||
if (!num_games)
|
||||
num_games = findGames(games, MAX_GAMES, false);
|
||||
|
||||
{
|
||||
TextureStack txstack;
|
||||
|
||||
for (int i=0; i<num_games; i++) {
|
||||
games[i].icon.create_texture();
|
||||
games[i].label.create_texture(games[i].text);
|
||||
}
|
||||
|
||||
selected = gameMenu(games, num_games);
|
||||
}
|
||||
|
||||
if (selected == -1)
|
||||
waitForDisk();
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (selected >= num_games)
|
||||
selected = -1;
|
||||
|
||||
if (selected >= 0)
|
||||
the_game = games[selected];
|
||||
|
||||
delete[] games;
|
||||
|
||||
if (selected>=0) {
|
||||
#if 0
|
||||
chdir(the_game.dir);
|
||||
#else
|
||||
chdir("/");
|
||||
dir_ret = the_game.dir;
|
||||
#endif
|
||||
engineId = the_game.engine_id;
|
||||
ret = the_game.filename_base;
|
||||
lang_ret = the_game.language;
|
||||
plf_ret = the_game.platform;
|
||||
icon = the_game.icon;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DYNAMIC_MODULES
|
||||
static int findPluginDirs(Game *plugin_dirs, int max, const Common::FSNode &base)
|
||||
{
|
||||
Common::FSList fslist;
|
||||
int curr_dir = 0;
|
||||
base.getChildren(fslist, Common::FSNode::kListDirectoriesOnly);
|
||||
for (Common::FSList::const_iterator entry = fslist.begin(); entry != fslist.end();
|
||||
++entry) {
|
||||
if (entry->isDirectory()) {
|
||||
if (curr_dir >= max)
|
||||
break;
|
||||
strncpy(plugin_dirs[curr_dir].dir, (*entry).getPath().toString().c_str(), 256);
|
||||
strncpy(plugin_dirs[curr_dir].text, (*entry).getName().c_str(), 256);
|
||||
plugin_dirs[curr_dir].icon.load(NULL, 0, 0);
|
||||
curr_dir++;
|
||||
}
|
||||
}
|
||||
return curr_dir;
|
||||
}
|
||||
|
||||
bool selectPluginDir(Common::String &selection, const Common::FSNode &base)
|
||||
{
|
||||
Game *plugin_dirs = new Game[MAX_PLUGIN_DIRS];
|
||||
int selected, num_plugin_dirs;
|
||||
|
||||
num_plugin_dirs = findPluginDirs(plugin_dirs, MAX_PLUGIN_DIRS, base);
|
||||
|
||||
{
|
||||
TextureStack txstack;
|
||||
|
||||
for (int i=0; i<num_plugin_dirs; i++) {
|
||||
plugin_dirs[i].icon.create_texture();
|
||||
plugin_dirs[i].label.create_texture(plugin_dirs[i].text);
|
||||
}
|
||||
|
||||
selected = gameMenu(plugin_dirs, num_plugin_dirs);
|
||||
}
|
||||
|
||||
if (selected >= num_plugin_dirs)
|
||||
selected = -1;
|
||||
|
||||
if (selected >= 0)
|
||||
selection = plugin_dirs[selected].dir;
|
||||
|
||||
delete[] plugin_dirs;
|
||||
|
||||
return selected >= 0;
|
||||
}
|
||||
#endif
|
||||
167
backends/platform/dc/softkbd.cpp
Normal file
167
backends/platform/dc/softkbd.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common/scummsys.h>
|
||||
#include "common/events.h"
|
||||
#include "engines/engine.h"
|
||||
|
||||
#include <ronin/ronin.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "dc.h"
|
||||
|
||||
|
||||
extern void draw_trans_quad(float x1, float y1, float x2, float y2,
|
||||
int c0, int c1, int c2, int c3);
|
||||
|
||||
|
||||
static const char key_names[] =
|
||||
"Esc\0F1\0F2\0F3\0F4\0F5\0F6\0F7\0F8\0F9\0F10\0"
|
||||
"1\0!\0""2\0\"\0""3\0#\0""4\0$\0""5\0%\0"
|
||||
"6\0&\0""7\0'\0""8\0(\0""9\0)\0""0\0~\0-\0=\0"
|
||||
"q\0Q\0w\0W\0e\0E\0r\0R\0t\0T\0y\0Y\0u\0U\0i\0I\0o\0O\0p\0P\0@\0`\0"
|
||||
"a\0A\0s\0S\0d\0D\0f\0F\0g\0G\0h\0H\0j\0J\0k\0K\0l\0L\0;\0+\0:\0*\0"
|
||||
"z\0Z\0x\0X\0c\0C\0v\0V\0b\0B\0n\0N\0m\0M\0,\0<\0.\0>\0/\0?\0\\\0_\0"
|
||||
"Shf\0Ctl\0Alt\0Space\0BS\0Ret";
|
||||
|
||||
#define K(a,b) ((a)|((b)<<8))
|
||||
|
||||
static const short key_codes[] =
|
||||
{
|
||||
Common::KEYCODE_ESCAPE, Common::KEYCODE_F1, Common::KEYCODE_F2, Common::KEYCODE_F3, Common::KEYCODE_F4, Common::KEYCODE_F5, Common::KEYCODE_F6, Common::KEYCODE_F7, Common::KEYCODE_F8, Common::KEYCODE_F9, Common::KEYCODE_F10,
|
||||
K('1','!'), K('2','"'), K('3','#'), K('4','$'), K('5','%'),
|
||||
K('6','&'), K('7','\''), K('8','('), K('9',')'), K('0','~'), K('-','='),
|
||||
K('q','Q'), K('w','W'), K('e','E'), K('r','R'), K('t','T'),
|
||||
K('y','Y'), K('u','U'), K('i','I'), K('o','O'), K('p','P'), K('@','`'),
|
||||
K('a','A'), K('s','S'), K('d','D'), K('f','F'), K('g','G'),
|
||||
K('h','H'), K('j','J'), K('k','K'), K('l','L'), K(';','+'), K(':','*'),
|
||||
K('z','Z'), K('x','X'), K('c','C'), K('v','V'), K('b','B'),
|
||||
K('n','N'), K('m','M'), K(',','<'), K('.','>'), K('/','?'), K('\\','_'),
|
||||
~Common::KBD_SHIFT, ~Common::KBD_CTRL, ~Common::KBD_ALT, ' ', Common::KEYCODE_BACKSPACE, Common::KEYCODE_RETURN
|
||||
};
|
||||
|
||||
SoftKeyboard::SoftKeyboard(const OSystem_Dreamcast *_os)
|
||||
: os(_os), shiftState(0), keySel(0)
|
||||
{
|
||||
assert((sizeof(key_codes)/sizeof(key_codes[0])) == SK_NUM_KEYS);
|
||||
|
||||
const char *np = key_names;
|
||||
for (int i=0; i<SK_NUM_KEYS; i++) {
|
||||
labels[0][i].create_texture(np);
|
||||
np += strlen(np)+1;
|
||||
if (key_codes[i]>8192) {
|
||||
labels[1][i].create_texture(np);
|
||||
np += strlen(np)+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoftKeyboard::draw(float x, float y, int transp)
|
||||
{
|
||||
float x0;
|
||||
int c = 0;
|
||||
unsigned int txt_alpha_mask = (255-2*transp)<<24;
|
||||
unsigned int bg_alpha_mask = (128-transp)<<24;
|
||||
|
||||
draw_trans_quad(x, y, x+312.0, y+172.0,
|
||||
bg_alpha_mask|0x8080ff, bg_alpha_mask|0x8080ff,
|
||||
bg_alpha_mask|0x8080ff, bg_alpha_mask|0x8080ff);
|
||||
x0 = x += 4.0;
|
||||
y += 4.0;
|
||||
for (int i=0; i<SK_NUM_KEYS; i++) {
|
||||
float w = (i == 58? 164.0 : 24.0);
|
||||
unsigned int bg = (i == keySel? bg_alpha_mask|0xffff00 :
|
||||
bg_alpha_mask|0xc0c0ff);
|
||||
draw_trans_quad(x, y, x+w, y+24.0, bg, bg, bg, bg);
|
||||
if (key_codes[i]<0 && (shiftState & ~key_codes[i]))
|
||||
labels[0][i].draw(x+2, y+5, txt_alpha_mask|0xffffff, 0.5);
|
||||
else if (key_codes[i]>8192 && (shiftState & Common::KBD_SHIFT))
|
||||
labels[1][i].draw(x+2, y+5, txt_alpha_mask|0x000000, 0.5);
|
||||
else
|
||||
labels[0][i].draw(x+2, y+5, txt_alpha_mask|0x000000, 0.5);
|
||||
x += w+4.0;
|
||||
if (++c == 11) {
|
||||
c = 0;
|
||||
x = x0;
|
||||
y += 28.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int SoftKeyboard::key(int k, byte &shiftFlags)
|
||||
{
|
||||
switch(k) {
|
||||
case 1001:
|
||||
if (++keySel == SK_NUM_KEYS)
|
||||
keySel = 0;
|
||||
break;
|
||||
case 1002:
|
||||
if (--keySel < 0)
|
||||
keySel = SK_NUM_KEYS - 1;
|
||||
break;
|
||||
case 1003:
|
||||
if (keySel >= 55) {
|
||||
if (keySel > 58)
|
||||
keySel += 5;
|
||||
keySel -= 55;
|
||||
} else if (keySel > 47) {
|
||||
if ((keySel += 6) < 59)
|
||||
keySel = 59;
|
||||
} else
|
||||
keySel += 11;
|
||||
break;
|
||||
case 1004:
|
||||
if (keySel > 58)
|
||||
keySel -= 6;
|
||||
else if ((keySel -= 11) < 0)
|
||||
if ((keySel += 66) > 58)
|
||||
if ((keySel -= 5) < 59)
|
||||
keySel = 59;
|
||||
break;
|
||||
case 1000:
|
||||
case 13:
|
||||
case 32:
|
||||
case 319:
|
||||
if (key_codes[keySel]<0)
|
||||
shiftState ^= ~key_codes[keySel];
|
||||
else {
|
||||
shiftFlags = shiftState;
|
||||
if (key_codes[keySel] > 8192)
|
||||
return ((shiftState & Common::KBD_SHIFT)? (key_codes[keySel]>>8):
|
||||
key_codes[keySel]) & 0xff;
|
||||
else
|
||||
return key_codes[keySel];
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SoftKeyboard::mouse(int x, int y)
|
||||
{
|
||||
os->mouseToSoftKbd(x, y, x, y);
|
||||
if (x >= 0 && x < 11*28 && y >= 0 && y < 6*28 &&
|
||||
x%28 >= 4 && y%28 >= 4)
|
||||
if ((keySel = 11*(y/28)+(x/28)) > 58)
|
||||
if ((keySel -= 5) < 59)
|
||||
keySel = 58;
|
||||
}
|
||||
49
backends/platform/dc/softkbd.h
Normal file
49
backends/platform/dc/softkbd.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DC_SOFTKBD_H
|
||||
#define DC_SOFTKBD_H
|
||||
|
||||
#include "label.h"
|
||||
|
||||
#define SK_NUM_KEYS 61
|
||||
|
||||
class OSystem_Dreamcast;
|
||||
|
||||
class SoftKeyboard : public Interactive
|
||||
{
|
||||
private:
|
||||
|
||||
const OSystem_Dreamcast *os;
|
||||
Label labels[2][SK_NUM_KEYS];
|
||||
byte shiftState;
|
||||
int8 keySel;
|
||||
|
||||
public:
|
||||
SoftKeyboard(const OSystem_Dreamcast *os);
|
||||
virtual ~SoftKeyboard() {}
|
||||
|
||||
void draw(float x, float y, int transp = 0);
|
||||
int key(int k, byte &shiftFlags);
|
||||
void mouse(int x, int y);
|
||||
};
|
||||
|
||||
#endif /* DC_SOFTKBD_H */
|
||||
55
backends/platform/dc/time.cpp
Normal file
55
backends/platform/dc/time.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define RONIN_TIMER_ACCESS
|
||||
|
||||
#include <common/scummsys.h>
|
||||
#include "dc.h"
|
||||
|
||||
|
||||
uint32 OSystem_Dreamcast::getMillis(bool skipRecord)
|
||||
{
|
||||
static uint32 msecs=0;
|
||||
static unsigned int t0=0;
|
||||
|
||||
unsigned int t = Timer();
|
||||
unsigned int dm, dt = t - t0;
|
||||
|
||||
t0 = t;
|
||||
dm = (dt << 6)/3125U;
|
||||
dt -= (dm * 3125U)>>6;
|
||||
t0 -= dt;
|
||||
|
||||
return msecs += dm;
|
||||
}
|
||||
|
||||
void OSystem_Dreamcast::delayMillis(uint msecs)
|
||||
{
|
||||
getMillis();
|
||||
unsigned int t, start = Timer();
|
||||
int time = (((unsigned int)msecs)*3125U)>>6;
|
||||
while (((int)((t = Timer())-start))<time) {
|
||||
if (_timerManager != NULL)
|
||||
((DefaultTimerManager *)_timerManager)->handler();
|
||||
checkSound();
|
||||
}
|
||||
getMillis();
|
||||
}
|
||||
439
backends/platform/dc/vmsave.cpp
Normal file
439
backends/platform/dc/vmsave.cpp
Normal file
@@ -0,0 +1,439 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
|
||||
#include <common/scummsys.h>
|
||||
#include "engines/engine.h"
|
||||
#include "dc.h"
|
||||
#include "icon.h"
|
||||
#include <common/savefile.h>
|
||||
#include <gui/gui-manager.h>
|
||||
#include <gui/message.h>
|
||||
#include <common/compression/deflate.h>
|
||||
|
||||
|
||||
// Savegame can not be bigger than this
|
||||
#define MAX_SAVE_SIZE (128*1024)
|
||||
|
||||
|
||||
enum vmsaveResult {
|
||||
VMSAVE_OK,
|
||||
VMSAVE_NOVM,
|
||||
VMSAVE_NOSPACE,
|
||||
VMSAVE_WRITEERROR
|
||||
};
|
||||
|
||||
|
||||
static int lastvm=-1;
|
||||
|
||||
static void displaySaveResult(vmsaveResult res)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
switch(res) {
|
||||
case VMSAVE_OK:
|
||||
Common::sprintf_s(buf, "Game saved on unit %c%d", 'A'+(lastvm/6), lastvm%6);
|
||||
break;
|
||||
case VMSAVE_NOVM:
|
||||
Common::strcpy_s(buf, "No memory card present!");
|
||||
break;
|
||||
case VMSAVE_NOSPACE:
|
||||
Common::strcpy_s(buf, "Not enough space available!");
|
||||
break;
|
||||
case VMSAVE_WRITEERROR:
|
||||
Common::strcpy_s(buf, "Write error!!!");
|
||||
break;
|
||||
default:
|
||||
Common::strcpy_s(buf, "Unknown error!!!");
|
||||
break;
|
||||
}
|
||||
|
||||
GUI::MessageDialog dialog(buf);
|
||||
dialog.runModal();
|
||||
}
|
||||
|
||||
static vmsaveResult trySave(const char *gamename, const char *data, int size,
|
||||
const char *filename, class Icon &icon, int vm)
|
||||
{
|
||||
struct vmsinfo info;
|
||||
struct superblock super;
|
||||
struct vms_file file;
|
||||
struct vms_file_header header;
|
||||
struct timestamp tstamp;
|
||||
struct tm tm;
|
||||
time_t t;
|
||||
unsigned char iconbuffer[512+32];
|
||||
|
||||
if (!vmsfs_check_unit(vm, 0, &info))
|
||||
return VMSAVE_NOVM;
|
||||
if (!vmsfs_get_superblock(&info, &super))
|
||||
return VMSAVE_NOVM;
|
||||
int free_cnt = vmsfs_count_free(&super);
|
||||
if (vmsfs_open_file(&super, filename, &file))
|
||||
free_cnt += file.blks;
|
||||
if (((128+512+size+511)>>9) > free_cnt)
|
||||
return VMSAVE_NOSPACE;
|
||||
|
||||
memset(&header, 0, sizeof(header));
|
||||
strncpy(header.shortdesc, "ScummVM savegame", 16);
|
||||
strncpy(header.longdesc, gamename, 32);
|
||||
strncpy(header.id, "ScummVM", 16);
|
||||
icon.create_vmicon(iconbuffer);
|
||||
header.numicons = 1;
|
||||
memcpy(header.palette, iconbuffer, sizeof(header.palette));
|
||||
time(&t);
|
||||
tm = *localtime(&t);
|
||||
tstamp.year = tm.tm_year+1900;
|
||||
tstamp.month = tm.tm_mon+1;
|
||||
tstamp.day = tm.tm_mday;
|
||||
tstamp.hour = tm.tm_hour;
|
||||
tstamp.minute = tm.tm_min;
|
||||
tstamp.second = tm.tm_sec;
|
||||
tstamp.wkday = (tm.tm_wday+6)%7;
|
||||
|
||||
vmsfs_beep(&info, 1);
|
||||
|
||||
vmsfs_errno = 0;
|
||||
if (!vmsfs_create_file(&super, filename, &header,
|
||||
iconbuffer+sizeof(header.palette), NULL,
|
||||
data, size, &tstamp)) {
|
||||
fprintf(stderr, "%s\n", vmsfs_describe_error());
|
||||
vmsfs_beep(&info, 0);
|
||||
return VMSAVE_WRITEERROR;
|
||||
}
|
||||
|
||||
vmsfs_beep(&info, 0);
|
||||
return VMSAVE_OK;
|
||||
}
|
||||
|
||||
static bool tryLoad(char *&buffer, int &size, const char *filename, int vm)
|
||||
{
|
||||
struct vmsinfo info;
|
||||
struct superblock super;
|
||||
struct vms_file file;
|
||||
|
||||
if (!vmsfs_check_unit(vm, 0, &info))
|
||||
return false;
|
||||
if (!vmsfs_get_superblock(&info, &super))
|
||||
return false;
|
||||
if (!vmsfs_open_file(&super, filename, &file))
|
||||
return false;
|
||||
|
||||
buffer = new char[size = file.size];
|
||||
|
||||
if (vmsfs_read_file(&file, (unsigned char *)buffer, size))
|
||||
return true;
|
||||
|
||||
delete[] buffer;
|
||||
buffer = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool tryDelete(const char *filename, int vm)
|
||||
{
|
||||
struct vmsinfo info;
|
||||
struct superblock super;
|
||||
|
||||
if (!vmsfs_check_unit(vm, 0, &info))
|
||||
return false;
|
||||
if (!vmsfs_get_superblock(&info, &super))
|
||||
return false;
|
||||
|
||||
if (!vmsfs_delete_file(&super, filename))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void tryList(const Common::String &glob, int vm, Common::StringArray &list)
|
||||
{
|
||||
struct vmsinfo info;
|
||||
struct superblock super;
|
||||
struct dir_iterator iter;
|
||||
struct dir_entry de;
|
||||
|
||||
if (!vmsfs_check_unit(vm, 0, &info))
|
||||
return;
|
||||
if (!vmsfs_get_superblock(&info, &super))
|
||||
return;
|
||||
vmsfs_open_dir(&super, &iter);
|
||||
while (vmsfs_next_dir_entry(&iter, &de))
|
||||
if (de.entry[0]) {
|
||||
char buf[16];
|
||||
strncpy(buf, (char *)de.entry+4, 12);
|
||||
buf[12] = 0;
|
||||
if (Common::matchString(buf, glob.c_str()))
|
||||
list.push_back(buf);
|
||||
}
|
||||
}
|
||||
|
||||
vmsaveResult writeSaveGame(const char *gamename, const char *data, int size,
|
||||
const char *filename, class Icon &icon)
|
||||
{
|
||||
vmsaveResult r, res = VMSAVE_NOVM;
|
||||
|
||||
if (lastvm >= 0 &&
|
||||
(res = trySave(gamename, data, size, filename, icon, lastvm)) == VMSAVE_OK)
|
||||
return res;
|
||||
|
||||
for (int i=0; i<24; i++)
|
||||
if ((r = trySave(gamename, data, size, filename, icon, i)) == VMSAVE_OK) {
|
||||
lastvm = i;
|
||||
return r;
|
||||
} else if (r > res)
|
||||
res = r;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool readSaveGame(char *&buffer, int &size, const char *filename)
|
||||
{
|
||||
if (lastvm >= 0 &&
|
||||
tryLoad(buffer, size, filename, lastvm))
|
||||
return true;
|
||||
|
||||
for (int i=0; i<24; i++)
|
||||
if (tryLoad(buffer, size, filename, i)) {
|
||||
lastvm = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool deleteSaveGame(const char *filename)
|
||||
{
|
||||
if (lastvm >= 0 &&
|
||||
tryDelete(filename, lastvm))
|
||||
return true;
|
||||
|
||||
for (int i=0; i<24; i++)
|
||||
if (tryDelete(filename, i)) {
|
||||
lastvm = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
class InVMSave : public Common::InSaveFile {
|
||||
private:
|
||||
char *buffer;
|
||||
int _pos, _size;
|
||||
bool _eos;
|
||||
|
||||
uint32 read(void *buf, uint32 cnt) override;
|
||||
bool skip(uint32 offset) override;
|
||||
bool seek(int64 offs, int whence) override;
|
||||
|
||||
public:
|
||||
InVMSave()
|
||||
: _pos(0), buffer(NULL), _eos(false)
|
||||
{ }
|
||||
|
||||
~InVMSave()
|
||||
{
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
bool eos() const override { return _eos; }
|
||||
void clearErr() override { _eos = false; }
|
||||
int64 pos() const override { return _pos; }
|
||||
int64 size() const override { return _size; }
|
||||
|
||||
bool readSaveGame(const char *filename)
|
||||
{ return ::readSaveGame(buffer, _size, filename); }
|
||||
};
|
||||
|
||||
class OutVMSave : public Common::WriteStream {
|
||||
private:
|
||||
char *buffer;
|
||||
int _pos, size, committed;
|
||||
char filename[16];
|
||||
bool iofailed;
|
||||
|
||||
public:
|
||||
uint32 write(const void *buf, uint32 cnt);
|
||||
virtual int64 pos() const { return _pos; }
|
||||
|
||||
OutVMSave(const char *_filename)
|
||||
: _pos(0), committed(-1), iofailed(false)
|
||||
{
|
||||
strncpy(filename, _filename, 16);
|
||||
buffer = new char[size = MAX_SAVE_SIZE];
|
||||
}
|
||||
|
||||
~OutVMSave();
|
||||
|
||||
bool err() const { return iofailed; }
|
||||
void clearErr() { iofailed = false; }
|
||||
void finalize();
|
||||
};
|
||||
|
||||
class VMSaveManager : public Common::SaveFileManager {
|
||||
private:
|
||||
static int nameCompare(const unsigned char *entry, const char *match) {
|
||||
return !scumm_strnicmp(reinterpret_cast<const char *>(entry), match, 12);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void updateSavefilesList(Common::StringArray &lockedFiles) {
|
||||
// TODO: implement this (locks files, preventing them from being listed, saved or loaded)
|
||||
}
|
||||
|
||||
VMSaveManager() {
|
||||
vmsfs_name_compare_function = nameCompare;
|
||||
}
|
||||
|
||||
Common::InSaveFile *openRawFile(const Common::String &filename) override {
|
||||
InVMSave *s = new InVMSave();
|
||||
if (s->readSaveGame(filename.c_str())) {
|
||||
return s;
|
||||
} else {
|
||||
delete s;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Common::OutSaveFile *openForSaving(const Common::String &filename, bool compress = true) override {
|
||||
OutVMSave *s = new OutVMSave(filename.c_str());
|
||||
return new Common::OutSaveFile(compress ? Common::wrapCompressedWriteStream(s) : s);
|
||||
}
|
||||
|
||||
Common::InSaveFile *openForLoading(const Common::String &filename) override {
|
||||
InVMSave *s = new InVMSave();
|
||||
if (s->readSaveGame(filename.c_str())) {
|
||||
return Common::wrapCompressedReadStream(s);
|
||||
} else {
|
||||
delete s;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool removeSavefile(const Common::String &filename) override {
|
||||
return ::deleteSaveGame(filename.c_str());
|
||||
}
|
||||
|
||||
Common::StringArray listSavefiles(const Common::String &pattern) override;
|
||||
|
||||
bool exists(const Common::String &filename) override {
|
||||
return InVMSave().readSaveGame(filename.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
void OutVMSave::finalize()
|
||||
{
|
||||
extern char gGameName[32];
|
||||
extern Icon icon;
|
||||
|
||||
if (committed >= _pos)
|
||||
return;
|
||||
|
||||
char *data = buffer;
|
||||
int len = _pos;
|
||||
|
||||
vmsaveResult r = writeSaveGame(gGameName, data, len, filename, icon);
|
||||
committed = _pos;
|
||||
if (r != VMSAVE_OK)
|
||||
iofailed = true;
|
||||
displaySaveResult(r);
|
||||
}
|
||||
|
||||
OutVMSave::~OutVMSave()
|
||||
{
|
||||
finalize();
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
uint32 InVMSave::read(void *buf, uint32 cnt)
|
||||
{
|
||||
int nbyt = cnt;
|
||||
if (_pos + nbyt > _size) {
|
||||
cnt = (_size - _pos);
|
||||
_eos = true;
|
||||
nbyt = cnt;
|
||||
}
|
||||
if (nbyt)
|
||||
memcpy(buf, buffer + _pos, nbyt);
|
||||
_pos += nbyt;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
bool InVMSave::skip(uint32 offset)
|
||||
{
|
||||
int nbyt = offset;
|
||||
if (_pos + nbyt > _size)
|
||||
nbyt = (_size - _pos);
|
||||
_pos += nbyt;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InVMSave::seek(int64 offs, int whence)
|
||||
{
|
||||
switch(whence) {
|
||||
case SEEK_SET:
|
||||
_pos = offs;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
_pos += offs;
|
||||
break;
|
||||
case SEEK_END:
|
||||
_pos = _size + offs;
|
||||
break;
|
||||
}
|
||||
if (_pos < 0)
|
||||
_pos = 0;
|
||||
else if (_pos > _size)
|
||||
_pos = _size;
|
||||
_eos = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 OutVMSave::write(const void *buf, uint32 cnt)
|
||||
{
|
||||
int nbyt = cnt;
|
||||
if (_pos + nbyt > size) {
|
||||
cnt = (size - _pos);
|
||||
nbyt = cnt;
|
||||
}
|
||||
if (nbyt)
|
||||
memcpy(buffer + _pos, buf, nbyt);
|
||||
_pos += nbyt;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
Common::StringArray VMSaveManager::listSavefiles(const Common::String &pattern)
|
||||
{
|
||||
Common::StringArray list;
|
||||
|
||||
for (int i=0; i<24; i++)
|
||||
tryList(pattern, i, list);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Common::SaveFileManager *OSystem_Dreamcast::createSavefileManager()
|
||||
{
|
||||
return new VMSaveManager();
|
||||
}
|
||||
Reference in New Issue
Block a user