diff options
author | Marcus Comstedt | 2002-02-02 15:44:27 +0000 |
---|---|---|
committer | Marcus Comstedt | 2002-02-02 15:44:27 +0000 |
commit | 352a7e17e1f15586e169eef3f0bda74e8ea77372 (patch) | |
tree | e69a0d3cb0d2ed5a4845e2d6aa460798233788b3 /dc | |
parent | de621c06e29cc018289c74789a9d02c4d887f42c (diff) | |
download | scummvm-rg350-352a7e17e1f15586e169eef3f0bda74e8ea77372.tar.gz scummvm-rg350-352a7e17e1f15586e169eef3f0bda74e8ea77372.tar.bz2 scummvm-rg350-352a7e17e1f15586e169eef3f0bda74e8ea77372.zip |
Port for SEGA Dreamcast
svn-id: r3550
Diffstat (limited to 'dc')
-rw-r--r-- | dc/.cvsignore | 2 | ||||
-rw-r--r-- | dc/Makefile | 43 | ||||
-rw-r--r-- | dc/audio.cpp | 42 | ||||
-rw-r--r-- | dc/dc.h | 7 | ||||
-rw-r--r-- | dc/dcmain.cpp | 91 | ||||
-rw-r--r-- | dc/display.cpp | 267 | ||||
-rw-r--r-- | dc/icon.cpp | 184 | ||||
-rw-r--r-- | dc/icon.h | 19 | ||||
-rw-r--r-- | dc/input.cpp | 95 | ||||
-rw-r--r-- | dc/label.cpp | 109 | ||||
-rw-r--r-- | dc/label.h | 10 | ||||
-rw-r--r-- | dc/portdefs.h | 9 | ||||
-rw-r--r-- | dc/selector.cpp | 313 |
13 files changed, 1191 insertions, 0 deletions
diff --git a/dc/.cvsignore b/dc/.cvsignore new file mode 100644 index 0000000000..6569dea36b --- /dev/null +++ b/dc/.cvsignore @@ -0,0 +1,2 @@ +scummvm +sound diff --git a/dc/Makefile b/dc/Makefile new file mode 100644 index 0000000000..626d25f97c --- /dev/null +++ b/dc/Makefile @@ -0,0 +1,43 @@ +# $Header$ + +ronindir = /usr/local/ronin + +VPATH = .. + +CC = sh-elf-g++ -ml -m4-single-only +CFLAGS = -O1 -Wno-multichar +DEFINES = -D__DC__ -DNONSTANDARD_PORT -DUSE_ADLIB +LDFLAGS := -Wl,-Ttext,0x8c010000 -nostartfiles ronin/crt0.o +INCLUDES:= -I./ -I../ -I../sound +CPPFLAGS= $(DEFINES) $(INCLUDES) +LIBS = ronin/libronin.a -lm + +INCS = scumm.h scummsys.h stdafx.h portdefs.h dc.h + +OBJS = actor.o boxes.o costume.o gfx.o object.o resource.o \ + saveload.o script.o scummvm.o sound.o string.o \ + sys.o verbs.o script_v1.o script_v2.o debug.o gui.o \ + sound/imuse.o sound/fmopl.o sound/adlib.o sound/gmidi.o debugrl.o \ + akos.o dcmain.o display.o audio.o input.o selector.o icon.o label.o + +.cpp.o: + $(CC) $(CFLAGS) $(CPPFLAGS) -c $(<) -o $*.o + +all: scummvm + +scummvm: $(OBJS) ronin + $(CC) $(LDFLAGS) -o $(@) $(OBJS) $(LIBS) + +$(OBJS): Makefile sound/.create ronin + +sound/.create: + mkdir sound && touch $@ + +ronin: + ln -s $(ronindir) $@ + +clean: + rm -f $(OBJS) scummvm + +check: +$(OBJS): $(INCS) diff --git a/dc/audio.cpp b/dc/audio.cpp new file mode 100644 index 0000000000..d256f7e560 --- /dev/null +++ b/dc/audio.cpp @@ -0,0 +1,42 @@ +#include "stdafx.h" +#include "scumm.h" +#include "dc.h" + +#include <ronin/soundcommon.h> + +EXTERN_C void *memcpy4(void *s1, const void *s2, unsigned int n); + +void checkSound(Scumm *s) +{ + 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; + + s->mixWaves((short*)temp_sound_buffer, 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/dc/dc.h b/dc/dc.h new file mode 100644 index 0000000000..814d8cfe88 --- /dev/null +++ b/dc/dc.h @@ -0,0 +1,7 @@ + +extern void checkSound(Scumm *s); +extern void handleInput(struct mapledev *pad, int16 &mouse_x, int16 &mouse_y, + byte &leftBtnPressed, byte &rightBtnPressed, + int &keyPressed); +extern bool selectGame(Scumm *s, char *&); + diff --git a/dc/dcmain.cpp b/dc/dcmain.cpp new file mode 100644 index 0000000000..d7e423c457 --- /dev/null +++ b/dc/dcmain.cpp @@ -0,0 +1,91 @@ +#include "stdafx.h" +#include "scumm.h" +#include "gui.h" +#include "sound.h" +#include "dc.h" + +Scumm scumm; +ScummDebugger debugger; +Gui gui; + +SoundEngine sound; +SOUND_DRIVER_TYPE snd_driv; + + +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(s); + 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) { + updateScreen(s); + oldmousex = s->mouse.x; + oldmousey = s->mouse.y; + } + } +} + +static char *argv[] = { "scummvm", NULL, NULL }; +static int argc = 2; + +int main() +{ + int delta,tmp; + int last_time, new_time; + +#ifndef NOSERIAL + serial_init(57600); + usleep(2000000); + printf("Serial OK\r\n"); +#endif + + cdfs_init(); + maple_init(); + dc_setup_ta(); + init_arm(); + + if(!selectGame(&scumm, argv[1])) + exit(0); + + sound.initialize(&scumm, &snd_driv); + printf("Sound initalized.\n"); + + scumm._gui = &gui; + scumm.scummMain(argc, argv); + + printf("scummMain called.\n"); + gui.init(&scumm); + + last_time = Timer(); + delta = 0; + do { + updateScreen(&scumm); + + new_time = Timer(); + waitForTimer(&scumm, delta * 15 - ((new_time - last_time)<<11)/100000); + last_time = Timer(); + + if (gui._active) { + gui.loop(); + delta = 5; + } else { + delta = scumm.scummLoop(delta); + } + } while(1); + + printf("All done. Returning to menu.\n"); + exit(0); +} diff --git a/dc/display.cpp b/dc/display.cpp new file mode 100644 index 0000000000..9d2a01fb09 --- /dev/null +++ b/dc/display.cpp @@ -0,0 +1,267 @@ +#include "stdafx.h" +#include "scumm.h" +#include "dc.h" + +#define SCREEN_W 320 +#define SCREEN_H 200 +#define MOUSE_W 64 +#define MOUSE_H 64 +#define NUM_BUFFERS 4 + +#define QACR0 (*(volatile unsigned int *)(void *)0xff000038) +#define QACR1 (*(volatile unsigned int *)(void *)0xff00003c) + + +static unsigned char *screen = NULL; +static unsigned short *mouse = NULL; +static void *screen_tx[NUM_BUFFERS] = { NULL, }; +static void *mouse_tx[NUM_BUFFERS] = { NULL, }; +static int current_buffer = 0; +static int shakePos = 0; +unsigned short palette[256]; + + +#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 updatePalette(Scumm *s) +{ + int first = s->_palDirtyMin; + int num = s->_palDirtyMax - first + 1; + unsigned char *src = s->_currentPalette; + unsigned short *dst = palette + first; + src += first*3; + if(num>0) + while( num-- ) { + *dst++ = ((src[0]<<7)&0x7c00)| + ((src[1]<<2)&0x03e0)| + ((src[2]>>3)&0x001f); + src += 3; + } +} + +void blitToScreen(Scumm *s, unsigned char *src, int x, int y, int w, int h) +{ + unsigned char *dst = screen + y*SCREEN_W + x; + do { + memcpy(dst, src, w); + dst += SCREEN_W; + src += SCREEN_W; + } while (--h); +} + +void setShakePos(Scumm *s, int shake_pos) +{ + shakePos = shake_pos; +} + +void updateScreen(Scumm *s) +{ + 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; + + if(s->_palDirtyMax != -1) { + updatePalette(s); + } + + 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 = shakePos*2.0; + 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/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; + s->drawMouse(); + // *((volatile unsigned int *)(void*)0xa05f8040) = 0xff00ff; + ta_commit_frame(); + + current_buffer++; + current_buffer &= NUM_BUFFERS-1; + // *((volatile unsigned int *)(void*)0xa05f8040) = 0x0; +} + +void drawMouse(Scumm *s, 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*2.0; + myvertex.y = (ydraw+shakePos)*2.0; + ta_commit_list(&myvertex); + + myvertex.x += w*2.0; + myvertex.u = w*(1.0/MOUSE_W); + ta_commit_list(&myvertex); + + myvertex.x = xdraw*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); +} + +void initGraphics(Scumm *s, bool fullScreen) +{ + 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; + shakePos = 0; + *(volatile unsigned int *)(0xa05f80e4) = SCREEN_W/32; //stride + // dc_reset_screen(0, 0); +} diff --git a/dc/icon.cpp b/dc/icon.cpp new file mode 100644 index 0000000000..ecb5785023 --- /dev/null +++ b/dc/icon.cpp @@ -0,0 +1,184 @@ +#include <ronin/ronin.h> +#include <string.h> + +#include "icon.h" + +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) +{ + 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_REPLACE|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 = 0; + 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/dc/icon.h b/dc/icon.h new file mode 100644 index 0000000000..6ffe4fe16e --- /dev/null +++ b/dc/icon.h @@ -0,0 +1,19 @@ + +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); +}; diff --git a/dc/input.cpp b/dc/input.cpp new file mode 100644 index 0000000000..324ebb75c6 --- /dev/null +++ b/dc/input.cpp @@ -0,0 +1,95 @@ +#include "stdafx.h" +#include "scumm.h" +#include "dc.h" + +void handleInput(struct mapledev *pad, int16 &mouse_x, int16 &mouse_y, + byte &leftBtnPressed, byte &rightBtnPressed, int &keyPressed) +{ + int lmb=0, rmb=0, newkey=0; + static int lastkey = 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(key >= 4 && key <= 0x1d) + newkey = key+((shift & 0x22)? ('A'-4) : ('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 0x4f: + mouse_x++; break; + case 0x50: + mouse_x--; break; + case 0x51: + mouse_y++; break; + case 0x52: + mouse_y--; break; + } + } + } + + if(lmb) + leftBtnPressed |= msClicked|msDown; + else + leftBtnPressed &= ~msDown; + if(rmb) + rightBtnPressed |= msClicked|msDown; + else + rightBtnPressed &= ~msDown; + + if(!newkey) + lastkey = 0; + else if(newkey != lastkey) + keyPressed = lastkey = newkey; +} + diff --git a/dc/label.cpp b/dc/label.cpp new file mode 100644 index 0000000000..14e331c11e --- /dev/null +++ b/dc/label.cpp @@ -0,0 +1,109 @@ +#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) +{ + 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|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; + myvertex.u = 1.0; + ta_commit_list(&myvertex); + + myvertex.x = x; + myvertex.y = y+25.0; + myvertex.u = 0.0; + myvertex.v = 25.0/32.0; + ta_commit_list(&myvertex); + + myvertex.x = x+u; + myvertex.u = 1.0; + myvertex.cmd |= TA_CMD_VERTEX_EOS; + ta_commit_list(&myvertex); +} + diff --git a/dc/label.h b/dc/label.h new file mode 100644 index 0000000000..bf43212499 --- /dev/null +++ b/dc/label.h @@ -0,0 +1,10 @@ +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); +}; diff --git a/dc/portdefs.h b/dc/portdefs.h new file mode 100644 index 0000000000..fd7929ffe7 --- /dev/null +++ b/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/dc/selector.cpp b/dc/selector.cpp new file mode 100644 index 0000000000..10a446ac4e --- /dev/null +++ b/dc/selector.cpp @@ -0,0 +1,313 @@ +#include "stdafx.h" +#include "scumm.h" +#include "dc.h" +#include "icon.h" +#include "label.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; + } + return false; +} + +static void checkName(Scumm *s, Game &game) +{ + s->_exe_name = game.filename_base; + if(s->detectGame()) { + char *n = s->getGameName(); + strcpy(game.text, n); + free(n); + } else + strcpy(game.text, game.filename_base); + s->_exe_name = NULL; +} + +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(Scumm *s, 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); + checkName(s, games[curr_game]); + 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 gameMenu(Game *games, int num_games) +{ + int top_game = 0, selector_pos = 0; + int16 mousex = 0, mousey = 0; + + if(!num_games) + return -1; + + for(;;) { + + ta_begin_frame(); + + draw_solid_quad(20.0, 20.0, 620.0, 460.0, + 0xff0000, 0x00ff00, 0x0000ff, 0xffffff); + + 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); + games[i].icon.set_palette(pal); + games[i].icon.draw(50.0, y, 82.0, y+32.0, pal); + + if(cnt == selector_pos) + draw_trans_quad(100.0, y, 590.0, y+32.0, + 0x7000ff00, 0x7000ff00, 0x7000ff00, 0x7000ff00); + + games[i].label.draw(104.0, y+4.0, (cnt == selector_pos? + 0xffffff00 : 0xffffffff)); + + y += 40.0; + } + + ta_commit_frame(); + + byte lmb=0, rmb=0; + int key=0; + + int mask = getimask(); + setimask(15); + handleInput(locked_get_pads(), mousex, mousey, lmb, rmb, key); + setimask(mask); + + if(lmb || key==13 || key==319) + return top_game + selector_pos; + + 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(Scumm *s, char *&ret) +{ + Game *games = new Game[MAX_GAMES]; + int num_games = findGames(s, games, MAX_GAMES); + int selected; + + ta_sync(); + void *mark = ta_txmark(); + + 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 >= num_games) + selected = -1; + + if(selected >= 0) + the_game = games[selected]; + + delete games; + + if(selected>=0) { + chdir(the_game.dir); + ret = the_game.filename_base; + return true; + } else + return false; +} |