1. 8
  1.  

  2. 5

    I am a HUGE fan of retro computing, but I’ve gotta say. I just don’t care.

    Microsoft “stole” from IBM, IBM “stole” from Honeywell, EVERYBODY “stole” from Von Neumann, and his ideas were a cheap knock off of Babbage.

    (OK so not really but you get my point.)

    1. 5

      hard to believe any smoking guns would actually have been published given the authors position with Microsoft

      1. 2

        If the sources are available, I would have guessed as much from the fact that no one reported something like this yet.

        1. 1

          That sounds similar to the many eyeballs argument. That one was refuted by the bugs found that were over a decade old in widely-used software. Someone would have to look, find evidence, present thin-looking evidence in a way they thought would achieve something, get noticed enough for us to know that, and (important if I did it) be ready to take all the legal muscle Microsoft would throw at you.

          I don’t think an absence of evidence proves anything here given nature of the evidence and chilling effect legal system might create. Also, I have no beliefs about this investigation one way or another: just noting many eyeballs doesn’t work consistently or prove anything. You need talented, time-consuming, trustworthy review instead for stuff like that.

      2. 4

        That’s a very long winded account of finding “goto error” in two different programs.

        1. 4

          Just another confirmation of Betteridge.

          1. 4

            That’s like saying your blog posts are a time-consuming way to display certificate warnings on others’ screens. Leaves out some detail people might enjoy reading.

            Main thing that was interesting to me is how he identifies or refutes whether something looked copied.

          2. 3

            The question wrestled with here is whether the source code was directly copied from CP/M to create QDOS. This isn’t the only relevant question; also relevant is whether QDOS copied the API.

            Starting with commands, we have:

            CP/M   86-DOS  Meaning
            ------------------------------------
            ERA    DEL    Delete a file
            DIR    DIR    List files on disk
            REN    REN    Rename a file
            SAVE   ?      Save a file to disk
            TYPE   TYPE   Print the contents of a file to the console
            

            What about system calls?

            #   CP/M                   86-DOS
            ----------------------------------------------
            0   System Reset           Program Terminate
            1   Console Input          Console Input
            2   Console Output         Console Output
            3   Reader Input           Auxiliary Input
            4   Punch Output           Auxiliary Output
            5   List Output            Printer Output
            6   Direct Console I/O     Direct Console I/O
            7   Get I/O Byte           ?
            8   Set I/O Byte           ?
            9   Print String           Output String
            10   Read Console Buffer   Input String
            11   Get Console Status    Check Console Status
            12   Return Version Number ?
            13   Reset Disk System     Disk System Reset
            14   Select Disk           Select Default Drive
            15   Open File             Open File
            16   Close File            Close File
            17   Search for First      Search for First
            18   Search for Next       Search for Next
            19   Delete File           Delete File
            20   Read Sequential       Sequential Read
            21   Write Sequential      Sequential Write
            22   Make File             Create File
            23   Rename File           Rename File
            24   Return Login Vector   ?
            25   Return Current Disk   Get Default Drive
            26   Set DMA Address       Set Disk I/O Address
            27   Get Addr (Alloc)      Allocation Address
            28   Write Protect Disk    ?
            29   Get Read/Only Vector  ?
            30   Set File Attributes   ?
            31   Get Addr (Disk Parms) Parameter Address
            32   Set/Get User Code     ?
            33   Read Random           Random Read
            34   Write Random          Random Write
            35   Compute File Size     Get File Size
            36   Set Random Rector     Get File Address
            

            Of these, the only one that’s really different is the last one (#36). The others are the same, as I understand, to facilitate porting code from CP/M to 86-DOS. Sounds a lot like the Oracle/Google debate/lawsuit to me.

            There are more similarities, too, beyond just the API. Both systems have a jump vector to make it easy to port to new hardware:

            CP/M              86-DOS
            ---------------------------------------
            4A00  JMP BOOT    0400  JMP INIT
            4A03  JMP WBOOT   0403  JMP STATUS
            4A06  JMP CONST   0406  JMP CONIN
            4A09  JMP CONIN   0409  JMP CONOUT
            4A0C  JMP CONOUT  040C  JMP PRINT
            4A0F  JMP LIST    040F JMP AUXIN
            4A12  JMP PUNCH   0412 JMP AUXOUT
            4A15  JMP READER  0415 JMP READ
            4A18  JMP HOME    0418  JMP WRITE
            4A1B  JMP SELDISK 041B  JMP FLUSH
            4A1E  JMP SETTRK  x
            4A21  JMP SETSEC  x
            4A24  JMP SETDMA  x
            4A27  JMP READ    x
            4A2A  JMP WRITE   x
            4A2D  JMP LISTST  x
            4A30  JMP SECTRAN x
            

            So 86-DOS skips some entries like WBOOT, but for the most part, these entries line up.

            Any how about the boot loaders? They look superficially different, but I think there are some interesting similarities.

            CP/M                                    86-DOS
            ---------------------------------------------------------------------------------------
            cold:
              lxi b,2 ; b=0, c=sector 2             MOV DI,LOAD  
              mvi d,sects                           MOV DX,SECTOR               
              lxi h,ccp                             MOV BL,2                    
            
            lsect:                                  SECT:
              ; load the next sector                  MOV AL,0D0H ; Force interrupt command
                                                      OUT DISK    ; To force Type I status
              ;    insert inline code at this         AAM                       
              ;    point to read 128 byte sector      CMP BL,MAXSECT+1 
              ;    from the track given in            JNZ NOSTEP   
              ;    register b, sector given in        MOV AL,58H ; Step in with update
              ;    register c, into the address       CALL DCOM
              ;    given by <hl>                      MOV BL,1
              ;                                     NOSTEP:
              ; branch to location "cold" if a        MOV AL,BL
              ; read error occurs                     OUTB DISK+2  
                                                      inb disk ; Get head load status
                                                      NOT AL
                                                      AND AL,20H   
                                                      JZ OUTCOM
                                                      MOV AL,4
                                                    OUTCOM:
                                                      OR AL,READCOM
                                                      OUTB DISK
                                                      MOV CX,128   
                                                      PUSH DI
                                                    READ:
              ; ************************              INB DISK+4   
              ; * user supplied read                  TEST AL,DONEBIT
              ; * operation goes here...              JNZ DONE
              ; ************************              INB DISK+3   
                                                      STOB
                                                      LOOP READ
              dcr d ; sects=sects-1                 DONE:                       
                                                      POP DI
              jz boot ; head for the bios             CALL GETSTAT 
                ; more sectors to load                
                ; we aren't using a stack,
                ; so use <sp> as as scratch
                ; register to hold the load        
                ; address segment                     
              lxi sp,128 ; 128 bytes per sector       
              dad sp ; <hl> = <hl> + 128              
              incr c ; sector = sector + 1                                      
              cpi 27 ; last sector of track?         AND AL,9CH
              jc lsect ; no, go read another         JNZ SECT
                ; end of track, increment to         ADD DI,128
                ; next track
              mvi c,1 ; sector = 1                                              
              inr b ; track = track + 1              INC BL
                                                     DEC DX
              jmp lsect ; for another group          JNZ SECT           
                                                     JMP 0,SEG
                                                   DCOM:
                                                     OUT DISK
                                                     AAM
            

            Sources: