2012-02-22 02:51:59 -08:00
|
|
|
Unit m_SDLCRT;
|
|
|
|
|
|
|
|
{$I M_OPS.PAS}
|
|
|
|
|
|
|
|
(*
|
|
|
|
Goals:
|
|
|
|
|
|
|
|
- Cross platform input and output capable of 80x25, 80x50, 132x50
|
|
|
|
- Input events remapped as compatible with current code base
|
|
|
|
- Full screen mode in Windows, OSX, and Linux if possible
|
|
|
|
- Direct access (read only) to a virtual screen buffer something like:
|
|
|
|
TSDLScreenBuffer = Record
|
|
|
|
Line : Array[1..132] of Record
|
|
|
|
Ch : Char;
|
|
|
|
Attr : Byte;
|
|
|
|
End;
|
|
|
|
- Current X location
|
|
|
|
- Current Y location
|
|
|
|
- Current Text Attribute
|
|
|
|
- Window function to set scroll points
|
|
|
|
- GotoXY
|
|
|
|
- Clear Screen (window based)
|
|
|
|
- Clear to end of line (with current attribute)
|
|
|
|
- Set Window title
|
|
|
|
- Hide screen
|
|
|
|
- Show Buffer
|
|
|
|
- KeyPressed : Boolean
|
|
|
|
- KeyWait (Timeout in seconds or MS) : Boolean
|
|
|
|
- ReadKey (from buffer, or waits infinity if nothing)
|
|
|
|
- Ability to wait for input event based on handle for WaitForMultipleObj ?
|
|
|
|
- Ability to play a .WAV/MP3/MIDI file or at least some sound?
|
|
|
|
- How to handle shutdown and resize window events? Lock resize?
|
|
|
|
- How to handle minimize? Minimize to tray in Windows?
|
|
|
|
*)
|
|
|
|
|
|
|
|
Interface
|
|
|
|
|
|
|
|
Uses
|
|
|
|
SDL;
|
|
|
|
|
|
|
|
Const
|
2012-02-22 08:02:09 -08:00
|
|
|
keyENTER = #13;
|
|
|
|
keyESCAPE = #27;
|
|
|
|
keyHOME = #71;
|
|
|
|
keyUP = #72;
|
|
|
|
keyPGUP = #73;
|
|
|
|
keyLEFT = #75;
|
|
|
|
keyRIGHT = #77;
|
|
|
|
keyEND = #79;
|
|
|
|
keyDOWN = #80;
|
|
|
|
keyPGDN = #81;
|
|
|
|
keyINSERT = #82;
|
|
|
|
keyDELETE = #83;
|
|
|
|
|
|
|
|
AppInputSize = 128;
|
|
|
|
SDLAppWindowX : Word = 800;
|
|
|
|
SDLAppWindowY : Word = 600;
|
2012-02-22 02:51:59 -08:00
|
|
|
|
|
|
|
Type
|
|
|
|
TSDLScreenMode = (mode_80x25, mode_80x50, mode_132x50);
|
|
|
|
|
2012-02-22 08:02:09 -08:00
|
|
|
TSDLKeyMap = Record
|
|
|
|
SDL : Word;
|
|
|
|
Key : String[2];
|
|
|
|
Shift : String[2];
|
|
|
|
Alt : String[2];
|
|
|
|
Ctrl : String[2];
|
|
|
|
End;
|
|
|
|
|
2012-02-22 02:51:59 -08:00
|
|
|
TSDLConsole = Class
|
2012-02-22 03:37:32 -08:00
|
|
|
InputBuffer : Array[1..AppInputSize] of Char;
|
|
|
|
InputPos : Integer;
|
|
|
|
InputSize : Integer;
|
2012-02-22 08:02:09 -08:00
|
|
|
InputEvent : pSDL_EVENT;
|
|
|
|
Screen : pSDL_SURFACE;
|
2012-02-22 03:37:32 -08:00
|
|
|
|
2012-02-22 08:02:09 -08:00
|
|
|
Constructor Create (InitMode: TSDLScreenMode);
|
|
|
|
Destructor Destroy; Override;
|
2012-02-22 03:37:32 -08:00
|
|
|
|
2012-02-22 08:02:09 -08:00
|
|
|
Procedure PushInput (Ch: Char);
|
|
|
|
Procedure PushExt (Ch: Char);
|
|
|
|
Procedure PushStr (Str: String);
|
2012-02-22 03:37:32 -08:00
|
|
|
Procedure ProcessEvent;
|
2012-02-22 08:02:09 -08:00
|
|
|
Function KeyPressed : Boolean;
|
|
|
|
Function ReadKey : Char;
|
|
|
|
Procedure Delay (MS: LongInt);
|
2012-02-22 02:51:59 -08:00
|
|
|
End;
|
|
|
|
|
|
|
|
Implementation
|
|
|
|
|
2012-02-22 08:02:09 -08:00
|
|
|
// SDL fails hard with keyboard handling. I think we need to use
|
|
|
|
// a lookup table that can be externalized into a data file so different
|
|
|
|
// countries can load their specific keyboard set.
|
|
|
|
//
|
|
|
|
// I just assumed things like this would NOT be a problem in SDL. Pretty
|
|
|
|
// disappointing actually. So below is the US mapping as I get time to
|
|
|
|
// work on it.
|
|
|
|
|
|
|
|
Const
|
|
|
|
SDLKeyMapSize = 3;
|
|
|
|
|
|
|
|
SDLKeyMapUS : Array[1..SDLKeyMapSize] of TSDLKeyMap = (
|
|
|
|
(SDL:SDLK_1; Key:'1'; Shift:'!'; Alt:'1'; CTRL:'1'),
|
|
|
|
(SDL:SDLK_2; Key:'2'; Shift:'@'; Alt:'2'; CTRL:'2'),
|
|
|
|
(SDL:SDLK_SLASH; Key:'/'; Shift:'?'; Alt:'/'; CTRL:'/')
|
|
|
|
);
|
|
|
|
|
2012-02-22 03:37:32 -08:00
|
|
|
Constructor TSDLConsole.Create (InitMode: TSDLScreenMode);
|
2012-02-22 02:51:59 -08:00
|
|
|
Begin
|
|
|
|
Inherited Create;
|
|
|
|
|
2012-02-22 08:02:09 -08:00
|
|
|
SDL_INIT(SDL_INIT_VIDEO);
|
2012-02-22 03:37:32 -08:00
|
|
|
|
2012-02-22 08:02:09 -08:00
|
|
|
Screen := SDL_SetVideoMode(SDLAppWindowX, SDLAppWindowY, 32, SDL_SWSURFACE);
|
2012-02-22 03:37:32 -08:00
|
|
|
|
|
|
|
If Screen = NIL Then Halt;
|
|
|
|
|
|
|
|
New (InputEvent);
|
|
|
|
|
|
|
|
InputSize := 0;
|
|
|
|
InputPos := 0;
|
2012-02-22 02:51:59 -08:00
|
|
|
End;
|
|
|
|
|
|
|
|
Destructor TSDLConsole.Destroy;
|
|
|
|
Begin
|
2012-02-22 03:37:32 -08:00
|
|
|
Dispose (InputEvent);
|
|
|
|
|
2012-02-22 02:51:59 -08:00
|
|
|
SDL_QUIT;
|
|
|
|
|
|
|
|
Inherited Destroy;
|
|
|
|
End;
|
|
|
|
|
2012-02-22 03:37:32 -08:00
|
|
|
Procedure TSDLConsole.PushInput (Ch: Char);
|
|
|
|
Begin
|
|
|
|
Inc (InputSize);
|
|
|
|
|
|
|
|
If InputSize > AppInputSize Then Begin
|
|
|
|
InputSize := 1;
|
2012-02-22 08:02:09 -08:00
|
|
|
InputPos := 0;
|
2012-02-22 03:37:32 -08:00
|
|
|
End;
|
|
|
|
|
|
|
|
InputBuffer[InputSize] := Ch;
|
|
|
|
End;
|
|
|
|
|
2012-02-22 08:02:09 -08:00
|
|
|
Procedure TSDLConsole.PushExt (Ch: Char);
|
|
|
|
Begin
|
|
|
|
PushInput(#0);
|
|
|
|
PushInput(Ch);
|
|
|
|
End;
|
|
|
|
|
|
|
|
Procedure TSDLConsole.PushStr (Str: String);
|
|
|
|
Begin
|
|
|
|
PushInput (Str[1]);
|
|
|
|
|
|
|
|
If Length(Str) > 1 Then PushInput (Str[2]);
|
|
|
|
End;
|
|
|
|
|
2012-02-22 03:37:32 -08:00
|
|
|
Procedure TSDLConsole.ProcessEvent;
|
2012-02-22 08:02:09 -08:00
|
|
|
Var
|
|
|
|
IsShift : Boolean = False;
|
|
|
|
IsCaps : Boolean = False;
|
|
|
|
IsAlt : Boolean = False;
|
|
|
|
IsCtrl : Boolean = False;
|
|
|
|
Found : Boolean;
|
|
|
|
Count : Integer;
|
2012-02-22 03:37:32 -08:00
|
|
|
Begin
|
2012-02-22 08:02:09 -08:00
|
|
|
IsShift := (InputEvent^.Key.KeySym.Modifier AND KMOD_SHIFT <> 0);
|
|
|
|
IsCaps := (InputEvent^.Key.KeySym.Modifier AND KMOD_CAPS <> 0);
|
|
|
|
IsAlt := (InputEvent^.Key.KeySym.Modifier AND KMOD_ALT <> 0);
|
|
|
|
IsCtrl := (InputEvent^.Key.KeySym.Modifier AND KMOD_CTRL <> 0);
|
|
|
|
|
2012-02-22 03:37:32 -08:00
|
|
|
Case InputEvent^.Type_ of
|
2012-02-22 08:02:09 -08:00
|
|
|
SDL_KEYDOWN : Begin
|
|
|
|
Case InputEvent^.Key.KeySym.Sym of
|
|
|
|
SDLK_A..
|
|
|
|
SDLK_Z : Begin
|
|
|
|
If IsShift or IsCaps Then Dec (InputEvent^.Key.KeySym.Sym, 32);
|
|
|
|
PushInput (Chr(InputEvent^.Key.KeySym.Sym));
|
|
|
|
End;
|
|
|
|
SDLK_DELETE : PushExt(keyDELETE);
|
|
|
|
SDLK_UP : PushExt(keyUP);
|
|
|
|
SDLK_DOWN : PushExt(keyDOWN);
|
|
|
|
SDLK_RIGHT : PushExt(keyRIGHT);
|
|
|
|
SDLK_LEFT : PushExt(keyLEFT);
|
|
|
|
SDLK_INSERT : PushExt(keyINSERT);
|
|
|
|
SDLK_HOME : PushExt(keyHome);
|
|
|
|
SDLK_END : PushExt(keyEnd);
|
|
|
|
SDLK_PAGEUP : PushExt(keyPGUP);
|
|
|
|
SDLK_PAGEDOWN : PushExt(keyPGDN);
|
|
|
|
SDLK_NUMLOCK..
|
|
|
|
SDLK_COMPOSE : ;
|
|
|
|
Else
|
|
|
|
Found := False;
|
|
|
|
|
|
|
|
For Count := 1 to SDLKeyMapSize Do
|
|
|
|
If InputEvent^.Key.KeySym.Sym = SDLKeyMapUS[Count].SDL Then Begin
|
|
|
|
If IsShift Then
|
|
|
|
PushStr(SDLKeyMapUS[Count].Shift)
|
|
|
|
Else
|
|
|
|
If IsAlt Then
|
|
|
|
PushStr(SDLKeyMapUS[Count].Alt)
|
|
|
|
Else
|
|
|
|
If IsCTRL Then
|
|
|
|
PushStr(SDLKeyMapUS[Count].CTRL)
|
|
|
|
Else
|
|
|
|
PushStr(SDLKeyMapUS[Count].Key);
|
|
|
|
|
|
|
|
Found := True;
|
|
|
|
|
|
|
|
Break;
|
|
|
|
End;
|
|
|
|
|
|
|
|
If Not Found Then PushInput(Chr(InputEvent^.Key.KeySym.Sym));
|
|
|
|
End;
|
2012-02-22 03:37:32 -08:00
|
|
|
End;
|
2012-02-22 08:02:09 -08:00
|
|
|
SDL_QUITEV : Halt;
|
2012-02-22 03:37:32 -08:00
|
|
|
End;
|
|
|
|
End;
|
|
|
|
|
|
|
|
Function TSDLConsole.KeyPressed : Boolean;
|
|
|
|
Var
|
|
|
|
Queued : LongInt;
|
|
|
|
Begin
|
|
|
|
Result := False;
|
|
|
|
|
|
|
|
Queued := SDL_PollEvent(InputEvent);
|
|
|
|
|
|
|
|
If Queued > 0 Then
|
|
|
|
ProcessEvent;
|
|
|
|
|
2012-02-22 08:02:09 -08:00
|
|
|
Result := InputPos <> InputSize;
|
|
|
|
End;
|
|
|
|
|
|
|
|
Function TSDLConsole.ReadKey : Char;
|
|
|
|
Begin
|
|
|
|
If InputPos = InputSize Then
|
|
|
|
Repeat
|
|
|
|
SDL_WaitEvent(InputEvent);
|
|
|
|
ProcessEvent;
|
|
|
|
Until (InputSize <> InputPos);
|
|
|
|
|
|
|
|
Inc (InputPos);
|
|
|
|
|
|
|
|
Result := InputBuffer[InputPos];
|
|
|
|
|
|
|
|
If InputPos = InputSize Then Begin
|
|
|
|
InputPos := 0;
|
|
|
|
InputSize := 0;
|
|
|
|
End;
|
2012-02-22 03:37:32 -08:00
|
|
|
End;
|
|
|
|
|
|
|
|
Procedure TSDLConsole.Delay (MS: LongInt);
|
|
|
|
Begin
|
|
|
|
SDL_DELAY(MS);
|
|
|
|
End;
|
|
|
|
|
2012-02-22 02:51:59 -08:00
|
|
|
End.
|