ALG: Initial version of American Laser Games engine#6500
ALG: Initial version of American Laser Games engine#6500sev- merged 10 commits intoscummvm:masterfrom
Conversation
|
I am aware there are still issues with memory leaks, I am trying to fix those in the next days |
sev-
left a comment
There was a problem hiding this comment.
Solid work!
Checked 19 / 29 files, put my comments and suggestions. Unfortunately some renames are required.
| _paletteDirty = true; | ||
| _screen = new Graphics::Surface(); | ||
| _rnd = new Common::RandomSource("alg"); | ||
| _screen->create(320, 200, Graphics::PixelFormat::createFormatCLUT8()); |
There was a problem hiding this comment.
It is advised to not do anything heavy in the constructor. Please move these to Game::run()
There was a problem hiding this comment.
@dckone the code is still in the init() function. Perhaps you forgot to push your changes?
There was a problem hiding this comment.
@bluegr I do not understand. The code is in the init() method in Game, each inheriting game class then has a call to its specific init() method in ::run(), which in turn calls the parents init() method.
Is there a problem with that setup?
|
Since each game has its own hardcoded logic, it would make sense to group all the game logic in a folder. For example, instead of having |
I like the idea, but not 100% sure how to achieve that at the moment. Currently each game has minor differences in handling its main game loop, as well as calling some functions provided in the base Game class. The state of the game is held be the extended class, for example GameMaddog. And then the majority of the code is just functions called by the game script/Scene file. These again need access to the state. So not 100% sure how to decouple all of this in a way that makes sense. // EDIT: or do you mean just literally moving the game-specific files as-is to the subfolder? In that case that would be easy of course... |
Yes, I was asking for the game-specific files to be moved. Any further big refactorings in the code can be done at a later stage in-tree |
ok, i moved it. |
I can't reliably comment on how to fix the existing commit, because everytime I tried something like that, I horribly failed - so I'll leave this up to the others :-D In order to prevent this to happen in the future, make sure that your git configuration is set to
This will avoid merge commits by always rebasing the current upstream code onto your fork. Then, you can update your fork by running
|
sounds great, I appreciate the help. I backed up my local repo just to be safe, and invited you as a collaborator on my github repo. I hope that is enough to give you write access. |
sev-
left a comment
There was a problem hiding this comment.
Thank you for addressing the review feedback so quickly.
I have only few tiny notes, so I consider it ready for merge.
| bool AlgEngine::hasFeature(EngineFeature f) const { | ||
| return (f == kSupportsReturnToLauncher) || | ||
| (f == kSupportsLoadingDuringRuntime) || | ||
| (f == kSupportsSavingDuringRuntime); |
There was a problem hiding this comment.
You may also consider to add ExtendedSaves support here, so then screenshots, and other metadata is handled for you. But it could be added after the merge.
There was a problem hiding this comment.
For now I would like to leave it as-is. There is only one save slot, as only saving via the original game interface is supported. Also screenshots might be misleading, as the save does not save exactly the location in the scene, but just the scene itself, so the scene is restarted on load, just like in the original interpreters.
|
@dckone Fixed commit history The commits are created by you, and committed by me (which is how git works) |
thank you very much for the help :) |
| int32 dstX = x; | ||
| int32 dstY = y; | ||
| Common::Rect subRect = Common::Rect(0, 0, src->w, src->h); | ||
| if (dstX < 0) { |
There was a problem hiding this comment.
There's a clip function in Graphics::Surface that may help simplify this.
There was a problem hiding this comment.
i will look into that hopefully soon
There was a problem hiding this comment.
after trying for 2 hours i gave up, somehow I do not understand how this clip function could work in my case. I might look into it again if I have more time in the future.
engines/alg/graphics.cpp
Outdated
| for (uint16 x = 0; x < width; x++) { | ||
| aniImage->setPixel(x, y, aniFile.readByte()); | ||
| } |
There was a problem hiding this comment.
| for (uint16 x = 0; x < width; x++) { | |
| aniImage->setPixel(x, y, aniFile.readByte()); | |
| } | |
| aniFile.read(aniImage->getBasePtr(0, y), width); |
Something similar can also be done in other places that read in rows of pixels at a time.
There was a problem hiding this comment.
same as above, will look into it
engines/alg/graphics.cpp
Outdated
| surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); | ||
| uint8 *pixels = new uint8[width * height](); | ||
| vgaFile.read(pixels, width * height); | ||
| surface->setPixels(pixels); |
There was a problem hiding this comment.
This leaks the memory allocated when calling surface->create. It might be simpler to just read directly to the surface memory rather than creating a separate buffer for it.
There was a problem hiding this comment.
do I interpret that correctly that the "new Graphics::Surface()" already allocates a pixel buffer and then the create() allocates another one and the original one is not freed?
There was a problem hiding this comment.
Close - create() creates the first buffer, then setPixels replaces it with the manually allocated one without freeing the first one.
engines/alg/video.cpp
Outdated
| } | ||
| while (runLength > 0) { | ||
| if (color > 0) { | ||
| _frame->setPixel(x, y, color); |
There was a problem hiding this comment.
You may find memset useful here for performance with longer values of runLength.
| error("GameBountyHunter::run(): Cannot find scene %s in libfile", scene->_name.c_str()); | ||
| } | ||
| _sceneSkipped = false; | ||
| Audio::PacketizedAudioStream *audioStream = _videoDecoder->getAudioStream(); |
There was a problem hiding this comment.
I'd recommend keeping the implementation details for the video decoder self-contained in case you need to support alternative video formats later.
There was a problem hiding this comment.
I am not sure what you mean by that. Is it that I should let the videoDecoder handle the playback of the audio?
There was a problem hiding this comment.
i moved the audio stream handling into the video decoder as a quick fix.
In the future I might rework the video decoding, currently it is a bit hacky in places. Also the frame timing should be handled by the video decoder, currently it is handled by game logic.
|
Would it be possible to provide the demos listed in the detection tables on our demos page? |
Sure, I need to request access, then I can supply these. I will followup on that soon hopefully. |
| case Alg::GType_CRIME_PATROL: { | ||
| GameCrimePatrol *game = new GameCrimePatrol(this, gd); | ||
| _debugger = new DebuggerCrimePatrol(game); | ||
| _game = game; | ||
| break; | ||
| } | ||
| case Alg::GType_DRUG_WARS: { | ||
| GameDrugWars *game = new GameDrugWars(this, gd); | ||
| _debugger = new DebuggerDrugWars(game); | ||
| _game = game; | ||
| break; | ||
| } |
There was a problem hiding this comment.
| case Alg::GType_CRIME_PATROL: { | |
| GameCrimePatrol *game = new GameCrimePatrol(this, gd); | |
| _debugger = new DebuggerCrimePatrol(game); | |
| _game = game; | |
| break; | |
| } | |
| case Alg::GType_DRUG_WARS: { | |
| GameDrugWars *game = new GameDrugWars(this, gd); | |
| _debugger = new DebuggerDrugWars(game); | |
| _game = game; | |
| break; | |
| } | |
| case Alg::GType_CRIME_PATROL: { | |
| _game = new GameCrimePatrol(this, gd); | |
| _debugger = new DebuggerCrimePatrol(_game); | |
| break; | |
| } | |
| case Alg::GType_DRUG_WARS: { | |
| _game = new GameDrugWars(this, gd); | |
| _debugger = new DebuggerDrugWars(_game); | |
| break; | |
| } |
Same for the cases below
There was a problem hiding this comment.
If i implement that change it does not compile anymore:
engines/alg/alg.cpp: In constructor 'Alg::AlgEngine::AlgEngine(OSystem*, const Alg::AlgGameDescription*)':
engines/alg/alg.cpp:43:53: error: invalid conversion from 'Alg::Game*' to 'Alg::GameCrimePatrol*' [-fpermissive]
43 | _debugger = new DebuggerCrimePatrol(_game);
|
Thanks, merging |


Initial version of the American Laser Games engine.
Currently supported and can be completed:
Crime Patrol DOS
Crime Patrol Demo DOS
Drug Wars DOS
Drug Wars Demo DOS
Who Shot Johnny Rock? DOS
Mad Dog McCree DOS
Mad Dog II: The Lost Gold DOS
Space Pirates DOS
Space Pirates Demo DOS
Partially implemented, but unsupported and can probably not be completed
The Last Bounty Hunter DOS
The Last Bounty Hunter Demo DOS
So far only DOS versions are supported, in the future 3DO versions are quite possible.
Of the supported games, there are still some issues remaining:
Feedback would be much appreciated :)
P.S. Sorry for the squashed commit, the reason I did that is because so far I only commited to a local repo and only manually transferred to github infrequently, also my previous (local) commits did not follow the ScummVM commit rules yet.
Also there is quite a lot of refactoring going on in my local commits which makes them not very suitable for reviewing I guess.