Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.os.msdos.programmer > #629 > unrolled thread

A (UK) celebration

Started bypete@nospam.demon.co.uk
First post2012-06-03 07:46 +0000
Last post2012-06-05 13:39 +0000
Articles 5 — 3 participants

Back to article view | Back to comp.os.msdos.programmer


Contents

  A (UK) celebration pete@nospam.demon.co.uk - 2012-06-03 07:46 +0000
    Re: A (UK) celebration Nomen Nescio <nobody@dizum.com> - 2012-06-03 15:29 +0200
    Re: A (UK) celebration "Rod Pemberton" <do_not_have@notemailntt.cmm> - 2012-06-03 17:23 -0400
      Re: A (UK) celebration pete@nospam.demon.co.uk - 2012-06-04 06:31 +0000
        Re: A (UK) celebration pete@nospam.demon.co.uk - 2012-06-05 13:39 +0000

#629 — A (UK) celebration

Frompete@nospam.demon.co.uk
Date2012-06-03 07:46 +0000
SubjectA (UK) celebration
Message-ID<1338709568snz@nospam.demon.co.uk>
I wrote the following piece of code around 15 years ago in connection 
with the IOCCC Obfuscated C competition and it has just sat on my PC 
doing nothing since then.  You might be aware that the UK is celebrating 
its Queen's 60th year on the throne this weekend, so now seemed an 
appropriate time to re-release this piece of fripperie, just for a bit 
of fun.  It is for pure MSDOS; Windows? forget it!

It compiles straight out of the box for MSC 5.1 but might need some 
tweaking for other (16 bit DOS) compilers.  You might need to redefine 
_I_ and/or _O_ if your lib uses different names for inp() and outp() 
to access the hardware.  For example if your IN and OUT functions are 
called inb() and outb(), compile using

    $(cc) -D_I_=inb -D_O_=outb -o jubilee.exe jubilee.c

(best viewed using a fixed pitch font)

-------- Start jubilee.c --------

#ifndef _I_
#define _I_ inp
#endif
#ifndef _O_
#define _O_ outp
#endif

#define I int
#define C char
#define L long
#define V void
#define S static
#define R register
#define U unsigned

L m[]={0x08E90801L,0x08E90801L,0x07F00801L,0x096F1001L,0x08E90301L,0x7F00802L,
0x07120801L,0x07120801L,0x06AD0801L,/*00*/0x07121001L,0x07F00301L,0x08E90802L,
0x07F00801L,                     0x08E90801L,                     0x096F0801L,
/**/0x08E90802L,                 0x08E90201L,                 0x07F00201L,/**/
/*    */0x07120201L,             0x06AD0202L,             0x05F10801L,/*    */
/*        */0x05F10801L,         0x05F10801L,         0x05F11001L,/*        */
/*            */0x06AD0301L,     0x07120802L,     0x06AD0801L,/*            */
/*                */0x06AD0801L, 0x06AD0801L, 0x06AD1001L,/*                */
/*00000*/0x07120301L,0x07F00802L,0x07120801L,0x06AD0201L,0x07120201L,/*00000*/
/*00000*/0x07F00201L,0x08E90201L,0x07121001L,0x06AD0301L,0x05F10802L,/*00000*/
/*00000*/0x054B0301L,0x06AD0301L,0x07120C01L,0x07F00C01L,0x08E91001L,/*00000*/
0L}               ;S V _0_(),_1_ ();I main() {R L *p;for(p=m;               *p
!=             0L;p++)_1_(p);    return(0);}      S V _1_(s)R U C           *s
;{        _O_(0x43,0xb6);       _O_(0x42,s[2]         );_O_(0x42,s[         3]
);    _O_(0x61,_I_(              0x61)|3);_0_             (s[1]);_O_(0x61,/**/
_I_(0x61)&~3);                  _0_(s[0]);}/*                 0000000000000 */
#define K                        (*(U I far*)                     0x46cL)/***/
S V _0_ (t) R U I t;{R U I n;++t;do{n=K;while(n==K);}while(--t);}/*0x7F00802L,
0x07120801L,0x07120801L,0x06AD0801L,0x07121001L,0x07F00301L,0x08E90802L,0000*/

-------- End jubilee.c --------

Enjoy!
Pete
-- 
Believe those who are seeking the truth.
Doubt those who find it.  -  André Gide

[toc] | [next] | [standalone]


#630

FromNomen Nescio <nobody@dizum.com>
Date2012-06-03 15:29 +0200
Message-ID<9f3b2c8c4155c761577b45dc70983ee6@dizum.com>
In reply to#629
Fantastic...really a piece of art.

[toc] | [prev] | [next] | [standalone]


#631

From"Rod Pemberton" <do_not_have@notemailntt.cmm>
Date2012-06-03 17:23 -0400
Message-ID<jqgkir$7j5$1@speranza.aioe.org>
In reply to#629
<pete@nospam.demon.co.uk> wrote in message
news:1338709568snz@nospam.demon.co.uk...
> I wrote the following piece of code around 15 years ago in connection
> with the IOCCC Obfuscated C competition and it has just sat on my PC
> doing nothing since then.  You might be aware that the UK is celebrating
> its Queen's 60th year on the throne this weekend, so now seemed an
> appropriate time to re-release this piece of fripperie, just for a bit
> of fun.  It is for pure MSDOS; Windows? forget it!
>

It runs in a Windows 98/SE DOS "console" window just fine.

> It compiles straight out of the box for MSC 5.1 but might need some
> tweaking for other (16 bit DOS) compilers.  You might need to redefine
> _I_ and/or _O_ if your lib uses different names for inp() and outp()
> to access the hardware.  For example if your IN and OUT functions are
> called inb() and outb(), compile using
>
>     $(cc) -D_I_=inb -D_O_=outb -o jubilee.exe jubilee.c
>
> (best viewed using a fixed pitch font)
>
> -------- Start jubilee.c --------
>
> [program]
> -------- End jubilee.c --------
>


Well, I don't have MSC 5.1.  With a couple of changes, it'll compile with
OpenWatcom v1.3 from the command line.  Sorry, I don't have a more
recent version of OW installed to confirm if it compiles properly for it.

For OWv1.3, the 7th line from bottom needs a cast.
Change this:
  0L;p++)_1_(p);

To this:
  0L;p++)_1_((U C *)p);

For OWv1.3, the 3rd line from bottom needs the "volatile" keyword.
Change this:
  (*(U I far*)

To this:
  (*(volatile U I far*)

Then:
  wcl/l=dos jubilee.c


I hope you don't mind, but I un-obfuscated your program.  I removed all the
unecessary C qualifiers too - "static" "register" "L" - and converted part
of it to unsigned types.  I reworked it so that it works for OpenWatcom
(both RM and PM) and DJGPP (PM).  Hopefully, the code is clean enough that
others can convert it to the compiler of their choice.  Then, they can
listen to it, or learn how to program the PC speaker.  I sort of intuitively
and randomly assigned names for your procedures.  The commented out notes at
the end of the program didn't seem to add anything to the song, so I didn't
add them.

My conversion of your program for just those two compilers is after my .sig.
Other DOS compilers will need a compiler specific version of the "k" pointer
and appropriate defines for "inport" and "outport".

I haven't used the "volatile" keyword nor accessed DOS memory locations via
C pointers in a few years...  So, getting the "K" #define to work as a
pointer - needed for DJGPP - was not pleasant.  I'm still not sure why the
'L' is needed for the one pointer for OW ...  I almost switched to using
MK_FP().  That's probably something to do with the use of "int" instead of
"long" or "short" or perhaps lack of "unsigned".  I should've but didn't
convert the "int" ...


Rod Pemberton


/* gcc -O2 *//* PM DPMI */
#ifdef __DJGPP__
#include <sys/nearptr.h>
#include <pc.h>
#define inport inportb
#define outport outportb
#endif

/* wcl/l=dos *//* RM */
/* wcl386/l=dos4g *//* PM DPMI */
#ifdef __WATCOMC__
#include <i86.h>
#include <conio.h>
#define inport inp
#define outport outp
#endif

unsigned long music[]=
{
0x08E90801,0x08E90801,0x07F00801,0x096F1001,
0x08E90301,0x07F00802,0x07120801,0x07120801,
0x06AD0801,0x07121001,0x07F00301,0x08E90802,
0x07F00801,0x08E90801,0x096F0801,0x08E90802,
0x08E90201,0x07F00201,0x07120201,0x06AD0202,
0x05F10801,0x05F10801,0x05F10801,0x05F11001,
0x06AD0301,0x07120802,0x06AD0801,0x06AD0801,
0x06AD0801,0x06AD1001,0x07120301,0x07F00802,
0x07120801,0x06AD0201,0x07120201,0x07F00201,
0x08E90201,0x07121001,0x06AD0301,0x05F10802,
0x054B0301,0x06AD0301,0x07120C01,0x07F00C01,
0x08E91001,
0L
};

void length(unsigned int time)
{
  unsigned int n;

#ifdef __DJGPP__
  volatile unsigned int *k;
  k=(volatile unsigned int *)
    (0x46c+__djgpp_conventional_base);
#endif

#ifdef __WATCOMC__
#ifdef __386__
  volatile unsigned int *k;
  k=(volatile unsigned int *)0x46c;
#else
  volatile unsigned int far *k;
  k=(volatile unsigned int *)0x46cL;
#endif
#endif

  time++;
  do{
    n=*k;
    while(n==*k);
    time--;
  }while(time);

}

void note(unsigned char *song)
{
  outport(0x43,0xb6);
  outport(0x42,song[2]);
  outport(0x42,song[3]);
  outport(0x61,inport(0x61)|3);
  length(song[1]);
  outport(0x61,inport(0x61)&~3);
  length(song[0]);
}

int main(void)
{
  unsigned long *play;

#ifdef __DJGPP__
  __djgpp_nearptr_enable();
#endif

  for(play=music;*play!=0;play++)
    note((unsigned char *)play);

return(0);
}


[toc] | [prev] | [next] | [standalone]


#632

Frompete@nospam.demon.co.uk
Date2012-06-04 06:31 +0000
Message-ID<1338791474snz@nospam.demon.co.uk>
In reply to#631
In article <jqgkir$7j5$1@speranza.aioe.org>
           do_not_have@notemailntt.cmm "Rod Pemberton" writes:

> <pete@nospam.demon.co.uk> wrote in message
> news:1338709568snz@nospam.demon.co.uk...
> > I wrote the following piece of code around 15 years ago in connection
> > with the IOCCC Obfuscated C competition and it has just sat on my PC
> > doing nothing since then.  You might be aware that the UK is celebrating
> > its Queen's 60th year on the throne this weekend, so now seemed an
> > appropriate time to re-release this piece of fripperie, just for a bit
> > of fun.  It is for pure MSDOS; Windows? forget it!
> >
> 
> It runs in a Windows 98/SE DOS "console" window just fine.

Of course -- I was thinking XP/Win7 and forgot that lurkers here would 
still be running Win9x...

> > It compiles straight out of the box for MSC 5.1 but might need some
> > [...]
> 
> Well, I don't have MSC 5.1.  With a couple of changes, it'll compile with
> OpenWatcom v1.3 from the command line.  Sorry, I don't have a more
> recent version of OW installed to confirm if it compiles properly for it.

The older the compiler, the fewer the problems you're likely to run in 
to :-)  MSC5 handles K&R C so doesn't bitch too much about abouts 
casts and pointer abuse...

> For OWv1.3, the 7th line from bottom needs a cast.
> Change this:
>   0L;p++)_1_(p);
> 
> To this:
>   0L;p++)_1_((U C *)p);
> 
> For OWv1.3, the 3rd line from bottom needs the "volatile" keyword.
> Change this:
>   (*(U I far*)
> 
> To this:
>   (*(volatile U I far*)
> 
> Then:
>   wcl/l=dos jubilee.c
> 
> 
> I hope you don't mind, but I un-obfuscated your program.

Not at all -- I would have done the same!  It was after all just a bit 
of fun.

>     I removed all the
> unecessary C qualifiers too - "static" "register" "L" - and converted part
> of it to unsigned types.  I reworked it so that it works for OpenWatcom
> (both RM and PM) and DJGPP (PM).  Hopefully, the code is clean enough that
> others can convert it to the compiler of their choice.  Then, they can
> listen to it, or learn how to program the PC speaker.  I sort of intuitively
> and randomly assigned names for your procedures.  The commented out notes at
> the end of the program didn't seem to add anything to the song, so I didn't
> add them.

[ASCII] Artistic licence ;-)  Some more "code" was needed to complete 
the picture/

> My conversion of your program for just those two compilers is after my .sig.
> Other DOS compilers will need a compiler specific version of the "k" pointer
> and appropriate defines for "inport" and "outport".
> 
> I haven't used the "volatile" keyword nor accessed DOS memory locations via
> C pointers in a few years...  So, getting the "K" #define to work as a
> pointer - needed for DJGPP - was not pleasant.  I'm still not sure why the
> 'L' is needed for the one pointer for OW ...  I almost switched to using
> MK_FP().  That's probably something to do with the use of "int" instead of
> "long" or "short" or perhaps lack of "unsigned".  I should've but didn't
> convert the "int" ...

FWIW the first cut of the program was for MWC-86 (small model only) 
and used its peek(offset, seg) lib function for reading the clock counter.

> 
> Rod Pemberton
> 
[snip un-obfuscated code]

Thanks for taking the time to deconstruct and clean up the program for 
other compilers!

Pete

PS. I just retried the original code with BC++ 3.1 and it compiled OK, 
albeit with several warnings about lack of prototypes.
-- 
Believe those who are seeking the truth.
Doubt those who find it.  -  André Gide

[toc] | [prev] | [next] | [standalone]


#633

Frompete@nospam.demon.co.uk
Date2012-06-05 13:39 +0000
Message-ID<1338903545snz@nospam.demon.co.uk>
In reply to#632
Just to put this thread to bed (for a few more years) I thought I 
would update Rod's deconstructed code to remove the obfuscation of the 
"long *" and "char *" (and modern compilers' need to explicitly cast 
them).  And also provide some support code for anyone else wanting to 
write "music" for the PC speaker.

1. Instead of the "long music[]" array, try this instead:

struct asbyte {
  unsigned char lo;
  unsigned char hi;
};

union DIVISOR {
  unsigned short w;
  struct asbyte b;
};

struct TUNE {
  union DIVISOR divisor;
  unsigned char ontime;
  unsigned char offtime;
};

initialised as:

struct TUNE music[] = {

  { { 0x08E9 }, 0x08, 0x01 },
  { { 0x08E9 }, 0x08, 0x01 },
  { { 0x07F0 }, 0x08, 0x01 },
  { { 0x096F }, 0x10, 0x01 },
  { { 0x08E9 }, 0x03, 0x01 },
  { { 0x07F0 }, 0x08, 0x02 },
  { { 0x0712 }, 0x08, 0x01 },
  { { 0x0712 }, 0x08, 0x01 },
  { { 0x06AD }, 0x08, 0x01 },
  { { 0x0712 }, 0x10, 0x01 },
  { { 0x07F0 }, 0x03, 0x01 },
  { { 0x08E9 }, 0x08, 0x02 },
  { { 0x07F0 }, 0x08, 0x01 },
  { { 0x08E9 }, 0x08, 0x01 },
  { { 0x096F }, 0x08, 0x01 },
  { { 0x08E9 }, 0x08, 0x02 },
  { { 0x08E9 }, 0x02, 0x01 },
  { { 0x07F0 }, 0x02, 0x01 },
  { { 0x0712 }, 0x02, 0x01 },
  { { 0x06AD }, 0x02, 0x02 },
  { { 0x05F1 }, 0x08, 0x01 },
  { { 0x05F1 }, 0x08, 0x01 },
  { { 0x05F1 }, 0x08, 0x01 },
  { { 0x05F1 }, 0x10, 0x01 },
  { { 0x06AD }, 0x03, 0x01 },
  { { 0x0712 }, 0x08, 0x02 },
  { { 0x06AD }, 0x08, 0x01 },
  { { 0x06AD }, 0x08, 0x01 },
  { { 0x06AD }, 0x08, 0x01 },
  { { 0x06AD }, 0x10, 0x01 },
  { { 0x0712 }, 0x03, 0x01 },
  { { 0x07F0 }, 0x08, 0x02 },
  { { 0x0712 }, 0x08, 0x01 },
  { { 0x06AD }, 0x02, 0x01 },
  { { 0x0712 }, 0x02, 0x01 },
  { { 0x07F0 }, 0x02, 0x01 },
  { { 0x08E9 }, 0x02, 0x01 },
  { { 0x0712 }, 0x10, 0x01 },
  { { 0x06AD }, 0x03, 0x01 },
  { { 0x05F1 }, 0x08, 0x02 },
  { { 0x054B }, 0x03, 0x01 },
  { { 0x06AD }, 0x03, 0x01 },
  { { 0x0712 }, 0x0C, 0x01 },
  { { 0x07F0 }, 0x0C, 0x01 },
  { { 0x08E9 }, 0x10, 0x01 },
};

#define NR_NOTES (sizeof(music)/sizeof(struct TUNE))

The note() and main() functions then become

void note(struct TUNE *song)
{
  outport(0x43,0xb6);
  outport(0x42,song->divisor.b.lo);
  outport(0x42,song->divisor.b.hi);
  outport(0x61,inport(0x61)|3);
  length(song->ontime);
  outport(0x61,inport(0x61)&~3);
  length(song->offtime);
}

int main(void)
{
  struct TUNE *play;

#ifdef __DJGPP__
  __djgpp_nearptr_enable();
#endif

  for (play = music; play < music + NR_NOTES; play++)
    note(play);

  return 0;
}

2. This program is an aid to establishing the correct timer divisor to 
produce the frequency of the desired notes:

#include <stdio.h>
#include <math.h>

double	timer_freq = 1193180.0; /* countdown timer freq */
double	middleC = 261.625;	/* frequency (Hz) of middle C */

char *octave[] = {
     "C ", "C#", "D ", "D#", "E ", "F ",
     "F#", "G ", "G#", "A ", "A#", "B "
};

#define OSIZE	(sizeof(octave)/sizeof(char *))

#define NR_OCTAVES  8   /* or however many you want */

int main()
{
  int     oct;
  double  startC;
  double  _12root2 = pow (2.0, 1.0/12.0); /* twelfth root of 2 */

  for (oct = 0, startC = middleC / 8.0; /* start 3 octaves lower */
       oct < NR_OCTAVES;
       oct++, startC *= 2.0)
  {
    int i;
    double freq = startC;

    printf ("---------\nOctave %d:\n---------\n", oct);

    for (i = 0; i < OSIZE; i++, freq *= _12root2)
    {
      double div = timer_freq / freq;
      printf ("%s freq = %7.2lf, divisor = %8.2lf [0x%04lx]\n",
                octave[i], freq, div, (long) (div + 0.5));
    }
  }
  return 0;
}

Pete
-- 
Believe those who are seeking the truth.
Doubt those who find it.  -  André Gide

[toc] | [prev] | [standalone]


Back to top | Article view | comp.os.msdos.programmer


csiph-web