void hmp2mid(char *hmp_name, unsigned char **midbuf, unsigned int *midlen) { int mi, i; short ms, time_div = 0xC0; hmp_file *hmp=NULL; hmp = hmp_open(hmp_name); if (hmp == NULL) return; *midlen = 0; time_div = hmp->tempo*1.6; // write MIDI-header *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + 4); memcpy(&(*midbuf)[*midlen], "MThd", 4); *midlen += 4; mi = MIDIINT(6); *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + sizeof(mi)); memcpy(&(*midbuf)[*midlen], &mi, sizeof(mi)); *midlen += sizeof(mi); ms = MIDISHORT(1); *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + sizeof(ms)); memcpy(&(*midbuf)[*midlen], &ms, sizeof(ms)); *midlen += sizeof(ms); ms = MIDISHORT(hmp->num_trks); *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + sizeof(ms)); memcpy(&(*midbuf)[*midlen], &ms, sizeof(ms)); *midlen += sizeof(ms); ms = MIDISHORT(time_div); *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + sizeof(ms)); memcpy(&(*midbuf)[*midlen], &ms, sizeof(ms)); *midlen += sizeof(ms); *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + sizeof(tempo)); memcpy(&(*midbuf)[*midlen], &tempo, sizeof(tempo)); *midlen += sizeof(tempo); // tracks for (i = 1; i < hmp->num_trks; i++) { int midtrklenpos = 0; *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + 4); memcpy(&(*midbuf)[*midlen], "MTrk", 4); *midlen += 4; midtrklenpos = *midlen; mi = 0; *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + sizeof(mi)); *midlen += sizeof(mi); mi = hmptrk2mid(hmp->trks[i].data, hmp->trks[i].len, midbuf, midlen); mi = MIDIINT(mi); memcpy(&(*midbuf)[midtrklenpos], &mi, 4); } hmp_close(hmp); }
d_define_method(emitter, embed_parameter)(struct s_object *self, const char *id, void *parameter) { struct s_signal *signal; void **new_parameters; if ((signal = d_call(self, m_emitter_get, id))) { signal->parameters_size++; if ((new_parameters = (void **) d_realloc(signal->parameters, (signal->parameters_size*sizeof(void *))))) { signal->parameters = new_parameters; signal->parameters[signal->parameters_size-1] = parameter; } } return (void *)signal; }
int gr_set_mode(u_int32_t mode) { unsigned int w, h; char *gr_bm_data; if (mode<=0) return 0; w=SM_W(mode); h=SM_H(mode); if (!gr_check_mode(mode)) { con_printf(CON_URGENT,"Cannot set %ix%i. Fallback to 640x480\n",w,h); w=640; h=480; Game_screen_mode=mode=SM(w,h); } gr_bm_data=(char *)grd_curscreen->sc_canvas.cv_bitmap.bm_data;//since we use realloc, we want to keep this pointer around. memset( grd_curscreen, 0, sizeof(grs_screen)); grd_curscreen->sc_mode = mode; grd_curscreen->sc_w = w; grd_curscreen->sc_h = h; grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*GameCfg.AspectX,grd_curscreen->sc_h*GameCfg.AspectY); gr_init_canvas(&grd_curscreen->sc_canvas, d_realloc(gr_bm_data,w*h), BM_OGL, w, h); gr_set_current_canvas(NULL); ogl_init_window(w,h);//platform specific code ogl_get_verinfo(); OGL_VIEWPORT(0,0,w,h); ogl_init_state(); gamefont_choose_game_font(w,h); gr_remap_color_fonts(); gr_remap_mono_fonts(); return 0; }
d_define_method(label, set_content_char)(struct s_object *self, char *string_content, TTF_Font *font, struct s_object *environment) { d_using(label); size_t string_length = f_string_strlen(string_content); if (string_length > 0) { if (label_attributes->string_content) { /* realloc only if really needed */ if (label_attributes->size < (string_length+1)) { if ((label_attributes->string_content = (char *)d_realloc(label_attributes->string_content, (string_length+1)))) label_attributes->size = (string_length+1); else d_die(d_error_malloc); } } else if ((label_attributes->string_content = (char *)d_malloc(string_length+1))) label_attributes->size = (string_length+1); else d_die(d_error_malloc); strncpy(label_attributes->string_content, string_content, string_length); label_attributes->string_content[string_length] = '\0'; } else if (label_attributes->string_content) memset(label_attributes->string_content, '\0', label_attributes->size); p_label_update_texture(self, font, environment); return self; }
d_define_method(stream, read_string)(struct s_object *self, struct s_object *string_supplied, size_t size) { d_using(stream); struct s_string_attributes *string_attributes = NULL; char character, buffer[d_stream_block_size]; size_t readed_local = 0; int tail = d_true; if ((stream_attributes->flags&e_stream_flag_opened) == e_stream_flag_opened) { if (((stream_attributes->parameters&O_RDWR) == O_RDWR) || ((stream_attributes->parameters&O_RDONLY) == O_RDONLY)) { while ((readed_local < size) && (read(stream_attributes->descriptor, &character, 1) > 0)) { tail = d_false; if ((character != '\n') && (character != '\0')) buffer[readed_local++] = character; else break; } if (!tail) { buffer[readed_local] = '\0'; if (!string_supplied) { string_supplied = f_string_new_size(d_new(string), buffer, (readed_local + 1)); } else { string_attributes = d_cast(string_supplied, string); if (string_attributes->size < (readed_local + 1)) { string_attributes->content = d_realloc(string_attributes->content, (readed_local + 1)); string_attributes->length = (readed_local + 1); } strncpy(string_attributes->content, buffer, readed_local); string_attributes->content[readed_local] = '\0'; string_attributes->length = readed_local; } } else string_supplied = NULL; } else d_throw(v_exception_unsupported, "read in a write-only stream exception"); } else d_throw(v_exception_closed, "read in a closed stream exception"); return string_supplied; }
// Set up everything for our music // NOTE: you might think this is done once per runtime but it's not! It's done for EACH song so that each mission can have it's own descent.sng structure. We COULD optimize that by only doing this once per mission. void songs_init() { int i = 0; char inputline[80+1]; PHYSFS_file * fp = NULL; char sng_file[PATH_MAX]; Songs_initialized = 0; if (BIMSongs != NULL) d_free(BIMSongs); memset(sng_file, '\0', sizeof(sng_file)); if (Current_mission != NULL) // try MISSION_NAME.sngdxx - might be rarely used but handy if you want a songfile for a specific mission outside of the mission hog file. use special extension to not crash with other ports of the game { snprintf(sng_file, strlen(Current_mission_filename)+8, "%s.sngdxx", Current_mission_filename); fp = PHYSFSX_openReadBuffered(sng_file); } if (fp == NULL) // try descent.sngdxx - a songfile specifically for dxx which level authors CAN use (dxx does not care if descent.sng contains MP3/OGG/etc. as well) besides the normal descent.sng containing files other versions of the game cannot play. this way a mission can contain a DOS-Descent compatible OST (hmp files) as well as a OST using MP3, OGG, etc. fp = PHYSFSX_openReadBuffered( "descent.sngdxx" ); if (fp == NULL) // try to open regular descent.sng fp = PHYSFSX_openReadBuffered( "descent.sng" ); if ( fp == NULL ) // No descent.sng available. Define a default song-set { int predef=30; // define 30 songs - period MALLOC(BIMSongs, bim_song_info, predef); if (!BIMSongs) return; strncpy(BIMSongs[SONG_TITLE].filename, "descent.hmp",sizeof(BIMSongs[SONG_TITLE].filename)); strncpy(BIMSongs[SONG_BRIEFING].filename, "briefing.hmp",sizeof(BIMSongs[SONG_BRIEFING].filename)); strncpy(BIMSongs[SONG_CREDITS].filename, "credits.hmp",sizeof(BIMSongs[SONG_CREDITS].filename)); strncpy(BIMSongs[SONG_ENDLEVEL].filename, "endlevel.hmp",sizeof(BIMSongs[SONG_ENDLEVEL].filename)); // can't find it? give a warning strncpy(BIMSongs[SONG_ENDGAME].filename, "endgame.hmp",sizeof(BIMSongs[SONG_ENDGAME].filename)); // ditto for (i = SONG_FIRST_LEVEL_SONG; i < predef; i++) { snprintf(BIMSongs[i].filename, sizeof(BIMSongs[i].filename), "game%02d.hmp", i - SONG_FIRST_LEVEL_SONG + 1); if (!PHYSFSX_exists(BIMSongs[i].filename,1)) snprintf(BIMSongs[i].filename, sizeof(BIMSongs[i].filename), "game%d.hmp", i - SONG_FIRST_LEVEL_SONG); if (!PHYSFSX_exists(BIMSongs[i].filename,1)) { memset(BIMSongs[i].filename, '\0', sizeof(BIMSongs[i].filename)); // music not available break; } } } else { while (!PHYSFS_eof(fp)) { PHYSFSX_fgets(inputline, 80, fp ); if ( strlen( inputline ) ) { BIMSongs = d_realloc(BIMSongs, sizeof(bim_song_info)*(i+1)); memset(BIMSongs[i].filename, '\0', sizeof(BIMSongs[i].filename)); sscanf( inputline, "%15s", BIMSongs[i].filename ); if (strrchr(BIMSongs[i].filename, '.')) if (!stricmp(strrchr(BIMSongs[i].filename, '.'), ".hmp") || !stricmp(strrchr(BIMSongs[i].filename, '.'), ".mp3") || !stricmp(strrchr(BIMSongs[i].filename, '.'), ".ogg") || !stricmp(strrchr(BIMSongs[i].filename, '.'), ".aif") || !stricmp(strrchr(BIMSongs[i].filename, '.'), ".mid") || !stricmp(strrchr(BIMSongs[i].filename, '.'), ".flac") ) i++; } } // HACK: If Descent.hog is patched from 1.0 to 1.5, descent.sng is turncated. So let's patch it up here if (i==12 && PHYSFSX_fsize("descent.sng")==422) { BIMSongs = d_realloc(BIMSongs, sizeof(bim_song_info)*(i+15)); for (i = 12; i <= 26; i++) snprintf(BIMSongs[i].filename, sizeof(BIMSongs[i].filename), "game%02d.hmp", i-4); } } Num_bim_songs = i; Songs_initialized = 1; if (fp != NULL) PHYSFS_close(fp); if (GameArg.SndNoMusic) GameCfg.MusicType = MUSIC_TYPE_NONE; // If SDL_Mixer is not supported (or deactivated), switch to no-music type if SDL_mixer-related music type was selected #ifdef USE_SDLMIXER if (GameArg.SndDisableSdlMixer) #else if (1) #endif { #ifndef _WIN32 if (GameCfg.MusicType == MUSIC_TYPE_BUILTIN) GameCfg.MusicType = MUSIC_TYPE_NONE; #endif if (GameCfg.MusicType == MUSIC_TYPE_CUSTOM) GameCfg.MusicType = MUSIC_TYPE_NONE; } if (GameCfg.MusicType == MUSIC_TYPE_REDBOOK) RBAInit(); #ifdef USE_SDLMIXER else if (GameCfg.MusicType == MUSIC_TYPE_CUSTOM) jukebox_load(); #endif songs_set_volume(GameCfg.MusicVolume); }
int mix_play_file(char *filename, int loop, void (*hook_finished_track)()) { SDL_RWops *rw = NULL; PHYSFS_file *filehandle = NULL; char full_path[PATH_MAX]; char *fptr; unsigned int bufsize = 0; mix_free_music(); // stop and free what we're already playing, if anything fptr = strrchr(filename, '.'); if (fptr == NULL) return 0; // It's a .hmp! if (!d_stricmp(fptr, ".hmp")) { hmp2mid(filename, ¤t_music_hndlbuf, &bufsize); rw = SDL_RWFromConstMem(current_music_hndlbuf,bufsize*sizeof(char)); current_music = Mix_LoadMUS_RW(rw); } // try loading music via given filename if (!current_music) current_music = Mix_LoadMUS(filename); // allow the shell convention tilde character to mean the user's home folder // chiefly used for default jukebox level song music referenced in 'descent.m3u' for Mac OS X if (!current_music && *filename == '~') { snprintf(full_path, PATH_MAX, "%s%s", PHYSFS_getUserDir(), &filename[1 + (!strncmp(&filename[1], PHYSFS_getDirSeparator(), strlen(PHYSFS_getDirSeparator())) ? strlen(PHYSFS_getDirSeparator()) : 0)]); current_music = Mix_LoadMUS(full_path); if (current_music) filename = full_path; // used later for possible error reporting } // no luck. so it might be in Searchpath. So try to build absolute path if (!current_music) { PHYSFSX_getRealPath(filename, full_path); current_music = Mix_LoadMUS(full_path); if (current_music) filename = full_path; // used later for possible error reporting } // still nothin'? Let's open via PhysFS in case it's located inside an archive if (!current_music) { filehandle = PHYSFS_openRead(filename); if (filehandle != NULL) { current_music_hndlbuf = d_realloc(current_music_hndlbuf, sizeof(char *)*PHYSFS_fileLength(filehandle)); bufsize = PHYSFS_read(filehandle, current_music_hndlbuf, sizeof(char), PHYSFS_fileLength(filehandle)); rw = SDL_RWFromConstMem(current_music_hndlbuf,bufsize*sizeof(char)); PHYSFS_close(filehandle); current_music = Mix_LoadMUS_RW(rw); } } if (current_music) { Mix_PlayMusic(current_music, (loop ? -1 : 1)); Mix_HookMusicFinished(hook_finished_track ? hook_finished_track : mix_free_music); return 1; } else { con_printf(CON_CRITICAL,"Music %s could not be loaded: %s\n", filename, Mix_GetError()); mix_stop_music(); } return 0; }
void play_hmi (void * arg) { int i; int pos = 0x308; int n_chunks = 0; int low_dtime; int low_chunk; int csec, lcsec; int qid; int ipc_read = 0; int k=0; struct msgbuf *rcv; Track_info *t_info; con_printf(CON_DEBUG,"play_hmi\n"); stop = 0; ipc_read=0; rcv=d_malloc(sizeof(long) + 16); rcv->mtype=1; rcv->mtext[0]='0'; qid=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's', 0660); if(qid == -1) { return; } do { ipc_read=do_ipc(qid,rcv,0); } while(rcv->mtext[0] != 'p'); stop=0; rcv->mtext[0] = '0'; seq_init(); n_chunks=data[0x30]; t_info = d_malloc(sizeof(Track_info)*n_chunks); while(1) { for(i=0;i<n_chunks;i++) { t_info[i].position = pos + 12; t_info[i].status = PLAYING; t_info[i].time = get_dtime(data,&t_info[i].position); pos += (( (0xff & data[pos + 5]) << 8 ) + (0xff & data[pos + 4])); } lcsec = 0; SEQ_START_TIMER(); do { low_chunk = -1; k++; i=0; do { if (t_info[i].status == PLAYING) low_chunk = i; i++; } while((low_chunk <=0) && (i<n_chunks)); if (low_chunk == -1) break; low_dtime = t_info[low_chunk].time; for(i=1;i<n_chunks;i++) { if ((t_info[i].time < low_dtime) && (t_info[i].status == PLAYING)) { low_dtime = t_info[i].time; low_chunk = i; } } if (low_dtime < 0) con_printf(CON_URGENT,"Serious warning: d_time negative!!!!!!\n"); csec = 0.86 * low_dtime; //flush sequencer buffer after 20 events if (k == 20) { ioctl(seqfd, SNDCTL_SEQ_SYNC); k = 0; } #ifdef WANT_AWE32 cut_trough(); #endif if (csec != lcsec) { SEQ_WAIT_TIME(csec); } lcsec = csec; t_info[low_chunk].status = do_track_event(data,&t_info[low_chunk].position); if (t_info[low_chunk].status == 3) { con_printf(CON_URGENT,"Error playing data in chunk %d\n",low_chunk); t_info[low_chunk].status = STOPPED; } if (t_info[low_chunk].status == PLAYING) t_info[low_chunk].time += get_dtime(data,&t_info[low_chunk].position); //Check if the song has reached the end stop = t_info[0].status; for(i=1;i<n_chunks;i++) stop &= t_info[i].status; // ZICO - since we don't seem to have a real repeat call we need a hack // endlevel song does change rephmi to 0 while endlevel. endlevel song takes about 1950 csec till it's finished if (!rephmi && csec > 1950) send_ipc("s"); if((do_ipc(qid,rcv,IPC_NOWAIT) > 0) && (rcv->mtext[0]=='p')) { n_chunks=data[0x30]; t_info = d_realloc(t_info,sizeof(Track_info)*n_chunks); stop = 1; rcv->mtext[0] = '0'; stop_all(); } } while(!stop); SEQ_STOP_TIMER(); if( stop == 2) { stop_all(); do { ipc_read=do_ipc(qid,rcv,0); } while(rcv->mtext[0] != 'p'); rcv->mtext[0] = '0'; n_chunks=data[0x30]; t_info = d_realloc(t_info,sizeof(Track_info)*n_chunks); stop = 0; } pos=0x308; } d_free(data); d_free(t_info); d_free(rcv); }
int do_ipc(int qid, struct msgbuf *buf, int flags) { int ipc_read; CFILE *fptr = NULL; float last_volume = volume; int l=0; ipc_read = msgrcv(qid,buf,16,0,flags | MSG_NOERROR); switch (ipc_read) { case -1: if (errno == ENOMSG) break; perror("IPC trouble"); break; case 0: break; default: con_printf(CON_DEBUG,"do_ipc %s\n", buf->mtext);//##########3 switch (buf->mtext[0]) { case 'v': volume = (double)(atof(buf->mtext + 1) / 128.0); con_printf(CON_DEBUG,"vol %f->%f\n", last_volume, volume); if (last_volume <= 0 && volume > 0) { buf->mtext[0] = 'p'; // start playing again if volume raised above 0 strcpy(buf->mtext + 1, digi_last_midi_song); // fall through to case 'p' } else if (last_volume > 0 && volume <= 0) { strcpy(buf->mtext, "s"); // stop playing if volume reduced to 0 stop = 2; break; } else break; case 'p': if (buf->mtext[1]) { strcpy(digi_last_midi_song, buf->mtext + 1); if (volume > 0) fptr = cfopen((buf->mtext + 1), "rb"); } if(fptr != NULL) { l = cfilelength(fptr); data=d_realloc(data,(size_t) l); cfread(data, l, 1, fptr); cfclose(fptr); con_printf(CON_DEBUG, "good. fpr=%p l=%i data=%p\n", fptr, l, data);//##########3 stop = 0; } else { strcpy(buf->mtext, "s"); // not playing, thus "stop". stop = 2; } break; case 's': stop = 2; break; case 'q': break; } } return ipc_read; }
static unsigned int hmptrk2mid(ubyte* data, int size, unsigned char **midbuf, unsigned int *midlen) { ubyte *dptr = data; ubyte lc1 = 0,last_com = 0; uint d; int n1, n2; unsigned int offset = *midlen; while (data < dptr + size) { if (data[0] & 0x80) { ubyte b = (data[0] & 0x7F); *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + 1); memcpy(&(*midbuf)[*midlen], &b, 1); *midlen += 1; } else { d = (data[0] & 0x7F); n1 = 0; while ((data[n1] & 0x80) == 0) { n1++; d += (data[n1] & 0x7F) << (n1 * 7); } n1 = 1; while ((data[n1] & 0x80) == 0) { n1++; if (n1 == 4) return 0; } for(n2 = 0; n2 <= n1; n2++) { ubyte b = (data[n1 - n2] & 0x7F); if (n2 != n1) b |= 0x80; *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + 1); memcpy(&(*midbuf)[*midlen], &b, 1); *midlen += 1; } data += n1; } data++; if (*data == 0xFF) { //meta? *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + 3 + data[2]); memcpy(&(*midbuf)[*midlen], data, 3 + data[2]); *midlen += 3 + data[2]; if (data[1] == 0x2F) break; } else { lc1=data[0] ; if ((lc1&0x80) == 0) return 0; switch (lc1 & 0xF0) { case 0x80: case 0x90: case 0xA0: case 0xB0: case 0xE0: if (lc1 != last_com) { *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + 1); memcpy(&(*midbuf)[*midlen], &lc1, 1); *midlen += 1; } *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + 2); memcpy(&(*midbuf)[*midlen], data + 1, 2); *midlen += 2; data += 3; break; case 0xC0: case 0xD0: if (lc1 != last_com) { *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + 1); memcpy(&(*midbuf)[*midlen], &lc1, 1); *midlen += 1; } *midbuf = (unsigned char *) d_realloc(*midbuf, *midlen + 1); memcpy(&(*midbuf)[*midlen], data + 1, 1); *midlen += 1; data += 2; break; default: return 0; } last_com = lc1; } } return (*midlen - offset); }