Groups | Search | Server Info | Login | Register


Groups > comp.sys.ibm.pc.demos > #35

Settling an old matter

Received by 10.224.186.20 with SMTP id cq20mr9696235qab.8.1351133345253; Wed, 24 Oct 2012 19:49:05 -0700 (PDT)
MIME-Version 1.0
Received by 10.52.37.12 with SMTP id u12mr3334809vdj.8.1351133345213; Wed, 24 Oct 2012 19:49:05 -0700 (PDT)
Path csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!news.glorb.com!x14no7317103qar.0!news-out.google.com!r17ni57592152qap.0!nntp.google.com!x14no7317097qar.0!postnews.google.com!b19g2000vbt.googlegroups.com!not-for-mail
Newsgroups comp.sys.ibm.pc.demos
Date Wed, 24 Oct 2012 19:49:04 -0700 (PDT)
Complaints-To groups-abuse@google.com
Injection-Info b19g2000vbt.googlegroups.com; posting-host=24.192.100.117; posting-account=-k9-qAoAAADKvOH-Q9SE4Q29wG7ejsxR
NNTP-Posting-Host 24.192.100.117
User-Agent G2/1.0
X-HTTP-UserAgent Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4,gzip(gfe)
Message-ID <ce8e3bb9-0a98-4c37-b60c-9737c0f32df2@b19g2000vbt.googlegroups.com> (permalink)
Subject Settling an old matter
From Trixter <mobygamer@gmail.com>
Injection-Date Thu, 25 Oct 2012 02:49:05 +0000
Content-Type text/plain; charset=ISO-8859-1
Content-Transfer-Encoding quoted-printable
Xref csiph.com comp.sys.ibm.pc.demos:35

Show key headers only | View raw


Nearly two decades ago, on this newsgroup as well as
comp.sys.ibm.pc.soundcard, there were some accusations flung around
that Josh Jensen (Cyberstrike / Renaissance) had copied entire chunks
of Mark J. Cox's MODPLAY to use in his own modplayer SuperProPlay (and
later MASI sound system).  Just as time has a way of healing old
wounds, advances in technology has a way of ripping them open again,
and a chance encounter with some familiar assembly code last night got
me thinking about the accusations against Jensen all those years ago.
I didn't give it much attention back then, but I'm a different person
now, with much more skill than I had 20 years ago.  With decades of
x86 assembler, reverse-engineering, and modplayer programming skills
under my belt, I decided to take another look at this issue to see if
it could be answered definitively.  Armed with much better RE tools
(IDA) and Josh's released Protracker Playing Source (PPS) v1.10 source
code (PPS110.ZIP), I spent about an hour last night looking at MODPLAY
and Josh's source.

My verdict:  Josh quite absolutely copied entire chunks of MODPLAY for
use in his own code.

When accused, Josh's paraphrased explanation at the time was "it's a
modplayer, of course some things are going to be the same from player
to player", but that only makes sense at a high level.  Yes, the
*basics* of playing a mod are the same across all players, such as
interpreting the data structures and effects, mixing four channels
into a single output channel, etc.  But the devil is in the details,
and it is the details that point to copying.  The code is not 100%
identical at an assembler level, but there are some very unique
choices Mark made in the original MODPLAY that mysteriously show up in
Josh's source, such as internal housekeeping, and the inner mixing
loop.

The mixing loop, I have found, is a good "fingerprint" for a modplayer
-- almost every author implements it in a different way.  There are
bare-metal fastest-possible implementation loops (such as the self-
modifying fixed-length code of Galaxy Player), loops optimized for low
memory usage (such as MODPLAY's loop which uses a MUL in the inner
loop), loops that trade memory for speed (such as TANTRAKR which uses
a 128K lookup table to eliminate MUL), and all sorts of targets
inbetween.  4 channels or N channels?  32-bit registers or 16-bit
registers?  Logarithmic or linear volume tables?  Just about every x86
mixing modplayer is different.  And the choice Mark Cox made --
utilizing a MUL in the inner loop and making heavy use of memory
variables -- was because he knew his target was a 286 or later and
could handle it.  You can also tell from the MODPLAY disassembly that
Mark was working in a vacuum, because his performance-sensitive code
is nowhere near as optimized as it could be (sorry Mark!).  Looking at
Jensen's source, you can see exactly the same methods at play,
including the inner loop (although Jensen made a few tiny 1- and 2-
opcode optimization changes here and there).

As much as I love the inner loop as a fingerprint, the most convincing
evidence that copying occurred is actually in the most boring sections
of both programs: The general housekeeping sections (things like
program startup/initialization, maintaining player state, etc.)  Mark
does something in MODPLAY that struck me as odd; he calls two tiny
procedures to set some variables based on whether or not a mod has 15
or 31 instruments (memory labels are my suggestions):

seg000:1E23 sub_1E23        proc near               ; CODE XREF:
sub_562D-1B73p
seg000:1E23                                          ; seg000:4B39p
seg000:1E23                 mov     sequence_offset, 1D8h
seg000:1E29                 mov     word_124, 258h
seg000:1E2F                 mov     header_size, 258h
seg000:1E35                 mov     num_inst, 0Fh
seg000:1E3B                 retn
seg000:1E3B sub_1E23        endp
seg000:1E3B
seg000:1E3C sub_1E3C        proc near               ; CODE XREF:
sub_562D:loc_3AACp
seg000:1E3C                 mov     sequence_offset, 3B8h
seg000:1E42                 mov     word_124, 438h
seg000:1E48                 mov     header_size, 43Ch
seg000:1E4E                 mov     num_inst, 1Fh
seg000:1E54                 retn
seg000:1E54 sub_1E3C        endp

That's a weird way to set some vars.  You don't normally call a tiny
procedure simply to set a handful of memory variables to fixed values
-- you just set the values directly.  It doesn't make any sense to do
it this way, and I don't know Mark's motivation for doing so.  This is
a very unusual section of code that I wouldn't expect to see again...

...and yet, Jensen follows the very same odd practice in PPM.ASM:

proc    sd_Set15Ins
	uses	ds
	mov	ax,@data
	mov	ds,ax
	mov	[Word NumberInstruments],15
	mov	[Word SequenceOffset],01D8h
	mov	[Word HeaderSize],0258h
	ret
endp	sd_Set15Ins

proc	sd_Set31Ins
	uses	ds
	mov	ax,@data
        mov     ds,ax
        mov     [Word NumberInstruments],31
	mov	[Word SequenceOffset],03B8h
	mov	[Word HeaderSize],043Ch
	ret
endp	sd_Set31Ins

Again, it's not the exact instructions that are copied or their order,
it's that entire concepts were copied, and because Mark implemented
them in a unique way, they stand out in Jensen's code.

As someone who has done a lot of cracking and reverse-engineering of
vintage software, Jensen's released source is full of other subtle
touches that indicate large sections of it are not his original work.
The most obvious are switching between hex and decimal values as a
basic notation from procedure to procedure; the copied chunks favor
hexidecimal notation while the original code favors decimal.  Also,
all throughout the code some lines are indented using 8-character tab
stops while other lines use spaces for padding which is indicative of
generating a file using one padding style and then editing it using
another style, which would not typically happen if you wrote all the
code from scratch.

In the last 20 years, Jensen has remained a professional programmer,
and just as my skills and integrity have increased over that time, I
have no doubt that his have increased as well.  It is not my intention
to libel Jensen as a whole; I simply wish to set the record straight
regarding only one of his claims.

Back to comp.sys.ibm.pc.demos | Previous | Next | Find similar


Thread

Settling an old matter Trixter <mobygamer@gmail.com> - 2012-10-24 19:49 -0700

csiph-web