diff options
Diffstat (limited to 'backends/dc')
-rw-r--r-- | backends/dc/.cvsignore | 5 | ||||
-rw-r--r-- | backends/dc/Makefile | 39 | ||||
-rw-r--r-- | backends/dc/README | 20 | ||||
-rw-r--r-- | backends/dc/audio.cpp | 86 | ||||
-rw-r--r-- | backends/dc/dc.h | 102 | ||||
-rw-r--r-- | backends/dc/dcmain.cpp | 201 | ||||
-rw-r--r-- | backends/dc/display.cpp | 303 | ||||
-rw-r--r-- | backends/dc/icon.cpp | 228 | ||||
-rw-r--r-- | backends/dc/icon.h | 21 | ||||
-rw-r--r-- | backends/dc/input.cpp | 173 | ||||
-rw-r--r-- | backends/dc/label.cpp | 131 | ||||
-rw-r--r-- | backends/dc/label.h | 11 | ||||
-rw-r--r-- | backends/dc/portdefs.h | 9 | ||||
-rw-r--r-- | backends/dc/selector.cpp | 487 | ||||
-rw-r--r-- | backends/dc/vmsave.cpp | 266 |
15 files changed, 2082 insertions, 0 deletions
diff --git a/backends/dc/.cvsignore b/backends/dc/.cvsignore new file mode 100644 index 0000000000..ed6bd2b99e --- /dev/null +++ b/backends/dc/.cvsignore @@ -0,0 +1,5 @@ +scummvm +sound +v3 +v4 +simon diff --git a/backends/dc/Makefile b/backends/dc/Makefile new file mode 100644 index 0000000000..18ba20d6fc --- /dev/null +++ b/backends/dc/Makefile @@ -0,0 +1,39 @@ +# $Header$ + +ronindir = /usr/local/ronin + +VPATH = .. + +CC = sh-elf-g++ -ml -m4-single-only +CFLAGS = -O1 -Wno-multichar +DEFINES = -D__DC__ -DNONSTANDARD_PORT -DNONSTANDARD_SAVE +LDFLAGS := -Wl,-Ttext,0x8c010000 -nostartfiles ronin/crt0.o +INCLUDES:= -I./ -I../ -I../sound +CPPFLAGS= $(DEFINES) $(INCLUDES) +LIBS = ronin/libronin.a ronin/libz.a -lm +EXEEXT = + +OBJS = dcmain.o display.o audio.o input.o selector.o icon.o \ + label.o vmsave.o + +include ../Makefile.common + +INCS += portdefs.h dc.h + +$(OBJS): Makefile sound/.create simon/.create v3/.create v4/.create ronin + +sound/.create: + mkdir sound && touch $@ + +simon/.create: + mkdir simon && touch $@ + +v3/.create: + mkdir v3 && touch $@ + +v4/.create: + mkdir v4 && touch $@ + +ronin: + ln -s $(ronindir) $@ + diff --git a/backends/dc/README b/backends/dc/README new file mode 100644 index 0000000000..d4bf04c5bd --- /dev/null +++ b/backends/dc/README @@ -0,0 +1,20 @@ +Compiling ScummVM for SEGA Dreamcast +==================================== + +If you want to compile ScummVM for your Dreamcast, +you'll need the following: + +* gcc-3.0.x configured as a cross-compiler for `sh-elf' + (including corresponding binutils) + +* newlib for sh-elf : <URL:http://mc.pp.se/dc/files/newlib-1.9.0.tar.gz> + +* libronin-0.3 : <URL:http://peter.bortas.org/scumm/libronin-0.3.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', and you should +get an ELF binary with the name `scummvm'. + diff --git a/backends/dc/audio.cpp b/backends/dc/audio.cpp new file mode 100644 index 0000000000..863c1e97ac --- /dev/null +++ b/backends/dc/audio.cpp @@ -0,0 +1,86 @@ +/* ScummVM - Scumm Interpreter + * Dreamcast port + * Copyright (C) 2002 Marcus Comstedt + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include "stdafx.h" +#include "scumm.h" +#include "dc.h" + +EXTERN_C void *memcpy4(void *s1, const void *s2, unsigned int n); + +void initSound() +{ + stop_sound(); + do_sound_command(CMD_SET_FREQ_EXP(FREQ_22050_EXP)); + do_sound_command(CMD_SET_BUFFER(3)); +} + +bool OSystem_Dreamcast::set_sound_proc(void *param, SoundProc *proc, + byte format) +{ +#if SAMPLE_MODE == 0 + assert(format == SOUND_16BIT); +#elif SAMPLE_MODE == 1 + assert(format == SOUND_8BIT); +#else +#error Invalid SAMPLE_MODE +#endif + _sound_proc_param = param; + _sound_proc = proc; + + return true; +} + +void OSystem_Dreamcast::checkSound() +{ + int n; + int curr_ring_buffer_samples; + + 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; + + _sound_proc(_sound_proc_param, (byte*)temp_sound_buffer, + SAMPLES_TO_BYTES(n)); + + if(fillpos+n > curr_ring_buffer_samples) { + int r = curr_ring_buffer_samples - fillpos; + memcpy4(RING_BUF+fillpos, temp_sound_buffer, SAMPLES_TO_BYTES(r)); + fillpos = 0; + n -= r; + memcpy4(RING_BUF, temp_sound_buffer+r, SAMPLES_TO_BYTES(n)); + } else { + memcpy4(RING_BUF+fillpos, temp_sound_buffer, SAMPLES_TO_BYTES(n)); + } + if((fillpos += n) >= curr_ring_buffer_samples) + fillpos = 0; +} diff --git a/backends/dc/dc.h b/backends/dc/dc.h new file mode 100644 index 0000000000..4a2b78cfb7 --- /dev/null +++ b/backends/dc/dc.h @@ -0,0 +1,102 @@ +#include <ronin/soundcommon.h> + +#define NUM_BUFFERS 4 + +class OSystem_Dreamcast : public OSystem { + + public: + // Set colors of the palette + void set_palette(const byte *colors, uint start, uint num); + + // Set the size of the video bitmap. + // Typically, 320x200 + void init_size(uint w, uint h); + + // Draw a bitmap to screen. + // The screen will not be updated to reflect the new bitmap + void copy_rect(const byte *buf, int pitch, int x, int y, int w, int h); + + // Update the dirty areas of the screen + void update_screen(); + + // Either show or hide the mouse cursor + bool show_mouse(bool visible); + + // Set the position of the mouse cursor + void set_mouse_pos(int x, int y); + + // Set the bitmap that's used when drawing the cursor. + void set_mouse_cursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y); + + // Shaking is used in SCUMM. Set current shake position. + void set_shake_pos(int shake_pos); + + // Get the number of milliseconds since the program was started. + uint32 get_msecs(); + + // Delay for a specified amount of milliseconds + void delay_msecs(uint msecs); + + // Create a thread + void *create_thread(ThreadProc *proc, void *param); + + // Get the next event. + // Returns true if an event was retrieved. + bool poll_event(Event *event); + + // Set function that generates samples + bool set_sound_proc(void *param, SoundProc *proc, byte sound); + + // Poll cdrom status + // Returns true if cd audio is playing + bool poll_cdrom(); + + // Play cdrom audio track + void play_cdrom(int track, int num_loops, int start_frame, int end_frame); + + // Stop cdrom audio track + void stop_cdrom(); + + // Update cdrom audio status + void update_cdrom(); + + // Quit + void quit(); + + // Set a parameter + uint32 property(int param, Property *value); + + static OSystem *create(); + + + private: + + 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; + int _current_shake_pos, _screen_h; + unsigned char *_ms_buf; + SoundProc *_sound_proc; + void *_sound_proc_param; + + unsigned char *screen; + unsigned short *mouse; + void *screen_tx[NUM_BUFFERS]; + void *mouse_tx[NUM_BUFFERS]; + int current_buffer; + unsigned short palette[256]; + + short temp_sound_buffer[RING_BUFFER_SAMPLES]; + + void checkSound(); + + void drawMouse(int xdraw, int ydraw, int w, int h, + unsigned char *buf, bool visible); + +}; + +extern int handleInput(struct mapledev *pad, + int &mouse_x, int &mouse_y, + byte &shiftFlags); +extern void initSound(); +extern bool selectGame(GameDetector *d, char *&, char *&, class Icon &); + diff --git a/backends/dc/dcmain.cpp b/backends/dc/dcmain.cpp new file mode 100644 index 0000000000..a64643a004 --- /dev/null +++ b/backends/dc/dcmain.cpp @@ -0,0 +1,201 @@ +/* ScummVM - Scumm Interpreter + * Dreamcast port + * Copyright (C) 2002 Marcus Comstedt + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include "stdafx.h" +#include "scumm.h" +#include "mididrv.h" +#include "gameDetector.h" +#include "dc.h" +#include "icon.h" + + +Icon icon; + + +OSystem *OSystem_Dreamcast_create() { + return OSystem_Dreamcast::create(); +} + +OSystem *OSystem_Dreamcast::create() { + OSystem_Dreamcast *syst = new OSystem_Dreamcast(); + return syst; +} + +/* 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=last; i>=first; --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; +} + +void OSystem_Dreamcast::play_cdrom(int track, int num_loops, + int start_frame, int end_frame) +{ + int first_sec, last_sec; +#if 1 + if(num_loops) + --num_loops; +#endif + if(num_loops>14) num_loops=14; + else if(num_loops<0) num_loops=15; // infinity + if(!find_track(track, first_sec, last_sec)) + return; + if(end_frame) + last_sec = first_sec + start_frame + end_frame; + first_sec += start_frame; + play_cdda_sectors(first_sec, last_sec, num_loops); +} + +void OSystem_Dreamcast::stop_cdrom() +{ + stop_cdda(); +} + +bool OSystem_Dreamcast::poll_cdrom() +{ + extern int getCdState(); + return getCdState() == 3; +} + +void OSystem_Dreamcast::update_cdrom() +{ + // Dummy. The CD drive takes care of itself. +} + +uint32 OSystem_Dreamcast::property(int param, Property *value) +{ + switch(param) { + + case PROP_GET_SAMPLE_RATE: + return 22050; + + } + + return 0; +} + +void OSystem_Dreamcast::quit() { + exit(0); +} + +void *OSystem_Dreamcast::create_thread(ThreadProc *proc, void *param) { + warning("Creating a thread! (not supported.)\n"); +} + +uint32 OSystem_Dreamcast::get_msecs() +{ + 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::delay_msecs(uint msecs) +{ + get_msecs(); + unsigned int t, start = Timer(); + int time = (((unsigned int)msecs)*100000U)>>11; + while(((int)((t = Timer())-start))<time) + checkSound(); + get_msecs(); +} + +/* +void waitForTimer(Scumm *s, int time) +{ + if(time<0) + return; + unsigned int start = Timer(); + unsigned int devpoll = start+USEC_TO_TIMER(25000); + unsigned int t; + int oldmousex = s->mouse.x, oldmousey = s->mouse.y; + time = (((unsigned int)time)*100000U)>>11; + int mask = getimask(); + while(((int)((t = Timer())-start))<time) + if(((int)(t-devpoll))>0) { + setimask(15); + checkSound(); + handleInput(locked_get_pads(), s->mouse.x, s->mouse.y, + s->_leftBtnPressed, s->_rightBtnPressed, s->_keyPressed); + setimask(mask); + devpoll += USEC_TO_TIMER(17000); + if(s->mouse.x != oldmousex || s->mouse.y != oldmousey) { + extern void updateScreen(Scumm *s); + updateScreen(s); + oldmousex = s->mouse.x; + oldmousey = s->mouse.y; + } + } +} +*/ + +void dc_init_hardware(void) +{ +#ifndef NOSERIAL + serial_init(57600); + usleep(2000000); + printf("Serial OK\r\n"); +#endif + + cdfs_init(); + maple_init(); + dc_setup_ta(); + init_arm(); +} + +int dc_setup(GameDetector &detector) +{ + static char *argv[] = { "scummvm", NULL, NULL, NULL }; + static int argc = 3; + + initSound(); + + if(!selectGame(&detector, argv[2], argv[1], icon)) + exit(0); + + detector.parseCommandLine(argc, argv); + + return 0; +} diff --git a/backends/dc/display.cpp b/backends/dc/display.cpp new file mode 100644 index 0000000000..97c7f2aed5 --- /dev/null +++ b/backends/dc/display.cpp @@ -0,0 +1,303 @@ +/* ScummVM - Scumm Interpreter + * Dreamcast port + * Copyright (C) 2002 Marcus Comstedt + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include "stdafx.h" +#include "scumm.h" +#include "dc.h" + +#define SCREEN_W 320 +#define SCREEN_H 240 +#define MOUSE_W 64 +#define MOUSE_H 64 + +#define TOP_OFFSET (240.0-_screen_h) + +#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; + } +} + +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::set_palette(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 += 4; + } +} + +void OSystem_Dreamcast::init_size(uint w, uint h) +{ + assert(w == SCREEN_W && h <= SCREEN_H); + + _screen_h = h; + ta_sync(); + if(!screen) + screen = new unsigned char[SCREEN_W*SCREEN_H]; + for(int i=0; i<NUM_BUFFERS; i++) + if(!screen_tx[i]) + screen_tx[i] = ta_txalloc(SCREEN_W*SCREEN_H*2); + for(int i=0; i<NUM_BUFFERS; i++) + if(!mouse_tx[i]) + mouse_tx[i] = ta_txalloc(MOUSE_W*MOUSE_H*2); + current_buffer = 0; + *(volatile unsigned int *)(0xa05f80e4) = SCREEN_W/32; //stride + // dc_reset_screen(0, 0); +} + +void OSystem_Dreamcast::copy_rect(const byte *buf, int pitch, int x, int y, + int w, int h) +{ + unsigned char *dst = screen + y*SCREEN_W + x; + do { + memcpy(dst, buf, w); + dst += SCREEN_W; + buf += pitch; + } while (--h); +} + +bool OSystem_Dreamcast::show_mouse(bool visible) +{ + bool last = _ms_visible; + _ms_visible = visible; + + return last; +} + +void OSystem_Dreamcast::set_mouse_pos(int x, int y) +{ + _ms_cur_x = x; + _ms_cur_y = y; +} + +void OSystem_Dreamcast::set_mouse_cursor(const byte *buf, uint w, uint h, + int hotspot_x, int hotspot_y) +{ + _ms_cur_w = w; + _ms_cur_h = h; + + _ms_hotspot_x = hotspot_x; + _ms_hotspot_y = hotspot_y; + + _ms_buf = (byte*)buf; +} + +void OSystem_Dreamcast::set_shake_pos(int shake_pos) +{ + _current_shake_pos = shake_pos; +} + +void OSystem_Dreamcast::update_screen(void) +{ + struct polygon_list mypoly; + struct packed_colour_vertex_list myvertex; + + unsigned short *dst = (unsigned short *)screen_tx[current_buffer]; + unsigned char *src = screen; + + // while((*((volatile unsigned int *)(void*)0xa05f810c) & 0x3ff) != 200); + // *((volatile unsigned int *)(void*)0xa05f8040) = 0xff0000; + + for( int y = 0; y<_screen_h; y++ ) + { + texture_memcpy64_pal( dst, src, SCREEN_W>>5, palette ); + src += SCREEN_W; + dst += SCREEN_W; + } + + // *((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_512|TA_POLYMODE2_V_SIZE_512; + mypoly.texture = TA_TEXTUREMODE_ARGB1555|TA_TEXTUREMODE_NON_TWIDDLED| + TA_TEXTUREMODE_STRIDE|TA_TEXTUREMODE_ADDRESS(screen_tx[current_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 = 0.0; + myvertex.y = _current_shake_pos*2.0+TOP_OFFSET; + ta_commit_list(&myvertex); + + myvertex.x = SCREEN_W*2.0; + myvertex.u = SCREEN_W/512.0; + ta_commit_list(&myvertex); + + myvertex.x = 0.0; + myvertex.y += _screen_h*2.0; + myvertex.u = 0.0; + myvertex.v = _screen_h*(1/512.0); + ta_commit_list(&myvertex); + + myvertex.x = SCREEN_W*2.0; + myvertex.u = SCREEN_W/512.0; + myvertex.cmd |= TA_CMD_VERTEX_EOS; + ta_commit_list(&myvertex); + + ta_commit_end(); + // *((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(); + + current_buffer++; + current_buffer &= NUM_BUFFERS-1; + // *((volatile unsigned int *)(void*)0xa05f8040) = 0x0; +} + +void OSystem_Dreamcast::drawMouse(int xdraw, int ydraw, int w, int h, + unsigned char *buf, bool visible) +{ + struct polygon_list mypoly; + struct packed_colour_vertex_list myvertex; + + unsigned short *dst = (unsigned short *)mouse_tx[current_buffer]; + int y=0; + + if(visible && w<=MOUSE_W && h<=MOUSE_H) + for(int y=0; y<h; y++) { + int x; + for(x=0; x<w; x++) + if(*buf == 0xff) { + *dst++ = 0; + buf++; + } else + *dst++ = palette[*buf++]|0x8000; + dst += MOUSE_W-x; + } + else + w = h = 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_FOG_DISABLED|TA_POLYMODE2_TEXTURE_REPLACE| + TA_POLYMODE2_U_SIZE_64|TA_POLYMODE2_V_SIZE_64; + mypoly.texture = TA_TEXTUREMODE_ARGB1555|TA_TEXTUREMODE_NON_TWIDDLED| + TA_TEXTUREMODE_ADDRESS(mouse_tx[current_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_y)*2.0; + myvertex.y = (ydraw+_current_shake_pos-_ms_hotspot_x)*2.0 + TOP_OFFSET; + ta_commit_list(&myvertex); + + myvertex.x += w*2.0; + myvertex.u = w*(1.0/MOUSE_W); + ta_commit_list(&myvertex); + + myvertex.x = (xdraw-_ms_hotspot_y)*2.0; + myvertex.y += h*2.0; + myvertex.u = 0.0; + myvertex.v = h*(1.0/MOUSE_H); + ta_commit_list(&myvertex); + + myvertex.x += w*2.0; + myvertex.u = w*(1.0/MOUSE_W); + myvertex.cmd |= TA_CMD_VERTEX_EOS; + ta_commit_list(&myvertex); +} + diff --git a/backends/dc/icon.cpp b/backends/dc/icon.cpp new file mode 100644 index 0000000000..93e70ad2b5 --- /dev/null +++ b/backends/dc/icon.cpp @@ -0,0 +1,228 @@ +/* ScummVM - Scumm Interpreter + * Dreamcast port + * Copyright (C) 2002 Marcus Comstedt + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#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 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::set_palette(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() +{ + int use[16]; + memset(use, 0, sizeof(use)); + for(int n=0; n<32*32/2; n++) { + unsigned char pix = bitmap[n]; + use[pix&0xf]++; + use[pix>>4]++; + } + for(int i=0; i<16; i++) + if(!use[i]) + return i; + return -1; +} + +bool Icon::load_image2(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; + 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, ((char *)data)+hdr.size, hdr.used<<2); + memcpy(bitmap, ((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; + int unused = find_unused_pixel(); + if(unused >= 0) { + unsigned char *mask = + ((unsigned char *)data)+hdr.size+(hdr.used<<2)+32*32/2; + 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(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, ((char *)data)+offs, 16); + if(hdr.bytes > 0 && hdr.offs >= 0 && hdr.offs+hdr.bytes <= len) + return load_image2(((char *)data)+hdr.offs, hdr.bytes); + else + return false; +} + +bool Icon::load(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, ((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; +} diff --git a/backends/dc/icon.h b/backends/dc/icon.h new file mode 100644 index 0000000000..b9cf344bab --- /dev/null +++ b/backends/dc/icon.h @@ -0,0 +1,21 @@ + +class Icon +{ + private: + unsigned char bitmap[32*32/2]; + unsigned int palette[16]; + void *texture; + + int find_unused_pixel(); + bool load_image1(void *data, int len, int offs); + bool load_image2(void *data, int len); + + public: + bool load(void *data, int len, int offs = 0); + bool load(const char *filename); + void create_texture(); + void set_palette(int pal); + void draw(float x1, float y1, float x2, float y2, int pal, + unsigned argb = 0xffffffff); + void create_vmicon(void *buffer); +}; diff --git a/backends/dc/input.cpp b/backends/dc/input.cpp new file mode 100644 index 0000000000..ed7289e463 --- /dev/null +++ b/backends/dc/input.cpp @@ -0,0 +1,173 @@ +/* ScummVM - Scumm Interpreter + * Dreamcast port + * Copyright (C) 2002 Marcus Comstedt + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include "stdafx.h" +#include "scumm.h" +#include "dc.h" + +int handleInput(struct mapledev *pad, int &mouse_x, int &mouse_y, + byte &shiftFlags) +{ + int lmb=0, rmb=0, newkey=0; + static int lastkey = 0; + static byte lastlmb = 0, lastrmb = 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 = 319; + else if(!(buttons & 512)) newkey = ' '; + else if(!(buttons & 1024)) newkey = '0'; + + if(!(buttons & 128)) mouse_x++; + if(!(buttons & 64)) mouse_x--; + if(!(buttons & 32)) mouse_y++; + if(!(buttons & 16)) mouse_y--; + + mouse_x += ((int)pad->cond.controller.joyx-128)>>4; + mouse_y += ((int)pad->cond.controller.joyy-128)>>4; + } 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 = 319; + + mouse_x += pad->cond.mouse.axis1; + mouse_y += pad->cond.mouse.axis2; + pad->cond.mouse.axis1 = 0; + pad->cond.mouse.axis2 = 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 |= OSystem::KBD_CTRL; + if(shift & 0x44) shiftFlags |= OSystem::KBD_ALT; + if(shift & 0x22) shiftFlags |= OSystem::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 >= 0x3a && key <= 0x43) + newkey = key+(315-0x3a); + else switch(key) { + case 0x27: case 0x62: + newkey = ((shift & 0x22)? '~' : '0'); break; + case 0x28: case 0x58: + newkey = 13; break; + case 0x29: + newkey = 27; break; + case 0x2a: + newkey = 8; break; + case 0x2b: + newkey = 9; break; + case 0x2c: + newkey = ' '; break; + case 0x4c: + if((shift & 0x11) && (shift & 0x44)) + exit(0); + break; + case 0x4f: + mouse_x++; break; + case 0x50: + mouse_x--; break; + case 0x51: + mouse_y++; break; + case 0x52: + mouse_y--; break; + } + } + } + + if(lmb && !lastlmb) { + lastlmb = 1; + return -OSystem::EVENT_LBUTTONDOWN; + } else if(lastlmb && !lmb) { + lastlmb = 0; + return -OSystem::EVENT_LBUTTONUP; + } + if(rmb && !lastrmb) { + lastrmb = 1; + return -OSystem::EVENT_RBUTTONDOWN; + } else if(lastrmb && !rmb) { + lastrmb = 0; + return -OSystem::EVENT_RBUTTONUP; + } + + if(!newkey) + lastkey = 0; + else if(newkey != lastkey) + return lastkey = newkey; + + return 0; +} + +bool OSystem_Dreamcast::poll_event(Event *event) +{ + unsigned int t = Timer(); + if(((int)(t-_devpoll))<0) + return false; + _devpoll += USEC_TO_TIMER(17000); + int mask = getimask(); + setimask(15); + checkSound(); + int e = handleInput(locked_get_pads(), _ms_cur_x, _ms_cur_y, + event->kbd.flags); + setimask(mask); + if (_ms_cur_x<0) _ms_cur_x=0; + if (_ms_cur_x>319) _ms_cur_x=319; + 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; + event->kbd.ascii = event->kbd.keycode = 0; + if(e<0) { + event->event_code = -e; + return true; + } else if(e>0) { + event->event_code = EVENT_KEYDOWN; + event->kbd.keycode = e; + event->kbd.ascii = (e>='a' && e<='z' && (event->kbd.flags & KBD_SHIFT)? + e &~ 0x20 : e); + return true; + } else if(_ms_cur_x != _ms_old_x || _ms_cur_y != _ms_old_y) { + event->event_code = EVENT_MOUSEMOVE; + _ms_old_x = _ms_cur_x; + _ms_old_y = _ms_cur_y; + return true; + } else { + event->event_code = 0; + return false; + } +} + diff --git a/backends/dc/label.cpp b/backends/dc/label.cpp new file mode 100644 index 0000000000..8f263eec0a --- /dev/null +++ b/backends/dc/label.cpp @@ -0,0 +1,131 @@ +/* ScummVM - Scumm Interpreter + * Dreamcast port + * Copyright (C) 2002 Marcus Comstedt + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include <ronin/ronin.h> +#include <string.h> + +#include "label.h" + +static void *get_romfont_address() +{ + void *ret; + __asm__("jsr @%1; mov #0,r1; mov r0,%0" : + "=r" (ret) : "r" (*(void **)0x8c0000b4) : + "pr", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7"); + return ret; +} + +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); +} + diff --git a/backends/dc/label.h b/backends/dc/label.h new file mode 100644 index 0000000000..d4a407307d --- /dev/null +++ b/backends/dc/label.h @@ -0,0 +1,11 @@ +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); +}; diff --git a/backends/dc/portdefs.h b/backends/dc/portdefs.h new file mode 100644 index 0000000000..fd7929ffe7 --- /dev/null +++ b/backends/dc/portdefs.h @@ -0,0 +1,9 @@ +#include <sys/types.h> +#include <stdio.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> +#include <ronin/ronin.h> diff --git a/backends/dc/selector.cpp b/backends/dc/selector.cpp new file mode 100644 index 0000000000..22cba5bbfc --- /dev/null +++ b/backends/dc/selector.cpp @@ -0,0 +1,487 @@ +/* ScummVM - Scumm Interpreter + * Dreamcast port + * Copyright (C) 2002 Marcus Comstedt + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include "stdafx.h" +#include "scumm.h" +#include "mididrv.h" +#include "gameDetector.h" +#include "dc.h" +#include "icon.h" +#include "label.h" + +#include <ronin/gddrive.h> + + +#define MAX_GAMES 100 +#define MAX_DIR 100 + + +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); +} + + +struct Game +{ + char dir[256]; + char filename_base[256]; + char text[256]; + Icon icon; + Label label; +}; + +struct Dir +{ + char name[256]; + char deficon[256]; +}; + +static Game the_game; + +static bool isGame(const char *fn, char *base) +{ + int l = strlen(fn); + if(l>4 && (!strcasecmp(fn+l-4, ".000") || + !strcasecmp(fn+l-4, ".SM0"))) { + strcpy(base, fn); + base[l-4]='\0'; + return true; + } + if(!strcasecmp(fn, "00.LFL") || + !strcasecmp(fn, "000.LFL")) { + *base = '\0'; + return true; + } + return false; +} + +static void checkName(GameDetector *d, Game &game) +{ + d->_exe_name = game.filename_base; + if(d->detectGame()) { + char *n = d->getGameName(); + strcpy(game.text, n); + free(n); + } else + strcpy(game.text, game.filename_base); + d->_exe_name = NULL; +} + +static bool checkExe(const char *dir, const char *f) +{ + char fn[520]; + int fd; + sprintf(fn, "%s%s.EXE", dir, f); + if((fd = open(fn, O_RDONLY))<0) + return false; + close(fd); + return true; +} + +static bool isIcon(const char *fn) +{ + int l = strlen(fn); + if(l>4 && !strcasecmp(fn+l-4, ".ICO")) + return true; + else + return false; +} + +static bool loadIcon(Game &game, Dir *dirs, int num_dirs) +{ + char icofn[520]; + sprintf(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]) { + sprintf(icofn, "%s%s", game.dir, dirs[i].deficon); + if(game.icon.load(icofn)) + return true; + break; + } + return false; +} + +static void makeDefIcon(Icon &icon) +{ + icon.load(NULL, 0); +} + +static int findGames(GameDetector *d, Game *games, int max) +{ + Dir *dirs = new Dir[MAX_DIR]; + int curr_game = 0, curr_dir = 0, num_dirs = 1; + strcpy(dirs[0].name, "/"); + while(curr_game < max && curr_dir < num_dirs) { + dirs[curr_dir].deficon[0] = '\0'; + DIR *dirp = opendir(dirs[curr_dir++].name); + if(dirp) { + struct dirent *entry; + while((entry = readdir(dirp))) + if(entry->d_size < 0) { + if(num_dirs < MAX_DIR) { + strcpy(dirs[num_dirs].name, dirs[curr_dir-1].name); + if(strlen(dirs[num_dirs].name)+strlen(entry->d_name)<255) { + strcat(dirs[num_dirs].name, entry->d_name); + strcat(dirs[num_dirs].name, "/"); + num_dirs++; + } + } + } else + if(isIcon(entry->d_name)) + strcpy(dirs[curr_dir-1].deficon, entry->d_name); + else if(curr_game < max && + isGame(entry->d_name, games[curr_game].filename_base)) { + strcpy(games[curr_game].dir, dirs[curr_dir-1].name); + if(!*games[curr_game].filename_base) { + int i; + for(i=strlen(games[curr_game].dir)-1; --i>=0; ) + if(games[curr_game].dir[i]=='/') + break; + if(i>=0) { + strcpy(games[curr_game].filename_base, + games[curr_game].dir+i+1); + games[curr_game].filename_base[strlen(games[curr_game]. + filename_base)-1]='\0'; +#if 0 + games[curr_game].dir[i+1]='\0'; +#endif + } + if(checkExe(games[curr_game].dir, "loom")) + strcpy(games[curr_game].filename_base, "loomcd"); + } + checkName(d, games[curr_game]); +#if 0 + printf("Registered game <%s> in <%s> <%s> because of <%s> <%s>\n", + games[curr_game].text, games[curr_game].dir, + games[curr_game].filename_base, + dirs[curr_dir-1].name, entry->d_name); +#endif + curr_game++; + } + closedir(dirp); + } + } + for(int i=0; i<curr_game; i++) + if(!loadIcon(games[i], dirs, num_dirs)) + makeDefIcon(games[i].icon); + delete dirs; + return curr_game; +} + +int getCdState() +{ + unsigned int param[4]; + gdGdcGetDrvStat(param); + return param[0]; +} + +static void drawBackground() +{ + draw_solid_quad(20.0, 20.0, 620.0, 460.0, + 0xff0000, 0x00ff00, 0x0000ff, 0xffffff); +} + +void waitForDisk() +{ + Label lab; + int wasopen = 0; + ta_sync(); + void *mark = ta_txmark(); + lab.create_texture("Please insert game CD."); + //printf("waitForDisk, cdstate = %d\n", getCdState()); + for(;;) { + int s = getCdState(); + if(s >= 6) + wasopen = 1; + if(s > 0 && s < 6 && wasopen) { + cdfs_reinit(); + chdir("/"); + chdir("/"); + ta_sync(); + ta_txrelease(mark); + return; + } + + ta_begin_frame(); + + drawBackground(); + + ta_commit_end(); + + lab.draw(166.0, 200.0, 0xffff2020); + + ta_commit_frame(); + + int mousex = 0, mousey = 0; + byte shiftFlags; + + int mask = getimask(); + setimask(15); + handleInput(locked_get_pads(), mousex, mousey, shiftFlags); + setimask(mask); + } +} + +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; + + if(!num_games) + return -1; + + for(;;) { + + if(getCdState()>=6) + return -1; + + ta_begin_frame(); + + drawBackground(); + + ta_commit_end(); + + float 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.set_palette(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==-OSystem::EVENT_LBUTTONDOWN || event==13 || event==319) { + int selected_game = top_game + selector_pos; + + for(int fade=0; fade<=256; fade+=4) { + + unsigned int fade_colour = 0x00ffffff | ((255-fade)<<24); + + ta_begin_frame(); + + drawBackground(); + + ta_commit_end(); + + float 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[selector_pos], 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(GameDetector *d, char *&ret, char *&dir_ret, Icon &icon) +{ + Game *games = new Game[MAX_GAMES]; + int selected, num_games; + + ta_sync(); + void *mark = ta_txmark(); + + for(;;) { + num_games = findGames(d, games, MAX_GAMES); + + 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); + + ta_sync(); + ta_txrelease(mark); + + 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("/"); + static char dirarg[258]; + sprintf(dirarg, "-p%s", the_game.dir); + dir_ret = dirarg; +#endif + ret = the_game.filename_base; + icon = the_game.icon; + return true; + } else + return false; +} diff --git a/backends/dc/vmsave.cpp b/backends/dc/vmsave.cpp new file mode 100644 index 0000000000..34bf2e40fa --- /dev/null +++ b/backends/dc/vmsave.cpp @@ -0,0 +1,266 @@ +/* ScummVM - Scumm Interpreter + * Dreamcast port + * Copyright (C) 2002 Marcus Comstedt + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include "stdafx.h" +#include "scumm.h" +#include "mididrv.h" +#include "gameDetector.h" +#include "dc.h" +#include "icon.h" +#include "saveload.h" + +#include <ronin/zlib.h> + + +// Savegame can not be bigger than this, even before compression +#define MAX_SAVE_SIZE (128*1024) + + +enum vmsaveResult { + VMSAVE_OK, + VMSAVE_NOVM, + VMSAVE_NOSPACE, + VMSAVE_WRITEERROR, +}; + + +static int lastvm=-1; + +static vmsaveResult trySave(GameDetector *d, 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); + char *game_name = d->getGameName(); + strncpy(header.longdesc, game_name, 32); + free(game_name); + 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; + 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 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; + return false; +} + +vmsaveResult writeSaveGame(GameDetector *d, const char *data, int size, + const char *filename, class Icon &icon) +{ + vmsaveResult r, res = VMSAVE_NOVM; + + if(lastvm >= 0 && + (res = trySave(d, data, size, filename, icon, lastvm)) == VMSAVE_OK) + return res; + + for(int i=0; i<24; i++) + if((r = trySave(d, 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; +} + + +struct vmStreamContext { + bool issave; + char *buffer; + int pos, size; + char filename[16]; +}; + +bool SerializerStream::fopen(const char *filename, const char *mode) +{ + vmStreamContext *c = new vmStreamContext; + context = c; + if(strchr(mode, 'w')) { + c->issave = true; + strncpy(c->filename, filename, 16); + c->pos = 0; + c->buffer = new char[c->size = MAX_SAVE_SIZE]; + return true; + } else if(readSaveGame(c->buffer, c->size, filename)) { + if(c->size > 0 && c->buffer[0] != 'S') { + // Data does not start with "SCVM". Maybe compressed? + char *expbuf = new char[MAX_SAVE_SIZE]; + unsigned long destlen = MAX_SAVE_SIZE; + if(!uncompress((Bytef*)expbuf, &destlen, (Bytef*)c->buffer, c->size)) { + delete(c->buffer); + c->buffer = expbuf; + c->size = destlen; + } else delete expbuf; + } + c->issave = false; + c->pos = 0; + return true; + } else { + delete c; + context = NULL; + return false; + } +} + +void SerializerStream::fclose() +{ + extern GameDetector detector; + extern Icon icon; + + if(context) { + vmStreamContext *c = (vmStreamContext *)context; + if(c->issave) { + if(c->pos) { + // Try compression + char *compbuf = new char[c->pos]; + unsigned long destlen = c->pos; + if(!compress((Bytef*)compbuf, &destlen, (Bytef*)c->buffer, c->pos)) { + delete c->buffer; + c->buffer = compbuf; + c->pos = destlen; + } else delete compbuf; + } + writeSaveGame(&detector, c->buffer, c->pos, + c->filename, icon); + } + delete c->buffer; + delete c; + context = NULL; + } +} + +int SerializerStream::fread(void *buf, int size, int cnt) +{ + vmStreamContext *c = (vmStreamContext *)context; + + if (!c || c->issave) + return -1; + + int nbyt = size*cnt; + if (c->pos + nbyt > c->size) { + cnt = (c->size - c->pos)/size; + nbyt = size*cnt; + } + if (nbyt) + memcpy(buf, c->buffer + c->pos, nbyt); + c->pos += nbyt; + return cnt; +} + +int SerializerStream::fwrite(void *buf, int size, int cnt) +{ + vmStreamContext *c = (vmStreamContext *)context; + + if (!c || !c->issave) + return -1; + + int nbyt = size*cnt; + if (c->pos + nbyt > c->size) { + cnt = (c->size - c->pos)/size; + nbyt = size*cnt; + } + if (nbyt) + memcpy(c->buffer + c->pos, buf, nbyt); + c->pos += nbyt; + return cnt; +} + |