Changeset 85:75cca35e667a

angolmois

File angolmois.c

← 84:1c54d34cca9a 85:75cca35e667a 87:4cf3f3a15bec
Author:
Kang Seonghoon <public+hg@mearie.org>
Committed on
Permission:
-rw-r--r--

massive option restructuring; now possible to map multiple keys to single virtual key; beep sound for speed adjustment; new survival gauge criteria (the original was waaaaaaaay easy); other small fixes and adjustments.

public+hg@0
     1 /*
public+hg@60
     2  * Angolmois -- the simple BMS player
public+hg@83
     3  * Copyright (c) 2005, 2007, 2009, 2012, Kang Seonghoon.
public+hg@60
     4  * Project Angolmois is copyright (c) 2003-2007, Choi Kaya (CHKY).
public+hg@0
     5  * 
public+hg@0
     6  * This program is free software; you can redistribute it and/or
public+hg@0
     7  * modify it under the terms of the GNU General Public License
public+hg@0
     8  * as published by the Free Software Foundation; either version 2
public+hg@0
     9  * of the License, or (at your option) any later version.
public+hg@0
    10  * 
public+hg@0
    11  * This program is distributed in the hope that it will be useful,
public+hg@0
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
public+hg@0
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
public+hg@0
    14  * GNU General Public License for more details.
public+hg@0
    15  * 
public+hg@0
    16  * You should have received a copy of the GNU General Public License
public+hg@0
    17  * along with this program; if not, write to the Free Software
public+hg@0
    18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
public+hg@0
    19  */
public+hg@0
    20 
public+hg@0
    21 #include <stdio.h>
public+hg@0
    22 #include <stdlib.h>
public+hg@62
    23 #include <string.h>
public+hg@85
    24 #include <stdarg.h>
public+hg@2
    25 #include <time.h>
public+hg@1
    26 #include <SDL.h>
public+hg@1
    27 #include <SDL_mixer.h>
public+hg@1
    28 #include <SDL_image.h>
public+hg@32
    29 #include <smpeg.h>
public+hg@60
    30 
public+hg@85
    31 static const char VERSION[] = "Angolmois 2.0.0 alpha 1";
public+hg@85
    32 static const char *argv0 = "angolmois";
public+hg@0
    33 
public+hg@20
    34 /******************************************************************************/
public+hg@20
    35 /* constants, variables */
public+hg@13
    36 
public+hg@11
    37 #define ARRAYSIZE(x) (sizeof(x)/sizeof(*x))
public+hg@26
    38 #define SWAP(x,y,t) {(t)=(x);(x)=(y);(y)=(t);}
public+hg@26
    39 
public+hg@85
    40 static int opt_mode = 0, opt_showinfo = 1, opt_fullscreen = 1, opt_random = 0, opt_bga = 0;
public+hg@85
    41 
public+hg@61
    42 static const char *bmsheader[] = {
public+hg@61
    43 	"title", "genre", "artist", "stagefile", "bpm", "player", "playlevel",
public+hg@61
    44 	"rank", "lntype", "lnobj", "wav", "bmp", "bga", "stop", "stp", "random",
public+hg@62
    45 	"if", "else", "endif", 0};
public+hg@61
    46 static char *bmspath, respath[512];
public+hg@61
    47 static char **bmsline = NULL;
public+hg@61
    48 static int nbmsline = 0;
public+hg@0
    49 
public+hg@63
    50 static char metadata[4][1024];
public+hg@61
    51 static double bpm = 130;
public+hg@61
    52 static int value[5] = {1, 0, 2, 1, 0};
public+hg@0
    53 #define v_player value[0]
public+hg@0
    54 #define v_playlevel value[1]
public+hg@0
    55 #define v_rank value[2]
public+hg@32
    56 #define lntype value[3]
public+hg@32
    57 #define lnobj value[4]
public+hg@3
    58 
public+hg@67
    59 static char *paths[2][1296];
public+hg@67
    60 #define sndpath paths[0]
public+hg@67
    61 #define imgpath paths[1]
public+hg@61
    62 static int (*blitcmd)[8] = NULL, nblitcmd = 0;
public+hg@61
    63 static Mix_Chunk *sndres[1296];
public+hg@61
    64 static SDL_Surface *imgres[1296];
public+hg@61
    65 static int stoptab[1296] = {0};
public+hg@61
    66 static double bpmtab[1296] = {0};
public+hg@61
    67 static SMPEG *mpeg = NULL;
public+hg@83
    68 int imgmpeg = -2;
public+hg@3
    69 
public+hg@80
    70 typedef struct {
public+hg@80
    71 	double time; /* time */
public+hg@80
    72 	int type; /* for notes: start(0) and end(1) of longnote, visible(2), invisible(3)
public+hg@80
    73 			   * for BGA: lower layer(0), upper layer(1), poor BGA(2)
public+hg@80
    74 			   * for BPM: direct(0), indirect(1)
public+hg@80
    75 			   * for STOP: unit=1/192 measure, indirect(0), unit=msec, direct(1)
public+hg@80
    76 			   * otherwise: always 0. note that removed one has type -1. */
public+hg@80
    77 	int index; /* associated resource or key value (if any) */
public+hg@80
    78 } bmsnote;
public+hg@80
    79 
public+hg@80
    80 static bmsnote *channel[22]; /* 0..17: notes, 18: BGM; 19: BGA; 20: BPM; 21: STOP */
public+hg@61
    81 static double _shorten[2005], *shorten = _shorten + 1;
public+hg@61
    82 static int nchannel[22] = {0};
public+hg@61
    83 static double length;
public+hg@4
    84 
public+hg@20
    85 /******************************************************************************/
public+hg@20
    86 /* system dependent functions */
public+hg@20
    87 
public+hg@20
    88 #ifdef WIN32
public+hg@61
    89 
public+hg@20
    90 #include <windows.h>
public+hg@61
    91 
public+hg@61
    92 static const char sep = '\\';
public+hg@61
    93 
public+hg@61
    94 static int filedialog(char *buf)
public+hg@61
    95 {
public+hg@62
    96 	OPENFILENAME ofn = {
public+hg@79
    97 		.lStructSize = sizeof ofn,
public+hg@62
    98 		.lpstrFilter =
public+hg@62
    99 			"All Be-Music Source File (*.bms;*.bme;*.bml)\0*.bms;*.bme;*.bml\0"
public+hg@62
   100 			"Be-Music Source File (*.bms)\0*.bms\0"
public+hg@62
   101 			"Extended Be-Music Source File (*.bme)\0*.bme\0"
public+hg@62
   102 			"Longnote Be-Music Source File (*.bml)\0*.bml\0"
public+hg@62
   103 			"All Files (*.*)\0*.*\0",
public+hg@62
   104 		.lpstrFile = buf,
public+hg@62
   105 		.nMaxFile = 512,
public+hg@62
   106 		.lpstrTitle = "Choose a file to play",
public+hg@62
   107 		.Flags = OFN_HIDEREADONLY};
public+hg@20
   108 	return GetOpenFileName(&ofn);
public+hg@20
   109 }
public+hg@20
   110 
public+hg@85
   111 static void die(const char *msg, ...)
public+hg@61
   112 {
public+hg@85
   113 	va_list v;
public+hg@61
   114 	char b[512];
public+hg@85
   115 	va_start(v, msg);
public+hg@85
   116 	vsprintf(b, c, v);
public+hg@85
   117 	va_end(a);
public+hg@85
   118 	MessageBox(0, b, VERSION, 0);
public+hg@85
   119 	exit(1);
public+hg@61
   120 }
public+hg@61
   121 
public+hg@61
   122 static void dirinit(void) {}
public+hg@61
   123 static void dirfinal(void) {}
public+hg@76
   124 static const char *adjust_path_case(char *file) { return file; }
public+hg@61
   125 
public+hg@61
   126 #else /* WIN32 */
public+hg@61
   127 
public+hg@20
   128 #include <dirent.h>
public+hg@20
   129 
public+hg@61
   130 static const char sep = '/';
public+hg@61
   131 static char *flist[2592];
public+hg@61
   132 static int nfiles = 0;
public+hg@61
   133 
public+hg@61
   134 static int filedialog(char *buf)
public+hg@61
   135 {
public+hg@20
   136 	return 0;
public+hg@20
   137 }
public+hg@61
   138 
public+hg@85
   139 static void die(const char *msg, ...)
public+hg@61
   140 {
public+hg@85
   141 	va_list v;
public+hg@85
   142 	fprintf(stderr, "%s: ", argv0);
public+hg@85
   143 	va_start(v, msg);
public+hg@85
   144 	vfprintf(stderr, msg, v);
public+hg@85
   145 	va_end(v);
public+hg@85
   146 	fprintf(stderr, "\n");
public+hg@85
   147 	exit(1);
public+hg@61
   148 }
public+hg@61
   149 
public+hg@78
   150 static int stricmp(const char *a, const char *b); /* DUMMY */
public+hg@61
   151 static char *strcopy(const char*); /* DUMMY */
public+hg@61
   152 
public+hg@61
   153 static void dirinit(void)
public+hg@61
   154 {
public+hg@61
   155 	DIR *d;
public+hg@61
   156 	struct dirent *e;
public+hg@61
   157 
public+hg@76
   158 	if (d = opendir(bmspath)) {
public+hg@61
   159 		while (e = readdir(d))
public+hg@61
   160 			flist[nfiles++] = strcopy(e->d_name);
public+hg@76
   161 		closedir(d);
public+hg@61
   162 	}
public+hg@61
   163 }
public+hg@61
   164 
public+hg@61
   165 static void dirfinal(void)
public+hg@61
   166 {
public+hg@61
   167 	while (nfiles--) free(flist[nfiles]);
public+hg@61
   168 }
public+hg@61
   169 
public+hg@76
   170 static const char *adjust_path_case(char *file)
public+hg@61
   171 {
public+hg@20
   172 	int i;
public+hg@61
   173 	for (i = 0; i < nfiles; ++i) {
public+hg@76
   174 		if (stricmp(flist[i], file)) return flist[i];
public+hg@61
   175 	}
public+hg@76
   176 	return ""; /* always nonexistent file */
public+hg@20
   177 }
public+hg@20
   178 #endif
public+hg@20
   179 
public+hg@20
   180 /******************************************************************************/
public+hg@20
   181 /* general functions */
public+hg@20
   182 
public+hg@78
   183 static int lcase(char c)
public+hg@78
   184 {
public+hg@78
   185 	return ((c|32)-19)/26-3 ? c : c|32;
public+hg@78
   186 }
public+hg@78
   187 
public+hg@78
   188 static int stricmp(const char *a, const char *b)
public+hg@78
   189 {
public+hg@78
   190 	while (*a && *b && lcase(*a) == lcase(*b)) ++a, ++b;
public+hg@78
   191 	return *a == *b;
public+hg@78
   192 }
public+hg@78
   193 
public+hg@61
   194 static char *adjust_path(char *path)
public+hg@61
   195 {
public+hg@76
   196 	strcpy(respath, bmspath);
public+hg@76
   197 	strcat(respath, adjust_path_case(path)); /* XXX could be overflow */
public+hg@20
   198 	return respath;
public+hg@20
   199 }
public+hg@20
   200 
public+hg@83
   201 static char *adjust_path_with_ext(char *path, char *ext)
public+hg@83
   202 {
public+hg@83
   203 	int len = strlen(bmspath);
public+hg@83
   204 	char *oldext;
public+hg@83
   205 	strcpy(respath, bmspath);
public+hg@83
   206 	strcpy(respath + len, path);
public+hg@83
   207 	oldext = strrchr(respath + len, '.');
public+hg@83
   208 	if (oldext) {
public+hg@83
   209 		strcpy(oldext, ext);
public+hg@83
   210 		strcpy(respath + len, adjust_path_case(respath + len));
public+hg@83
   211 	}
public+hg@83
   212 	return respath;
public+hg@83
   213 }
public+hg@83
   214 
public+hg@61
   215 static char *strcopy(const char *src)
public+hg@61
   216 {
public+hg@77
   217 	char *dest = malloc(strlen(src)+1);
public+hg@77
   218 	return strcpy(dest, src);
public+hg@20
   219 }
public+hg@20
   220 
public+hg@20
   221 /******************************************************************************/
public+hg@20
   222 /* bms parser */
public+hg@20
   223 
public+hg@4
   224 #define GET_CHANNEL(player, chan) ((player)*9+(chan)-1)
public+hg@4
   225 #define ADD_NOTE(player, chan, time, index) \
public+hg@80
   226 	add_note(GET_CHANNEL(player,chan), (time), 2/*NOTE*/, (index))
public+hg@4
   227 #define ADD_INVNOTE(player, chan, time, index) \
public+hg@80
   228 	add_note(GET_CHANNEL(player,chan), (time), 3/*INVNOTE*/, (index))
public+hg@11
   229 #define ADD_LNDONE(player, chan, time, index) \
public+hg@80
   230 	add_note(GET_CHANNEL(player,chan), (time), 0/*LNDONE*/, (index))
public+hg@4
   231 #define ADD_LNSTART(player, chan, time, index) \
public+hg@80
   232 	add_note(GET_CHANNEL(player,chan), (time), 1/*LNSTART*/, (index))
public+hg@61
   233 #define ADD_BGM(time, index) \
public+hg@61
   234 	add_note(18, (time), 0, (index))
public+hg@61
   235 #define ADD_BGA(time, index) \
public+hg@61
   236 	add_note(19, (time), 0, (index))
public+hg@61
   237 #define ADD_BGA2(time, index) \
public+hg@61
   238 	add_note(19, (time), 1, (index))
public+hg@61
   239 #define ADD_POORBGA(time, index) \
public+hg@61
   240 	add_note(19, (time), 2, (index))
public+hg@61
   241 #define ADD_BPM(time, index) \
public+hg@61
   242 	add_note(20, (time), 0, (index))
public+hg@61
   243 #define ADD_BPM2(time, index) \
public+hg@61
   244 	add_note(20, (time), 1, (index))
public+hg@61
   245 #define ADD_STOP(time, index) \
public+hg@61
   246 	add_note(21, (time), 0, (index))
public+hg@61
   247 #define ADD_STP(time, index) \
public+hg@61
   248 	add_note(21, (time), 1, (index))
public+hg@0
   249 
public+hg@61
   250 static int getdigit(int n)
public+hg@61
   251 {
public+hg@61
   252 	return 47<n && n<58 ? n-48 : ((n|32)-19)/26==3 ? (n|32)-87 : -1296;
public+hg@61
   253 }
public+hg@1
   254 
public+hg@61
   255 static int key2index(const char *a)
public+hg@61
   256 {
public+hg@61
   257 	return getdigit(*a) * 36 + getdigit(a[1]);
public+hg@61
   258 }
public+hg@61
   259 
public+hg@61
   260 static int compare_bmsline(const void *a, const void *b)
public+hg@61
   261 {
public+hg@2
   262 	int i, j;
public+hg@61
   263 	for (i = 0; i < 6; ++i) {
public+hg@61
   264 		if (j = (*(char**)a)[i] - (*(char**)b)[i]) return j;
public+hg@61
   265 	}
public+hg@2
   266 	return 0;
public+hg@2
   267 }
public+hg@2
   268 
public+hg@61
   269 static int compare_bmsnote(const void *a, const void *b)
public+hg@61
   270 {
public+hg@73
   271 	const bmsnote *A = a, *B = b;
public+hg@11
   272 	return (A->time > B->time ? 1 : A->time < B->time ? -1 : A->type - B->type);
public+hg@11
   273 }
public+hg@11
   274 
public+hg@61
   275 static void add_note(int chan, double time, int type, int index)
public+hg@61
   276 {
public+hg@73
   277 	bmsnote temp = {time, type, index};
public+hg@73
   278 	channel[chan] = realloc(channel[chan], sizeof(bmsnote) * (nchannel[chan]+1));
public+hg@5
   279 	channel[chan][nchannel[chan]++] = temp;
public+hg@3
   280 }
public+hg@3
   281 
public+hg@61
   282 static void remove_note(int chan, int index)
public+hg@61
   283 {
public+hg@73
   284 	if (chan < 18 && channel[chan][index].index) {
public+hg@73
   285 		ADD_BGM(channel[chan][index].time, channel[chan][index].index);
public+hg@11
   286 	}
public+hg@73
   287 	channel[chan][index].type = -1;
public+hg@11
   288 }
public+hg@11
   289 
public+hg@63
   290 #define KEY_PATTERN "%2[0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]"
public+hg@63
   291 
public+hg@61
   292 static int parse_bms(void)
public+hg@61
   293 {
public+hg@61
   294 	FILE *fp;
public+hg@65
   295 	int i, j, k;
public+hg@61
   296 	int rnd = 1, ignore = 0;
public+hg@11
   297 	double t;
public+hg@73
   298 	char linebuf[4096], buf1[4096], buf2[4096];
public+hg@62
   299 	char *line = linebuf;
public+hg@61
   300 
public+hg@6
   301 	fp = fopen(bmspath, "r");
public+hg@61
   302 	if (!fp) return 1;
public+hg@6
   303 
public+hg@2
   304 	srand(time(0));
public+hg@73
   305 	while (fgets(line = linebuf, sizeof linebuf, fp)) {
public+hg@61
   306 		if (line[0] != '#') continue;
public+hg@61
   307 		++line;
public+hg@2
   308 
public+hg@62
   309 		for (i = 0; bmsheader[i]; ++i) {
public+hg@61
   310 			for (j = 0; bmsheader[i][j]; ++j)
public+hg@62
   311 				if (((bmsheader[i][j] ^ line[j]) | 32) != 32) break;
public+hg@61
   312 			if (!bmsheader[i][j]) break;
public+hg@0
   313 		}
public+hg@61
   314 
public+hg@61
   315 		switch (i) {
public+hg@32
   316 		case 15: /* random */
public+hg@63
   317 			if (sscanf(line+j, "%*[ ]%d", &j) >= 1) {
public+hg@63
   318 				rnd = rand() % abs(j) + 1;
public+hg@61
   319 			}
public+hg@0
   320 			break;
public+hg@61
   321 
public+hg@32
   322 		case 16: /* if */
public+hg@63
   323 			if (sscanf(line+j, "%*[ ]%d", &j) >= 1) {
public+hg@63
   324 				ignore = (rnd != j);
public+hg@63
   325 			}
public+hg@2
   326 			break;
public+hg@61
   327 
public+hg@32
   328 		case 17: /* else */
public+hg@2
   329 			ignore = !ignore;
public+hg@2
   330 			break;
public+hg@61
   331 
public+hg@32
   332 		case 18: /* endif */
public+hg@2
   333 			ignore = 0;
public+hg@2
   334 			break;
public+hg@2
   335 		}
public+hg@63
   336 
public+hg@61
   337 		if (!ignore) {
public+hg@61
   338 			switch (i) {
public+hg@2
   339 			case 0: /* title */
public+hg@2
   340 			case 1: /* genre */
public+hg@2
   341 			case 2: /* artist */
public+hg@2
   342 			case 3: /* stagefile */
public+hg@67
   343 				sscanf(line+j, "%*[ ]%[^\r\n]", metadata[i]);
public+hg@2
   344 				break;
public+hg@61
   345 
public+hg@2
   346 			case 4: /* bpm */
public+hg@63
   347 				if (sscanf(line+j, "%*[ ]%lf", &bpm) >= 1) {
public+hg@63
   348 					/* do nothing, bpm is set */
public+hg@63
   349 				} else if (sscanf(line+j, KEY_PATTERN "%*[ ]%lf", buf1, &t) >= 2) {
public+hg@63
   350 					i = key2index(buf1);
public+hg@63
   351 					if (i >= 0) bpmtab[i] = t;
public+hg@2
   352 				}
public+hg@2
   353 				break;
public+hg@61
   354 
public+hg@2
   355 			case 5: /* player */
public+hg@2
   356 			case 6: /* playlevel */
public+hg@2
   357 			case 7: /* rank */
public+hg@32
   358 			case 8: /* lntype */
public+hg@63
   359 				sscanf(line+j, "%*[ ]%d", &value[i-5]);
public+hg@2
   360 				break;
public+hg@61
   361 
public+hg@32
   362 			case 9: /* lnobj */
public+hg@63
   363 				if (sscanf(line+j, "%*[ ]" KEY_PATTERN, buf1) >= 1) {
public+hg@63
   364 					lnobj = key2index(buf1);
public+hg@63
   365 				}
public+hg@2
   366 				break;
public+hg@61
   367 
public+hg@32
   368 			case 10: /* wav## */
public+hg@32
   369 			case 11: /* bmp## */
public+hg@67
   370 				if (sscanf(line+j, KEY_PATTERN "%*[ ]%[^\r\n]", buf1, buf2) >= 2) {
public+hg@67
   371 					j = key2index(buf1);
public+hg@67
   372 					if (j >= 0) {
public+hg@77
   373 						free(paths[i-10][j]);
public+hg@67
   374 						paths[i-10][j] = strcopy(buf2);
public+hg@63
   375 					}
public+hg@61
   376 				}
public+hg@2
   377 				break;
public+hg@61
   378 
public+hg@32
   379 			case 12: /* bga## */
public+hg@24
   380 				i = nblitcmd;
public+hg@24
   381 				blitcmd = realloc(blitcmd, sizeof(int) * 8 * (i+1));
public+hg@64
   382 				if (sscanf(line+j, KEY_PATTERN "%*[ ]" KEY_PATTERN "%*[ ]%d %d %d %d %d %d",
public+hg@63
   383 							buf1, buf2, blitcmd[i]+2, blitcmd[i]+3, blitcmd[i]+4,
public+hg@63
   384 							blitcmd[i]+5, blitcmd[i]+6, blitcmd[i]+7) >= 8) {
public+hg@63
   385 					blitcmd[i][0] = key2index(buf1);
public+hg@63
   386 					blitcmd[i][1] = key2index(buf2);
public+hg@63
   387 					if (blitcmd[i][0] >= 0 && blitcmd[i][1] >= 0) ++nblitcmd;
public+hg@61
   388 				}
public+hg@2
   389 				break;
public+hg@61
   390 
public+hg@32
   391 			case 13: /* stop## */
public+hg@63
   392 				if (sscanf(line+j, KEY_PATTERN "%*[ ]%d", buf1, &j) >= 2) {
public+hg@63
   393 					i = key2index(buf1);
public+hg@63
   394 					if (i >= 0) stoptab[i] = j;
public+hg@63
   395 				}
public+hg@2
   396 				break;
public+hg@61
   397 
public+hg@32
   398 			case 14: /* stp## */
public+hg@64
   399 				if (sscanf(line+j, "%d.%d %d", &i, &j, &k) >= 3) {
public+hg@63
   400 					ADD_STP(i+j/1e3, k);
public+hg@63
   401 				}
public+hg@2
   402 				break;
public+hg@61
   403 
public+hg@63
   404 			case 19: /* #####:... */
public+hg@63
   405 				/* only check validity, do not store them yet */
public+hg@63
   406 				if (sscanf(line+j, "%*5c:%c", buf1) >= 1) {
public+hg@63
   407 					bmsline = realloc(bmsline, sizeof(char*) * (nbmsline+1));
public+hg@63
   408 					bmsline[nbmsline] = strcopy(line);
public+hg@63
   409 					++nbmsline;
public+hg@63
   410 				}
public+hg@1
   411 			}
public+hg@0
   412 		}
public+hg@0
   413 	}
public+hg@6
   414 	fclose(fp);
public+hg@2
   415 
public+hg@65
   416 	return 0;
public+hg@65
   417 }
public+hg@65
   418 
public+hg@65
   419 static int parse_bmsline(void)
public+hg@65
   420 {
public+hg@65
   421 	int prev[40] = {0};
public+hg@65
   422 	int i, j, k, a, b, c;
public+hg@65
   423 	int measure, chan;
public+hg@65
   424 	double t;
public+hg@65
   425 
public+hg@2
   426 	qsort(bmsline, nbmsline, sizeof(char*), compare_bmsline);
public+hg@65
   427 
public+hg@61
   428 	for (i = 0; i < nbmsline; ++i) {
public+hg@65
   429 		j = atoi(bmsline[i]);
public+hg@61
   430 		measure = j / 100;
public+hg@61
   431 		chan = j % 100;
public+hg@61
   432 		if (chan == 2) {
public+hg@22
   433 			shorten[measure] = atof(bmsline[i]+6);
public+hg@3
   434 		} else {
public+hg@65
   435 			j = 6 + strspn(bmsline[i]+6, " \t\r\n");
public+hg@65
   436 			a = strcspn(bmsline[i]+j, " \t\r\n") / 2;
public+hg@61
   437 			for (k = 0; k < a; ++k, j+=2) {
public+hg@30
   438 				b = key2index(bmsline[i]+j);
public+hg@11
   439 				t = measure + 1. * k / a;
public+hg@61
   440 				if (b) {
public+hg@61
   441 					if (chan == 1) {
public+hg@11
   442 						ADD_BGM(t, b);
public+hg@61
   443 					} else if (chan == 3 && (b/36<16 && b%36<16)) {
public+hg@11
   444 						ADD_BPM(t, b/36*16+b%36);
public+hg@61
   445 					} else if (chan == 4) {
public+hg@11
   446 						ADD_BGA(t, b);
public+hg@61
   447 					} else if (chan == 6) {
public+hg@11
   448 						ADD_POORBGA(t, b);
public+hg@61
   449 					} else if (chan == 7) {
public+hg@11
   450 						ADD_BGA2(t, b);
public+hg@61
   451 					} else if (chan == 8) {
public+hg@11
   452 						ADD_BPM2(t, b);
public+hg@61
   453 					} else if (chan == 9) {
public+hg@11
   454 						ADD_STOP(t, b);
public+hg@61
   455 					} else if (chan % 10 != 0 && chan > 9 && chan < 30) {
public+hg@61
   456 						if (lnobj && b == lnobj) {
public+hg@10
   457 							c = GET_CHANNEL(chan>20, chan%10);
public+hg@80
   458 							if (nchannel[c] && channel[c][nchannel[c]-1].type==2/*NOTE*/) {
public+hg@80
   459 								channel[c][nchannel[c]-1].type = 1/*LNSTART*/;
public+hg@11
   460 								ADD_LNDONE(chan>20, chan%10, t, b);
public+hg@5
   461 							}
public+hg@5
   462 						} else {
public+hg@11
   463 							ADD_NOTE(chan>20, chan%10, t, b);
public+hg@4
   464 						}
public+hg@61
   465 					} else if (chan % 10 != 0 && chan > 29 && chan < 50) {
public+hg@11
   466 						ADD_INVNOTE(chan>40, chan%10, t, b);
public+hg@4
   467 					}
public+hg@5
   468 				}
public+hg@61
   469 				if (chan % 10 != 0 && chan > 49 && chan < 70) {
public+hg@61
   470 					if (lntype == 1 && b) {
public+hg@61
   471 						if (prev[chan-50]) {
public+hg@4
   472 							prev[chan-50] = 0;
public+hg@11
   473 							ADD_LNDONE(chan>60, chan%10, t, 0);
public+hg@4
   474 						} else {
public+hg@4
   475 							prev[chan-50] = b;
public+hg@11
   476 							ADD_LNSTART(chan>60, chan%10, t, b);
public+hg@4
   477 						}
public+hg@61
   478 					} else if (lntype == 2) {
public+hg@61
   479 						if (prev[chan-50] || prev[chan-50] != b) {
public+hg@61
   480 							if (prev[chan-50]) {
public+hg@61
   481 								if (prev[chan-30] + 1 < measure) {
public+hg@12
   482 									ADD_LNDONE(chan>60, chan%10, prev[chan-30]+1, 0);
public+hg@61
   483 								} else if (prev[chan-50] != b) {
public+hg@12
   484 									ADD_LNDONE(chan>60, chan%10, t, 0);
public+hg@12
   485 								}
public+hg@10
   486 							}
public+hg@61
   487 							if (b && (prev[chan-50]!=b || prev[chan-30]+1<measure)) {
public+hg@11
   488 								ADD_LNSTART(chan>60, chan%10, t, b);
public+hg@4
   489 							}
public+hg@12
   490 							prev[chan-30] = measure;
public+hg@12
   491 							prev[chan-50] = b;
public+hg@4
   492 						}
public+hg@4
   493 					}
public+hg@3
   494 				}
public+hg@3
   495 			}
public+hg@3
   496 		}
public+hg@12
   497 		free(bmsline[i]);
public+hg@3
   498 	}
public+hg@12
   499 	free(bmsline);
public+hg@30
   500 	length = measure + 2;
public+hg@61
   501 	for (i = 0; i < 20; ++i) {
public+hg@61
   502 		if (prev[i]) {
public+hg@61
   503 			if (lntype == 2 && prev[i+20] + 1 < measure) {
public+hg@12
   504 				ADD_LNDONE(i>10, i%10, prev[i+20]+1, 0);
public+hg@12
   505 			} else {
public+hg@30
   506 				ADD_LNDONE(i>10, i%10, length - 1, 0);
public+hg@12
   507 			}
public+hg@4
   508 		}
public+hg@4
   509 	}
public+hg@61
   510 
public+hg@65
   511 	return 0;
public+hg@65
   512 }
public+hg@65
   513 
public+hg@65
   514 static int sanitize_bmsline(void)
public+hg@65
   515 {
public+hg@79
   516 	int i, j, k, b, c;
public+hg@65
   517 
public+hg@61
   518 	for (i = 0; i < 22; ++i) {
public+hg@61
   519 		if (!channel[i]) continue;
public+hg@73
   520 		qsort(channel[i], nchannel[i], sizeof(bmsnote), compare_bmsnote);
public+hg@79
   521 
public+hg@61
   522 		if (i != 18 && i < 21) {
public+hg@61
   523 			b = 0;
public+hg@79
   524 			j = 0;
public+hg@79
   525 			while (j < nchannel[i]) {
public+hg@79
   526 				k = j;
public+hg@79
   527 				c = 0;
public+hg@79
   528 				for (k = j; k < nchannel[i] && channel[i][k].time <= channel[i][j].time; ++k) {
public+hg@79
   529 					if (c & 1 << channel[i][k].type) {
public+hg@79
   530 						remove_note(i, k);
public+hg@79
   531 					} else {
public+hg@79
   532 						c |= 1 << channel[i][k].type;
public+hg@11
   533 					}
public+hg@11
   534 				}
public+hg@79
   535 
public+hg@79
   536 				if (b) {
public+hg@79
   537 					/* remove starting longnote if there's no ending longnote */
public+hg@80
   538 					c &= ~(c & 1 ? 0 : 2);
public+hg@79
   539 					/* remove visible note */
public+hg@80
   540 					c &= ~4;
public+hg@80
   541 					/* remove invisible note if there is any longnote */
public+hg@80
   542 					c &= ~(c & 3 ? 8 : 0);
public+hg@79
   543 
public+hg@80
   544 					b = !(c & 1);
public+hg@79
   545 				} else {
public+hg@79
   546 					/* remove starting longnote if there's also ending longnote */
public+hg@80
   547 					c &= ~(c & 1 ? 2 : 0);
public+hg@79
   548 					/* remove ending longnote */
public+hg@80
   549 					c &= ~1;
public+hg@80
   550 					/* keep only one note, in the order of importance */
public+hg@80
   551 					c &= -c;
public+hg@79
   552 
public+hg@80
   553 					b = (c & 2);
public+hg@79
   554 				}
public+hg@79
   555 
public+hg@79
   556 				for (; j < k; ++j) {
public+hg@79
   557 					if (channel[i][j].type < 0) continue;
public+hg@79
   558 
public+hg@79
   559 					if (i < 18 && !(c & 1 << channel[i][j].type)) {
public+hg@79
   560 						remove_note(i, j);
public+hg@79
   561 					}
public+hg@79
   562 				}
public+hg@11
   563 			}
public+hg@79
   564 			if (i < 18 && b) {
public+hg@79
   565 				/* remove last starting longnote which is unfinished */
public+hg@73
   566 				while (j >= 0 && channel[i][--j].type < 0);
public+hg@80
   567 				if (j >= 0 && channel[i][j].type == 1/*LNSTART*/) remove_note(i, j);
public+hg@11
   568 			}
public+hg@11
   569 		}
public+hg@11
   570 		k = 0;
public+hg@61
   571 		for (j = 0; j < nchannel[i]; ++j) {
public+hg@73
   572 			if (channel[i][j].type >= 0) {
public+hg@61
   573 				channel[i][j-k] = channel[i][j];
public+hg@61
   574 			} else {
public+hg@61
   575 				++k;
public+hg@61
   576 			}
public+hg@11
   577 		}
public+hg@11
   578 		nchannel[i] -= k;
public+hg@11
   579 	}
public+hg@11
   580 
public+hg@61
   581 	for (i = 0; i < 2005; ++i) {
public+hg@61
   582 		if (_shorten[i] <= .001)
public+hg@30
   583 			_shorten[i] = 1;
public+hg@61
   584 	}
public+hg@16
   585 
public+hg@6
   586 	return 0;
public+hg@6
   587 }
public+hg@4
   588 
public+hg@65
   589 static int read_bms(void)
public+hg@65
   590 {
public+hg@65
   591 	if (parse_bms()) return 1;
public+hg@65
   592 	if (parse_bmsline()) return 1;
public+hg@65
   593 	if (sanitize_bmsline()) return 1;
public+hg@65
   594 
public+hg@65
   595 	return 0;
public+hg@65
   596 }
public+hg@65
   597 
public+hg@61
   598 static SDL_Surface *newsurface(int f, int w, int h); /* DUMMY */
public+hg@61
   599 static SDL_Rect *newrect(int x, int y, int w, int h); /* DUMMY */
public+hg@61
   600 
public+hg@61
   601 static int load_resource(void (*callback)(const char *))
public+hg@61
   602 {
public+hg@13
   603 	SDL_Surface *temp;
public+hg@83
   604 	int i;
public+hg@61
   605 
public+hg@61
   606 	for (i = 0; i < 1296; ++i) {
public+hg@61
   607 		if (sndpath[i]) {
public+hg@61
   608 			if (callback) callback(sndpath[i]);
public+hg@76
   609 			sndres[i] = Mix_LoadWAV(adjust_path(sndpath[i]));
public+hg@83
   610 			if (!sndres[i]) sndres[i] = Mix_LoadWAV(adjust_path_with_ext(sndpath[i], ".mp3"));
public+hg@83
   611 			if (!sndres[i]) sndres[i] = Mix_LoadWAV(adjust_path_with_ext(sndpath[i], ".ogg"));
public+hg@83
   612 			free(sndpath[i]);
public+hg@83
   613 			sndpath[i] = 0;
public+hg@13
   614 		}
public+hg@61
   615 		if (imgpath[i]) {
public+hg@83
   616 			char *ext = strrchr(imgpath[i], '.');
public+hg@61
   617 			if (callback) callback(imgpath[i]);
public+hg@85
   618 			if (ext && stricmp(ext, ".mpg") && opt_bga < 1 && !mpeg) {
public+hg@83
   619 				mpeg = SMPEG_new(adjust_path(imgpath[i]), NULL, 0);
public+hg@83
   620 				imgmpeg = i;
public+hg@85
   621 			} else if (opt_bga < 2) {
public+hg@83
   622 				temp = IMG_Load(adjust_path(imgpath[i]));
public+hg@83
   623 				if (!temp) temp = IMG_Load(adjust_path_with_ext(imgpath[i], ".png"));
public+hg@83
   624 				if (!temp) temp = IMG_Load(adjust_path_with_ext(imgpath[i], ".jpg"));
public+hg@83
   625 				if (temp) {
public+hg@83
   626 					imgres[i] = SDL_DisplayFormat(temp);
public+hg@83
   627 					SDL_FreeSurface(temp);
public+hg@83
   628 					SDL_SetColorKey(imgres[i], SDL_SRCCOLORKEY|SDL_RLEACCEL, 0);
public+hg@83
   629 				}
public+hg@13
   630 			}
public+hg@61
   631 			free(imgpath[i]);
public+hg@61
   632 			imgpath[i] = 0;
public+hg@11
   633 		}
public+hg@6
   634 	}
public+hg@61
   635 
public+hg@61
   636 	for (i = 0; i < nblitcmd; ++i) {
public+hg@61
   637 		if (blitcmd[i][0]<0 || blitcmd[i][1]<0 || !imgres[blitcmd[i][1]]) continue;
public+hg@24
   638 		temp = imgres[blitcmd[i][0]];
public+hg@61
   639 		if (!temp) {
public+hg@24
   640 			imgres[blitcmd[i][0]] = temp = newsurface(SDL_SWSURFACE, 256, 256);
public+hg@83
   641 			SDL_FillRect(temp, 0, SDL_MapRGB(imgres[blitcmd[i][0]]->format, 0, 0, 0));
public+hg@24
   642 			SDL_SetColorKey(temp, SDL_SRCCOLORKEY|SDL_RLEACCEL, 0);
public+hg@24
   643 		}
public+hg@61
   644 		if (blitcmd[i][2] < 0) blitcmd[i][2] = 0;
public+hg@61
   645 		if (blitcmd[i][3] < 0) blitcmd[i][3] = 0;
public+hg@61
   646 		if (blitcmd[i][4] > blitcmd[i][2] + 256) blitcmd[i][4] = blitcmd[i][2] + 256;
public+hg@61
   647 		if (blitcmd[i][5] > blitcmd[i][3] + 256) blitcmd[i][5] = blitcmd[i][3] + 256;
public+hg@24
   648 		SDL_BlitSurface(imgres[blitcmd[i][1]],
public+hg@24
   649 			newrect(blitcmd[i][2], blitcmd[i][3], blitcmd[i][4]-blitcmd[i][2], blitcmd[i][5]-blitcmd[i][3]),
public+hg@24
   650 			temp, newrect(blitcmd[i][6], blitcmd[i][7], 0, 0));
public+hg@24
   651 	}
public+hg@24
   652 	free(blitcmd);
public+hg@61
   653 
public+hg@5
   654 	return 0;
public+hg@5
   655 }
public+hg@5
   656 
public+hg@61
   657 static int xflag, xnnotes, xscore; /* DUMMY */
public+hg@61
   658 
public+hg@13
   659 /*
public+hg@13
   660 bit 0: it uses 7 keys?
public+hg@13
   661 bit 1: it uses long-note?
public+hg@13
   662 bit 2: it uses pedal?
public+hg@18
   663 bit 3: it has bpm variation?
public+hg@13
   664 */
public+hg@61
   665 static void get_bms_info(void)
public+hg@61
   666 {
public+hg@13
   667 	int i, j;
public+hg@61
   668 
public+hg@30
   669 	xflag = xnnotes = 0;
public+hg@61
   670 	if (nchannel[7] || nchannel[8] || nchannel[16] || nchannel[17]) xflag |= 1;
public+hg@61
   671 	if (nchannel[6] || nchannel[15]) xflag |= 4;
public+hg@61
   672 	if (nchannel[20]) xflag |= 8;
public+hg@61
   673 	for (i = 0; i < 18; ++i) {
public+hg@61
   674 		for (j = 0; j < nchannel[i]; ++j) {
public+hg@80
   675 			if (channel[i][j].type == 1/*LNSTART*/) {
public+hg@80
   676 				xflag |= 2;
public+hg@80
   677 				++xnnotes;
public+hg@80
   678 			} else if (channel[i][j].type == 2/*NOTE*/) {
public+hg@80
   679 				++xnnotes;
public+hg@80
   680 			}
public+hg@11
   681 		}
public+hg@30
   682 	}
public+hg@61
   683 	for (i = 0; i < xnnotes; ++i) {
public+hg@30
   684 		xscore += (int)(300 * (1 + 1. * i / xnnotes));
public+hg@61
   685 	}
public+hg@30
   686 }
public+hg@30
   687 
public+hg@61
   688 static double adjust_object_position(double base, double time); /* DUMMY */
public+hg@61
   689 
public+hg@61
   690 static int pcur[22]; /* DUMMY */
public+hg@61
   691 
public+hg@61
   692 static int get_bms_duration(void)
public+hg@61
   693 {
public+hg@30
   694 	int i, j, time, rtime, ttime;
public+hg@30
   695 	double pos, xbpm, tmp;
public+hg@30
   696 
public+hg@30
   697 	xbpm = bpm;
public+hg@61
   698 	time = rtime = 0;
public+hg@61
   699 	pos = -1;
public+hg@61
   700 	while (1) {
public+hg@61
   701 		for (i = 0, j = -1; i < 22; ++i) {
public+hg@73
   702 			if (pcur[i] < nchannel[i] && (j < 0 || channel[i][pcur[i]].time < channel[j][pcur[j]].time)) j = i;
public+hg@61
   703 		}
public+hg@61
   704 		if (j < 0) {
public+hg@30
   705 			time += (int)(adjust_object_position(pos, length) * 24e7 / xbpm);
public+hg@30
   706 			break;
public+hg@30
   707 		}
public+hg@73
   708 		time += (int)(adjust_object_position(pos, channel[j][pcur[j]].time) * 24e7 / xbpm);
public+hg@61
   709 
public+hg@73
   710 		i = channel[j][pcur[j]].index;
public+hg@61
   711 		ttime = 0;
public+hg@61
   712 		if (j < 19) {
public+hg@61
   713 			if (sndres[i]) ttime = (int)(sndres[i]->alen / .1764);
public+hg@61
   714 		} else if (j == 20) {
public+hg@73
   715 			tmp = (channel[j][pcur[j]].type ? bpmtab[i] : i);
public+hg@61
   716 			if (tmp > 0) {
public+hg@30
   717 				xbpm = tmp;
public+hg@61
   718 			} else if (tmp < 0) {
public+hg@30
   719 				time += (int)(adjust_object_position(-1, pos) * 24e7 / xbpm);
public+hg@30
   720 				break;
public+hg@30
   721 			}
public+hg@61
   722 		} else if (j == 21) {
public+hg@73
   723 			if (channel[j][pcur[j]].type) {
public+hg@61
   724 				time += i;
public+hg@61
   725 			} else {
public+hg@61
   726 				time += (int)(stoptab[i] * 125e4 * shorten[(int)(pos+1)-1] / xbpm);
public+hg@61
   727 			}
public+hg@30
   728 		}
public+hg@61
   729 		if (rtime < time + ttime) rtime = time + ttime;
public+hg@73
   730 		pos = channel[j][pcur[j]].time;
public+hg@61
   731 		++pcur[j];
public+hg@30
   732 	}
public+hg@30
   733 	return (time > rtime ? time : rtime) / 1000;
public+hg@11
   734 }
public+hg@11
   735 
public+hg@61
   736 static void clone_bms(void)
public+hg@61
   737 {
public+hg@80
   738 	int i;
public+hg@26
   739 
public+hg@61
   740 	for (i = 0; i < 9; ++i) {
public+hg@77
   741 		free(channel[i+9]);
public+hg@26
   742 		nchannel[i+9] = nchannel[i];
public+hg@73
   743 		channel[i+9] = malloc(sizeof(bmsnote) * nchannel[i]);
public+hg@80
   744 		memcpy(channel[i+9], channel[i], sizeof(bmsnote) * nchannel[i]);
public+hg@26
   745 	}
public+hg@26
   746 }
public+hg@26
   747 
public+hg@61
   748 static void shuffle_bms(int mode, int player)
public+hg@61
   749 {
public+hg@73
   750 	bmsnote *tempchan, *result[18] = {0};
public+hg@73
   751 	int nresult[18] = {0};
public+hg@26
   752 	int map[18], perm[18], nmap;
public+hg@73
   753 	int ptr[18] = {0,}, thru[18] = {0}, target[18];
public+hg@26
   754 	int thrumap[18], thrurmap[18];
public+hg@73
   755 	int i, j, flag = 1, temp;
public+hg@26
   756 	double t;
public+hg@26
   757 
public+hg@26
   758 	srand(time(0));
public+hg@61
   759 	for (i = 0; i < 18; ++i) map[i] = perm[i] = i;
public+hg@61
   760 	if (!nchannel[7] && !nchannel[8] && !nchannel[16] && !nchannel[17]) {
public+hg@26
   761 		map[7] = map[8] = map[16] = map[17] = -1;
public+hg@61
   762 	}
public+hg@61
   763 	if (!nchannel[6] && !nchannel[15]) {
public+hg@26
   764 		map[6] = map[15] = -1;
public+hg@61
   765 	}
public+hg@61
   766 	if (mode != 3 && mode != 5) {
public+hg@26
   767 		map[5] = map[6] = map[14] = map[15] = -1;
public+hg@26
   768 	}
public+hg@61
   769 	if (player) {
public+hg@61
   770 		for (i = 0; i < 9; ++i) map[player==1 ? i+9 : i] = -1;
public+hg@61
   771 	}
public+hg@61
   772 	for (i = j = 0; i < 18; ++i) {
public+hg@61
   773 		if (map[i] < 0) {
public+hg@61
   774 			++j;
public+hg@61
   775 		} else {
public+hg@61
   776 			map[i-j] = map[i];
public+hg@61
   777 		}
public+hg@61
   778 	}
public+hg@26
   779 	nmap = 18 - j;
public+hg@26
   780 
public+hg@61
   781 	if (mode < 2) { /* mirror */
public+hg@61
   782 		for (i = 0, j = nmap-1; i < j; ++i, --j) {
public+hg@26
   783 			SWAP(channel[map[i]], channel[map[j]], tempchan);
public+hg@26
   784 			SWAP(nchannel[map[i]], nchannel[map[j]], temp);
public+hg@26
   785 		}
public+hg@61
   786 	} else if (mode < 4) { /* shuffle */
public+hg@61
   787 		for (i = nmap-1; i > 0; --i) {
public+hg@26
   788 			j = rand() % i;
public+hg@26
   789 			SWAP(channel[map[i]], channel[map[j]], tempchan);
public+hg@26
   790 			SWAP(nchannel[map[i]], nchannel[map[j]], temp);
public+hg@26
   791 		}
public+hg@61
   792 	} else if (mode < 6) { /* random */
public+hg@61
   793 		while (flag) {
public+hg@61
   794 			for (i = nmap-1; i > 0; --i) {
public+hg@26
   795 				j = rand() % i;
public+hg@26
   796 				SWAP(perm[i], perm[j], temp);
public+hg@26
   797 			}
public+hg@26
   798 			t = 1e4;
public+hg@26
   799 			flag = 0;
public+hg@61
   800 			for (i = 0; i < nmap; ++i) {
public+hg@61
   801 				if (ptr[map[i]] < nchannel[map[i]]) {
public+hg@61
   802 					flag = 1;
public+hg@61
   803 					target[i] = 1;
public+hg@73
   804 					if (t > channel[map[i]][ptr[map[i]]].time)
public+hg@73
   805 						t = channel[map[i]][ptr[map[i]]].time - 1e-4;
public+hg@26
   806 				} else {
public+hg@26
   807 					target[i] = 0;
public+hg@26
   808 				}
public+hg@26
   809 			}
public+hg@26
   810 			t += 2e-4;
public+hg@61
   811 			for (i = 0; i < nmap; ++i) {
public+hg@73
   812 				if (target[i] && channel[map[i]][ptr[map[i]]].time > t)
public+hg@26
   813 					target[i] = 0;
public+hg@26
   814 			}
public+hg@61
   815 			for (i = 0; i < nmap; ++i) {
public+hg@61
   816 				if (!target[i]) continue;
public+hg@73
   817 				temp = channel[map[i]][ptr[map[i]]].type;
public+hg@80
   818 				if (temp == 0/*LNDONE*/) {
public+hg@26
   819 					j = thrumap[i];
public+hg@26
   820 					thru[j] = 2;
public+hg@26
   821 				} else {
public+hg@26
   822 					j = perm[i];
public+hg@61
   823 					while (thru[j]) j = perm[thrurmap[j]];
public+hg@80
   824 					if (temp == 1/*LNSTART*/) {
public+hg@26
   825 						thrumap[i] = j;
public+hg@26
   826 						thrurmap[j] = i;
public+hg@26
   827 						thru[j] = 1;
public+hg@26
   828 					}
public+hg@26
   829 				}
public+hg@73
   830 				result[j] = realloc(result[j], sizeof(bmsnote) * (nresult[j]+1));
public+hg@26
   831 				result[j][nresult[j]++] = channel[map[i]][ptr[map[i]]++];
public+hg@26
   832 			}
public+hg@61
   833 			for(i = 0; i < nmap; ++i) {
public+hg@61
   834 				if (thru[i] == 2) thru[i] = 0;
public+hg@61
   835 			}
public+hg@26
   836 		}
public+hg@61
   837 		for (i = 0; i < nmap; ++i) {
public+hg@26
   838 			free(channel[map[i]]);
public+hg@26
   839 			channel[map[i]] = result[i];
public+hg@26
   840 			nchannel[map[i]] = nresult[i];
public+hg@26
   841 		}
public+hg@26
   842 	}
public+hg@26
   843 }
public+hg@26
   844 
public+hg@5
   845 /******************************************************************************/
public+hg@20
   846 /* general graphic functions */
public+hg@5
   847 
public+hg@61
   848 static SDL_Surface *screen;
public+hg@61
   849 static SDL_Event event;
public+hg@61
   850 static SDL_Rect rect[2];
public+hg@61
   851 static int _rect=0;
public+hg@14
   852 
public+hg@61
   853 static int getpixel(SDL_Surface *s, int x, int y)
public+hg@61
   854 {
public+hg@83
   855 	Uint8 r, g, b;
public+hg@83
   856 	SDL_GetRGB(((Uint32*)s->pixels)[x+y*s->pitch/4], s->format, &r, &g, &b);
public+hg@83
   857 	return (int)(r << 16) | ((int)g << 8) | (int)b;
public+hg@83
   858 }
public+hg@83
   859 
public+hg@83
   860 static Uint32 map(int c)
public+hg@83
   861 {
public+hg@83
   862 	return SDL_MapRGB(screen->format, c >> 16, (c >> 8) & 255, c & 255);
public+hg@61
   863 }
public+hg@14
   864 
public+hg@61
   865 static int putpixel(SDL_Surface *s, int x, int y, int c)
public+hg@61
   866 {
public+hg@83
   867 	c = SDL_MapRGB(s->format, c >> 16, (c >> 8) & 255, c & 255);
public+hg@61
   868 	return ((Uint32*)s->pixels)[x+y*s->pitch/4] = c;
public+hg@61
   869 }
public+hg@61
   870 
public+hg@61
   871 static int blend(int x, int y, int a, int b)
public+hg@61
   872 {
public+hg@61
   873 	int i = 0;
public+hg@61
   874 	for (; i < 24; i += 8)
public+hg@61
   875 		y += ((x>>i&255) - (y>>i&255))*a/b << i;
public+hg@61
   876 	return y;
public+hg@61
   877 }
public+hg@61
   878 
public+hg@61
   879 static void putblendedpixel(SDL_Surface *s, int x, int y, int c, int o)
public+hg@61
   880 {
public+hg@61
   881 	putpixel(s, x, y, blend(getpixel(s,x,y), c, o, 255));
public+hg@61
   882 }
public+hg@61
   883 
public+hg@61
   884 static SDL_Surface *newsurface(int f, int w, int h)
public+hg@61
   885 {
public+hg@61
   886 	return SDL_CreateRGBSurface(f, w, h, 32, 0xff0000, 0xff00, 0xff, 0);
public+hg@61
   887 }
public+hg@61
   888 
public+hg@61
   889 static SDL_Rect *newrect(int x, int y, int w, int h)
public+hg@61
   890 {
public+hg@61
   891 	SDL_Rect *r = rect+_rect++%2;
public+hg@61
   892 	r->x = x;
public+hg@61
   893 	r->y = y;
public+hg@61
   894 	r->w = w;
public+hg@61
   895 	r->h = h;
public+hg@61
   896 	return r;
public+hg@61
   897 }
public+hg@61
   898 
public+hg@61
   899 static int bicubic_kernel(int x, int y) {
public+hg@61
   900 	if (x < 0) x = -x;
public+hg@61
   901 	if (x < y) {
public+hg@14
   902 		return ((y*y - 2*x*x + x*x/y*x) << 11) / y / y;
public+hg@61
   903 	} else if (x < y * 2) {
public+hg@14
   904 		return ((4*y*y - 8*x*y + 5*x*x - x*x/y*x) << 11) / y / y;
public+hg@14
   905 	} else {
public+hg@14
   906 		return 0;
public+hg@14
   907 	}
public+hg@14
   908 }
public+hg@14
   909 
public+hg@61
   910 static int bicubic_interpolation(SDL_Surface *src, SDL_Surface *dest) {
public+hg@14
   911 	int x, dx, y, dy, ww, hh, w, h;
public+hg@30
   912 	int i, j, k, r, g, b, c, xx, yy, a[4][2], d;
public+hg@14
   913 
public+hg@14
   914 	dx = x = 0;
public+hg@61
   915 	ww = src->w - 1;
public+hg@61
   916 	hh = src->h - 1;
public+hg@61
   917 	w = dest->w - 1;
public+hg@61
   918 	h = dest->h - 1;
public+hg@61
   919 	for (i = 0; i <= w; ++i) {
public+hg@14
   920 		dy = y = 0;
public+hg@61
   921 		for (j = 0; j <= h; ++j) {
public+hg@14
   922 			r = g = b = 0;
public+hg@61
   923 			for (k = 0; k < 4; ++k) {
public+hg@61
   924 				a[k][0] = bicubic_kernel((x+k-1)*w - i*ww, w);
public+hg@61
   925 				a[k][1] = bicubic_kernel((y+k-1)*h - j*hh, h);
public+hg@30
   926 			}
public+hg@61
   927 			for (k = 0; k < 16; ++k) {
public+hg@61
   928 				xx = x + k/4 - 1;
public+hg@61
   929 				yy = y + k%4 - 1;
public+hg@61
   930 				if (xx>=0 && xx<=ww && yy>=0 && yy<=hh) {
public+hg@61
   931 					c = getpixel(src, xx, yy);
public+hg@61
   932 					d = a[k/4][0] * a[k%4][1] >> 6;
public+hg@83
   933 					r += (c>>16) * d;
public+hg@61
   934 					g += (c>>8&255) * d;
public+hg@83
   935 					b += (c&255) * d;
public+hg@30
   936 				}
public+hg@14
   937 			}
public+hg@14
   938 			r = (r<0 ? 0 : r>>24 ? 255 : r>>16);
public+hg@14
   939 			g = (g<0 ? 0 : g>>24 ? 255 : g>>16);
public+hg@14
   940 			b = (b<0 ? 0 : b>>24 ? 255 : b>>16);
public+hg@83
   941 			putpixel(dest, i, j, (r<<16) | (g<<8) | b);
public+hg@61
   942 
public+hg@61
   943 			dy += hh;
public+hg@61
   944 			if (dy > h) {
public+hg@61
   945 				++y;
public+hg@61
   946 				dy -= h;
public+hg@61
   947 			}
public+hg@14
   948 		}
public+hg@61
   949 		dx += ww;
public+hg@61
   950 		if (dx > w) {
public+hg@61
   951 			++x;
public+hg@61
   952 			dx -= w;
public+hg@61
   953 		}
public+hg@14
   954 	}
public+hg@14
   955 
public+hg@14
   956 	return 0;
public+hg@14
   957 }
public+hg@14
   958 
public+hg@14
   959 /******************************************************************************/
public+hg@20
   960 /* font functions */
public+hg@5
   961 
public+hg@82
   962 static int fontdatawords[] = {0, 0, 2, 6, 2, 5, 32, 96, 97, 15, 497, 15,
public+hg@82
   963 	1521, 15, 1537, 16, 48, 176, 1, 3, 1, 3, 7, 1, 4080, 4096, 3, 1, 8,
public+hg@82
   964 	3, 4097, 4080, 16, 16128, 240, 1, 2, 9, 3, 8177, 15, 16385, 240, 15,
public+hg@82
   965 	1, 47, 721, 143, 2673, 2, 6, 7, 1, 31, 17, 16, 63, 64, 33, 0, 1, 2,
public+hg@82
   966 	1, 8, 3};
public+hg@82
   967 static const char *fontdataindices =
public+hg@82
   968 	"!!7a/&w7a!!g'M*Qg(O&J!!&Je!!g2Qg-B!!u2cQ[b7b2[[Q7b2[bQ!c!i&d>UT2c&"
public+hg@82
   969 	"b>WT!b2eGW&!c!i2MbUbD!.8(M$UQCb-b!!l'U*2eTXb2Gb5b>9ZW!!k*e8(J$b!!u"
public+hg@82
   970 	"*8(M$Q!h#b'O*?!!k#Q'O*?b!h8(M$Q!!m&JTLcG_&J>]TLc&J!!o&Je7[&Je!!{&J"
public+hg@82
   971 	"dM$Q!!s7[!!}e&Je!!m0b3b.8(M$U!Cb-b!o>UQ2Ub]ba9Y[SbQCb2GW!!k*MbQbBb"
public+hg@82
   972 	"!kaQ!!k>UQ2Ub]bG8.M(U$[!Ca[!!k>UQ2d!IJQ!d2cGW!!k78bM6U2Cb2ea[2!c!l"
public+hg@82
   973 	"a[!2e>[Q!d2cGW!!k>UQ2c!b>[Q2gGW!!ka[Q!UbDb.8(J&h!!k>UQ2eIXQ2gGW!!k"
public+hg@82
   974 	">UQ2gaWQ!b2cGW!!m&Je!!e&Je!!m&Je!!e&JdM$Q!!k3b.8(M$U!H#W'O,?4!!t7["
public+hg@82
   975 	"!!c7[!!r:#W'O,?5!.8(M$U!Cb!k>UQ2cUbD!.8(J!!&Jc!!k>UJ)LKKhGb!)7W!!k"
public+hg@82
   976 	"'8,M=UWCQ2ca[Q2e!!k>[Q2eI[Q2gG[!!k>MSUQC!2gQ:RWGO!!k,[<2WbQhUbDb.["
public+hg@82
   977 	"!!ka[!2e7[!2ga[!!ka[!2e7[!2j!k>MSUQC!2c[bWbQ:RWGO!!kQ2ga[Q2i!!k7[&"
public+hg@82
   978 	"Jo7[!!kQm2eGW!!kU2Db.9([$b#b'b,@<2Wb!!l2qa[!!kU:^[adT2cQh!!kQ2d:R["
public+hg@82
   979 	"Vba@_2WbQd!!k,M=UWCQ2gU:EW.O!!k>[Q2gG[!2h!k>UQ2iVbabIW_!Wb!j>[Q2gI"
public+hg@82
   980 	"[Q2g!!k>UQ2c!b>WQ!d2cGW!!k7[&Jq!!kQ2qGW!!kQ2kU:EW.O(?!!kQ2gTfa[CW2"
public+hg@82
   981 	"Q!!kM+U:^[GW.O,M>U`[WCO-!!kM'U,D<.W(O&Ji!!ka[Q!Ub]bG8.M(U$[!Ca[!!k"
public+hg@82
   982 	"*Q!p*b!!n+b:#W'O,?4!1b!p*Qb!pQ!!g'8,M=UWCO-!!}oa[!!i#Q'O,?4!!}b>QQ"
public+hg@82
   983 	"!caUQ2eaW!!l2e>[Q2iG[!!o>UQ2c!dQdGW!!kQfaUQ2iaW!!o>UQ2ea[!2UbGW!!k"
public+hg@82
   984 	">8TJc&b7[&Ji!!oaUQ2gaWQ!b2cGW!!f2e>[Q2m!!k&Jc!!&Jm!!kQd!dQi2eGW!!h"
public+hg@82
   985 	"2cUbDb.9(['b,@<2Wb!!k*Jb?b!o!p;[abT2gQd!!o>[Q2m!!o>UQ2kGW!!o>[Q2kG"
public+hg@82
   986 	"[!2f!iaUQ2kaWQ!e!j>[Q2c!k!o>UW2!b>WQ!d:GW!!k&Jc7[&JeTfG?!!oQ2mGW!!"
public+hg@82
   987 	"oQ2gU:EW.O(?!!oQ2eTfa[FW!!oM+U:EW.O,M=UWCO-!!oQ2f:RWGO.A(M$U!Cb!ka"
public+hg@82
   988 	"[]!G8.M(U$[!Ca[!!i78&Jg%[&Jg7?!!e&J}c!!c#[&Jg7A&Jg$[!!k#]NaaPG?!!}"
public+hg@82
   989 	"o7[.W(O";
public+hg@7
   990 
public+hg@82
   991 static Uint16 fontdata[3072];
public+hg@66
   992 static Uint8 (*zoomfont[16])[96] = {NULL};
public+hg@61
   993 
public+hg@82
   994 static void fontdecompress(void)
public+hg@82
   995 {
public+hg@82
   996 	int i, ch;
public+hg@82
   997 
public+hg@82
   998 	for (i = ch = 0; i < ARRAYSIZE(fontdatawords); ++i) {
public+hg@82
   999 		ch += fontdatawords[i];
public+hg@82
  1000 		fontdatawords[i] = ch;
public+hg@82
  1001 	}
public+hg@82
  1002 	for (i = 0; ch = *fontdataindices++; ) {
public+hg@82
  1003 		if (ch > 97) {
public+hg@82
  1004 			while (ch-- > 97) fontdata[i] = fontdata[i-2], ++i;
public+hg@82
  1005 		} else if (ch > 32) {
public+hg@82
  1006 			fontdata[i++] = fontdatawords[ch - 33];
public+hg@82
  1007 		}
public+hg@82
  1008 	}
public+hg@82
  1009 }
public+hg@82
  1010 
public+hg@61
  1011 static int _fontprocess(int x, int y, int z, int c, int s)
public+hg@61
  1012 {
public+hg@9
  1013 	int i, j;
public+hg@61
  1014 	for (i = 0; i < z; ++i) {
public+hg@61
  1015 		for (j = (s==1 ? z-i : s==3 ? i+1 : 0); j < (s==2 ? i : s==4 ? z-i-1 : z); ++j)
public+hg@66
  1016 			zoomfont[z][(y*z+i)*z+j][c] |= 1<<(7-x);
public+hg@61
  1017 	}
public+hg@9
  1018 	return z;
public+hg@7
  1019 }
public+hg@7
  1020 
public+hg@61
  1021 static void fontprocess(int z)
public+hg@61
  1022 {
public+hg@82
  1023 	int i, j, k, l, v;
public+hg@66
  1024 
public+hg@66
  1025 	zoomfont[z] = calloc(16*z*z, 96);
public+hg@82
  1026 	for (i = l = 0; i < 96; ++i) {
public+hg@82
  1027 		for (j = 0; j < 16; ++j, l+=2) {
public+hg@82
  1028 			v = fontdata[l] << 16 | fontdata[l+1];
public+hg@66
  1029 			for (k = 0; k < 8; ++k, v >>= 4) {
public+hg@66
  1030 				if ((v & 15) == 15) _fontprocess(k, j, z, i, 0); /* XXX? */
public+hg@66
  1031 				if (v & 1) _fontprocess(k, j, z, i, 1); /* /| */
public+hg@66
  1032 				if (v & 2) _fontprocess(k, j, z, i, 2); /* |\ */
public+hg@66
  1033 				if (v & 4) _fontprocess(k, j, z, i, 3); /* \| */
public+hg@66
  1034 				if (v & 8) _fontprocess(k, j, z, i, 4); /* |/ */
public+hg@61
  1035 			}
public+hg@9
  1036 		}
public+hg@9
  1037 	}
public+hg@9
  1038 }
public+hg@9
  1039 
public+hg@61
  1040 static int printchar(SDL_Surface *s, int x, int y, int z, int c, int u, int v)
public+hg@61
  1041 {
public+hg@8
  1042 	int i, j;
public+hg@82
  1043 
public+hg@66
  1044 	if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
public+hg@30
  1045 		c -= (c<0 ? -96 : c<33 || c>126 ? c : 32);
public+hg@61
  1046 		for (i = 0; i < 16*z; ++i) {
public+hg@61
  1047 			for (j = 0; j < 8*z; ++j) {
public+hg@66
  1048 				if (zoomfont[z][i*z+j%z][c] & (1<<(7-j/z)))
public+hg@17
  1049 					putpixel(s, x+j, y+i, blend(u, v, i, 16*z-1));
public+hg@61
  1050 			}
public+hg@61
  1051 		}
public+hg@16
  1052 	}
public+hg@82
  1053 
public+hg@16
  1054 	return 8*z;
public+hg@7
  1055 }
public+hg@7
  1056 
public+hg@61
  1057 static void printstr(SDL_Surface *s, int x, int y, int z, const char *c, int u, int v)
public+hg@61
  1058 {
public+hg@82
  1059 	while (*c) {
public+hg@61
  1060 		x += printchar(s, x, y, z, (Uint8)*c++, u, v);
public+hg@82
  1061 	}
public+hg@61
  1062 }
public+hg@8
  1063 
public+hg@13
  1064 /******************************************************************************/
public+hg@20
  1065 /* main routines */
public+hg@13
  1066 
public+hg@61
  1067 static double playspeed = 1, targetspeed;
public+hg@69
  1068 static int now, origintime, starttime, stoptime = 0, adjustspeed = 0;
public+hg@75
  1069 static double startoffset = -1, startshorten = 1;
public+hg@61
  1070 static int xflag, xnnotes, xscore, xduration;
public+hg@61
  1071 static int pcur[22] = {0}, pfront[22] = {0}, prear[22] = {0}, pcheck[18] = {0}, thru[22] = {0};
public+hg@61
  1072 static int bga[3] = {-1,-1,0}, poorbga = 0, bga_updated = 1;
public+hg@61
  1073 static int score = 0, scocnt[5] = {0}, scombo = 0, smaxcombo = 0;
public+hg@61
  1074 static double gradefactor;
public+hg@85
  1075 static int gradetime = 0, grademode, gauge = 256, survival = 150;
public+hg@19
  1076 
public+hg@61
  1077 static SDL_Surface *sprite=0;
public+hg@85
  1078 static int keymap[SDLK_LAST]; /* -1: none, 0..17: notes, 18..19: speed down/up */
public+hg@61
  1079 static int keypressed[18] = {0};
public+hg@61
  1080 static int tkeyleft[18] = {41,67,93,119,145,0,223,171,197, 578,604,630,656,682,760,537,708,734};
public+hg@61
  1081 static int tkeywidth[18] = {25,25,25,25,25,40,40,25,25, 25,25,25,25,25,40,40,25,25};
public+hg@61
  1082 static int tpanel1 = 264, tpanel2 = 536, tbga = 272;
public+hg@16
  1083 #define WHITE 0x808080
public+hg@16
  1084 #define BLUE 0x8080ff
public+hg@61
  1085 static int tkeycolor[18] = {
public+hg@61
  1086 	WHITE, BLUE, WHITE, BLUE, WHITE, 0xff8080, 0x80ff80, BLUE, WHITE,
public+hg@61
  1087 	WHITE, BLUE, WHITE, BLUE, WHITE, 0xff8080, 0x80ff80, BLUE, WHITE};
public+hg@16
  1088 #undef WHITE
public+hg@16
  1089 #undef BLUE
public+hg@61
  1090 static char *tgradestr[5] = {"MISS", "BAD", "GOOD", "GREAT", "COOL"};
public+hg@61
  1091 static int tgradecolor[5][2] = {
public+hg@30
  1092 	{0xff4040, 0xffc0c0}, {0xff40ff, 0xffc0ff}, {0xffff40, 0xffffc0},
public+hg@30
  1093 	{0x40ff40, 0xc0ffc0}, {0x4040ff, 0xc0c0ff}};
public+hg@16
  1094 
public+hg@85
  1095 static Mix_Chunk *beep;
public+hg@85
  1096 
public+hg@85
  1097 static void check_exit(void)
public+hg@61
  1098 {
public+hg@61
  1099 	while (SDL_PollEvent(&event)) {
public+hg@85
  1100 		if (event.type == SDL_QUIT || (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE)) exit(0);
public+hg@14
  1101 	}
public+hg@14
  1102 }
public+hg@14
  1103 
public+hg@79
  1104 static SDLKey get_sdlkey_from_name(const char *str)
public+hg@79
  1105 {
public+hg@79
  1106 	SDLKey i;
public+hg@79
  1107 
public+hg@79
  1108 	/* XXX maybe won't work in SDL 1.3 */
public+hg@79
  1109 	for (i = SDLK_FIRST; i < SDLK_LAST; ++i) {
public+hg@79
  1110 		if (stricmp(SDL_GetKeyName(i), str)) return i;
public+hg@79
  1111 	}
public+hg@79
  1112 	return SDLK_UNKNOWN;
public+hg@79
  1113 }
public+hg@79
  1114 
public+hg@85
  1115 static void read_keymap(void)
public+hg@79
  1116 {
public+hg@85
  1117 	static const struct { const char *name, *def; int base, limit; } envvars[] = {
public+hg@85
  1118 		{"ANGOLMOIS_1P_KEYS", "z|s|x|d|c|left shift|left alt|f|v", 0, 9},
public+hg@85
  1119 		{"ANGOLMOIS_2P_KEYS", "m|k|,|l|.|right shift|right alt|;|/", 9, 18},
public+hg@85
  1120 		{"ANGOLMOIS_SPEED_KEYS", "f3|f4", 18, 20},
public+hg@79
  1121 	};
public+hg@85
  1122 	char *s, buf[256] = "";
public+hg@85
  1123 	int i, j, k, sep;
public+hg@79
  1124 	SDLKey key;
public+hg@79
  1125 
public+hg@85
  1126 	for (i = 0; i < SDLK_LAST; ++i) keymap[i] = -1;
public+hg@85
  1127 	for (i = 0; i < 3; ++i) {
public+hg@85
  1128 		s = getenv(envvars[i].name);
public+hg@85
  1129 		strncpy(buf, s ? s : envvars[i].def, sizeof(buf) - 1);
public+hg@85
  1130 		s = buf;
public+hg@85
  1131 		sep = 1;
public+hg@85
  1132 		for (j = envvars[i].base; sep && j < envvars[i].limit; ) {
public+hg@85
  1133 			k = strcspn(s, "%|"); /* both character is not used as a key name in SDL 1.2 */
public+hg@85
  1134 			sep = s[k];
public+hg@85
  1135 			s[k++] = '\0';
public+hg@85
  1136 			key = get_sdlkey_from_name(s);
public+hg@85
  1137 			if (key == SDLK_UNKNOWN) {
public+hg@85
  1138 				die("Unknown key name in the environment variable %s: %s", envvars[i].name, s);
public+hg@85
  1139 			}
public+hg@85
  1140 			keymap[key] = j;
public+hg@85
  1141 			if (sep != '%') ++j;
public+hg@85
  1142 			s += k;
public+hg@85
  1143 		}
public+hg@85
  1144 	}
public+hg@85
  1145 	
public+hg@85
  1146 }
public+hg@79
  1147 
public+hg@85
  1148 static void create_beep(void)
public+hg@85
  1149 {
public+hg@85
  1150 	Sint32 samples[12000]; /* approx. 0.14 seconds */
public+hg@85
  1151 	int i;
public+hg@85
  1152 
public+hg@85
  1153 	for (i = 0; i < 12000; ++i) {
public+hg@85
  1154 		/* sawtooth wave at 3150 Hz, quadratic decay after 0.02 seconds. */
public+hg@85
  1155 		samples[i] = (i%28-14)*(i<2000 ? 2000 : (12000-i)*(12000-i)/50000);
public+hg@79
  1156 	}
public+hg@85
  1157 	beep = Mix_QuickLoad_RAW((Uint8*)samples, sizeof samples);
public+hg@79
  1158 }
public+hg@79
  1159 
public+hg@61
  1160 static int initialize(void)
public+hg@61
  1161 {
public+hg@61
  1162 	if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0)
public+hg@85
  1163 		die("SDL Initialization Failure: %s", SDL_GetError());
public+hg@13
  1164 	atexit(SDL_Quit);
public+hg@26
  1165 	screen = SDL_SetVideoMode(800, 600, 32, opt_fullscreen ? SDL_FULLSCREEN : SDL_SWSURFACE|SDL_DOUBLEBUF);
public+hg@61
  1166 	if (!screen)
public+hg@85
  1167 		die("SDL Video Initialization Failure: %s", SDL_GetError());
public+hg@17
  1168 	SDL_ShowCursor(SDL_DISABLE);
public+hg@83
  1169 	IMG_Init(IMG_INIT_JPG|IMG_INIT_PNG);
public+hg@83
  1170 	Mix_Init(MIX_INIT_OGG|MIX_INIT_MP3);
public+hg@83
  1171 	if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048)<0)
public+hg@85
  1172 		die("SDL Mixer Initialization Failure: %s", Mix_GetError());
public+hg@60
  1173 	SDL_WM_SetCaption(VERSION, 0);
public+hg@5
  1174 
public+hg@82
  1175 	fontdecompress();
public+hg@66
  1176 	fontprocess(1);
public+hg@9
  1177 	fontprocess(2);
public+hg@9
  1178 	fontprocess(3);
public+hg@85
  1179 	read_keymap(); /* this is unfortunate, but get_sdlkey_from_name depends on SDL_Init. */
public+hg@85
  1180 	create_beep();
public+hg@13
  1181 	return 0;
public+hg@13
  1182 }
public+hg@61
  1183 
public+hg@61
  1184 static SDL_Surface *stagefile_tmp;
public+hg@85
  1185 static int last_flip = -1;
public+hg@13
  1186 
public+hg@61
  1187 static void callback_resource(const char *path) {
public+hg@85
  1188 	/* try not to refresh the screen within 1/20 seconds */
public+hg@85
  1189 	int t = SDL_GetTicks();
public+hg@85
  1190 	if (last_flip >= 0 && (t - last_flip) < 50) return;
public+hg@85
  1191 
public+hg@85
  1192 	last_flip = t;
public+hg@14
  1193 	SDL_BlitSurface(stagefile_tmp, newrect(0,0,800,20), screen, newrect(0,580,800,20));
public+hg@77
  1194 	printstr(screen, 797-8*strlen(path), 582, 1, path, 0x808080, 0xc0c0c0);
public+hg@14
  1195 	SDL_Flip(screen);
public+hg@85
  1196 	check_exit();
public+hg@10
  1197 }
public+hg@10
  1198 
public+hg@61
  1199 static void play_show_stagefile(void)
public+hg@61
  1200 {
public+hg@13
  1201 	SDL_Surface *temp, *stagefile;
public+hg@19
  1202 	char buf[256];
public+hg@15
  1203 	int i, j, t;
public+hg@13
  1204 
public+hg@60
  1205 	sprintf(buf, "%s: %s - %s", VERSION, metadata[2], metadata[0]);
public+hg@85
  1206 	/*SDL_WM_SetCaption(buf, 0);*/
public+hg@17
  1207 	printstr(screen, 248, 284, 2, "loading bms file...", 0x202020, 0x808080);
public+hg@14
  1208 	SDL_Flip(screen);
public+hg@14
  1209 
public+hg@14
  1210 	stagefile_tmp = newsurface(SDL_SWSURFACE, 800, 20);
public+hg@77
  1211 	if (*metadata[3] && (temp = IMG_Load(adjust_path(metadata[3])))) {
public+hg@13
  1212 		stagefile = SDL_DisplayFormat(temp);
public+hg@13
  1213 		bicubic_interpolation(stagefile, screen);
public+hg@13
  1214 		SDL_FreeSurface(temp);
public+hg@13
  1215 		SDL_FreeSurface(stagefile);
public+hg@13
  1216 	}
public+hg@61
  1217 	if (opt_showinfo) {
public+hg@61
  1218 		for (i = 0; i < 800; ++i) {
public+hg@61
  1219 			for (j = 0; j < 42; ++j) putblendedpixel(screen, i, j, 0x101010, 64);
public+hg@61
  1220 			for (j = 580; j < 600; ++j) putblendedpixel(screen, i, j, 0x101010, 64);
public+hg@17
  1221 		}
public+hg@17
  1222 		printstr(screen, 6, 4, 2, metadata[0], 0x808080, 0xffffff);
public+hg@77
  1223 		printstr(screen, 792-8*strlen(metadata[1]), 4, 1, metadata[1], 0x808080, 0xffffff);
public+hg@77
  1224 		printstr(screen, 792-8*strlen(metadata[2]), 20, 1, metadata[2], 0x808080, 0xffffff);
public+hg@22
  1225 		i = sprintf(buf, "Level %d | BPM %.2f%s | %d note%s [%dKEY%s]",
public+hg@22
  1226 			v_playlevel, bpm, "?"+((xflag&8)==0), xnnotes,
public+hg@22
  1227 			"s"+(xnnotes==1), (xflag&1) ? 7 : 5, (xflag&2) ? "-LN" : "");
public+hg@17
  1228 		printstr(screen, 3, 582, 1, buf, 0x808080, 0xffffff);
public+hg@17
  1229 		SDL_BlitSurface(screen, newrect(0,580,800,20), stagefile_tmp, newrect(0,0,800,20));
public+hg@13
  1230 	}
public+hg@14
  1231 	SDL_Flip(screen);
public+hg@14
  1232 
public+hg@15
  1233 	t = SDL_GetTicks() + 3000;
public+hg@17
  1234 	load_resource(opt_showinfo ? callback_resource : 0);
public+hg@61
  1235 	if (opt_showinfo) {
public+hg@85
  1236 		last_flip = -1; /* force update */
public+hg@17
  1237 		callback_resource("loading...");
public+hg@17
  1238 		SDL_FreeSurface(stagefile_tmp);
public+hg@17
  1239 	}
public+hg@85
  1240 	while ((int)SDL_GetTicks() < t) check_exit();
public+hg@15
  1241 }
public+hg@15
  1242 
public+hg@61
  1243 static void play_prepare(void)
public+hg@61
  1244 {
public+hg@22
  1245 	int i, j, c;
public+hg@61
  1246 
public+hg@22
  1247 	/* panel position */
public+hg@61
  1248 	if ((xflag&4) == 0) {
public+hg@22
  1249 		tkeyleft[6] = tkeyleft[15] = -1;
public+hg@22
  1250 		tpanel1 -= tkeywidth[6] + 1;
public+hg@22
  1251 		tpanel2 += tkeywidth[15] + 1;
public+hg@22
  1252 	}
public+hg@61
  1253 	if ((xflag&1) == 0) {
public+hg@22
  1254 		tkeyleft[7] = tkeyleft[8] = tkeyleft[16] = tkeyleft[17] = -1;
public+hg@61
  1255 		for (i = 9; i < 16; ++i) {
public+hg@61
  1256 			if (i != 14 && tkeyleft[i] >= 0)
public+hg@22
  1257 				tkeyleft[i] += tkeywidth[16] + tkeywidth[17] + 2;
public+hg@61
  1258 		}
public+hg@61
  1259 		if (tkeyleft[6] > 0)
public+hg@22
  1260 			tkeyleft[6] -= tkeywidth[7] + tkeywidth[8] + 2;
public+hg@22
  1261 		tpanel1 -= tkeywidth[7] + tkeywidth[8] + 2;
public+hg@22
  1262 		tpanel2 += tkeywidth[16] + tkeywidth[17] + 2;
public+hg@22
  1263 	}
public+hg@61
  1264 	if (v_player == 1) {
public+hg@61
  1265 		for (i = 9; i < 18; ++i) tkeyleft[i] = -1;
public+hg@61
  1266 	} else if (v_player == 3) {
public+hg@61
  1267 		for (i = 9; i < 18; ++i) tkeyleft[i] += tpanel1 - tpanel2;
public+hg@22
  1268 		tpanel1 += 801 - tpanel2;
public+hg@28
  1269 	}
public+hg@61
  1270 	if (v_player % 2) {
public+hg@22
  1271 		tpanel2 = 0;
public+hg@22
  1272 		tbga = tpanel1 / 2 + 282;
public+hg@22
  1273 	}
public+hg@61
  1274 
public+hg@22
  1275 	/* sprite */
public+hg@22
  1276 	sprite = newsurface(SDL_SWSURFACE, 1200, 600);
public+hg@61
  1277 	for (i = 0; i < 18; ++i) {
public+hg@61
  1278 		if (tkeyleft[i] < 0) continue;
public+hg@61
  1279 		for (j = 140; j < 520; ++j)
public+hg@17
  1280 			SDL_FillRect(sprite, newrect(tkeyleft[i],j,tkeywidth[i],1), blend(tkeycolor[i], 0, j-140, 1000));
public+hg@61
  1281 		if (i < 9) {
public+hg@61
  1282 			for (j = 0; j*2 < tkeywidth[i]; ++j)
public+hg@28
  1283 				SDL_FillRect(sprite, newrect(800+tkeyleft[i]+j,0,tkeywidth[i]-2*j,600), blend(tkeycolor[i], 0xffffff, tkeywidth[i]-j, tkeywidth[i]));
public+hg@28
  1284 		}
public+hg@16
  1285 	}
public+hg@61
  1286 	for (j = -244; j < 556; ++j) {
public+hg@61
  1287 		for (i = -10; i < 20; ++i) {
public+hg@22
  1288 			c = (i*2+j*3+750) % 2000;
public+hg@22
  1289 			c = blend(0xc0c0c0, 0x606060, c>1000 ? 1850-c : c-150, 700);
public+hg@22
  1290 			putpixel(sprite, j+244, i+10, c);
public+hg@22
  1291 		}
public+hg@61
  1292 		for (i = -20; i < 60; ++i) {
public+hg@22
  1293 			c = (i*3+j*2+750) % 2000;
public+hg@22
  1294 			c = blend(0xc0c0c0, 0x404040, c>1000 ? 1850-c : c-150, 700);
public+hg@22
  1295 			putpixel(sprite, j+244, i+540, c);
public+hg@22
  1296 		}
public+hg@22
  1297 	}
public+hg@22
  1298 	SDL_FillRect(sprite, newrect(tpanel1+20,0,(tpanel2?tpanel2:820)-tpanel1-40,600), 0);
public+hg@61
  1299 	for (i = 0; i < 20; ++i) {
public+hg@61
  1300 		for (j = 20; j*j+i*i > 400; --j) {
public+hg@22
  1301 			putpixel(sprite, tpanel1+j, i+10, 0);
public+hg@22
  1302 			putpixel(sprite, tpanel1+j, 539-i, 0);
public+hg@61
  1303 			if (tpanel2) {
public+hg@22
  1304 				putpixel(sprite, tpanel2-j-1, i+10, 0);
public+hg@22
  1305 				putpixel(sprite, tpanel2-j-1, 539-i, 0);
public+hg@22
  1306 			}
public+hg@22
  1307 		}
public+hg@22
  1308 	}
public+hg@61
  1309 	if (!tpanel2 && !opt_mode) {
public+hg@30
  1310 		SDL_FillRect(sprite, newrect(0,584,368,16), 0x404040);
public+hg@30
  1311 		SDL_FillRect(sprite, newrect(4,588,360,8), 0);
public+hg@30
  1312 	}
public+hg@30
  1313 	SDL_FillRect(sprite, newrect(10,564,tpanel1,1), 0x404040);
public+hg@16
  1314 
public+hg@22
  1315 	/* screen */
public+hg@83
  1316 	SDL_FillRect(screen, 0, map(0));
public+hg@22
  1317 	SDL_BlitSurface(sprite, newrect(0,0,800,30), screen, newrect(0,0,0,0));
public+hg@22
  1318 	SDL_BlitSurface(sprite, newrect(0,520,800,80), screen, newrect(0,520,0,0));
public+hg@30
  1319 
public+hg@83
  1320 	/* video (if any) */
public+hg@83
  1321 	if (mpeg) {
public+hg@83
  1322 		imgres[imgmpeg] = newsurface(SDL_SWSURFACE, 256, 256);
public+hg@83
  1323 		SMPEG_enablevideo(mpeg, 1);
public+hg@83
  1324 		SMPEG_setdisplay(mpeg, imgres[imgmpeg], NULL, NULL);
public+hg@83
  1325 	}
public+hg@83
  1326 
public+hg@30
  1327 	/* configuration */
public+hg@30
  1328 	origintime = starttime = SDL_GetTicks();
public+hg@28
  1329 	targetspeed = playspeed;
public+hg@22
  1330 	Mix_AllocateChannels(128);
public+hg@61
  1331 	for (i = 0; i < 22; ++i) pcur[i] = 0;
public+hg@32
  1332 	gradefactor = 1.5 - v_rank * .25;
public+hg@15
  1333 }
public+hg@15
  1334 
public+hg@61
  1335 static double adjust_object_time(double base, double offset)
public+hg@61
  1336 {
public+hg@18
  1337 	int i = (int)(base+1)-1;
public+hg@61
  1338 	if ((i + 1 - base) * shorten[i] > offset)
public+hg@18
  1339 		return base + offset / shorten[i];
public+hg@18
  1340 	offset -= (i + 1 - base) * shorten[i];
public+hg@61
  1341 	while (shorten[++i] <= offset)
public+hg@18
  1342 		offset -= shorten[i];
public+hg@18
  1343 	return i + offset / shorten[i];
public+hg@18
  1344 }
public+hg@18
  1345 
public+hg@61
  1346 static double adjust_object_position(double base, double time)
public+hg@61
  1347 {
public+hg@18
  1348 	int i = (int)(base+1)-1, j = (int)(time+1)-1;
public+hg@18
  1349 	base = (time - j) * shorten[j] - (base - i) * shorten[i];
public+hg@61
  1350 	while (i < j) base += shorten[i++];
public+hg@18
  1351 	return base;
public+hg@16
  1352 }
public+hg@16
  1353 
public+hg@69
  1354 static void update_grade(int grade)
public+hg@69
  1355 {
public+hg@69
  1356 	++scocnt[grade];
public+hg@69
  1357 	grademode = grade;
public+hg@69
  1358 	gradetime = now + 700;
public+hg@69
  1359 
public+hg@69
  1360 	if (grade < 1) {
public+hg@69
  1361 		scombo = 0;
public+hg@85
  1362 		gauge -= 30;
public+hg@69
  1363 		poorbga = now + 600;
public+hg@69
  1364 	} else if (grade < 2) {
public+hg@69
  1365 		scombo = 0;
public+hg@85
  1366 		gauge -= 15;
public+hg@69
  1367 	} else if (grade < 3) {
public+hg@69
  1368 		/* do nothing */
public+hg@69
  1369 	} else {
public+hg@69
  1370 		++scombo;
public+hg@85
  1371 		gauge += (grade<4 ? 2 : 3) + (scombo<100 ? scombo : 100) / 50;
public+hg@69
  1372 	}
public+hg@69
  1373 
public+hg@69
  1374 	if (scombo > smaxcombo) smaxcombo = scombo;
public+hg@69
  1375 }
public+hg@69
  1376 
public+hg@61
  1377 static int play_process(void)
public+hg@61
  1378 {
public+hg@85
  1379 	int i, j, k, l, ibottom, eop;
public+hg@19
  1380 	double bottom, top, line, tmp;
public+hg@30
  1381 	char buf[99];
public+hg@15
  1382 
public+hg@61
  1383 	if (adjustspeed) {
public+hg@28
  1384 		tmp = targetspeed - playspeed;
public+hg@61
  1385 		if (-0.001 < tmp && tmp < 0.001) {
public+hg@61
  1386 			adjustspeed = 0;
public+hg@61
  1387 			playspeed = targetspeed;
public+hg@61
  1388 			for (i = 0; i < 22; ++i) prear[i] = pfront[i];
public+hg@28
  1389 		} else {
public+hg@85
  1390 			playspeed += tmp * 0.1;
public+hg@28
  1391 		}
public+hg@28
  1392 	}
public+hg@28
  1393 
public+hg@69
  1394 	now = SDL_GetTicks();
public+hg@69
  1395 	if (now < stoptime) {
public+hg@26
  1396 		bottom = startoffset;
public+hg@61
  1397 	} else if (stoptime) {
public+hg@69
  1398 		starttime = now;
public+hg@26
  1399 		stoptime = 0;
public+hg@26
  1400 		bottom = startoffset;
public+hg@26
  1401 	} else {
public+hg@69
  1402 		bottom = startoffset + (now - starttime) * bpm / startshorten / 24e4;
public+hg@26
  1403 	}
public+hg@18
  1404 	ibottom = (int)(bottom + 1) - 1;
public+hg@61
  1405 	if (bottom > -1 && startshorten != shorten[ibottom]) {
public+hg@18
  1406 		starttime += (int)((ibottom - startoffset) * 24e4 * startshorten / bpm);
public+hg@19
  1407 		startoffset = ibottom;
public+hg@18
  1408 		startshorten = shorten[ibottom];
public+hg@18
  1409 	}
public+hg@85
  1410 	line = bottom;/*adjust_object_time(bottom, 0.03/playspeed);*/
public+hg@17
  1411 	top = adjust_object_time(bottom, 1.25/playspeed);
public+hg@85
  1412 	eop = 1;
public+hg@61
  1413 	for (i = 0; i < 22; ++i) {
public+hg@73
  1414 		while (pfront[i] < nchannel[i] && channel[i][pfront[i]].time < bottom) ++pfront[i];
public+hg@73
  1415 		while (prear[i] < nchannel[i] && channel[i][prear[i]].time <= top) ++prear[i];
public+hg@73
  1416 		while (pcur[i] < nchannel[i] && channel[i][pcur[i]].time < line) {
public+hg@73
  1417 			j = channel[i][pcur[i]].index;
public+hg@61
  1418 			if (i == 18) {
public+hg@61
  1419 				if (sndres[j]) {
public+hg@32
  1420 					j = Mix_PlayChannel(-1, sndres[j], 0);
public+hg@61
  1421 					if (j >= 0) {
public+hg@61
  1422 						Mix_Volume(j, 96);
public+hg@61
  1423 						Mix_GroupChannel(j, 1);
public+hg@61
  1424 					}
public+hg@16
  1425 				}
public+hg@61
  1426 			} else if (i == 19) {
public+hg@73
  1427 				bga[channel[i][pcur[i]].type] = j;
public+hg@15
  1428 				bga_updated = 1;
public+hg@61
  1429 			} else if (i == 20) {
public+hg@73
  1430 				if (tmp = (channel[i][pcur[i]].type ? bpmtab[j] : j)) {
public+hg@69
  1431 					starttime = now;
public+hg@30
  1432 					startoffset = bottom;
public+hg@30
  1433 					bpm = tmp;
public+hg@30
  1434 				}
public+hg@61
  1435 			} else if (i == 21) {
public+hg@69
  1436 				if (now >= stoptime) stoptime = now;
public+hg@73
  1437 				if (channel[i][pcur[i]].type) {
public+hg@32
  1438 					stoptime += j;
public+hg@26
  1439 				} else {
public+hg@32
  1440 					stoptime += (int)(stoptab[j] * 1250 * startshorten / bpm);
public+hg@26
  1441 				}
public+hg@26
  1442 				startoffset = bottom;
public+hg@80
  1443 			} else if (opt_mode && channel[i][pcur[i]].type != 3/*INVNOTE*/ && sndres[j]) {
public+hg@32
  1444 				j = Mix_PlayChannel(-1, sndres[j], 0);
public+hg@61
  1445 				if (j >= 0) Mix_GroupChannel(j, 0);
public+hg@81
  1446 				score += (int)(300 * (1 + 1. * scombo / xnnotes));
public+hg@81
  1447 				update_grade(4);
public+hg@15
  1448 			}
public+hg@61
  1449 			++pcur[i];
public+hg@15
  1450 		}
public+hg@61
  1451 		if (i<18 && !opt_mode) {
public+hg@61
  1452 			for (; pcheck[i] < pcur[i]; ++pcheck[i]) {
public+hg@73
  1453 				j = channel[i][pcheck[i]].type;
public+hg@80
  1454 				if (j < 0 || j == 3/*INVNOTE*/ || (j == 0/*LNDONE*/ && !thru[i])) continue;
public+hg@73
  1455 				tmp = channel[i][pcheck[i]].time;
public+hg@32
  1456 				tmp = (line - tmp) * shorten[(int)tmp] / bpm * gradefactor;
public+hg@69
  1457 				if (tmp > 6e-4) update_grade(0); else break;
public+hg@30
  1458 			}
public+hg@85
  1459 			if (pfront[i] < nchannel[i]) eop = 0;
public+hg@30
  1460 		}
public+hg@15
  1461 	}
public+hg@15
  1462 
public+hg@61
  1463 	while (SDL_PollEvent(&event)) {
public+hg@61
  1464 		if (event.type == SDL_QUIT) {
public+hg@85
  1465 			return (eop ? 0 : -1);
public+hg@61
  1466 		} else if (event.type == SDL_KEYUP) {
public+hg@61
  1467 			if (event.key.keysym.sym == SDLK_ESCAPE) {
public+hg@85
  1468 				return (eop ? 0 : -1);
public+hg@61
  1469 			} else if (!opt_mode) {
public+hg@85
  1470 				i = keymap[event.key.keysym.sym];
public+hg@85
  1471 				if (i >= 0 && i < 18 && tkeyleft[i] >= 0) {
public+hg@85
  1472 					j = keypressed[i];
public+hg@85
  1473 					if (j > 0) --keypressed[i];
public+hg@85
  1474 					if (j == 1 && nchannel[i] && thru[i]) {
public+hg@85
  1475 						for (j = pcur[i]; channel[i][j].type != 0/*LNDONE*/; --j);
public+hg@85
  1476 						thru[i] = 0;
public+hg@85
  1477 						tmp = (channel[i][j].time - line) * shorten[(int)line] / bpm * gradefactor;
public+hg@85
  1478 						if (-6e-4 < tmp && tmp < 6e-4) {
public+hg@85
  1479 							channel[i][j].type ^= -1;
public+hg@85
  1480 						} else {
public+hg@85
  1481 							update_grade(0);
public+hg@28
  1482 						}
public+hg@28
  1483 					}
public+hg@28
  1484 				}
public+hg@16
  1485 			}
public+hg@61
  1486 		} else if (event.type == SDL_KEYDOWN) {
public+hg@85
  1487 			i = keymap[event.key.keysym.sym];
public+hg@85
  1488 			if (i == 18/*SPEED_DOWN*/) {
public+hg@61
  1489 				if (targetspeed > 20) targetspeed -= 5;
public+hg@61
  1490 				else if (targetspeed > 10) targetspeed -= 1;
public+hg@61
  1491 				else if (targetspeed > 1) targetspeed -= .5;
public+hg@61
  1492 				else if (targetspeed > .201) targetspeed -= .2;
public+hg@24
  1493 				else continue;
public+hg@28
  1494 				adjustspeed = 1;
public+hg@85
  1495 				Mix_PlayChannel(-1, beep, 0);
public+hg@85
  1496 			} else if (i == 19/*SPEED_UP*/) {
public+hg@61
  1497 				if (targetspeed < 1) targetspeed += .2;
public+hg@61
  1498 				else if (targetspeed < 10) targetspeed += .5;
public+hg@61
  1499 				else if (targetspeed < 20) targetspeed += 1;
public+hg@61
  1500 				else if (targetspeed < 95) targetspeed += 5;
public+hg@28
  1501 				else continue;
public+hg@28
  1502 				adjustspeed = 1;
public+hg@85
  1503 				Mix_PlayChannel(-1, beep, 0);
public+hg@61
  1504 			} else if (!opt_mode) {
public+hg@85
  1505 				if (i >= 0 && i < 18 && tkeyleft[i] >= 0) {
public+hg@85
  1506 					if (keypressed[i]++ || !nchannel[i]) continue;
public+hg@80
  1507 
public+hg@85
  1508 					j = (pcur[i] < 1 || (pcur[i] < nchannel[i] && channel[i][pcur[i]-1].time + channel[i][pcur[i]].time < 2*line) ? pcur[i] : pcur[i]-1);
public+hg@85
  1509 					if (sndres[channel[i][j].index]) {
public+hg@85
  1510 						l = Mix_PlayChannel(-1, sndres[channel[i][j].index], 0);
public+hg@85
  1511 						if (l >= 0) Mix_GroupChannel(l, 0);
public+hg@85
  1512 					}
public+hg@80
  1513 
public+hg@85
  1514 					if (j < pcur[i]) {
public+hg@85
  1515 						while (j >= 0 && channel[i][j].type == 3/*INVNOTE*/) --j;
public+hg@85
  1516 						if (j < 0) continue;
public+hg@85
  1517 					} else {
public+hg@85
  1518 						while (j < nchannel[i] && channel[i][j].type == 3/*INVNOTE*/) ++j;
public+hg@85
  1519 						if (j == nchannel[i]) continue;
public+hg@85
  1520 					}
public+hg@80
  1521 
public+hg@85
  1522 					if (channel[i][j].type == 0/*LNDONE*/) {
public+hg@85
  1523 						if (thru[i]) update_grade(0);
public+hg@85
  1524 					} else if (channel[i][j].type >= 0) {
public+hg@85
  1525 						tmp = (channel[i][j].time - line) * shorten[(int)line] / bpm * gradefactor;
public+hg@85
  1526 						if (tmp < 0) tmp *= -1;
public+hg@85
  1527 						if (channel[i][j].type >= 0 && tmp < 6e-4) {
public+hg@85
  1528 							if (channel[i][j].type == 1/*LNSTART*/) thru[i] = 1;
public+hg@85
  1529 							channel[i][j].type ^= -1;
public+hg@85
  1530 							score += (int)((300 - tmp * 5e5) * (1 + 1. * scombo / xnnotes));
public+hg@85
  1531 							update_grade(tmp<0.6e-4 ? 4 : tmp<2.0e-4 ? 3 : tmp<3.5e-4 ? 2 : 1);
public+hg@24
  1532 						}
public+hg@19
  1533 					}
public+hg@16
  1534 				}
public+hg@16
  1535 			}
public+hg@16
  1536 		}
public+hg@16
  1537 	}
public+hg@61
  1538 	if (bottom > length) {
public+hg@84
  1539 		if (opt_mode ? Mix_Playing(-1)==0 : Mix_GroupNewer(1)==-1) return 0;
public+hg@61
  1540 	} else if (bottom < -1) {
public+hg@28
  1541 		return 0;
public+hg@26
  1542 	}
public+hg@15
  1543 
public+hg@83
  1544 	SDL_FillRect(screen, newrect(0,30,tpanel1,490), map(0x404040));
public+hg@83
  1545 	if (tpanel2) SDL_FillRect(screen, newrect(tpanel2,30,800-tpanel2,490), map(0x404040));
public+hg@61
  1546 	for (i = 0; i < 18; ++i) {
public+hg@61
  1547 		if (tkeyleft[i] < 0) continue;
public+hg@83
  1548 		SDL_FillRect(screen, newrect(tkeyleft[i],30,tkeywidth[i],490), map(0));
public+hg@61
  1549 		if (keypressed[i]) {
public+hg@17
  1550 			SDL_BlitSurface(sprite, newrect(tkeyleft[i],140,tkeywidth[i],380), screen, newrect(tkeyleft[i],140,0,0));
public+hg@16
  1551 		}
public+hg@15
  1552 	}
public+hg@22
  1553 	SDL_SetClipRect(screen, newrect(0,30,800,490));
public+hg@61
  1554 	for (i = 0; i < 18; ++i) {
public+hg@61
  1555 		if (tkeyleft[i] < 0) continue;
public+hg@61
  1556 		for (j = pfront[i]; j < prear[i]; ++j) {
public+hg@73
  1557 			k = (int)(525 - 400 * playspeed * adjust_object_position(bottom, channel[i][j].time));
public+hg@80
  1558 			if (channel[i][j].type == 1/*LNSTART*/) {
public+hg@26
  1559 				l = k + 5;
public+hg@73
  1560 				k = (int)(530 - 400 * playspeed * adjust_object_position(bottom, channel[i][++j].time));
public+hg@61
  1561 				if (k < 30) k = 30;
public+hg@80
  1562 			} else if (channel[i][j].type == 0/*LNDONE*/) {
public+hg@26
  1563 				k += 5;
public+hg@24
  1564 				l = 520;
public+hg@80
  1565 			} else if (channel[i][j].type == 2/*NOTE*/) {
public+hg@24
  1566 				l = k + 5;
public+hg@24
  1567 			} else {
public+hg@24
  1568 				continue;
public+hg@22
  1569 			}
public+hg@61
  1570 			if (k > 0 && l > k) {
public+hg@24
  1571 				SDL_BlitSurface(sprite, newrect(800+tkeyleft[i%9],0,tkeywidth[i%9],l-k), screen, newrect(tkeyleft[i],k,0,0));
public+hg@24
  1572 			}
public+hg@24
  1573 		}
public+hg@80
  1574 		if (pfront[i]==prear[i] && prear[i]<nchannel[i] && channel[i][prear[i]].type==0/*LNDONE*/) {
public+hg@24
  1575 			SDL_BlitSurface(sprite, newrect(800+tkeyleft[i%9],0,tkeywidth[i%9],490), screen, newrect(tkeyleft[i],30,0,0));
public+hg@16
  1576 		}
public+hg@16
  1577 	}
public+hg@61
  1578 	for (i = ibottom; i < top; ++i) {
public+hg@24
  1579 		j = (int)(530 - 400 * playspeed * adjust_object_position(bottom, i));
public+hg@83
  1580 		SDL_FillRect(screen, newrect(0,j,tpanel1,1), map(0xc0c0c0));
public+hg@83
  1581 		if (tpanel2) SDL_FillRect(screen, newrect(tpanel2,j,800-tpanel2,1), map(0xc0c0c0));
public+hg@17
  1582 	}
public+hg@69
  1583 	if (now < gradetime) {
public+hg@81
  1584 		int delta = (gradetime - now - 400) / 30;
public+hg@81
  1585 		if (delta < 0) delta = 0;
public+hg@81
  1586 		printstr(screen, tpanel1/2-8*strlen(tgradestr[grademode]), 260 - delta, 2,
public+hg@77
  1587 				tgradestr[grademode], tgradecolor[grademode][0], tgradecolor[grademode][1]);
public+hg@61
  1588 		if (scombo > 1) {
public+hg@30
  1589 			i = sprintf(buf, "%d COMBO", scombo);
public+hg@81
  1590 			printstr(screen, tpanel1/2-4*i, 288 - delta, 1, buf, 0x808080, 0xffffff);
public+hg@30
  1591 		}
public+hg@81
  1592 		if (opt_mode) printstr(screen, tpanel1/2-24, 302 - delta, 1, "(AUTO)", 0x404040, 0xc0c0c0);
public+hg@61
  1593 		if (!grademode) bga_updated = 1;
public+hg@30
  1594 	}
public+hg@18
  1595 	SDL_SetClipRect(screen, 0);
public+hg@84
  1596 	if (bga_updated > 0 || (bga_updated < 0 && now >= poorbga) || (mpeg && SMPEG_status(mpeg) == SMPEG_PLAYING)) {
public+hg@83
  1597 		SDL_FillRect(screen, newrect(tbga,172,256,256), map(0));
public+hg@83
  1598 		for (i = 0; i < 3; ++i) {
public+hg@83
  1599 			if (bga_updated > 0 && bga[i] == imgmpeg && SMPEG_status(mpeg) != SMPEG_PLAYING) SMPEG_play(mpeg);
public+hg@83
  1600 		}
public+hg@69
  1601 		if (now < poorbga) {
public+hg@61
  1602 			if (bga[2] >= 0 && imgres[bga[2]])
public+hg@26
  1603 				SDL_BlitSurface(imgres[bga[2]], newrect(0,0,256,256), screen, newrect(tbga,172,0,0));
public+hg@30
  1604 			bga_updated = -1;
public+hg@26
  1605 		} else {
public+hg@61
  1606 			for (i = 0; i < 2; ++i)
public+hg@83
  1607 				if (bga[i] >= 0 && imgres[bga[i]])
public+hg@26
  1608 					SDL_BlitSurface(imgres[bga[i]], newrect(0,0,256,256), screen, newrect(tbga,172,0,0));
public+hg@26
  1609 			bga_updated = 0;
public+hg@26
  1610 		}
public+hg@15
  1611 	}
public+hg@30
  1612 
public+hg@69
  1613 	i = (now - origintime) / 1000;
public+hg@61
  1614 	j = xduration / 1000;
public+hg@30
  1615 	sprintf(buf, "SCORE %07d%c%4.1fx%c%02d:%02d / %02d:%02d%c@%9.4f%cBPM %6.2f",
public+hg@30
  1616 			score, 0, targetspeed, 0, i/60, i%60, j/60, j%60, 0, bottom, 0, bpm);
public+hg@30
  1617 	SDL_BlitSurface(sprite, newrect(0,0,800,30), screen, newrect(0,0,0,0));
public+hg@30
  1618 	SDL_BlitSurface(sprite, newrect(0,520,800,80), screen, newrect(0,520,0,0));
public+hg@30
  1619 	printstr(screen, 10, 8, 1, buf, 0, 0);
public+hg@30
  1620 	printstr(screen, 5, 522, 2, buf+14, 0, 0);
public+hg@30
  1621 	printstr(screen, tpanel1-94, 565, 1, buf+20, 0, 0x404040);
public+hg@30
  1622 	printstr(screen, 95, 538, 1, buf+34, 0, 0);
public+hg@30
  1623 	printstr(screen, 95, 522, 1, buf+45, 0, 0);
public+hg@69
  1624 	i = (now - origintime) * tpanel1 / xduration;
public+hg@32
  1625 	printchar(screen, 6+(i<tpanel1?i:tpanel1), 548, 1, -1, 0x404040, 0x404040);
public+hg@61
  1626 	if (!tpanel2 && !opt_mode) {
public+hg@61
  1627 		if (gauge > 512) gauge = 512;
public+hg@85
  1628 		k = (int)(160*startshorten*(1+bottom)) % 40; /* i.e. cycles four times per measure */
public+hg@85
  1629 		i = (gauge<0 ? 0 : (gauge*400>>9) - k);
public+hg@85
  1630 		j = (gauge>=survival ? 0xc0 : 0xc0 - k*4) << 16;
public+hg@85
  1631 		SDL_FillRect(screen, newrect(4,588,i>360?360:i<5?5:i,8), map(j));
public+hg@19
  1632 	}
public+hg@19
  1633 
public+hg@15
  1634 	SDL_Flip(screen);
public+hg@16
  1635 	return 1;
public+hg@15
  1636 }
public+hg@15
  1637 
public+hg@20
  1638 /******************************************************************************/
public+hg@20
  1639 /* entry point */
public+hg@20
  1640 
public+hg@61
  1641 static int play(void)
public+hg@61
  1642 {
public+hg@30
  1643 	int i;
public+hg@76
  1644 	char *pos1, *pos2;
public+hg@61
  1645 
public+hg@61
  1646 	if (initialize()) return 1;
public+hg@61
  1647 
public+hg@85
  1648 	if (read_bms()) die("Couldn't load BMS file: %s", bmspath);
public+hg@61
  1649 	if (v_player == 4) clone_bms();
public+hg@61
  1650 	if (opt_random) {
public+hg@61
  1651 		if (v_player == 3) {
public+hg@26
  1652 			shuffle_bms(opt_random, 0);
public+hg@26
  1653 		} else {
public+hg@26
  1654 			shuffle_bms(opt_random, 1);
public+hg@61
  1655 			if (v_player != 1) shuffle_bms(opt_random, 2);
public+hg@26
  1656 		}
public+hg@26
  1657 	}
public+hg@30
  1658 	get_bms_info();
public+hg@61
  1659 
public+hg@76
  1660 	/* get basename of bmspath */
public+hg@76
  1661 	pos1 = strrchr(bmspath, '/');
public+hg@76
  1662 	pos2 = strrchr(bmspath, '\\');
public+hg@76
  1663 	if (!pos1) pos1 = bmspath + 1;
public+hg@76
  1664 	if (!pos2) pos2 = bmspath + 1;
public+hg@76
  1665 	(pos1>pos2 ? pos1 : pos2)[1] = '\0';
public+hg@76
  1666 	if (pos1 == pos2) { /* will be pos1 = pos2 = bmspath + 1 */
public+hg@76
  1667 		bmspath[0] = '.';
public+hg@76
  1668 		bmspath[1] = sep;
public+hg@76
  1669 	}
public+hg@76
  1670 
public+hg@76
  1671 	dirinit();
public+hg@15
  1672 	play_show_stagefile();
public+hg@72
  1673 	dirfinal();
public+hg@61
  1674 
public+hg@30
  1675 	xduration = get_bms_duration();
public+hg@15
  1676 	play_prepare();
public+hg@61
  1677 	while ((i = play_process()) > 0);
public+hg@61
  1678 
public+hg@61
  1679 	if (!opt_mode && i == 0) {
public+hg@85
  1680 		if (gauge >= survival) {
public+hg@30
  1681 			printf("*** CLEARED! ***\n");
public+hg@61
  1682 			for (i = 4; i >= 0; --i)
public+hg@30
  1683 				printf("%-5s %4d    %s", tgradestr[i], scocnt[i], "\n"+(i!=2));
public+hg@30
  1684 			printf("MAX COMBO %d\nSCORE %07d (max %07d)\n", smaxcombo, score, xscore);
public+hg@30
  1685 		} else {
public+hg@30
  1686 			printf("YOU FAILED!\n");
public+hg@30
  1687 		}
public+hg@30
  1688 	}
public+hg@61
  1689 
public+hg@30
  1690 	return 0;
public+hg@17
  1691 }
public+hg@15
  1692 
public+hg@85
  1693 int usage(void)
public+hg@61
  1694 {
public+hg@85
  1695 	fprintf(stderr,
public+hg@85
  1696 		"%s -- the simple BMS player\n"
public+hg@85
  1697 		"http://mearie.org/projects/angolmois/\n\n"
public+hg@85
  1698 		"Usage: %s <options> <path>\n"
public+hg@85
  1699 		"  Accepts any BMS, BME or BML file.\n"
public+hg@85
  1700 		"  Resources should be in the same directory as the BMS file.\n\n"
public+hg@85
  1701 		"Options:\n"
public+hg@85
  1702 		"  -h, --help            This help\n"
public+hg@85
  1703 		"  -V, --version         Shows the version\n"
public+hg@85
  1704 		"  -a #.#, --speed #.#   Sets the initial play speed (default: 1.0x)\n"
public+hg@85
  1705 		"  -#                    Same as '-a #.0'\n"
public+hg@85
  1706 		"  -v, --autoplay        Enables AUTO PLAY (viewer) mode\n"
public+hg@85
  1707 		"  --fullscreen          Enables the fullscreen mode (default)\n"
public+hg@85
  1708 		"  -w, --no-fullscreen   Disables the fullscreen mode\n"
public+hg@85
  1709 		"  --info                Shows a brief information about the song (default)\n"
public+hg@85
  1710 		"  -q, --no-info         Do not show an information about the song\n"
public+hg@85
  1711 		"  -m, --mirror          Uses a mirror modifier\n"
public+hg@85
  1712 		"  -r, --random          Uses a random modifier\n"
public+hg@85
  1713 		"  -R, --random-ex       Uses a random modifier, even for scratches\n"
public+hg@85
  1714 		"  -s, --srandom         Uses a super-random modifier\n"
public+hg@85
  1715 		"  -S, --srandom-ex      Uses a super-random modifier, even for scratches\n"
public+hg@85
  1716 		"  --bga                 Loads and shows the BGA (default)\n"
public+hg@85
  1717 		"  -B, --no-bga          Do not load and show the BGA\n"
public+hg@85
  1718 		"  -M, --no-movie        Do not load and show the BGA movie\n\n"
public+hg@85
  1719 		"Environment Variables:\n"
public+hg@85
  1720 		"  ANGOLMOIS_1P_KEYS=<1>|<2>|<3>|<4>|<5>|<scratch>|<pedal>|<6>|<7>\n"
public+hg@85
  1721 		"  ANGOLMOIS_2P_KEYS=<1>|<2>|<3>|<4>|<5>|<scratch>|<pedal>|<6>|<7>\n"
public+hg@85
  1722 		"  ANGOLMOIS_SPEED_KEYS=<speed down>|<speed up>\n"
public+hg@85
  1723 		"    Specifies the keys used for gameplay. Key names should follow them of\n"
public+hg@85
  1724 		"    SDL (e.g. 'a', 'right shift' etc.). The mapping for 1P/2P is as follows:\n"
public+hg@85
  1725 		"                   <2> <4> <6>\n"
public+hg@85
  1726 		"      <scratch>  <1> <3> <5> <7>  <pedal>\n"
public+hg@85
  1727 		"    One can map multiple keys by separating key names with '%%'.\n"
public+hg@85
  1728 		"    The default mapping is to use zsxdcfv and mk,l.;/ for 1P and 2P,\n"
public+hg@85
  1729 		"    respectively. F3 and F4 is used for speed adjustment.\n\n",
public+hg@85
  1730 		VERSION, argv0);
public+hg@85
  1731 	return 1;
public+hg@13
  1732 }
public+hg@13
  1733 
public+hg@61
  1734 int main(int argc, char **argv)
public+hg@61
  1735 {
public+hg@85
  1736 	static char *longargs[] =
public+hg@85
  1737 		{"h--help", "V--version", "a--speed", "v--autoplay", "w--windowed",
public+hg@85
  1738 		 "w--no-fullscreen", " --fullscreen", " --info", "q--no-info", "m--mirror",
public+hg@85
  1739 		 "r--random", "R--random-ex", "s--srandom", "S--srandom-ex", " --bga",
public+hg@85
  1740 		 "B--no-bga", " --movie", "M--no-movie", NULL};
public+hg@61
  1741 	char buf[512]={0};
public+hg@85
  1742 	int i, j, cont;
public+hg@24
  1743 
public+hg@85
  1744 	argv0 = argv[0];
public+hg@85
  1745 	for (i = 1; argv[i]; ++i) {
public+hg@85
  1746 		if (argv[i][0] != '-') {
public+hg@85
  1747 			if (!bmspath) bmspath = argv[i];
public+hg@85
  1748 		} else if (!strcmp(argv[i], "--")) {
public+hg@85
  1749 			if (!bmspath) bmspath = argv[++i];
public+hg@85
  1750 			break; 
public+hg@85
  1751 		} else {
public+hg@85
  1752 			if (argv[i][1] == '-') {
public+hg@85
  1753 				for (j = 0; longargs[j]; ++j) {
public+hg@85
  1754 					if (!strcmp(argv[i], longargs[j]+1)) {
public+hg@85
  1755 						argv[i][1] = longargs[j][0];
public+hg@85
  1756 						argv[i][2] = '\0';
public+hg@85
  1757 						break;
public+hg@85
  1758 					}
public+hg@85
  1759 				}
public+hg@85
  1760 				if (!longargs[j]) die("Invalid option: %s", argv[i]);
public+hg@85
  1761 			}
public+hg@85
  1762 			for (j = cont = 1; cont; ++j) {
public+hg@85
  1763 				switch (argv[i][j]) {
public+hg@85
  1764 				case 'h': case 'V': usage(); exit(1);
public+hg@85
  1765 				case 'v': opt_mode = 1; break;
public+hg@85
  1766 				case 'w': opt_fullscreen = 0; break;
public+hg@85
  1767 				case 'q': opt_showinfo = 0; break;
public+hg@85
  1768 				case 'm': opt_random = 1; break;
public+hg@85
  1769 				case 's': opt_random = 2; break;
public+hg@85
  1770 				case 'S': opt_random = 3; break;
public+hg@85
  1771 				case 'r': opt_random = 4; break;
public+hg@85
  1772 				case 'R': opt_random = 5; break;
public+hg@85
  1773 				case 'a':
public+hg@85
  1774 					playspeed = atof(argv[i][++j] ? argv[i]+j : argv[++i]);
public+hg@85
  1775 					if (playspeed <= 0) playspeed = 1;
public+hg@85
  1776 					if (playspeed < .1) playspeed = .1;
public+hg@85
  1777 					if (playspeed > 99) playspeed = 99;
public+hg@85
  1778 				case 'B': opt_bga = 2; break;
public+hg@85
  1779 				case 'M': opt_bga = 1; break;
public+hg@85
  1780 				case '\0': cont = 0;
public+hg@85
  1781 				case ' ': break;
public+hg@85
  1782 				default:
public+hg@85
  1783 					if (argv[i][j] >= '1' && argv[i][j] <= '9') {
public+hg@85
  1784 						playspeed = argv[i][j] - '0';
public+hg@85
  1785 					} else {
public+hg@85
  1786 						die("Invalid option: -%c", argv[i][j]);
public+hg@85
  1787 					}
public+hg@85
  1788 				}
public+hg@85
  1789 			}
public+hg@17
  1790 		}
public+hg@17
  1791 	}
public+hg@61
  1792 
public+hg@85
  1793 	if (!bmspath && filedialog(buf)) bmspath = buf;
public+hg@85
  1794 	return bmspath ? play() : usage();
public+hg@0
  1795 }
public+hg@0
  1796 
public+hg@0
  1797 /* vim: set ts=4 sw=4: */

Powered by Mercurial