1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "common/config-manager.h"
24 #include "image/bmp.h"
25 
26 #include "ultima/ultima8/gumps/cru_credits_gump.h"
27 
28 #include "ultima/ultima8/ultima8.h"
29 #include "ultima/ultima8/kernel/mouse.h"
30 #include "ultima/ultima8/graphics/render_surface.h"
31 #include "ultima/ultima8/graphics/palette_manager.h"
32 #include "ultima/ultima8/graphics/fonts/rendered_text.h"
33 #include "ultima/ultima8/graphics/fonts/font.h"
34 #include "ultima/ultima8/graphics/fonts/font_manager.h"
35 #include "ultima/ultima8/graphics/fonts/shape_font.h"
36 #include "ultima/ultima8/audio/music_process.h"
37 
38 namespace Ultima {
39 namespace Ultima8 {
40 
DEFINE_RUNTIME_CLASSTYPE_CODE(CruCreditsGump)41 DEFINE_RUNTIME_CLASSTYPE_CODE(CruCreditsGump)
42 
43 CruCreditsGump::CruCreditsGump()
44 	: ModalGump(), _timer(0), _background(nullptr), _nextScreenStart(0),
45 		_screenNo(-1) {
46 }
47 
CruCreditsGump(Common::SeekableReadStream * txtrs,Common::SeekableReadStream * bmprs,uint32 flags,int32 layer)48 CruCreditsGump::CruCreditsGump(Common::SeekableReadStream *txtrs,
49 									   Common::SeekableReadStream *bmprs,
50 									   uint32 flags, int32 layer)
51 		: ModalGump(0, 0, 640, 480, 0, flags, layer),
52 		_timer(0), _background(nullptr), _nextScreenStart(0), _screenNo(-1)
53 {
54 	Image::BitmapDecoder decoder;
55 	_background = RenderSurface::CreateSecondaryRenderSurface(640, 480);
56 	_background->Fill32(0xFF000000, 0, 0, 640, 480); // black background
57 
58 	if (decoder.loadStream(*bmprs)) {
59 		// This does an extra copy via the ManagedSurface, but it's a once-off.
60 		const Graphics::Surface *bmpsurf = decoder.getSurface();
61 		Graphics::ManagedSurface *ms = new Graphics::ManagedSurface(bmpsurf);
62 		ms->setPalette(decoder.getPalette(), decoder.getPaletteStartIndex(), decoder.getPaletteColorCount());
63 		_background->Blit(ms, 0, 0, 640, 480, 0, 0);
64 	} else {
65 		warning("couldn't load bitmap background for credits.");
66 	}
67 
68 	// Lots of extra copies here, but it's only 4kb of text so it's fine.
69 	CredScreen screen;
70 	CredLine credline;
71 
72 	// not sure what these 4 bytes are?
73 	txtrs->readUint32LE();
74 	while (!txtrs->eos()) {
75 		Common::String line = txtrs->readString();
76 		if (!line.size())
77 			break;
78 		credline._text = line.substr(1);
79 		switch (line[0]) {
80 			case '@':
81 				credline._lineType = kCredTitle;
82 				screen._lines.push_back(credline);
83 				break;
84 			case '$':
85 				credline._lineType = kCredName;
86 				screen._lines.push_back(credline);
87 				break;
88 			case '*': {
89 				unsigned int i = 1;
90 				while (i < line.size() && line[i] == '*')
91 					i++;
92 				screen._delay = 60 * i;
93 				_screens.push_back(screen);
94 				screen._lines.clear();
95 				break;
96 			}
97 			default:
98 				if (line.size())
99 					debug(6, "unhandled line in credits: %s", line.c_str());
100 				break;
101 		}
102 	}
103 }
104 
~CruCreditsGump()105 CruCreditsGump::~CruCreditsGump() {
106 	delete _background;
107 
108 	for (Common::Array<RenderedText *>::iterator iter = _currentLines.begin(); iter != _currentLines.end(); iter++) {
109 		delete *iter;
110 	}
111 }
112 
InitGump(Gump * newparent,bool take_focus)113 void CruCreditsGump::InitGump(Gump *newparent, bool take_focus) {
114 	ModalGump::InitGump(newparent, take_focus);
115 
116 	Mouse::get_instance()->pushMouseCursor();
117 	Mouse::get_instance()->setMouseCursor(Mouse::MOUSE_NONE);
118 
119 	MusicProcess *musicproc = MusicProcess::get_instance();
120 	if (musicproc) {
121 		if (GAME_IS_REMORSE)
122 			musicproc->playMusic(19);
123 		else
124 			musicproc->playMusic(17);
125 	}
126 }
127 
Close(bool no_del)128 void CruCreditsGump::Close(bool no_del) {
129 	Mouse::get_instance()->popMouseCursor();
130 
131 	ModalGump::Close(no_del);
132 
133 	// Just let it play out?
134 	//MusicProcess *musicproc = MusicProcess::get_instance();
135 	//if (musicproc) musicproc->restoreMusic();
136 }
137 
run()138 void CruCreditsGump::run() {
139 	ModalGump::run();
140 
141 	_timer++;
142 
143 	if (_timer < _nextScreenStart)
144 		return;
145 
146 	_screenNo++;
147 	if (_screenNo >= static_cast<int>(_screens.size())) {
148 		Close();
149 		return;
150 	}
151 
152 	_nextScreenStart += _screens[_screenNo]._delay;
153 	for (Common::Array<RenderedText *>::iterator iter = _currentLines.begin();
154 		 iter != _currentLines.end(); iter++) {
155 		delete *iter;
156 	}
157 	_currentLines.clear();
158 
159 	const Common::Array<CredLine> &lines = _screens[_screenNo]._lines;
160 
161 	Font *titlefont = FontManager::get_instance()->getGameFont(16, true);
162 	Font *namefont = FontManager::get_instance()->getGameFont(17, true);
163 	Palette *pal = PaletteManager::get_instance()->getPalette(PaletteManager::Pal_Cred);
164 
165 	ShapeFont *titleshapefont = dynamic_cast<ShapeFont *>(titlefont);
166 	if (pal && titleshapefont)
167 		titleshapefont->setPalette(pal);
168 	ShapeFont *nameshapefont = dynamic_cast<ShapeFont *>(namefont);
169 	if (pal && nameshapefont)
170 		nameshapefont->setPalette(pal);
171 
172 	for (Common::Array<CredLine>::const_iterator iter = lines.begin();
173 		 iter != lines.end(); iter++) {
174 		Font *linefont = (iter->_lineType == kCredTitle) ? titlefont : namefont;
175 
176 		unsigned int remaining;
177 		RenderedText *rendered = linefont->renderText(iter->_text, remaining, 640, 0, Font::TEXT_CENTER);
178 		_currentLines.push_back(rendered);
179 	}
180 }
181 
PaintThis(RenderSurface * surf,int32 lerp_factor,bool scaled)182 void CruCreditsGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
183 	surf->Blit(_background->getRawSurface(), 0, 0, 640, 480, 0, 0);
184 
185 	unsigned int nlines = _currentLines.size();
186 	if (!nlines)
187 		return;
188 
189 	int width, height;
190 	_currentLines[0]->getSize(width, height);
191 	int vlead = _currentLines[0]->getVlead();
192 
193 	int total = nlines * (height + vlead);
194 	int yoffset = 240 - total / 2;
195 
196 	for (Common::Array<RenderedText *>::iterator iter = _currentLines.begin();
197 		 iter != _currentLines.end(); iter++) {
198 		(*iter)->draw(surf, 0, yoffset);
199 		yoffset += (height + vlead);
200 	}
201 }
202 
OnKeyDown(int key,int mod)203 bool CruCreditsGump::OnKeyDown(int key, int mod) {
204 	if (key == Common::KEYCODE_ESCAPE)
205 		Close();
206 
207 	return true;
208 }
209 
210 } // End of namespace Ultima8
211 } // End of namespace Ultima
212