*/
Love this site? Hate it? Leave us some comments.
*/

View \TPA&OOP.PAS

TP&Asm Integrated Compile-Time Assembler Version 2.2

Submitted By: WEBMASTER
Rating: (Not rated) (Rate It)


{???????????????????????????????? TPA_OOP ????????????????????????????????}
{ Demonstrates TP&Asm support for Object Oriented Pascal, including:      }
{                                                                         }
{ - Use of Assemble and Internal in method definitions                    }
{   (Supports both "ObjectName@MethodName" and "ObjectName.MethodName")   }
{                                                                         }
{ - Unqualified Indexed Reference to Object data within its methods       }
{   (Unindexed Reference to Static Object data uses Pascal Record syntax) }
{                                                                         }
{ - Automatic support for assembly references to "Self" and "VMT"         }
{   (Freely change object structure without rewriting any assembly code!) }
{                                                                         }
{ - Direct call to Static AND VIRTUAL methods using Unindexed MethodName  }
{                                                                         }
{ - Standard virtual call to Virtual methods using Indexed MethodName     }
{                                                                         }
{=> Compile to Disk or Memory and Run.  Move HappyFace with cursor keys <=}
{?????????????????????????????????????????????????????????????????????????}
Program TPA_OOP;

TYPE
 {- A ScreenCell is a Screen Location which can be Read or Written -}
  ScreenCell = Object
    X,Y: Byte;
    procedure Init(InitX, InitY, InitAttr : Byte; InitSym: Char);
    function GetDisplay : Word;
    procedure SetDisplay(NewContents : Word);
  end;

 {- An OccupiedCell is a ScreenCell which knows its current/prior contents -}
  OccupiedCell = Object(ScreenCell)
    Visible: Boolean;
    Occupant,Occupied: Word;
    constructor Init(InitX, InitY, InitAttr : Byte; InitSym: Char);
    destructor Done;
    Procedure Show; virtual;
    Procedure Hide; virtual;
    Procedure MoveRight; virtual;
    Procedure MoveLeft; virtual;
    Procedure MoveUp; virtual;
    Procedure MoveDown; virtual;
  end;


PROCEDURE ScreenCell.Init(InitX, InitY, InitAttr : Byte; InitSym: Char);
BEGIN
  X := InitX;
  Y := InitY;
  SetDisplay( Byte(InitSym) OR (InitAttr SHL 8) );
END; {PROCEDURE ScreenCell.Init;}


Internal ScreenCellMethods
CODE Segment
ScreenCell@GetDisplay PROC FAR     ;or use "ScreenCell.GetDisplay"

  Self EQU D [Bp+6]   ;Internal/External statements must define "Self"

  Push Bp
  Mov Bp,Sp

  Mov Ah,0F           ;get active page into Bh
  Int 10h

  Les Di,Self         ;Load pointer to "Self"
  Es Mov Dl,X[Di]     ;Indexed reference to ScreenCell.X
  Dec Dl
  Es Mov Dh,[Di+Y]    ;Indexed reference to ScreenCell.Y
  Dec Dh
  Mov Ah,02           ;set cursor position
  Int 10h
  Mov Ah,08           ;get char and attr into Ax
  Int 10h             ; (leave function result in Ax)

  Pop Bp              ;No need to  Mov Sp,Bp
  Ret 4               ;Remove "Self" parameter (using implied RetF)

ScreenCell@GetDisplay ENDP

CODE ENDS

End Internal ScreenCellMethods;


Procedure ScreenCell.SetDisplay(NewContents : Word);
BEGIN
  Assembly
    Mov Ah,0F         ;get active page into Bh
    Int 10h
    Les Di,Self       ;Assembly statements can reference "Self" parameter
    Mov Dl,Es:X[Di]   ;Indexed reference to ScreenCell.X
    Dec Dl
    Mov Dh,Es:[Di+Y]  ;Indexed reference to ScreenCell.Y
    Dec Dh
    Mov Ah,02         ;set cursor position
    Int 10h
    Mov Ax,NewContents
    Mov Bl,Ah         ;put attr in Bl
    Mov Cx,1          ;count of bytes to write
    Mov Ah,09         ;write char and attr
    Int 10h
  END; {Assembly}
  {- Standard Procedure exit code will code the required Retf 6 -}
END; {Procedure ScreenCell.SetDisplay}



constructor OccupiedCell.Init(InitX, InitY, InitAttr : Byte; InitSym: Char);
BEGIN
 {- Code part in assembly to avoid unnecessarily reloading Es:Di -}
  Assembly
    Les Di,Self               ;Load pointer to Self
    Es Mov Visible[Di],FALSE  ;- Visible := FALSE;

    Mov Al,InitX
    Es Mov X[Di],Al           ;- X := InitX;

    Mov Al,InitY
    Mov Es:[Di+Y],Al          ;- Y := InitY;

    Mov Al,InitSym
    Mov Ah,InitAttr           ;- Occupant := Byte(InitSym)
    Mov Es:[Di]Occupant,Ax    ;-            OR (InitAttr SHL 8);

  END; {Assembly}

  Show;               {- Let Turbo handle this virtual Call         -}
                      {- See MoveRight for an Assembly virtual call -}

END; {PROCEDURE ScreenCell.Init;}


Procedure OccupiedCell.Show;
BEGIN
  IF NOT Visible THEN Assembly

    Les Di,Self               ;- Visible := TRUE;
    Es Mov Visible[Di],TRUE

    Push Es,Di                ;Push "Self" parameter
    Call GetDisplay           ;Direct Call to Static Method, result in Ax
    Les Di,Self               ;Reload, most methods destroy Es:Di
    Es Mov Occupied[Di],Ax    ;- Occupied := GetDisplay;

    Es Push Occupant[Di]      ;- SetDisplay(Occupant);
    Push Es,Di                ;Push "Self" parameter
    Call SetDisplay           ;Direct Call to Static Method

  END; {IF NOT Visible THEN }
END; {Procedure OccupiedCell.Show}


Internal OccupiedCellMethods;
CODE Segment
OccupiedCell.MoveRight PROC   ;or use "OccupiedCell@MoveRight"

  Self EQU D [Bp+6]           ;Internal/External statements must define "Self"

  Push Bp
  Mov Bp,Sp

                              ;- Hide; (VMT call)
  Les Di,Self                 ;Load "Self" pointer
  Push Es,Di                  ;Pass as self parameter
  Es Mov Di,VMT[Di]           ;Pick up VMT offset from VMT field
  Call Hide[Di]               ;Indexed reference codes Virtual Call

  Les Di,Self                 ;Reload "Self" pointer
  Es Cmp X[Di],80             ;- IF X<80
  IF B Es Inc X[Di]           ;-  THEN Inc(X);

                              ;- Show; (VMT call)
  Push Es,Di                  ;Es:[Di] is still valid
  Mov Di,Es:[Di+VMT]          ;Pick up VMT offset from VMT field
  Call [Di+Show]              ;Indexed reference codes Virtual Call

  Pop Bp                      ;No need to  Mov Sp,Bp
  Ret 4                       ;Remove "Self" parameter

OccupiedCell.MoveRight ENDP


OccupiedCell@MoveLeft PROC    ;or use "OccupiedCell.MoveLeft"

  Self EQU D [Bp+6]           ;Internal/External statements must define "Self"

  Push Bp
  Mov Bp,Sp

                              ;- Hide; (Direct Call)
  Les Di,Self                 ;Load "Self" pointer
  Push Es,Di                  ;Pass as self parameter
 ;--> Use an unindexed reference to code STATIC (Direct) Calls
  Call OccupiedCell.Hide      ;STATIC (Direct) Call to virtual method

  Les Di,Self                 ;Reload "Self" pointer
  Es Cmp X[Di],1              ;- IF X>1
  IF A Es Dec X[Di]           ;-  THEN Dec(X);

                              ;- Show; (Direct Call)
  Push Es,Di                  ;Es:[Di] is still valid
  Call Show                   ;STATIC (Direct) Call to virtual method

  Pop Bp                      ;No need to  Mov Sp,Bp
  Ret 4                       ;Remove "Self" parameter

OccupiedCell@MoveLeft ENDP

CODE ENDS

End Internal OccupiedCellMethods;


{- Code remaining methods in Pascal -}

Procedure OccupiedCell.MoveUp;
BEGIN
  Hide;
  IF Y>1 THEN Dec(Y);
  Show;
END; {Procedure OccupiedCell.MoveUp}

Procedure OccupiedCell.MoveDown;
BEGIN
  Hide;
  IF Y<25 THEN Inc(Y);
  Show;
END; {Procedure OccupiedCell.MoveDown}

Procedure OccupiedCell.Hide;
BEGIN
  SetDisplay(Occupied);
  Visible := FALSE;
END; {Procedure OccupiedCell.Hide}

destructor OccupiedCell.Done;
BEGIN
  Hide;
END; {destructor OccupiedCell.Done;}


FUNCTION ReadScan: Byte; { Read keyboard scan code without echo to screen }
 Assembly             {- Inline Directive -}
  Mov Ah,0
  Int 16h
  Mov Al,Ah           ;Put Assembly/Inline Directive result in Al
 END; {Assembly}

FUNCTION GetCursor: WORD;      { Get cursor position on active video page }
 Assembly             {- Inline Directive -}
  Mov Ah,0F           ;get active page into Bh
  Int 10h
  Mov Ah,03           ;get cursor position into Dx
  Int 10h
  Mov Ax,Dx           ;Put Assembly/Inline Directive result in Ax
 END; {Assembly}

PROCEDURE RestoreCursor(SvPos: Word);     { Restore saved cursor position }
 Assembly             {- Inline Directive -}
  Mov Ah,0F           ;get active page into Bh
  Int 10h
  Pop Dx              ;Parameter to Assembly/Inline Directive
  Mov Ah,02           ;set cursor position
  Int 10h
 END; {Assembly}



CONST {- Scan Codes of cursor and escape keys -}
      UpArrow = $48;      RtArrow = $4D;      Escape  = $01;
      DnArrow = $50;      LfArrow = $4B;

VAR
  HappyFace: OccupiedCell;
  MsgBlock: ARRAY[1..20] OF OccupiedCell;
  n: Integer;
  SavedCursor: WORD;

CONST
  ExitMsg: STRING[20] = 'Press <Esc> to Exit';

BEGIN {MAIN}

  SavedCursor := GetCursor;

  FOR n := 1 TO Length(ExitMsg)
   DO MsgBlock[n].Init(n+30,1,$87,ExitMsg[n]);

  HappyFace.Init(20,5,6,#2);

  WHILE TRUE
  DO Case ReadScan OF
    UpArrow: HappyFace.MoveUp;
    DnArrow: HappyFace.MoveDown;
    RtArrow: HappyFace.MoveRight;
    LfArrow: HappyFace.MoveLeft;
    Escape:  BEGIN
               HappyFace.Done;
               FOR n := 1 TO Length(ExitMsg)
                DO MsgBlock[n].Done;
               RestoreCursor(SavedCursor);
               Halt;
             END;
  END; {DO Case ReadScan }

END.

corner
© 1996-2008 CommunityHeaven LLC. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
North American business development: Nicolai Wadstrom. Publisher: Lars Hagelin.