aboutsummaryrefslogtreecommitdiff
path: root/engines/made/pmvplayer.cpp
blob: 704947132e1156e20d3762f9aeaf9d49ee94d3e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "made/pmvplayer.h"

namespace Made {

PmvPlayer::PmvPlayer(OSystem *system, Audio::Mixer *mixer) : _fd(NULL), _system(system), _mixer(mixer) {
}

PmvPlayer::~PmvPlayer() {
}

void PmvPlayer::play(const char *filename) {

    _abort = false;
    _surface = NULL;

    _fd = new Common::File();
    _fd->open(filename);

    uint32 chunkType, chunkSize;

	readChunk(chunkType, chunkSize);	// "MOVE"
    readChunk(chunkType, chunkSize);	// "MHED"

    // TODO: Evaluate header
    //_fd->skip(0x3A);

	uint frameDelay = _fd->readUint16LE();
	_fd->skip(10);
	uint soundFreq = _fd->readUint16LE();
	// FIXME: weird frequencies... (11127 or 22254)
	//if (soundFreq == 11127) soundFreq = 11025;
	//if (soundFreq == 22254) soundFreq = 22050;

	int unk;

	for (int i = 0; i < 22; i++) {
		unk = _fd->readUint16LE();
		debug(2, "%i ", unk);
	}
	debug(2, "\n");

    _mixer->stopAll();

    _audioStream = Audio::makeAppendableAudioStream(soundFreq, Audio::Mixer::FLAG_UNSIGNED);
	_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream);

    // Read palette
    _fd->read(_palette, 768);
    updatePalette();

	//FILE *raw = fopen("track.raw", "wb");

    while (!_abort && !_fd->eof()) {

        readChunk(chunkType, chunkSize);

		if (_fd->eof())
			break;

        byte *frameData = new byte[chunkSize];
        _fd->read(frameData, chunkSize);

		byte *audioData = frameData + READ_LE_UINT32(frameData + 8) - 8;
		uint16 chunkSize = READ_LE_UINT16(audioData + 4);
		uint16 chunkCount = READ_LE_UINT16(audioData + 6);

		if (chunkCount > 50) break;	// FIXME: this is a hack

		debug(2, "chunkCount = %d; chunkSize = %d\n", chunkCount, chunkSize);

		uint32 soundSize = chunkCount * chunkSize;
    	byte *soundData = new byte[soundSize];
    	decompressSound(audioData + 8, soundData, chunkSize, chunkCount);
    	_audioStream->queueBuffer(soundData, soundSize);
    	
    	//fwrite(soundData, soundSize, 1, raw);

        byte *imageData = frameData + READ_LE_UINT32(frameData + 12) - 8;

        uint32 frameNum = READ_LE_UINT32(frameData);
        uint16 width = READ_LE_UINT16(imageData + 8);
        uint16 height = READ_LE_UINT16(imageData + 10);
        uint16 cmdOffs = READ_LE_UINT16(imageData + 12);
        uint16 pixelOffs = READ_LE_UINT16(imageData + 16);
        uint16 maskOffs = READ_LE_UINT16(imageData + 20);
        uint16 lineSize = READ_LE_UINT16(imageData + 24);

        debug(2, "width = %d; height = %d; cmdOffs = %04X; pixelOffs = %04X; maskOffs = %04X; lineSize = %d\n",
        	width, height, cmdOffs, pixelOffs, maskOffs, lineSize);

        if (!_surface) {
            _surface = new Graphics::Surface();
            _surface->create(width, height, 1);
        }

        decompressImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize, frameNum > 0);

		handleEvents();
        updateScreen();

        delete[] frameData;

		_system->delayMillis(frameDelay);
    }

    _audioStream->finish();
    _mixer->stopAll();
    
    //delete _audioStream;
    delete _fd;
    delete _surface;

	//fclose(raw);

}

void PmvPlayer::readChunk(uint32 &chunkType, uint32 &chunkSize) {
    chunkType = _fd->readUint32BE();
    chunkSize = _fd->readUint32LE();

    debug(2, "chunkType = %c%c%c%c; chunkSize = %d\n",
        (chunkType >> 24) & 0xFF, (chunkType >> 16) & 0xFF, (chunkType >> 8) & 0xFF, chunkType & 0xFF,
        chunkSize);

}

void PmvPlayer::handleEvents() {
	Common::Event event;
	while (_system->getEventManager()->pollEvent(event)) {
	    if (event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) {
	        _abort = true;
		}
	}
}

void PmvPlayer::updatePalette() {
    byte colors[1024];
    for (int i = 0; i < 256; i++) {
        colors[i * 4 + 0] = _palette[i * 3 + 0];
        colors[i * 4 + 1] = _palette[i * 3 + 1];
        colors[i * 4 + 2] = _palette[i * 3 + 2];
        colors[i * 4 + 3] = 0;
    }
    _system->setPalette(colors, 0, 256);
}

void PmvPlayer::updateScreen() {
    _system->copyRectToScreen((const byte*)_surface->pixels, _surface->pitch, 0, 0, _surface->w, _surface->h);
    _system->updateScreen();
}

}