#include #include #include #include #include #include "Input.h" #include "Output.h" #include "psxdev/bs.h" #include "generic.h" #include "cdutils.h" #include "psxdev/xadecode.h" #include "Main.h" /* From the documentation: 32 bytes header: StSTATUS : 2 bytes 0 StTYPE : 2 bytes 2 StSECTOR_OFFSET: 2 bytes 4 StSECTOR_SIZE : 2 bytes 6 StFRAME_NO : 4 bytes 10 StFRAME_SIZE : 4 bytes 14 StMOVIE_WIDTH : 2 bytes 16 StMOVIE_HEIGHT : 2 bytes 18 StMOVIE_HEADM : 4 bytes 22 StMOVIE_HEADV : 4 bytes 26 Channels : 2 bytes 30 */ struct STR_Header { Uint16 StSTATUS; Uint16 StTYPE; Uint16 StSECTOR_OFFSET; Uint16 StSECTOR_SIZE; Uint32 StFRAME_NO; Uint32 StFRAME_SIZE; Uint16 StMOVIE_WIDTH; Uint16 StMOVIE_HEIGHT; Uint32 StMOVIE_HEADM; Uint32 StMOVIE_HEADV; Uint16 Channels; } PACKED; Byte * video = 0, * audio = 0, * audio2 = 0, * tbuffer = 0; int channel = -1; int width, height; SDL_Surface * screen = 0; Uint8 bpp; int32 audio_len = 0, audio_len2 = 0; Uint8 *audio_pos; void mixaudio(void *unused, Uint8 *stream, int len) { /* Only play if we have data left */ if ( audio_len == 0 ) return; /* Mix as much data as possible */ len = ( len > audio_len ? audio_len : len ); SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME); audio_pos += len; audio_len -= len; } CODE_BEGINS int process_one_sector(Handle * f) { Byte sector[2336]; STR_Header * h; if (!f->read(sector, 2336)) return 0; h = (STR_Header *) ((Byte *) sector + 8); #ifdef CHATTING printm(M_INFO, "SubHeader: FN = %x, CN = %x, SM = %x, CI = %x: ", sector[0], sector[1], sector[2], sector[3]); printm(M_BARE, "SubHeader FN : %x\n", sector[0]); printm(M_BARE, "SubHeader CN : %x\n", sector[1]); printm(M_BARE, "SubHeader SM : %x\n", sector[2]); printm(M_BARE, "SubHeader CI : %x\n", sector[3]); #endif if ((channel != -1) && (channel != sector[1])) return -1; if ((sector[2] == 0x48) || (sector[2] == 0x42) || ((sector[2] == 8) && (sector[14] == 8))) { #ifdef CHATTING printm(M_BARE, "Video sector\n"); printm(M_BARE, "Status : %04x\n", h->StSTATUS); printm(M_BARE, "Type : %04x\n", h->StTYPE); printm(M_BARE, "Sector Offset: %i\n", h->StSECTOR_OFFSET); printm(M_BARE, "Sector Size : %i\n", h->StSECTOR_SIZE); printm(M_BARE, "Frame Number : %i\n", h->StFRAME_NO); printm(M_BARE, "Frame Size : %i\n", h->StFRAME_SIZE); printm(M_BARE, "Movie Width : %i\n", h->StMOVIE_WIDTH); printm(M_BARE, "Movie Height : %i\n", h->StMOVIE_HEIGHT); printm(M_BARE, "Movie HeadM : %08x\n", h->StMOVIE_HEADM); printm(M_BARE, "Movie HeadV : %08x\n", h->StMOVIE_HEADV); printm(M_BARE, "Channels : %04x\n", h->Channels); #endif if (h->StSECTOR_OFFSET == 0) { bs_init(); video = (Byte *) malloc(h->StSECTOR_SIZE * 2016); if (!screen) { width = h->StMOVIE_WIDTH; height = h->StMOVIE_HEIGHT; screen = SDL_SetVideoMode(width, height, 24, SDL_HWSURFACE | SDL_DOUBLEBUF); if (!screen) { printm(M_ERROR, "Couldn't get framebuffer\n"); exit(-1); } bpp = screen->format->BytesPerPixel; } } memcpy(video + h->StSECTOR_OFFSET * 2016, sector + 40, 2016); if (h->StSECTOR_SIZE == (h->StSECTOR_OFFSET + 1)) { // Frame finished. #ifdef CHATTING printm(M_BARE, "End of Frame.\n"); #endif Uint8 * buffer = ((Uint8 *) screen->pixels); if (SDL_MUSTLOCK(screen)) if (SDL_LockSurface(screen) < 0) exit(1); #ifdef CHATTING printm(M_BARE, "Width: %i, Height: %i - bpp: %i\n", width, height, bpp); #endif memset(video + h->StFRAME_SIZE, 0, h->StSECTOR_SIZE * 2016 - h->StFRAME_SIZE); #ifdef DUMPING String fn; fn.set("frame-%04i.bs", h->StFRAME_NO); Output * tf = new Output(fn); tf->write(video, h->StFRAME_SIZE); delete tf; #endif bs_decode_rgb24(buffer, (bs_header_t *) video, width, height, 0); // fwrite(screen->pixels, 3, width * height, stdout); if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); SDL_Flip(screen); free(video); } } else if (sector[2] == 0x64) { int locked = 0; SoundSector * buffer = (SoundSector *) sector; #ifdef CHATTING printm(M_BARE, "Audio sector\n"); printm(M_BARE, "Frequency: %i\n", xahalfhz(buffer) ? 18900 : 37800); printm(M_BARE, "Channels : %s\n", xastereo(buffer) ? "stereo" : "mono"); #endif // fwrite(sector + 8, 1, 2324, stdout); while (audio_len > 0) { SDL_Delay(1); } if (!audio2) { SDL_AudioSpec fmt; /* Un son sereo de 16 bits à 44kHz */ fmt.freq = xahalfhz(buffer) ? 18900 : 37800; fmt.format = AUDIO_S16; fmt.channels = xastereo(buffer) ? 2 : 1; fmt.samples = 128; /*Une bonne valeur pour les jeux */ fmt.callback = mixaudio; fmt.userdata = NULL; /* Ouvre le contexte audio et joue le son */ if (SDL_OpenAudio(&fmt, NULL) < 0) { fprintf(stderr, "Impossible d'accéder à l'audio: %s\n", SDL_GetError()); exit(1); } initXaDecode(); } else { if (audio) { SDL_LockAudio(); free(audio); locked = 1; } audio_pos = audio = audio2; audio_len = audio_len2; } audio2 = (Byte *) malloc(8192); switchXaDecode(xachannel(buffer)); audio_len2 = convXaToWave((char *) buffer, (char *) audio2, xachannel(buffer), 0, 255); if (locked) SDL_UnlockAudio(); else if (audio) SDL_PauseAudio(0); saveXaDecode(xachannel(buffer)); } else { #ifdef CHATTING printm(M_BARE, "Unknow sector\n"); #endif } #ifdef CHATTING printm(M_BARE, "---------------------------------\n\n"); #endif return 1; } virtual int startup() throw (GeneralException) { Handle * file = 0; int c; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0) { printm(M_ERROR, "Couldn't initialise SDL: %s\n", SDL_GetError()); exit(-1); } atexit(SDL_Quit); SDL_ShowCursor(SDL_DISABLE); while ((c = getopt(argc, argv, "c:")) != EOF) { switch (c) { case 'c': channel = atoi(optarg); break; default: printm(M_ERROR, "Unknow argument.\n"); break; } } switch (argc - optind) { case 0: file = &Stdin; break; case 1: file = new Input(argv[optind]); break; default: printm(M_ERROR, "Too much arguments.\n"); exit(-1); } while (process_one_sector(file)); if (!audio) SDL_CloseAudio(); SDL_Quit(); return 0; } CODE_ENDS