• Please review our updated Terms and Rules here

MagiDuck, a DOS / CGA text mode game project

Looking good! If you need help with coding certain aspects, you may want to create a new thread, as this one -- as distracted as it gets -- is dedicated to MagiDuck.
 
Well, technically, the Adlib is 80s tech It came on the market in 1987.

I was wondering what the best way would be to approach designing sounds. Seeing your tool was very helpful and inspirational!

Yep, meant to say early 80s there :)

Glad to hear the video could be of use to someone so experienced. My poor understanding of programming concepts has usually resulted in me making my own rudimentary tools, instead of painfully reading through pages of specs for things like PCX loading or level editor files. Since I pretty much only started to understand binary files and memory about a year ago I'm hoping I can shake off the worst parts of that habit.

Your blog post was a fun read, I've already read many of your previous posts and am slowly starting to understand the technicalities. If you're about to make those multiplexed frequencies, you probably need something very close to MONOTONE so I'm surprised to hear you would still opt to make your own editor.

Actually went through PakuPaku's SOUND.PAS for the first time and tried to see how it stored note sequences... If I understood correctly it stores every note/event as an individual object with links to the first and next note in the pattern. Makes sense I suppose, since every note object can store data needed for every sound device and the sequence(s) are only played when the player can't interact. Just wondering how much overhead this would cause compared to a simple string of data. Although considering long sequences with variable pauses between notes the solution seems to make more and more sense. I'd still be terrified of creating a new object for each note and hoping they'll be deleted from memory reliably eventually.

My own sound system just uses a 64 note buffer, where notes from the main track are copied when a sound effect is requested. The buffer plays one note per frame and clears it afterwards. A nice side effect is that some previously queued notes can survive even if a new sound effect is queued on top of them. I'm supposing some NES games do things somewhat like this, since sound effects can reserve a channel for themselves for their duration and free it for music afterwards.

I'm trying to imagine what would have happened if this had been around in say 1982 (or even 85 after SMB1 came around) ... it would have changed EVERYTHING about gaming on computers for years to come.

Thanks for trying it out :)
Certainly a fun thought experiment, although I think the same could (or should be able to) be said for most modern homebrew projects. I'm more and more amazed at what old games could accomplish, considering the tools and information available at the time. Just opening up a text editor in DosBox with settings equaling the 5150 is so sluggish that I don't see how people could survive development back then. Every typo would cost at least three minutes of starting up editors and compilers.

What I've got is a single laptop with:
- Notepad++ for editing.
- Photoshop for graphics
- TilED for levels
- A hex editor for debugging files
- Sourcetree for version control
- DosBox @ 40000 cycles for compiling and data conversion.
- DosBox @ 8000 cycles for quick testing
- DosBox @ 270 cycles for target testing
- Internet full of information
- Thousands of old games to learn (steal?) from

All running at the same time and it's still taken over two years to get at 95% complete of a game :)

But hey, progress has been made. Tilesets are pretty much done, there's a bunch of new levels and a new reward for completing levels 100%. Alot of little additions and tweaks in the code and it still mostly runs decently 270 cycles.

Still wondering about the problem of reloading levels faster after dying... I'll probably go with storing a seperate version of each level with only the tiles that could potentially change.

I am working on another game project for the XT

code named project 16

http://4ch.mooo.com/16/

Looks really intriguing! Not too many japanese style games for old PCs. At least in english... Zone 66 is the only one that comes to mind right now. But yeah, probably a good idea to make your own thread for the project since this one's already going into so many directions :)

I'll be sure to follow up on your dev blog at least :)
 
Actually went through PakuPaku's SOUND.PAS for the first time and tried to see how it stored note sequences... If I understood correctly it stores every note/event as an individual object with links to the first and next note in the pattern.
It's actually a variation on how midi works, with a unique header.

fileHeader Offsets:
0x00 BYTE number of tracks
0x01 BYTE tempo
0x02 start tracks

trackHeader Offsets:
0x00 BYTE Device channel/voice number
0x01 BYTE Track Patch/Voice number (does not apply to all devices)
0x02 WORD Track size in bytes
0x04 start trackData

trackData Values:
For the track data the top 2 bits determine operation, bottom 6 are data:
0b0000000 == end of data
0b00xxxxxx == wait x+1 "ticks"
0b01xxxxxx == note x on -- if x is zero, that's a note off.
0b10xxxxxx == set volume x
0b11xxxxxx == change patch (currently disabled as PP doesn't use this)

1 tick == 1/4th of a beat, so shortest possible note is a 16th. Originally I wanted 48ths for triplet accuracy, but a 4.77mhz machine can't keep up with that. (starting to see why the original MPU401 had a hardware mode!)

To play the tracks I just point the current track pointer at the first track and loop through them making them "step" until "next" is nil. Each "step" method decrements the "wait" if set, if not set it pulls the next command byte from the pointer into the track.

Theoretically this format could support up to 255 tracks. 256 if I changed it so number of tracks started at zero.

The difference from MIDI:

1) I only support 64 notes, not 128, making my format is single byte commands while MIDI is multi-byte of varying lengths.

2) MIDI is a single data stream time indexed where the "tracks" are mixed together as they would occur. Mine keeps the tracks separate.

So... I know what you're thinking; Why did I make my own format? I wanted something tiny for the data stream. As a .MID thanks to each command at minimum taking 6 bytes the data would have been five times larger in memory.

What it sounds like mangis is doing is the "tracker" method, much akin to how an Amiga mod file works where he has a fixed size table that contains the "track". That can chew up a lot of memory fast and result in processing operations that don't need processing... but said approach has the advantage that like a piano roll it's very easy to make new music for.

Basically if his approach was an unencoded raw bitmap, mine's RLL encoded.

Paku 2.0 will use a somewhat more simplified implementation of the same concept as it only supports two tracks (bass and lead) since really the entire game doesn't actually use more than two voices at once. It's also going monolithic so the music will be stored in the data segment as constants, so the tempo set and number of tracks header is going away. I may also flip the control bits to the bottom to make it more efficient and mix in some ASM to shrink the code size, though since nothing else is really going on inside the music playback the effort may be a waste of time for PP... though 2.0 is a testbed for future games where I may have music playing during gameplay, hence it's worth it in the long run to implement this now.

I've been playing with just using .mid for future projects, or making my own variant of it. The time index per event approach has it's merits in being very simple to perform operations with. I'm thinking to keep it simple having this:

0x00000000 == end of data
0x0xxxxxxx == wait x
0x1xxxyyyy == command x, channel y

Then the command would be followed by a data byte. This is similar to how MIDI operates, but with smaller/easier time indexes that should take less time to process.
 
Last edited:
Since adlib and other popular soundcards came much after IBM 5150, it ruins the "roleplaying the 80's" element of the development for me.
Well, technically, the Adlib is 80s tech :) It came on the market in 1987.

Yeah, but the 5150 was discontinued in 1987. I'm guessing the emphasis is on the 5150, not on the full decade.

Honestly, even the Covox only came out in 1986 – five years into the 5150's six-year run. For authentic period-accuracy it's gotta be the PC speaker first and foremost.

That being said, my own 5150, when I get it and my shit back together, is totally going to see a Covox attached. Admittedly, that's in part just because the setup I'm working towards will end up having two LPTs, and while LPT1 gets the printer, I gotta put LPT2 to good use as well, because otherwise things would be, err, ritually unclean.

Planned setup, in case anyone cares:

slot1: original CGA w/ RGBI and composite output
slot2: AST RAMpage! RAM card w/ 640K; possibly some extra EMS for use as a RAM drive
slot3: hardware-hacked Hercules clone, so it can drive a VGA CRT I have – unless I actually buy a 5151 monitor too; this card includes an LPT(2) <-- Covox
slot4: NIC; not decided yet; need to know which 16bit NICs work in 8bit slots or if there are 8bit RJ45 NICs – advice/recommendations welcome
slot5: multi-IO controller; has 2 floppy drive controller, RTC, 2 serial ports [ribbons threaded out of case; COM1 for mouse; COM2 hypothetically for modem use, or in practice prolly for null modem cable connectivity; I wonder if the NIC will at all be faster?], 1 game port, and one LPT(1) <-- printer

PS: Does anyone know what that round hole in the back of the case is for? I know there's a little cover for it, and I have the cover, and besides, I'm actually using that hole to thread the serial port ribbon cables out, but what's the hole really for? Some peripheral that never saw the light of day? Some kind of case lock?
Optional original IBM cigarette lighter? Or an aperture for endoscope entry for final inspection? Clandestine classroom chewing gum disposal? Inquiring minds want to know.
 
Your blog post was a fun read, I've already read many of your previous posts and am slowly starting to understand the technicalities. If you're about to make those multiplexed frequencies, you probably need something very close to MONOTONE so I'm surprised to hear you would still opt to make your own editor.

Well, my idea is to play back MOD pattern data. But instead of the samples in a MOD, I would have PC speaker 'instruments'. I only need an editor for these 'instruments'. I guess the requirements for this are slightly different from a full tracker like MONOTONE, so I don't think I can avoid making my own editor for best results.
Indeed, I could use MONOTONE as a start... I could export a pattern from MONOTONE as an 'instrument' for my system.
My main concern here is that trackers such as MONOTONE do not allow editing sounds at the tick-level. For MODs this is not an issue, since the samples give you extra precision. But in my case the 'instruments' play this role. The pattern editor already does the rest.
 
Yeah, but the 5150 was discontinued in 1987. I'm guessing the emphasis is on the 5150, not on the full decade.

It's all quite arbitrary I guess.
Even though the 5150/5160 were no longer produced, software and hardware supporting these machines, and compatible clones, was still produced for years.
Although... perhaps more interesting would be to support PCjr's built-in audio chip? :)
As I understood, the game itself already works on PCjr.
 
That being said, my own 5150, when I get it and my shit back together, is totally going to see a Covox attached.

I don't think you'll see a lot of software other than Covox's own utilities that will work on a 5150; it takes a lot of horsepower to drive an LPT DAC.

The Disney Sound Source was engineered for a 4.77MHz system; it has a 16-byte FIFO and maxes out at 7KHz, reducing the interrupt load for a slow CPU dramatically. Driving a Disney Sound Source (properly, by software that is programmed specifically for it) works on slower systems. Unfortunately, all of the games that drive it properly that I know of (Arachnophobia, Rocketeer, etc.) require 8MHz to be fun. The educational titles probably work fine though.
 
I don't think you'll see a lot of software other than Covox's own utilities that will work on a 5150; it takes a lot of horsepower to drive an LPT DAC.

The Disney Sound Source was engineered for a 4.77MHz system; it has a 16-byte FIFO and maxes out at 7KHz, reducing the interrupt load for a slow CPU dramatically. Driving a Disney Sound Source (properly, by software that is programmed specifically for it) works on slower systems. Unfortunately, all of the games that drive it properly that I know of (Arachnophobia, Rocketeer, etc.) require 8MHz to be fun. The educational titles probably work fine though.

Thank you very much for this information.

Do you know if it's possible to build or buy the DSS on a budget? (Zero hits on ebay for the DSS. Are designs freely available?)

Btw., I've also just noticed that this picture on Wikipedia's Covox article shows that the original Covox was a dongle that again provided a parallel port at its back end. Does this mean that the passed-through parallel port was still usable e.g. for a printer? Presumably you couldn't print and play audio at the same time though, right? (I know, most PCs back then didn't multi-task anyway, but for the sake of argument.) I guess if the Covox doesn't "eat up" a parallel port, then my semi-ludicrous reasons for considering the Covox sound upgrade in the first place don't even apply...

Getting back to scali's comment above, didn't you, Trixter, have a PCjr? I know nothing about it or its audio chip. Have you (has anyone) tried to run Magiduck on it? (Apologies if that's already ITT; I read it before but might have forgotten.)
 
Do you know if it's possible to build or buy the DSS on a budget? (Zero hits on ebay for the DSS. Are designs freely available?)

Keep monitoring ebay and one will usually turn up for $20 or so. Not sure you can build one without cracking an existing one open, although the tech reference at ftp://ftp.oldskool.org/pub/misc/Hardware/Disney Sound Source/ does have a hardware diagram.

Does this mean that the passed-through parallel port was still usable e.g. for a printer? Presumably you couldn't print and play audio at the same time though, right?

Yes and yes.
 
See the wiki page for a list.
Hmm. Wiki page list is incomplete. The PS1 (or at least certain models) had the same functionality, just on a different port than the Junior or Tandy 1000.

Jr/Tandy == 0x00C0
PS/1 == 0x0205

WHY they put it at a different port when it's 100% compatible, damned if I know.

Hence my now not only having Tandy / Junior detection:

Code:
; function tandyDetect:boolean;
pProcNoArgs tandyDetect
	push  ds
	mov   ax, 0xF000
	mov   ds, ax
	xor   ax, ax
	cmp  [0xFFFE], BYTE 0xFD
	je   .isTandy
	cmp  [0xFFFE], BYTE 0xFF
	jne  .notTandy
	cmp  [0xC000], BYTE 0x21
	jne  .notTandy
.isTandy:
	inc  ax
.notTandy:
	pop  ds
	retf

But also PS/1 detection for the appropriate models:
Code:
; function PS1Detect:boolean;
pProcNoArgs PS1Detect
	mov  ah, 0xC0
	stc
	int  0x15
	jc   .failed
	mov  ax, [es:bx + 2]
	cmp  ax, 0x0BFC ; PS/1 LW-Type 44 or Model 2011
	je   .success
	cmp  al, 0xF8
	jne  .failed
	cmp  ah, 0x30 ; PS/1 Model 2121
	je   .success
	cmp  ah, 0x0E ; PS/1 486SX
	je   .success
	cmp  ah, 0x0F ; PS/1 486DX
	je   .success
.failed:
	xor  ax, ax
.success:
	retf

The hardest part in dealing with it is that the ports are write only, so to track which voices are playing you need to have a 4 byte buffer set up. The reason for this is the "level" of what's playing on each channel is stored 4 bytes apiece. I tell you, figuring this *** out:

Code:
; procedure tandySetLevel(left, right, voice:word);
; left level is ignored, right sets volume for entire channel
pProcArgs tandySetLevel
	mov   bx, [bp + 6]
	mov   al, bl
	mov   cl, 3
	and   al, cl
	ror   al, cl
	or    al, 0x90
	mov   cl, 0x0F
	mov   ch, [bp + 8]
	and   ch, cl
	sub   cl, ch
	or    al, cl
	mov   [bx + tandyLevels], al
	pRet  6

Was a pain in the arse. Notice that the left level is thrown away since this is mono chip. The "procedure" is called via pointer where I swap the pointer program-side to the appropriate sound chip.

It also helps to have a frequency to "interval" table created so you aren't doing long divides every time you change the voice -- I go with a 4096 byte one myself even though that skips every other hz with a 8khz max. (there is usually little reason on these chips to try anything higher).

I should probably upload the current version of my sound routines, they're a far cry from what I was doing in Paku 1.x and makes it easier to add/remove soundcards. More fun since I've added SSI 2001 and soundblaster MIDI support to it. (original SB midi is not even CLOSE to MPU-401 compatible).

Lemme see, current working cardlist in the code as it sits right now:
PC speaker in 2 voice 120hz arpeggio, Adlib, CMS, JR/Tandy, PS/1, MPU-401 dumb, and original Soundblaster DSP Midi.

On the to-do list would be AY-3-8930 (covox sound master), and IBM Music Feature... The latter is really hard to do when I have neither the hardware to test on, or documentation that's worth a flying ****; the IMF remaining one of the worst documented pieces of hardware I've ever encountered in that era.

Again if anyone can tell me how to just set it up to work as easily as MPU401 dumb / SB DSP ... I've yet to find ANY code for it that makes the least bit of sense!

Sadly with my health in the toilet I don't know if I'll actually get to implementing either of those; right now it'll be a miracle if Paku 2.0 sees the light of day even though it's ~85% complete.

Of course if I do the 8930 I should probably write a 8910 implementation, though Mockingboard's for the PC are probably the rarest cards of all.
 
Last edited:
IBM had to change the music port to keep the PS/1 machines AT compatible. The second DMA controller sits at C0-DF. Tandy eventually had to do this as well, although they chose a different port, 1E0. I imagine it would be easy enough to add support for the later Tandy models with a command line switch. I do not know how you would autodetect a Tandy with a chip at the alternate address.

Do you find the IBM Music Feature's Technical Reference to be such poor documentation?

I'd love to try your SSI-2001 support sometime on my replica. If you can encompass the Covox Sound Master and IBM Music Feature, your game will support the greatest number of music devices ever. No one supported them all.
 
IBM had to change the music port to keep the PS/1 machines AT compatible.
Thank you, that makes perfect sense. Been wondering that one for a few years, never got a straight answer.

Tandy eventually had to do this as well, although they chose a different port, 1E0.
Was completely unaware of that -- good to know. I'll have to investigate to see if I can figure a auto-detect method. You'd think since it's a AT thing just detecting 286 or not would be sufficient, but dimes to dinars those XT class 286 machines lack that second DMA controller... Well, if there's a way to detect the second DMA controller, that would be suffiicent. If it's there, use the other port.

Though as you suggested, command line switch is probably the way to go. As it is, I believe I put in port overrides on the new code stack for EVERY device "just in case".

Do you find the IBM Music Feature's Technical Reference to be such poor documentation?
I have ranted at great lengths about what a steaming pile of **** that is. It's like it was written in bad broken engrish like trying to get tech support from AT&T, translated to Japanese, and then into English. None of the code samples make sense, seem to be functional, and nothing I've tried for code has worked for any of the people who have one trying to test for me.

Which is annoying since all I want for routines is:

Select internal or external.

Normal everyday dumb MIDI UART write.

Since I've got FB-01 working on MPU-401 and SB-DSP... Which should be ALL I need to implement to enable IMF. Pissed me off so bad I pulled the plug on IMF support and haven't even looked at the code in a year, since... well, EVERY bit of documentation I've found about it leaves me wanting to get medieval on someone's tuchas Samuel L. Jackson style with:

Ácweðan hwá ágéncuman! Ácweðan hwá ágéncuman! Ic néðe þú, Ic twifealde néðe þú! Englisc, modor-wyrter! Gedon eow cweþan hit!?!

... and yes that's English, just a few centuries out of date. ... and how do I know this, you should know how; certain place I worked in the town you're living in! I can read Beowulf without needing the translation!

Let's just say "what" ain't no country I ever heard of, and leave it at that.

I'd love to try your SSI-2001 support sometime on my replica.
I'll toss together a standalone demo and post it up in it's own thread for testing. It's still untested on real hardware, but since it's just a 1:1 port from my C64 version (that was designed to use different clocks since, well, PAL VS. NTSC -- so PC's different feeder was easy enough to adjust to) and seems to work with DOSBox's emulation on YKHWong's builds. I'd still like to get confirmation from something resembling real hardware BEFORE I release RC1 of Paku 2.0 (which will be the first public release)

If you can encompass the Covox Sound Master and IBM Music Feature, your game will support the greatest number of music devices ever. No one supported them all.
I'd have thought sierra's AGI/SCI games would have come close. Hell I was using a disassembly of Sierra's IMF driver as a guide as the manuals and documentation were so malfing useless.

Though on a LOT of this stuff my efforts are simply hobbled by a lack of access to the real hardware. I have a cute little board I got from Jameco back in the 80's that lets be verify values coming in/out of ports that I can at least fake proper responses with, but that's nowhere near knowing if the real device is gonna output what it should.

See my CMS struggles where a real game blaster worked, but SB's didn't... got that all squared away now. Newest version is ~30% faster and should work with every SA1099 equipped card out there.
 
You'd think since it's a AT thing just detecting 286 or not would be sufficient, but dimes to dinars those XT class 286 machines lack that second DMA controller... Well, if there's a way to detect the second DMA controller, that would be suffiicent.

I asked Trixter that question recently, about the XT/286. Apparently the XT/286 is fully AT-compatible, so the 'XT' in the name is a bit of a misnomer.
I think in general it's a safe assumption that all 286+ PCs are AT-compatible (perhaps Tandy's are an exception here, but they're in a special class anyway).
Anyway, I faced a similar problem recently, where I wanted to reprogram the PIC to use auto-EOI.
The problem here is that an AT has two PICs, so you need to program them differently from a PC/XT-class machine with PICs.

So I would read and write the interrupt mask of the second PIC to see if it would 'stick'. If so, there's a PIC at that address, if not, then I assume there is only one PIC in the system, so PC/XT.
I don't think you can do such a trick with the DMA controller, but you could detect a second PIC. It's pretty much a given that a machine with two PICs also has two DMA controllers, and is AT-compatible.
 
I asked Trixter that question recently, about the XT/286. Apparently the XT/286 is fully AT-compatible, so the 'XT' in the name is a bit of a misnomer.
True for real XT/286's, but the tandy's were a bit different in that they still had 8 bit slots, so there was probably no reason to put in a controller for data lines that didn't exist.

Mostly that would be the Tandy 1000 TL, RL and RLX -- 286 with a 768k memory limit and 8 bit slots. :(

Its kind of a laugh, I don't think Tandy even made a machine with 16 bit ISA slots until they were making 386SX rigs -- the 1000 RSX.

Hmm, that could be a detection, all of those models TL/RL/RLX/RSX will pass my TL test, so if it has a 386 or higher instead of a 286, the port has been moved?

That's a good question actually, did Tandy even make a full AT class machine? Yeah, the wikipedia article says only the RSX moves the port, so that's the machine to isolate. Well, unless the 2500's / newer retained that capability, but I thought by that time it had been axed.
 
Ok, MagiDuck beta 1 is now available for download: http://www.indiedb.com/games/magiduck/downloads/magiduck-beta-1


Apologies for not posting anything about the progress. I've had some pretty taxing projects at my day job, so all my weekend energy has gone into development and lazing around... Then again, as said before, it's mostly been a grind lately. I guess the last 99% is the hardest? Mostly just working on new graphics, levels and scripting-type programming for different events and actors.

The beta features:
- 10 levels
- 3 secret levels
- 1 boss level
- In-game help
- High-scores
- Ending animation
- Power Orbs to collect in levels completed 100%. They allow flight, a score multiplier and higher damage.
- Improved scoring
- Improved enemy behavior
- Improved level RLE encoding
- Reloading a level no longer loads spawner data

Also, it's finally possible to look down with 5 key as well as the down arrow.

The high score file has some simple XOR-encoding to avoid tampering, but only for the names at the moment.

Level loading times are slightly faster than before, thanks to the RLE noticing long runs of non-sequential tiles and not saving run-lengths for those. Spawner data is no longer reloaded when a level is loaded twice either. I tried thinking about solutions to save potentially changing tiles to a seperate string, but none seemed worth the extra space required... But let me know if the load times are too annoying :)

The game folder is 162 KB. I hope fitting into a 180 KB floppy is still acceptable for a 5150 release?

These are the test runs I've made for it so far:
- DosBox-X 270 cycles, CGA: Played through the game twice.
- DosBox, 270 cycles, EGA: Played a run of 5 levels.
- PcEM, CGA: Played a run of 5 levels.
- Real 386, VGA: Played through the game once.

Had no problems on any of the runs. I'll start doing some fine tuning for the final release and wait for any disastrous bug reports or critiques. If everything goes well, I hope to release 1.0 before Dec 31. :)

I'll ask everyone involved here for a permission to add your name to the credits once the game has been proven stable (or nothing comes up).
 
Last edited:
The game folder is 162 KB. I hope fitting into a 180 KB floppy is still acceptable for a 5150 release?

Well, you could also take a page from the book of C64, and make it a double-sided game?
On C64 you often had to 'flip disk' at some point in the game.
That way you could create a game that fills two 160 KB sides of a floppy, giving you 320 KB in total.

You can probably implement that in a reasonably straightforward way:
Put the data of the first X levels on side 1 of the disk, and the remainder on side 2 (duplicating some shared data if required).
Then when you need to load a new level, if you can't find the file, you display a 'flip disk' screen, and wait for the user to flip disk and press a key, then you try to load again.
Don't forget to always save the hi-scores on the same side of the disk as well, so perhaps you need a 'flip disk' trigger there as well :)

When running from a larger floppy or a harddisk, all files will always be found immediately, so the 'flip disk' screen is simply never triggered, so no extra work to be done.
 
Back
Top