Author Topic: Leaked Original SCI Source  (Read 10346 times)

0 Members and 1 Guest are viewing this topic.

Offline OmerMor

Leaked Original SCI Source
« on: November 26, 2015, 03:34:56 PM »
Hi,
I got my hands on leaked sci source code. Unfortunately I can't share it in its entirety.
Please don't try to pressure me on this.

I will however share a few bits. Hopefully it'll help us all understand SCI better.

Here's the SAVE.SC script:
Code: [Select]
;;;;
;;;;  SAVE.SC
;;;;
;;;;  (c) Sierra On-Line, Inc, 1992
;;;;
;;;;  Author:  Jeff Stephenson
;;;;  Updated: Brian K. Hughes
;;;;
;;;;  Classes which create the save/restore game user interface.  Also
;;;;  contains a number of instances of Dialogs and associated DItems
;;;;  used in the interface.
;;;;
;;;;  Classes:
;;;;     SRDialog
;;;;     Save
;;;;     Restore


(script# SAVE)


(include "990.shm")

(define  GAMESSHOWN 8)     ;the number of games displayed in the selector
(define  MAXGAMES 20)      ;maximum number of games in a save directory
(define  COMMENTSIZE 36)   ;size of user's description of the game
(define  COMMENTBUFF (/ (+ 1 COMMENTSIZE) 2))

(define  DIRECTORYSIZE 29) ;size of the save directory name
(define  DIRECTORYBUFF (/ (+ 1 DIRECTORYSIZE) 2))

(define  BUFFERSIZE (+ (* MAXGAMES COMMENTBUFF) 1))


(procedure
   GetDirectory
   HaveSpace
   GetStatus
   NeedDescription
)

(public
   GetDirectory   0
)

(local
   default
   i
   numGames
   selected
   theStatus
   [butbuf1 15]
   [butbuf2 15]
   [butbuf3 15]
   [butbuf4 15]
   [SRbuf 25]
)



(enum
   RESTORE        ;Restore games
   HAVESPACE      ;Save, with space on disk
   NOSPACE        ;Save, no space on disk but games to replace
   NOREPLACE      ;Save, no space on disk, no games to replace
)

(class SRDialog kindof Dialog
   ;;; The SRDialog class implements the user interface for save/restore.
   ;;; Its subclasses are the specific save and restore game dialogs,
   ;;; Save and Restore.

   (method (dispose)
      (super dispose: &rest)
   )

   (method (init theComment names nums
         &tmp [buf 250]
      )

      ;; Initialize the dialog.

      ; give ourself the system window as our window
      (= window systemWindow)

      ;Re-init our size, with no elements.
      (= nsBottom 0)

      ;Get some files for this directory.
      (= numGames (GetSaveFiles (theGame name?) names nums))
      (if (== numGames -1)
         (return FALSE)
      )

      (= theStatus (GetStatus))

      ;Set up the edit item for saved games.
      (if (== theStatus HAVESPACE)
         (editI
            text: (StrCpy theComment names),
            font: smallFont,
            setSize:,
            moveTo: MARGIN MARGIN
         )
         (self add: editI, setSize:)
      )

      ;Set up the selectorI box.
      (selectorI
         text: names,
         font: smallFont,
         setSize:,
         moveTo: MARGIN (+ nsBottom MARGIN),
         state: dExit
      )

      ;Add four buttons down the side.
      (switch theStatus
         (0
            (Message MsgGet SAVE BUTTON_RESTORE NULL NULL 1 @butbuf1)
         )
         (1
            (Message MsgGet SAVE BUTTON_SAVE NULL NULL 1 @butbuf1)
         )
         (else
            (Message MsgGet SAVE BUTTON_REPLACE NULL NULL 1 @butbuf1)
         )
      )
      (= i (+ (selectorI nsRight?) MARGIN))
      (okI
         text: @butbuf1,
         setSize:,
         moveTo: i (selectorI nsTop?),
         state:
            (if (or
                  (and (== theStatus RESTORE) (not numGames))
                  (== theStatus NOREPLACE)
                )
                  0
            else
               (| dActive dExit)
            )
      )
      (Message MsgGet SAVE BUTTON_DELETE NULL NULL 1 @butbuf2)
      (deleteI
         text:       @butbuf2,
         setSize:,
         moveTo:     i (+ (okI nsBottom?) MARGIN),
         state:      (if (not numGames)
                        0
                     else
                        (| dActive dExit)
                     )
      )
      (Message MsgGet SAVE BUTTON_CHANGE NULL NULL 1 @butbuf3)
      (changeDirI
         text:    @butbuf3,
         setSize:,
         moveTo:  i (+ (deleteI nsBottom?) MARGIN),
         state:   (& (changeDirI state?) (~ dSelected))
      )
      (Message MsgGet SAVE BUTTON_CANCEL NULL NULL 1 @butbuf4)
      (cancelI
         text:       @butbuf4,
         setSize:,
         moveTo:     i (+ (changeDirI nsBottom?) MARGIN),
         state:      (& (cancelI state?) (~ dSelected))
      )

      ;Put these elements into the dialog and size it.
      (self
         add: selectorI okI deleteI changeDirI cancelI,
         setSize:
      )

      ;Use the width of the dialog to size the text which goes into it.
      (switch theStatus
         (0
            (Message MsgGet SAVE SELECT_GAME NULL NULL 1 @buf)
         )
         (1
            (Message MsgGet SAVE TYPE_DESC NULL NULL 1 @buf)
         )
         (else
            (Message MsgGet SAVE DIR_NOROOM NULL NULL 1 @buf)
         )
      )
      (textI
         text: @buf,
         setSize: (- (- nsRight nsLeft) (* 2 MARGIN)),
         moveTo: MARGIN MARGIN
      )

      ;Now move all elements down by the height of the text.
      (= i (+ (textI nsBottom?) MARGIN))
      (self eachElementDo: #move: 0 i)

      ;Add the text to the dialog, and resize.
      (self
         add: textI,
         setSize:,
         center:,
         open: wTitled -1        ;don't save PMAP
;***        open: wTitled 15
      )

      (return TRUE)
   )




   (method  (doit theComment
                  &tmp  fd ret offset
                        [names BUFFERSIZE] [nums (+ MAXGAMES 1)]
                        [str 100] [dir 40]
            )

      ;If restore: is called with a TRUE parameter, do nothing if there
      ;are no saved games.  This allows optionally presenting the user
      ;with his saved games at the start of the game.
      (if
         (and
            (== self Restore)
            argc
            theComment
         )

         (= fd (FileIO fileOpen (Format @str {%ssg.dir} (theGame name?))))
         (if (== fd -1)
            ;no directory -> no saved games
            (return)
         )
         (FileIO fileClose fd)
      )

      (if (not (self init: theComment @names @nums))
         (return -1)
      )

      (repeat
         (= default
            (switch theStatus
               (RESTORE
                  (if numGames okI else changeDirI)
               )
               (HAVESPACE
                  ;Edit item of save games is active if present
                  editI
               )
               (NOSPACE
                  ;If there are save-games to replace, 'Replace'
                  ;button is active.
                  okI
               )
               (else
                  ;Otherwise 'Change Directory' button is active.
                  changeDirI
               )
            )
         )

         (= i (super doit: default))

         (= selected (selectorI indexOf: (selectorI cursor?)))
         (= offset (* selected COMMENTBUFF))
         (cond
            ((== i changeDirI)
               ;; kill save window to save hunk
               (self dispose:)
               (if (GetDirectory curSaveDir)
                  (= numGames
                     (GetSaveFiles (theGame name?) @names @nums)
                  )
                  (if (== numGames -1)
                     (= ret -1)
                     (break)
                  )
               )
               ;; open save back up with new directory
               (self init: theComment @names @nums)
            )

            ((and (== theStatus NOSPACE) (== i okI))
               (self dispose:)
               (if (GetReplaceName doit: (StrCpy theComment @[names offset]))
                  (= ret [nums selected])
                  (break)
               )
               (self init: theComment @names @nums)
            )

            ((and (== theStatus HAVESPACE) (or (== i okI) (== i editI)))
               (if (== (StrLen theComment) 0)
                  (self dispose:)
                  (NeedDescription)
                  (self init: theComment @names @nums)
                  (continue)
               )

               (= ret -1)
               (for  ((= i 0))
                     (< i numGames)
                     ((++ i))

                  (= ret (StrCmp theComment @[names (* i COMMENTBUFF)]))
                  (breakif (not ret))
               )

               (cond
                  ((not ret)
                     (= ret [nums i])
                  )
                  ((== numGames MAXGAMES)
                     (= ret [nums selected])
                  )
                  (else
                     ; find the lowest unused game number
                     (for ((= ret 0)) TRUE ((++ ret))
                        (for ((= i 0)) (< i numGames) ((++ i))
                           (breakif (== ret [nums i])) ; this number is used
                        )
                        (if (== i numGames)  ; checked all entries in nums
                           (break)           ; and none matched
                        )
                     )
                  )
               )
               (break)
            )
           
            ((== i deleteI)
               ;; kill save window to save hunk
               (self dispose:)
               ; confirm deletion
               (if (not
                  ((Print new:)
                     addText:    DEL_TEXT NULL NULL 1 0 0 SAVE,
                     addButton:  FALSE BUTTON_NO NULL NULL 1 0 35 SAVE,
                     addButton:  TRUE  BUTTON_YES NULL NULL 1 50 35 SAVE,
                     init:
                   ))
                  (self init: theComment @names @nums)
                  (continue)
               )
               
               ; open the saved game directory file
               ((= fd (File new:))
                  name: (DeviceInfo MakeSaveDirName @str (theGame name?)),
                  open: fTrunc,
               )
               
               ; (File write:) requires a pointer to the data it is to write,
               ; so need to put values into variables, rather than just
               ; passing them as immediates
               (= ret $0a0a)  ; so both high and low byte is correct

               ; write the number and name of each saved game, except the
               ; one that was selected for deletion
               (for ((= i 0)) (< i numGames) ((++ i))
                  (if (!= i selected)
                     (fd write: @[nums i] 2)
                     (fd writeString: @[names (* i COMMENTBUFF)])
                     (fd write: @ret 1)
                  )
               )

               ; terminate saved game directory with a word of f's
               (= ret -1)
               (fd
                  write: @ret 2,
                  close:,
                  dispose:,
               )

               ; delete the save game file itself
               (DeviceInfo MakeSaveFileName
                     @str (theGame name?) [nums selected]
               )
               (FileIO fileUnlink @str)

               ; reinit to display updated dialog
               (self init: theComment @names @nums)
            )

            ((== i okI)
               (= ret [nums selected])
               (break)
            )

            ((or (== i -1) (== i cancelI))
               (= ret -1)
               (break)
            )

            ((== theStatus HAVESPACE)
               (editI
                  cursor:
                     (StrLen (StrCpy theComment @[names offset])),
                  draw:
               )
            )
         )
      )
      (DisposeScript FILE)
      (self dispose:)
      (DisposeScript SAVE)
      (return ret)
   )

   (procedure (GetStatus)
      (return
         (cond
            ((== self Restore)
               RESTORE
            )
            ((HaveSpace)
               HAVESPACE
            )
            (numGames
               NOSPACE
            )
            (else
               NOREPLACE
            )
         )
      )
   )
)

(class Restore of SRDialog
   (method (init)
      (Message MsgGet SAVE DIALOG_RESTORE NULL NULL 1 @SRbuf)
      (= text @SRbuf)
      (super init: &rest)
   )
)

(class Save of SRDialog
   (method (init)
      (Message MsgGet SAVE DIALOG_SAVE NULL NULL 1 @SRbuf)
      (= text @SRbuf)
      (super init: &rest)
   )
)

(instance GetReplaceName of Dialog

   (method (doit theComment
         &tmp ret [buf1 15] [buf2 15] [buf3 15] [buf4 15]
      )

      ; give ourself the system window as our window
      (= window systemWindow)

      (Message MsgGet SAVE DTEXT_REPLACE NULL NULL 1 @buf1)
      (text1
         text:    @buf1,
         setSize:,
         moveTo:  MARGIN MARGIN
      )
      (self add:text1, setSize:)
      (oldName
         text: theComment,
         font: smallFont,
         setSize:,
         moveTo:MARGIN nsBottom
      )
      (self add:oldName, setSize:)
      (Message MsgGet SAVE DTEXT_WITH NULL NULL 1 @buf2)
      (text2
         text:    @buf2,
         setSize:,
         moveTo:  MARGIN nsBottom
      )
      (self add:text2, setSize:)
      (newName
         text: theComment,
         font: smallFont,
         setSize:,
         moveTo: MARGIN nsBottom
      )
      (self add:newName, setSize:)

      (Message MsgGet SAVE DTEXT_REPLACE NULL NULL 1 @buf3)
      (button1
         text:       @buf3,
         nsLeft:     0,
         nsTop:      0,
         setSize:
      )
      (Message MsgGet SAVE BUTTON_NODIRCHG NULL NULL 1 @buf4)
      (button2
         text:       @buf4,
         nsLeft:     0,
         nsTop:      0,
         setSize:
      )
      (button2
         moveTo:
            (- nsRight (+ (button2 nsRight?) MARGIN))
            nsBottom
      )
      (button1
         moveTo:
            (- (button2 nsLeft?) (+ (button1 nsRight?) MARGIN))
            nsBottom
      )

      (self
         add:button1 button2,
         setSize:,
         center:,
         open:stdWindow -1       ;don't save PMAP
;***        open:stdWindow 15
      )

      (= ret (super doit:newName))
      (self dispose:)
      (if (not (StrLen theComment))
         (NeedDescription)
         (= ret 0)
      )

      (return (or (== ret newName) (== ret button1)))
   )
)
(procedure (GetDirectory where &tmp result
            [newDir 40] [str 100] [buf1 50] len
            )
   (repeat
      (= len (+ (Max DIRECTORYSIZE (+ (StrLen where) 6)) 11))
      (= result
         ((Print new:)
            font:       SYSFONT,
            addText:    DIR_PROMPT NULL NULL 1 0 0 SAVE,
            addEdit:    (StrCpy @newDir where) len 0 20 where,
            addButton:  TRUE BUTTON_OK NULL NULL 1 0 34 SAVE,
            addButton:  FALSE BUTTON_NODIRCHG NULL NULL 1 50 34 SAVE,
            init:
         )
      )

      ;Pressed ESC -- return FALSE.
      (if (not result)
         (return FALSE)
      )

      ;No string defaults to current drive.
      (if (not (StrLen @newDir))
         (GetCWD @newDir)
      )

      ;If drive is valid, return TRUE, otherwise complain.
      (if (ValidPath @newDir)
         (StrCpy where @newDir)
         (return TRUE)
      else
         (Message MsgGet SAVE DIR_INVALID NULL NULL 1 @buf1)
         (Format @str @buf1 @newDir)
         ((Print new:)
            font:    SYSFONT,
            addText: @str,
            init:
         )
      )
   )
)

(procedure (HaveSpace)
   (return (and (< numGames MAXGAMES) (CheckFreeSpace curSaveDir)))
)

(procedure (NeedDescription)
   ((Print new:)
      font:    SYSFONT,
      addText: NO_DESC NULL NULL 1 0 0 SAVE,
      init:
   )
)


(instance selectorI of DSelector
   (properties
      x: COMMENTSIZE
      y: GAMESSHOWN
   )
)

(instance editI of DEdit
   (properties
      max: (- COMMENTSIZE 1)
   )
)

(instance okI of DButton
   (method (dispose)
      (super dispose: TRUE)
   )
)

(instance cancelI of DButton
   (method (dispose)
      (super dispose: TRUE)
   )
)

(instance changeDirI of DButton
   (method (dispose)
      (super dispose: TRUE)
   )
)

(instance deleteI of DButton
   (method (dispose)
      (super dispose: TRUE)
   )
)

(instance textI of DText
   (properties
      font: SYSFONT
   )
   (method (dispose)
      (super dispose: TRUE)
   )
)

(instance text1 of DText
   (properties
      font: SYSFONT
   )
   (method (dispose)
      (super dispose: TRUE)
   )
)

(instance text2 of DText
   (properties
      font: SYSFONT
   )
   (method (dispose)
      (super dispose: TRUE)
   )
)

(instance oldName of DText
   (method (dispose)
      (super dispose: TRUE)
   )
)

(instance newName of DEdit
   (properties
      max: (- COMMENTSIZE 1)
   )
)

(instance button1 of DButton
   (method (dispose)
      (super dispose: TRUE)
   )
)

(instance button2 of DButton
   (method (dispose)
      (super dispose: TRUE)
   )
)



Offline troflip

Re: Leaked Original SCI Source
« Reply #1 on: November 26, 2015, 03:55:39 PM »
Wow, cool!

Some interesting things in there... the array syntax I don't think we've seen before. Looks like

Code: [Select]
// SCI Studio
buffer[100]

// Sierra
[buffer 100]

I see a cond statement in there too, which is like LISP. And a repeat statement.

And it looks like they use a strange syntax for temp variables:

Code: [Select]
(method (doit theComment
&tmp ret [buf1 15] [buf2 15] [buf3 15] [buf4 15]
)

.. they are declared inline with the method parameters. Interesting... lots to look at in there!
Check out my website: http://icefallgames.com
Groundhog Day Competition

Online Kawa

Re: Leaked Original SCI Source
« Reply #2 on: November 26, 2015, 04:13:51 PM »
Oh this is exciting!

Offline MusicallyInspired

Re: Leaked Original SCI Source
« Reply #3 on: November 26, 2015, 05:40:28 PM »
So cool! Thanks for sharing this!
Brass Lantern Prop Competition

Online Kawa

Re: Leaked Original SCI Source
« Reply #4 on: November 26, 2015, 05:48:07 PM »
Maybe with this the decompiler can be improved so it doesn't have to fall back to assembly for SRDialog::doit and proc990_0 GetDirectory :D

Offline troflip

Re: Leaked Original SCI Source
« Reply #5 on: November 26, 2015, 06:25:39 PM »
Possibly, but the decompiler is very complex, and I'm not sure the amount-of-work to benefit ratio would be good.
Check out my website: http://icefallgames.com
Groundhog Day Competition

Online Kawa

Re: Leaked Original SCI Source
« Reply #6 on: November 26, 2015, 07:04:59 PM »
Even with all the other fallen-back scripts?

Offline troflip

Re: Leaked Original SCI Source
« Reply #7 on: November 26, 2015, 07:19:23 PM »
I think only about 2% of the code "falls back" to assembly. Making changes to the decompiler at this point is too risky, and the functions in assembly don't block people from making games.

Unless you want to fund me at a full-time salary until it's done, then I'll be glad to do it :-).
Check out my website: http://icefallgames.com
Groundhog Day Competition

Online Kawa

Re: Leaked Original SCI Source
« Reply #8 on: November 26, 2015, 08:00:30 PM »
Then we will never have readable card game code. And that's okay by me. :D

Oh, also various puzzles.

Because for Hoyle's Classic Card Games and Dr. Brain, that 2% is more like 40%. ;D
« Last Edit: November 26, 2015, 08:32:13 PM by Kawa »

Offline Collector

Re: Leaked Original SCI Source
« Reply #9 on: November 26, 2015, 08:13:22 PM »
Unless you want to fund me at a full-time salary until it's done, then I'll be glad to do it :-).

If I ever hit the lotto consider yourself hired.
KQII Remake Pic

Offline Cloudee1

Re: Leaked Original SCI Source
« Reply #10 on: November 26, 2015, 10:36:02 PM »
Well if I ever did a kickstarter for any games, I had always intended to set aside some of it for you for the IDE development and Brandon would probably get some as well for the music composition. My best chance of a successful one might have been the current SQ: The Early Years but that would require a lot more for licensing as well. Besides feeling wrong about selling the two fan games included in there. We'll just have to wait on that for a truly unique endeavor which I am not sure will ever actually happen on my end  :P

But anyway, the thought's what matters right... and I have thought about it.
Halloween Competition Brass Lantern Prop Competition Groundhog Day Competition

Offline OmerMor

Re: Leaked Original SCI Source
« Reply #11 on: November 27, 2015, 01:44:56 AM »
Here's the header for the Tandy keyboard driver TANDYKBD.S:
Code: [Select]
;TANDYKBD.S
;Keyboard driver for the Tandy 1000 machines and their brain-damaged keyboards.

 ;D

Online Kawa

Re: Leaked Original SCI Source
« Reply #12 on: November 27, 2015, 04:59:54 AM »
It gets better when you have a browser extension that turns "keyboard" into "leopard".

Online Kawa

Re: Leaked Original SCI Source
« Reply #13 on: November 27, 2015, 08:00:29 AM »
I got a little bored waiting for something unrelated, so here's GetDirectory (aka proc990_0) rewritten in Studio dialect, reducing a 112-line routine to 32 lines. I've already tested this to work.

Code: [Select]
(procedure public (GetDirectory where)
(var result, newDir[40], str[100], buf1[50], len)
(while (TRUE) //closest thing to "repeat".
= len (+ Max(29 (+ StrLen(where) 6)) 11) //29 = DIRECTORYSIZE
= result (Print:
font(0)
addText(1 0 0 1 0 0 scriptNumber)
addEdit(StrCpy(@newDir where) len 0 20 where)
addButton(TRUE 27 0 0 1 0 34 scriptNumber)
addButton(FALSE 38 0 0 1 50 34 scriptNumber)
init()
)
(if (not result)
return FALSE
)
(if (not StrLen(@newDir))
GetCWD(@newDir)
)
(if (ValidPath(@newDir))
StrCpy(where @newDir)
return TRUE
)(else
Message(msgGET scriptNumber 29 0 0 1 @buf1)
Format(@str @buf1 @newDir) //Could probably FormatPrint/Printf this instead. I don't care.
(Print:
font(0)
addText(@str)
init()
)
)
)
)

I think it might be the repeat that killed it. Also, you need to (use "obj") for Max.

The next big question is, should I do this to SRDialog::doit(), 486 lines in Companion, 197 in OmerMor's leak?
« Last Edit: November 27, 2015, 01:57:03 PM by Kawa »

Offline OmerMor

Re: Leaked Original SCI Source
« Reply #14 on: November 27, 2015, 11:07:02 AM »
I'll just put this pdf document here.

Code: [Select]
                      The Script Programming Language

                          Author: Jeff Stephenson
                            Date: 4 April 1988
« Last Edit: November 27, 2015, 11:36:54 AM by OmerMor »


SMF 2.0.14 | SMF © 2017, Simple Machines
Simple Audio Video Embedder

Page created in 0.134 seconds with 23 queries.