Sprites? Wow!
So, running this twice (a Doom in each sym-window) next to each other, will likely fail visually, right?
No, no... The sprite trick was used only on the MSX-DOS version. On SymbOS this behaves like standard SymbOS application... No any MSX specific tricks are used.
Oh, I had the same question wolf asked! haha, nice!
Holy crap, that is even more impressive!
Crazy, for me this is just amazing. How did you convert this?!
Well... Easy question to ask, but a bit harder to explain. As there might be anyway other people interested as well, I'll try to explain the major dance steps as I think they are pretty much common for all similar projects:
The good thing in this source is that it is very much doing everything by it self and not trusting to help of TI-OS. This made the port pretty straight forward in the first place. Another important aspect is that it was easy to make it compile on SjAsmPlus. From SymbOS perspective this was very important as AFAIK SjAsmPlus is currently ONLY standalone assembler that supports relocation tables and practically you can't compile any SymbOS application if the feature is missing.
So... I first wrote a simple application frame that opens a Form and places a standard simple graphics object of same size in to it. Then it creates a timer process, calls the game and once the game exits, it asks OS to kill the timer and the program it self... One thing that you need to know is that for all processes it is important that they don't try to exit or return. If you want to exit, you just ask "please kill me" and then go to task switching (RST #30) loop. The OS will kill you, close your windows and free your memory once it has some spare time. I also wrote a small "checkmessages"-routine that scans trough the pending messages that OS sends (like "Someone pushed close-button", "your window lost focus" and such) and handles the interesting ones. After this part looked ok, I included the main game file in to the code area. As the game it self does not need to interact with OS elements, I had no need to put different parts to different memory areas. It is enough that our created graphics object was pointed to transfer area.
Ok, then to the game... It can be divided in to 3 main routines... First the is the menu that practically works so that it unpacks the graphics and places text to the screen buffer, then it calls "flush the buffer to screen"-routine. After that it calls "wait for key press"-routine and works out the result from input. This loop is continued until start or continue is selected.
When the game is started there is then the main loop that practically renders the walls, places the enemies to the buffer, adds menu etc. elements and then calls the "flush the buffer to screen"-routine and loops back to start.
The 3rd routine is the interrupt routine that calculates the time , reads the keyboard button statuses and moves the player and enemies.
First I rewrote the "flush the buffer to screen"... On MSX-DOS version it copies the graphics to sprites, but in SymbOS I made it to copy the graphics to our graphics object. Practically this is just a single table lookup loop. For performance reasons I added a routine that calculates on start a bit different tables for CPC and MSX, so that it is more fast as the OS does not need to do conversions anymore. After the copy I added request to refresh the area to screen... I also added a call to my "checkmessages" here as this routine is called each time the screen is drawn ready.
Then it was time to rewrite "wait for key press"-routine... I guess you know about what such looks like, but as this is random length "idle loop" I also added call to "checkmessages" here and to avoid useless CPU consumption, I added one RST #30 to the keyboard poll loop as well.
Last I needed to convert the interrupt routine in to proper timer process... As I told you the process can not exit, so I did this by removing the push & exx stuff from front, pop & exx stuff from back and made the end of interrupt to jump back to start of interrupt where I once again added one RST #30. As I didn't want to create and kill timer processes on the game code, I made a flag to to see if the timer process should actually do something or just loop, but that is practically the steps that were needed to make the code run. Sure I needed to remove the original interrupt init routines and such blah, blah, blah stuff, but I think I covered the important/interesting parts.
Thank you for your long report, it was a very interesting read. And a lot of things to think about when doing things like this! If I look to the running project it I still do not believe that it is working But it does!
Wait, so, if I read correctly, it means that this would also work on SymbOS for CPC?! woah!
Wait, so, if I read correctly, it means that this would also work on SymbOS for CPC?! woah!
Yes... As you already noticed the math routines used are not that great and therefore it currently runs a bit too slowly on CPC and MSX2, but actually Prodatron already took the source today and started fixing those issues...
It should come in a SymbOS bundle of "standard" applications released with the OS
;-)
Yes, today I tested it on my CPC:
https://www.youtube.com/watch?v=AL3d7LqM0lY
I did some optimizations, but only reached 20% until now, so on a 4Mhz system (inside a GUI multitasking OS :P ) it's not superfast but already useable somehow. I hope there is still some optimization potential.
Anyway it is just cool to have Doom on a Z80 homecomputer running in a window even multiple times.
Thanks so much to NYYRIKKI and the zDoom TI-calculator guys for the great project! :D