/* A quick and dirty reader was created in order to read the ROM
   content of Kenwood R-2000 communication receiver. 

   DB0..DB7 connected to D0..D7 of parallel port.
   nRESET connected to nC0 of parallel port.
   EA = 12V
   4MHz crystal + 2x 20pF ceramic capacitors.

   80c49 has 2KB of ROM. Upper 4bit of address is set by PB0..PB3.
   Since the size is 2K, only PB0..PB2 are meaningful.  I just used
   jumpers to set the most significant 3 bits of address. the remaining
   8 bits are set through parallel port's D0..D7.

   One execution dumps 256 bytes. 8 different jumper combinations are
   possible, and by concatenating eight 256B files, I got 2KB of code.
 */

#include<stdio.h>
#include<sys/io.h>
#include<unistd.h>

#define BASE 0x378
                                                                              
                                                                              
#define wr(data) (data & 0xcf)
#define rd(data) (data | 0x20)
#define b1off(data) (data & 0xfe)
#define b1on(data) (data | 0x01)

unsigned char read_8049(int addr)
{
                                                                              
   int data, j, a, b, max;
   unsigned char tmp, code;
   unsigned char buff[40];

   /* we read a byte 40 times. why? because there are errors. the error
      rate is as high as 15% when I tested.  Inserting delays can lower
      the error rate, but won't eliminate it.  I removed artificial
      delays after implementing "the redundant read and vote" thing.
    */
   for (j=0; j<40; j++)
   {
        tmp = wr(inb(BASE+2));   // Write
        tmp = b1off(tmp);         // RESET off
        outb(tmp, BASE+2);
        outb((unsigned char)addr, BASE);  // ADDR
        // blink reset
        outb(b1on(inb(BASE+2)), BASE+2);
        outb(b1off(inb(BASE+2)), BASE+2);
        tmp = rd(inb(BASE+2));   // Read
        outb(tmp, BASE+2);
        buff[j] = inb(BASE+4);
   }

   /* find the most frequent one among 40 reads */
   max=0;
   for (j=0; j<40; j++)
   {
        tmp = buff[j];
        a = 0;
        for (b=j; b<40; b++)
        {
           if(buff[b]==tmp) a++;
        }
        if(a > max)
        {
           code = tmp;
           max = a;
        }
   }
   return code;
}

int main()
{
	int i;

	/* initialize */	
	if (iopl(3)) return 1;
	
	for(i=0; i <= 0xff; i++)
		printf("%c", read_8049(i));
}
