瀏覽代碼

Module Graph2 in progress

Arthur Yefimov 3 年之前
父節點
當前提交
446ec3d239
共有 5 個文件被更改,包括 1306 次插入0 次删除
  1. 499 0
      src/Allegro5.Mod
  2. 209 0
      src/GTest.Mod
  3. 13 0
      src/Gcmp.sh
  4. 585 0
      src/Graph2.Mod
  5. 二進制
      src/img.png

+ 499 - 0
src/Allegro5.Mod

@@ -0,0 +1,499 @@
+MODULE [foreign] Allegro5;
+IMPORT SYSTEM;
+
+CONST
+  (** Values of al_set_new_display_flags *)
+  windowed*                = 0;
+  fullscreen*              = 1;
+  opengl*                  = 2;
+  direct3dInternal*        = 3;
+  resizable*               = 4;
+  frameless*               = 5;
+  generateExposeEvents*    = 6;
+  opengl30*                = 7;
+  openglForwardCompatible* = 8;
+  fullscreenWindow*        = 9;
+  minimized*               = 10;
+  programmablePipeline*    = 11;
+  gtkToplevelInternal*     = 12;
+  maximized*               = 13;
+  openglEsProfile*         = 14;
+
+  (** Values of parameter importance in al_set_new_display_option *)
+  dontcare* = 0;
+  require*  = 1;
+  suggest*  = 2;
+
+  (** Values of parameter option in al_set_new_display_option *)
+  redSize*               = 0;
+  greenSize*             = 1;
+  blueSize*              = 2;
+  alphaSize*             = 3;
+  redShift*              = 4;
+  greenShift*            = 5;
+  blueShift*             = 6;
+  alphaShift*            = 7;
+  accRedSize*            = 8;
+  accGreenSize*          = 9;
+  accBlueSize*           = 10;
+  accAlphaSize*          = 11;
+  stereo*                = 12;
+  auxBuffers*            = 13;
+  colorSize*             = 14;
+  depthSize*             = 15;
+  stencilSize*           = 16;
+  sampleBuffers*         = 17;
+  samples*               = 18;
+  renderMethod*          = 19;
+  floatColor*            = 20;
+  floatDepth*            = 21;
+  singleBuffer*          = 22;
+  swapMethod*            = 23;
+  compatibleDisplay*     = 24;
+  updateDisplayRegion*   = 25;
+  vsync*                 = 26;
+  maxBitmapSize*         = 27;
+  supportNpotBitmap*     = 28;
+  canDrawIntoBitmap*     = 29;
+  supportSeparateAlpha*  = 30;
+  autoConvertBitmaps*    = 31;
+  supportedOrientations* = 32;
+  openglMajorVersion*    = 33;
+  openglMinorVersion*    = 34;
+  displayOptionsCount*   = 35;
+
+  (** Values of Event.type *)
+  eventJoystickAxis*          =  1;
+  eventJoystickButtonDown*    =  2;
+  eventJoystickButtonUp*      =  3;
+  eventJoystickConfiguration* =  4;
+
+  eventKeyDown*               = 10;
+  eventKeyChar*               = 11;
+  eventKeyUp*                 = 12;
+
+  eventMouseAxes*             = 20;
+  eventMouseButtonDown*       = 21;
+  eventMouseButtonUp*         = 22;
+  eventMouseEnterDisplay*     = 23;
+  eventMouseLeaveDisplay*     = 24;
+  eventMouseWarped*           = 25;
+
+  eventTimer*                 = 30;
+
+  eventDisplayExpose*         = 40;
+  eventDisplayResize*         = 41;
+  eventDisplayClose*          = 42;
+  eventDisplayLost*           = 43;
+  eventDisplayFound*          = 44;
+  eventDisplaySwitchIn*       = 45;
+  eventDisplaySwitchOut*      = 46;
+  eventDisplayOrientation*    = 47;
+  eventDisplayHaltDrawing*    = 48;
+  eventDisplayResumeDrawing*  = 49;
+
+  eventTouchBegin*            = 50;
+  eventTouchEnd*              = 51;
+  eventTouchMove*             = 52;
+  eventTouchCancel*           = 53;
+
+  eventDisplayConnected*      = 60;
+  eventDisplayDisconnected*   = 61;
+
+  (** Flip flags for al_draw_bitmap *)
+  flipHorizontal* = 1;
+  flipVertical* = 2;
+
+  (** Key codes *)
+  keyA* = 1;
+  keyB* = 2;
+  keyC* = 3;
+  keyD* = 4;
+  keyE* = 5;
+  keyF* = 6;
+  keyG* = 7;
+  keyH* = 8;
+  keyI* = 9;
+  keyJ* = 10;
+  keyK* = 11;
+  keyL* = 12;
+  keyM* = 13;
+  keyN* = 14;
+  keyO* = 15;
+  keyP* = 16;
+  keyQ* = 17;
+  keyR* = 18;
+  keyS* = 19;
+  keyT* = 20;
+  keyU* = 21;
+  keyV* = 22;
+  keyW* = 23;
+  keyX* = 24;
+  keyY* = 25;
+  keyZ* = 26;
+
+  key0* = 27;
+  key1* = 28;
+  key2* = 29;
+  key3* = 30;
+  key4* = 31;
+  key5* = 32;
+  key6* = 33;
+  key7* = 34;
+  key8* = 35;
+  key9* = 36;
+
+  keyPad0* = 37;
+  keyPad1* = 38;
+  keyPad2* = 39;
+  keyPad3* = 40;
+  keyPad4* = 41;
+  keyPad5* = 42;
+  keyPad6* = 43;
+  keyPad7* = 44;
+  keyPad8* = 45;
+  keyPad9* = 46;
+
+  keyF1*  = 47;
+  keyF2*  = 48;
+  keyF3*  = 49;
+  keyF4*  = 50;
+  keyF5*  = 51;
+  keyF6*  = 52;
+  keyF7*  = 53;
+  keyF8*  = 54;
+  keyF9*  = 55;
+  keyF10* = 56;
+  keyF11* = 57;
+  keyF12* = 58;
+
+  keyEscape*      = 59;
+  keyTilde*       = 60;
+  keyMinus*       = 61;
+  keyEquals*      = 62;
+  keyBackspace*   = 63;
+  keyTab*         = 64;
+  keyOpenbrace*   = 65;
+  keyClosebrace*  = 66;
+  keyEnter*       = 67;
+  keySemicolon*   = 68;
+  keyQuote*       = 69;
+  keyBackslash*   = 70;
+  keyBackslash2*  = 71;
+  keyComma*       = 72;
+  keyFullstop*    = 73;
+  keySlash*       = 74;
+  keySpace*       = 75;
+
+  keyInsert*      = 76;
+  keyDelete*      = 77;
+  keyHome*        = 78;
+  keyEnd*         = 79;
+  keyPgup*        = 80;
+  keyPgdn*        = 81;
+  keyLeft*        = 82;
+  keyRight*       = 83;
+  keyUp*          = 84;
+  keyDown*        = 85;
+
+  keyPadSlash*    = 86;
+  keyPadAsterisk* = 87;
+  keyPadMinus*    = 88;
+  keyPadPlus*     = 89;
+  keyPadDelete*   = 90;
+  keyPadEnter*    = 91;
+
+  keyPrintscreen* = 92;
+  keyPause*       = 93;
+
+  keyAbntC1*      = 94;
+  keyYen*         = 95;
+  keyKana*        = 96;
+  keyConvert*     = 97;
+  keyNoconvert*   = 98;
+  keyAt*          = 99;
+  keyCircumflex*  = 100;
+  keyColon2*      = 101;
+  keyKanji*       = 102;
+
+  keyPadEquals*   = 103;
+  keyBackquote*   = 104;
+  keySemicolon2*  = 105;
+  keyCommand*     = 106;
+
+  keyBack*        = 107;
+  keyVolumeUp*    = 108;
+  keyVolumeDown*  = 109;
+
+  keySearch*      = 110;
+  keyDpadCenter*  = 111;
+  keyButtonX*     = 112;
+  keyButtonY*     = 113;
+  keyDpadUp*      = 114;
+  keyDpadDown*    = 115;
+  keyDpadLeft*    = 116;
+  keyDpadRight*   = 117;
+  keySelect*      = 118;
+  keyStart*       = 119;
+  keyButtonL1*    = 120;
+  keyButtonR1*    = 121;
+  keyButtonL2*    = 122;
+  keyButtonR2*    = 123;
+  keyButtonA*     = 124;
+  keyButtonB*     = 125;
+  keyThumbl*      = 126;
+  keyThumbr*      = 127;
+
+  keyUnknown*     = 128;
+
+  keyModifiers*   = 215;
+
+  keyLshift*      = 215;
+  keyRshift*      = 216;
+  keyLctrl*       = 217;
+  keyRctrl*       = 218;
+  keyAlt*         = 219;
+  keyAltgr*       = 220;
+  keyLwin*        = 221;
+  keyRwin*        = 222;
+  keyMenu*        = 223;
+  keyScrolllock*  = 224;
+  keyNumlock*     = 225;
+  keyCapslock*    = 226;
+
+  keyMax*         = 227;
+
+  keymodShift*      = 0;
+  keymodCtrl*       = 1;
+  keymodAlt*        = 2;
+  keymodLwin*       = 3;
+  keymodRwin*       = 4;
+  keymodMenu*       = 5;
+  keymodAltgr*      = 6;
+  keymodCommand*    = 7;
+  keymodScrolllock* = 8;
+  keymodNumlock*    = 9;
+  keymodCapslock*   = 10;
+  keymodInaltseq*   = 11;
+  keymodAccent1*    = 12;
+  keymodAccent2*    = 13;
+  keymodAccent3*    = 14;
+  keymodAccent4*    = 15;
+
+  (* Other *)
+  intMax* = 2147483647;
+
+TYPE
+  ADRINT* = SYSTEM.ADRINT;
+  SHORTCHAR* = SYSTEM.CHAR8;
+  SHORTINT* = SYSTEM.INT16;
+  LONGREAL* = SYSTEM.REAL64;
+  LONGINT* = SYSTEM.INT64;
+
+  Color* = RECORD [1]
+    r*, g*, b*, a*: REAL
+  END;
+
+  Transform* = RECORD [1]
+    m*: ARRAY 4, 4 OF REAL
+  END;
+
+  LockedRegion* = POINTER [1] TO LockedRegionDesc;
+  LockedRegionDesc* = RECORD [1]
+    data*: ADRINT;
+    format*: INTEGER;
+    pitch*: INTEGER;
+    pixelSize*: INTEGER
+  END;
+
+  Display* = POINTER [1] TO RECORD [1] END;
+  Bitmap* = POINTER [1] TO RECORD [1] END;
+  EventQueue* = POINTER [1] TO RECORD [1] END;
+  Timer* = POINTER [1] TO RECORD [1] END;
+  EventSource* = POINTER [1] TO RECORD [1] END;
+
+  DisplayEvent* = RECORD [1]
+    type*: INTEGER;
+    source*: Display;
+    timestamp*: LONGREAL;
+    x*, y*: INTEGER;
+    width*, height*: INTEGER;
+    orientation*: INTEGER
+  END;
+
+  KeyboardEvent* = RECORD [1]
+    type*: INTEGER;
+    source*: ADRINT;
+    timestamp*: LONGREAL;
+    display*: Display;
+    keycode*: INTEGER;
+    unichar*: INTEGER;
+    modifiers*: SET;
+    repeat*: BOOLEAN
+  END;
+
+  MouseEvent* = RECORD [1]
+    type*: INTEGER;
+    source*: ADRINT;
+    timestamp*: LONGREAL;
+    display*: Display;
+    x*, y*, z*, w*: INTEGER;
+    dx*, dy*, dz*, dw*: INTEGER;
+    button*: INTEGER;
+    pressure*: REAL
+  END;
+
+  TouchEvent* = RECORD [1]
+    type*: INTEGER;
+    source*: ADRINT;
+    timestamp*: LONGREAL;
+    display*: Display;
+    id*: INTEGER;
+    x*, y*: REAL;
+    dx*, dy*: REAL;
+    primary*: BOOLEAN
+  END;
+
+  TimerEvent* = RECORD [1]
+    type*: INTEGER;
+    source*: ADRINT;
+    timestamp*: LONGREAL;
+    count*: LONGINT;
+    error*: LONGREAL
+  END;
+
+  Event* = RECORD [1]
+    type*: INTEGER;
+    source*: ADRINT;
+    timestamp*: LONGREAL;
+    pad: ARRAY 1000 OF BYTE
+  END;
+
+  PEvent* = POINTER TO Event;
+  PTimerEvent* = POINTER [1] TO TimerEvent;
+  PKeyboardEvent* = POINTER [1] TO KeyboardEvent;
+  PMouseEvent* = POINTER [1] TO MouseEvent;
+  PDisplayEvent* = POINTER [1] TO DisplayEvent;
+
+  MonitorInfo* = RECORD [1]
+    x1*, y1*, x2*, y2*: INTEGER
+  END;
+
+PROCEDURE get_allegro_version* ["al_get_allegro_version"] (): INTEGER;
+PROCEDURE install_system* ["al_install_system"] (version, atexit: ADRINT): BOOLEAN;
+PROCEDURE uninstall_system* ["al_uninstall_system"] ();
+PROCEDURE install_keyboard* ["al_install_keyboard"] (): BOOLEAN;
+PROCEDURE install_mouse* ["al_install_mouse"] (): BOOLEAN;
+PROCEDURE create_timer* ["al_create_timer"] (period: LONGREAL): Timer;
+PROCEDURE get_keyboard_event_source* ["al_get_keyboard_event_source"] (): EventSource;
+PROCEDURE get_mouse_event_source* ["al_get_mouse_event_source"] (): EventSource;
+PROCEDURE get_display_event_source* ["al_get_display_event_source"] (display: Display): EventSource;
+PROCEDURE get_timer_event_source* ["al_get_timer_event_source"] (timer: Timer): EventSource;
+PROCEDURE start_timer* ["al_start_timer"] (timer: Timer);
+PROCEDURE register_event_source* ["al_register_event_source"] (queue: EventQueue; source: EventSource);
+PROCEDURE wait_for_event* ["al_wait_for_event"] (queue: EventQueue; VAR event: Event);
+PROCEDURE clear_to_color* ["al_clear_to_color"] (color: Color);
+PROCEDURE destroy_timer* ["al_destroy_timer"] (timer: Timer);
+PROCEDURE destroy_event_queue* ["al_destroy_event_queue"] (queue: EventQueue);
+
+PROCEDURE create_event_queue* ["al_create_event_queue"] (): EventQueue;
+PROCEDURE is_event_queue_empty* ["al_is_event_queue_empty"] (queue: EventQueue): BOOLEAN;
+
+PROCEDURE set_new_display_flags* ["al_set_new_display_flags"] (flags: SET);
+PROCEDURE set_new_display_option* ["al_set_new_display_option"] (option, value, importance: INTEGER);
+PROCEDURE set_new_window_position* ["al_set_new_window_position"] (x, y: INTEGER);
+PROCEDURE set_window_title* ["al_set_window_title"] (display: Display; title: ARRAY OF SHORTCHAR);
+PROCEDURE set_new_window_title* ["al_set_new_window_title"] (title: ARRAY OF SHORTCHAR);
+PROCEDURE create_display* ["al_create_display"] (w, h: INTEGER): Display;
+PROCEDURE get_current_display* ["al_get_current_display"] (): Display;
+PROCEDURE resize_display* ["al_resize_display"] (display: Display; width, height: INTEGER): BOOLEAN;
+PROCEDURE flip_display* ["al_flip_display"] ();
+PROCEDURE acknowledge_resize* ["al_acknowledge_resize"] (display: Display);
+PROCEDURE get_display_width* ["al_get_display_width"] (display: Display): INTEGER;
+PROCEDURE get_display_height* ["al_get_display_height"] (display: Display): INTEGER;
+PROCEDURE destroy_display* ["al_destroy_display"] (display: Display);
+
+PROCEDURE create_bitmap* ["al_create_bitmap"] (w, h: INTEGER): Bitmap;
+PROCEDURE destroy_bitmap* ["al_destroy_bitmap"] (bmp: Bitmap);
+PROCEDURE clone_bitmap* ["al_clone_bitmap"] (bmp: Bitmap): Bitmap;
+PROCEDURE load_bitmap* ["al_load_bitmap"] (filename: ARRAY OF SHORTCHAR): Bitmap;
+PROCEDURE load_bitmap_flags* ["al_load_bitmap_flags"] (filename: ARRAY OF SHORTCHAR; flags: SET): Bitmap;
+PROCEDURE save_bitmap* ["al_save_bitmap"] (filename: ARRAY OF SHORTCHAR; VAR bitmap: Bitmap): BOOLEAN;
+PROCEDURE get_bitmap_flags* ["al_get_bitmap_flags"] (bmp: Bitmap): SET;
+PROCEDURE get_bitmap_format* ["al_get_bitmap_format"] (bmp: Bitmap): INTEGER;
+PROCEDURE get_bitmap_width* ["al_get_bitmap_width"] (bmp: Bitmap): INTEGER;
+PROCEDURE get_bitmap_height* ["al_get_bitmap_height"] (bmp: Bitmap): INTEGER;
+PROCEDURE hold_bitmap_drawing* ["al_hold_bitmap_drawing"] (hold: BOOLEAN);
+PROCEDURE is_bitmap_drawing_held* ["al_is_bitmap_drawing_held"] (): BOOLEAN;
+
+PROCEDURE create_sub_bitmap* ["al_create_sub_bitmap"] (parent: Bitmap; x, y, w, h: INTEGER): Bitmap;
+PROCEDURE is_sub_bitmap* ["al_is_sub_bitmap"] (bmp: Bitmap): BOOLEAN;
+PROCEDURE get_parent_bitmap* ["al_get_parent_bitmap"] (bmp: Bitmap): Bitmap;
+PROCEDURE get_bitmap_x* ["al_get_bitmap_x"] (bmp: Bitmap): INTEGER;
+PROCEDURE get_bitmap_y* ["al_get_bitmap_y"] (bmp: Bitmap): INTEGER;
+PROCEDURE reparent_bitmap* ["al_reparent_bitmap"] (bmp, parent: Bitmap; x, y, w, h: INTEGER);
+
+PROCEDURE lock_bitmap* ["al_lock_bitmap"] (bmp: Bitmap; format, flags: INTEGER): LockedRegion;
+PROCEDURE lock_bitmap_region* ["al_lock_bitmap_region"] (bmp: Bitmap; x, y, w, h, format, flags: INTEGER): LockedRegion;
+PROCEDURE is_bitmap_locked* ["al_is_bitmap_locked"] (bmp: Bitmap): BOOLEAN;
+PROCEDURE unlock_bitmap* ["al_unlock_bitmap"] (bmp: Bitmap);
+
+PROCEDURE convert_bitmap* ["al_convert_bitmap"] (bmp: Bitmap);
+PROCEDURE convert_memory_bitmaps* ["al_convert_memory_bitmaps"];
+PROCEDURE is_compatible_bitmap* ["al_is_compatible_bitmap"] (bmp: Bitmap): BOOLEAN;
+
+PROCEDURE set_new_bitmap_flags* ["al_set_new_bitmap_flags"] (flags: SET);
+PROCEDURE add_new_bitmap_flag* ["al_add_new_bitmap_flag"] (flags: SET);
+PROCEDURE get_new_bitmap_flags* ["al_get_new_bitmap_flags"] (): SET;
+PROCEDURE set_new_bitmap_format* ["al_set_new_bitmap_format"] (format: INTEGER);
+PROCEDURE get_new_bitmap_format* ["al_get_new_bitmap_format"] (): INTEGER;
+
+PROCEDURE draw_bitmap* ["al_draw_bitmap"] (bmp: Bitmap; dx, dy: REAL; flip: SET);
+PROCEDURE draw_tinted_bitmap* ["al_draw_tinted_bitmap"] (bmp: Bitmap; tint: Color; dx, dy: REAL; flip: SET);
+PROCEDURE draw_bitmap_region* ["al_draw_bitmap_region"] (bmp: Bitmap; sx, sy, sw, sh, dx, dy: REAL; flip: SET);
+PROCEDURE draw_tinted_bitmap_region* ["al_draw_tinted_bitmap_region"] (bmp: Bitmap; tint: Color; sx, sy, sw, sh, dx, dy: REAL; flip: SET);
+PROCEDURE draw_pixel* ["al_draw_pixel"] (x, y: REAL; color: Color);
+PROCEDURE draw_rotated_bitmap* ["al_draw_rotated_bitmap"] (bmp: Bitmap; cx, cy, dx, dy, angle: REAL; flip: SET);
+PROCEDURE draw_tinted_rotated_bitmap* ["al_draw_tinted_rotated_bitmap"] (bmp: Bitmap; tint: Color; cx, cy, dx, dy, angle: REAL; flip: SET);
+PROCEDURE draw_scaled_rotated_bitmap* ["al_draw_scaled_rotated_bitmap"] (bmp: Bitmap; cx, cy, dx, dy, xScale, yScale, angle: REAL; flip: SET);
+PROCEDURE draw_tinted_scaled_rotated_bitmap* ["al_draw_tinted_scaled_rotated_bitmap"] (bmp: Bitmap; tint: Color; cx, cy, dx, dy, xScale, yScale, angle: REAL; flip: SET);
+PROCEDURE draw_t_s_r_b_region* ["al_draw_tinted_scaled_rotated_bitmap_region"] (bmp: Bitmap; sx, sy, sw, sh: REAL; tint: Color; cx, cy, dx, dy, xScale, yScale, angle: REAL; flip: SET);
+PROCEDURE draw_scaled_bitmap* ["al_draw_scaled_bitmap"] (bmp: Bitmap; sx, sy, sw, sh, dx, dy, dw, dh: REAL; flip: SET);
+PROCEDURE draw_tinted_scaled_bitmap* ["al_draw_tinted_scaled_bitmap"] (bmp: Bitmap; tint: Color; sx, sy, sw, sh, dx, dy, dw, dh: REAL; flip: SET);
+
+PROCEDURE set_target_bitmap* ["al_set_target_bitmap"] (bmp: Bitmap);
+PROCEDURE get_target_bitmap* ["al_get_target_bitmap"] (): Bitmap;
+PROCEDURE set_target_backbuffer* ["al_set_target_backbuffer"] (display: Display);
+PROCEDURE put_pixel* ["al_put_pixel"] (x, y: INTEGER; c: Color);
+PROCEDURE put_blended_pixel* ["al_put_blended_pixel"] (x, y: INTEGER; c: Color);
+
+PROCEDURE init_primitives_addon* ["al_init_primitives_addon"] (): BOOLEAN;
+PROCEDURE init_image_addon* ["al_init_image_addon"] (): BOOLEAN;
+PROCEDURE init_audio_addon* ["al_init_audio_addon"] (): BOOLEAN;
+PROCEDURE init_acodec_addon* ["al_init_acodec_addon"] (): BOOLEAN;
+PROCEDURE init_font_addon* ["al_init_font_addon"] (): BOOLEAN;
+PROCEDURE init_native_dialog_addon* ["al_init_native_dialog_addon"] (): BOOLEAN;
+
+PROCEDURE draw_line* ["al_draw_line"] (x1, y1, x2, y2: REAL; color: Color; thickness: REAL);
+PROCEDURE draw_triangle* ["al_draw_triangle"] (x1, y1, x2, y2, x3, y3: REAL; color: Color; thickness: REAL);
+PROCEDURE draw_rectangle* ["al_draw_rectangle"] (x1, y1, x2, y2: REAL; color: Color; thickness: REAL);
+PROCEDURE draw_filled_rectangle* ["al_draw_filled_rectangle"] (x1, y1, x2, y2: REAL; color: Color);
+PROCEDURE draw_rounded_rectangle* ["al_draw_rounded_rectangle"] (x1, y1, x2, y2, rx, ry: REAL; color: Color; thickness: REAL);
+PROCEDURE draw_filled_rounded_rectangle* ["al_draw_filled_rounded_rectangle"] (x1, y1, x2, y2, rx, ry: REAL; color: Color);
+PROCEDURE draw_circle* ["al_draw_circle"] (cx, cy, r: REAL; color: Color; thickness: REAL);
+PROCEDURE draw_filled_circle* ["al_draw_filled_circle"] (cx, cy, r: REAL; color: Color);
+PROCEDURE draw_ellipse* ["al_draw_ellipse"] (cx, cy, rx, ry: REAL; color: Color; thickness: REAL);
+PROCEDURE draw_filled_ellipse* ["al_draw_filled_ellipse"] (cx, cy, rx, ry: REAL; color: Color);
+PROCEDURE draw_polyline* ["al_draw_polyline"] (vertices: ARRAY OF REAL; vertexCount, joinStyle, capStyle: INTEGER; color: Color; thickness, miterLimit: REAL);
+PROCEDURE draw_polygon* ["al_draw_polygon"] (vertices: ARRAY OF REAL; vertexCount, joinStyle: INTEGER; color: Color; thickness, miterLimit: REAL);
+PROCEDURE draw_filled_polygon* ["al_draw_filled_polygon"] (vertices: ARRAY OF REAL; vertexCount: INTEGER; color: Color);
+PROCEDURE draw_filled_polygon_with_holes* ["al_draw_filled_polygon_with_holes"] (vertices: ARRAY OF REAL; vertexCounts: ARRAY OF INTEGER; color: Color);
+
+PROCEDURE get_monitor_info* ["al_get_monitor_info"] (adapter: INTEGER; VAR info: MonitorInfo): BOOLEAN;
+
+PROCEDURE rest* ["al_rest"] (seconds: LONGREAL);
+
+PROCEDURE build_transform* ["al_build_transform"] (VAR trans: Transform; x, y, sx, sy, theta: REAL);
+PROCEDURE use_transform* ["al_use_transform"] (VAR trans: Transform);
+
+END Allegro5.

+ 209 - 0
src/GTest.Mod

@@ -0,0 +1,209 @@
+MODULE GTest;
+IMPORT G := Graph2, Out;
+VAR main: G.Window;
+  dialogs: ARRAY 10 OF G.Window;
+  nofdialogs: INTEGER;
+  quit: BOOLEAN;
+  redraw: BOOLEAN;
+  Z: INTEGER;
+  t: G.Timer;
+  c1, c2: G.Color;
+
+PROCEDURE OpenDialog;
+BEGIN
+  IF nofdialogs # LEN(dialogs) THEN
+    dialogs[nofdialogs] := G.NewWindow(-1, -1,
+      300, 100 + 50 * nofdialogs, 'Dialog', {G.centered});
+    INC(nofdialogs)
+  END
+END OpenDialog;
+
+PROCEDURE CloseDialog(W: G.Window);
+VAR i: INTEGER;
+BEGIN
+  i := 0;
+  WHILE (i # nofdialogs) & (dialogs[i] # W) DO INC(i) END;
+  IF i # nofdialogs THEN
+    G.CloseWindow(dialogs[i]);
+    dialogs[i] := dialogs[nofdialogs - 1];
+    DEC(nofdialogs)
+  END
+END CloseDialog;
+
+PROCEDURE DrawWin(W: G.Window);
+VAR i, x, y, w, h: INTEGER;
+BEGIN
+  G.Target(W);
+  G.ClearToColor(c1);
+
+  FOR i := 0 TO 8 DO
+    x := i MOD 3; y := i DIV 3;
+    w := (W.w - 1) * (x + 1) DIV 3 - 1;
+    h := (W.h - 1) * (y + 1) DIV 3 - 1;
+    x := (W.w - 1) * x DIV 3 + 1;
+    y := (W.h - 1) * y DIV 3 + 1;
+    IF Z MOD 9 = i THEN
+      G.FillRect(x, y, w, h, c2)
+    ELSE
+      G.Rect(x, y, w, h, c2);
+      G.Line(x, y, w, h, c2);
+      G.Line(x, h, w, y, c2)
+    END
+  END;
+
+  G.Flip
+END DrawWin;
+
+PROCEDURE Draw;
+VAR i: INTEGER;
+BEGIN
+  DrawWin(main);
+  i := 0;
+  WHILE (i # nofdialogs) & ~quit DO
+    DrawWin(dialogs[i]);
+    INC(i)
+  END
+END Draw;
+
+PROCEDURE Run;
+VAR e: G.Event;
+BEGIN
+  quit := FALSE;
+  redraw := TRUE;
+  G.StartTimer(t);
+  REPEAT
+    IF redraw & G.NoEvents() THEN
+      Draw;
+      redraw := FALSE
+    END;
+
+    G.WaitEvent(e);
+    IF e.type = G.mouseDown THEN
+      Out.String('Mouse DOWN '); Out.Int(e.x, 0); Out.Char(':'); Out.Int(e.y, 0); Out.Ln;
+      OpenDialog;
+      redraw := TRUE
+    ELSIF e.type = G.timer THEN
+      INC(Z);
+      redraw := TRUE
+    ELSIF e.type = G.keyDown THEN
+      Out.String('Key Down');Out.Ln;
+      IF G.GetWindow(e) = main THEN
+        INC(Z)
+      ELSE
+        DEC(Z)
+      END;
+      redraw := TRUE
+    ELSIF e.type = G.char THEN
+      IF G.GetWindow(e) = main THEN Out.String('Main window ') END;
+      Out.String('char typed: '); Out.Char(e.ch); Out.Ln;
+      Out.String('         Code '); Out.Int(ORD(e.ch), 0); Out.Ln;
+      redraw := TRUE
+    ELSIF e.type = G.resize THEN
+      Out.String('Resize');Out.Ln;
+      G.ApplyResize(e);
+      redraw := TRUE
+    ELSIF e.type = G.quit THEN
+      Out.String('Quit');Out.Ln;
+      IF G.GetWindow(e) = main THEN
+        quit := TRUE
+      ELSE
+        CloseDialog(G.GetWindow(e))
+      END
+    END
+  UNTIL quit
+END Run;
+
+PROCEDURE RunSingle;
+VAR i: INTEGER;
+  B: G.Bitmap;
+  c3, c4, c5: G.Color;
+BEGIN
+  G.Settings(320, 200, {G.fullscreen, G.exact});
+  G.Init;
+  G.MakeCol(210, 80, 30, c1);
+  G.MakeCol(0, 255, 0, c2);
+  G.MakeCol(255, 255, 255, c3);
+  G.MakeCol(50, 30, 255, c4);
+  B := G.LoadBitmap('img.png');
+  IF B = NIL THEN Out.String('COULD NOT LOAD img.png'); Out.Ln END;
+  G.ClearScreen;
+    (*DELETEME*)          G.Flip; G.Delay(20);
+
+  i := 0;
+  REPEAT
+    G.Line(0, i, G.Width() - 1, i, c1);
+    G.Flip; G.Delay(1);
+    G.MakeCol(150 - i DIV 2, 80 - i DIV 4, 30 - i DIV 10, c5);
+    INC(i);
+    G.Line(0, i, G.Width() - 1, i, c5);
+    G.Flip; G.Delay(1);
+    INC(i, 2)
+  UNTIL i >= G.Height();
+
+  i := 0;
+  REPEAT
+    G.DrawRotated(B, B.w DIV 2, B.h DIV 2, 15 + i * 25, 80,
+      FLT(i) * 15 / 180.0 * 3.14, {});
+    G.DrawRotated(B, B.w DIV 2, B.h DIV 2, G.Width() - 15 - i * 25, 130,
+      FLT(i) * 15 / 180.0 * 3.14, {G.flipHor});
+      (*DELETEME*)          G.Flip; G.Delay(50);
+    INC(i)
+  UNTIL i = 14;
+  G.Line(0, 0, 0, 10, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.Line(2, 0, 2, 10, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.Line(10, 0, 40, 30, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.Line(10, 10, 40, 70, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.PutPixel(4, 4, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.PutPixel(6, 4, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.PutPixel(6, 4, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.PutPixel2(4, 14, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.PutPixel2(6, 14, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.PutPixel2(6, 14, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.PutPixel2(6, 13, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.PutPixel2(7, 13, c2);
+    (*DELETEME*)          G.Flip; G.Delay(20);
+  G.Target(B);
+
+  G.Line(0, 0, 15, 0, c2);
+  G.Line(0, 22, 15, 22, c2);
+  G.Line(0, 0, 0, 22, c2);
+  G.Line(15, 0, 15, 22, c2);
+
+  G.Line(0, 0, 15, 5, c4);
+  G.Line(15, 0, 12, 22, c3);
+
+  G.TargetScreen;
+  G.Draw(B, 130, 100);
+  G.Flip;
+  G.Delay(1000);
+  G.Close
+END RunSingle;
+
+BEGIN
+  RunSingle;
+(*
+  nofdialogs := 0;
+  Z := 0;
+
+  G.Settings(-1, -1, {G.manual});
+  G.Init;
+  main := G.NewWindow(-1, -1, 800, 600, 'Oberon Allegro 5 Test',
+    {G.resizable, G.maximized});
+  t := G.NewTimer(1.0);
+  G.MakeCol(180, 80, 20, c1);
+  G.MakeCol(240, 180, 80, c2);
+
+  Run;
+  G.Close*)
+END GTest.

+ 13 - 0
src/Gcmp.sh

@@ -0,0 +1,13 @@
+ofront+ -887ws Allegro5.Mod && \
+ofront+ -887ws Graph2.Mod && \
+ofront+ -887wm GTest.Mod && \
+gcc -o GTest -g3 -O0 -fno-exceptions \
+  -I ../data/bin/OfrontPlus/Target/Linux_amd64/../../Mod/Lib \
+  -I ../data/bin/OfrontPlus/Target/Linux_amd64/Lib/Obj \
+  Graph2.c GTest.c \
+  ../data/bin/libFreeOberon.a \
+  ../data/bin/OfrontPlus/Target/Linux_amd64/Lib/libOfront.a \
+  $(pkg-config \
+    allegro_primitives-5 allegro_image-5 allegro_audio-5 \
+    allegro_acodec-5 allegro_font-5 allegro_dialog-5 \
+    allegro-5 --libs --cflags)

+ 585 - 0
src/Graph2.Mod

@@ -0,0 +1,585 @@
+MODULE Graph2;
+IMPORT Out, Al := Allegro5, Utf8, SYSTEM;
+
+CONST
+  (* Settings set members *)
+  manual*      = 0;
+  fullscreen*  = 1;
+  exact*       = 2;
+  smooth*      = 3;
+  software*    = 4;
+  initMouse*   = 5;
+  centered*    = 6;
+  resizable*   = 7;
+  maximized*   = 8;
+  minimized*   = 9;
+  frameless*   = 10;
+
+  (* Event.type possible values *)
+  quit*        = 1;
+  timer*       = 2;
+  windowEvent* = 3;
+  keyDown*     = 4;
+  keyUp*       = 5;
+  char*        = 6;
+  mouseMove*   = 7;
+  mouseDown*   = 8;
+  mouseUp*     = 9;
+  mouseWheel*  = 10;
+  resize*      = 11;
+
+  (* Flip flags *)
+  flipHor*  = 1;
+  flipVert* = 2;
+
+TYPE
+  ADRINT = SYSTEM.ADRINT;
+  REAL = SYSTEM.REAL64;
+  SHORTREAL = SYSTEM.REAL32;
+  LONGINT = SYSTEM.INT64;
+  SHORTCHAR = SYSTEM.CHAR8;
+
+  Color* = RECORD
+    r, g, b, a: SHORTREAL
+  END;
+
+  Transform* = RECORD
+    m: ARRAY 4, 4 OF REAL
+  END;
+
+  Timer* = POINTER TO TimerDesc;
+  TimerDesc* = RECORD
+    tmr: Al.Timer
+  END;
+
+  Bitmap* = POINTER TO BitmapDesc;
+  BitmapDesc* = RECORD
+    bmp: Al.Bitmap;
+    w*, h*: INTEGER;
+    scaleX, scaleY: REAL
+  END;
+
+  Window* = POINTER TO WindowDesc;
+  WindowDesc* = RECORD(BitmapDesc)
+    display: Al.Display;
+    winW, winH: INTEGER;
+    next: Window (* See windowList below *)
+  END;
+
+  Event* = RECORD
+    type*: INTEGER;
+    time*: REAL;
+    x*, y*, z*, w*, h*: INTEGER;
+    dx*, dy*, dz*, dw*: INTEGER;
+    button*: INTEGER;
+    buttons*: SET; (* What mouse buttons are pressed *)
+    down*: BOOLEAN;
+    count*: LONGINT; (* Timer counter *)
+    key*: INTEGER; (* Physical key code *)
+    ch*: CHAR; (* Typed character for event.type = char *)
+    mod*: SET; (* Key modifiers *)
+    repeat*: BOOLEAN;
+    display: Al.Display;
+    source: ADRINT
+  END;
+
+VAR
+  settings: SET; (* See list of constants Settings above *)
+  wantW, wantH: INTEGER; (* Assigned in procedure Settings *)
+  sizeStepX, sizeStepY: INTEGER; (* Assigned in procedure SetSizeStep *)
+  scaleX, scaleY: REAL; (* Assigned in procedure SetScale *)
+  wantScreenTitle: ARRAY 256 OF CHAR; (* Assigned in procedure SetTitle *)
+  queue: Al.EventQueue;
+  windowList: Window;
+  screen: Window;
+  target: Bitmap;
+
+PROCEDURE GetDesktopResolution*(VAR w, h: INTEGER);
+VAR info: Al.MonitorInfo;
+BEGIN
+  IF Al.get_monitor_info(0, info) THEN
+    w := info.x2 - info.x1;
+    h := info.y2 - info.y1
+  ELSE w := -1; h := -1
+  END
+END GetDesktopResolution;
+
+PROCEDURE GetScreen*(): Window;
+RETURN screen END GetScreen;
+
+PROCEDURE Width*(): INTEGER;
+RETURN screen.w END Width;
+
+PROCEDURE Height*(): INTEGER;
+RETURN screen.h END Height;
+
+PROCEDURE Settings*(w, h: INTEGER; flags: SET);
+BEGIN wantW := w; wantH := h; settings := flags
+END Settings;
+
+PROCEDURE SetSizeStep*(w, h: INTEGER);
+BEGIN sizeStepX := w; sizeStepY := h
+END SetSizeStep;
+
+PROCEDURE Target*(W: Bitmap);
+BEGIN target := W;
+  IF (W IS Window) & (W.bmp = NIL) THEN
+    Al.set_target_backbuffer(W(Window).display)
+  ELSE Al.set_target_bitmap(SYSTEM.VAL(Al.Bitmap, W.bmp))
+  END
+END Target;
+
+PROCEDURE TargetScreen*;
+BEGIN
+  IF screen # NIL THEN Target(screen)
+  ELSIF windowList # NIL THEN Target(windowList)
+  END
+END TargetScreen;
+
+PROCEDURE ApplyScale*(W: Window);
+VAR t: Al.Transform;
+BEGIN
+  (*Target(W);
+  Al.build_transform(t, 0.0, 0.0, 6.0, 6.0, 0.0);
+  Al.use_transform(t)*)
+END ApplyScale;
+
+PROCEDURE SetWindowScale*(W: Window; x, y: REAL);
+BEGIN W.scaleX := x; W.scaleY := y; ApplyScale(W)
+END SetWindowScale;
+
+PROCEDURE SetScale*(x, y: REAL);
+BEGIN
+  IF screen # NIL THEN SetWindowScale(screen, x, y) END
+END SetScale;
+
+PROCEDURE SetTitle*(title: ARRAY OF CHAR);
+BEGIN wantScreenTitle := title
+END SetTitle;
+
+(*PROCEDURE ColorToRGB*(color: INTEGER; VAR r, g, b: INTEGER);
+PROCEDURE ColorToRGBA*(color: INTEGER; VAR r, g, b, a: INTEGER);
+PROCEDURE ClearBitmap*(bmp: Bitmap);
+PROCEDURE ClearScreenToColor*(color: INTEGER);*)
+
+PROCEDURE LoadBitmap*(fname: ARRAY OF CHAR): Bitmap;
+VAR B: Bitmap;
+  q: ARRAY 2048 OF SHORTCHAR;
+BEGIN NEW(B); Utf8.Encode(fname, q); B.bmp := Al.load_bitmap(q);
+  IF B.bmp = NIL THEN B := NIL
+  ELSE B.w := Al.get_bitmap_width(B.bmp); B.h := Al.get_bitmap_height(B.bmp)
+  END
+RETURN B END LoadBitmap;
+
+PROCEDURE Flip*;
+VAR tmp: Al.Bitmap;
+BEGIN
+  IF (target # NIL) & (target IS Window) & (target.bmp # NIL) THEN
+    tmp := Al.get_target_bitmap();
+    Al.set_target_backbuffer(target(Window).display);
+    Al.draw_scaled_bitmap(target.bmp, 0.0, 0.0, FLT(target.w), FLT(target.h),
+      0.0, 0.0, FLT(target(Window).winW), FLT(target(Window).winH), {});
+    Al.flip_display();
+    Al.set_target_bitmap(tmp)
+  ELSE Al.flip_display()
+  END;
+END Flip;
+
+PROCEDURE PutPixel2*(x, y: INTEGER; c: Color);
+BEGIN Al.draw_filled_rectangle(FLT(x), FLT(y), FLT(x + 1), FLT(y + 1),
+  SYSTEM.VAL(Al.Color, c))
+END PutPixel2;
+
+PROCEDURE PutPixel*(x, y: INTEGER; c: Color);
+BEGIN Al.draw_pixel(FLT(x) + 0.5, FLT(y) + 0.5, SYSTEM.VAL(Al.Color, c))
+END PutPixel;
+
+PROCEDURE MakeCol*(r, g, b: INTEGER; VAR c: Color);
+BEGIN c.r := r / 255; c.g := g / 255; c.b := b / 255; c.a := 1.0
+END MakeCol;
+
+PROCEDURE ClearToColor*(c: Color);
+BEGIN Al.clear_to_color(SYSTEM.VAL(Al.Color, c))
+END ClearToColor;
+
+PROCEDURE ClearScreen*;
+VAR c: Color;
+BEGIN MakeCol(0, 0, 0, c); Al.clear_to_color(SYSTEM.VAL(Al.Color, c))
+END ClearScreen;
+
+PROCEDURE ThickLineF*(x1, y1, x2, y2: REAL; color: Color; thickness: REAL);
+BEGIN Al.draw_line(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), thickness)
+END ThickLineF;
+
+PROCEDURE ThickLine*(x1, y1, x2, y2: INTEGER; color: Color;
+    thickness: INTEGER);
+BEGIN
+  Al.draw_line(FLT(x1) + 0.5, FLT(y1) + 0.5, FLT(x2) + 0.5, FLT(y2) + 0.5,
+    SYSTEM.VAL(Al.Color, color), FLT(thickness))
+END ThickLine;
+
+PROCEDURE LineF*(x1, y1, x2, y2: REAL; color: Color);
+BEGIN
+  IF x1 < x2 THEN x2 := x2 + 1
+  ELSIF x1 > x2 THEN x1 := x1 + 1
+  ELSE x1 := x1 + 0.5; x2 := x2 + 0.5
+  END;
+  IF y1 < y2 THEN y2 := y2 + 1
+  ELSIF y1 > y2 THEN y1 := y1 + 1
+  ELSE y1 := y1 + 0.5; y2 := y2 + 0.5
+  END;
+  Al.draw_line(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), 0.0)
+END LineF;
+
+PROCEDURE Line*(x1, y1, x2, y2: INTEGER; color: Color);
+BEGIN
+  LineF(FLT(x1), FLT(y1), FLT(x2), FLT(y2), color)
+  (*Al.draw_line(FLT(x1) + 0.5, FLT(y1) + 0.5,
+    FLT(x2) + 0.5, FLT(y2) + 0.5, SYSTEM.VAL(Al.Color, color), 1.0)*)
+END Line;
+
+PROCEDURE FillRectF*(x1, y1, x2, y2: REAL; color: Color);
+BEGIN Al.draw_filled_rectangle(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color))
+END FillRectF;
+
+PROCEDURE FillRect*(x1, y1, x2, y2: INTEGER; color: Color);
+BEGIN
+  Al.draw_filled_rectangle(FLT(x1), FLT(y1),
+    FLT(x2 + 1), FLT(y2 + 1), SYSTEM.VAL(Al.Color, color))
+END FillRect;
+
+PROCEDURE ThickRectF*(x1, y1, x2, y2: REAL; color: Color; thickness: REAL);
+BEGIN Al.draw_rectangle(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), thickness)
+END ThickRectF;
+
+PROCEDURE ThickRect*(x1, y1, x2, y2: INTEGER; color: Color;
+    thickness: INTEGER);
+BEGIN
+  Al.draw_rectangle(FLT(x1) + 0.5, FLT(y1) + 0.5,
+    FLT(x2) + 0.5, FLT(y2) + 0.5, SYSTEM.VAL(Al.Color, color), FLT(thickness))
+END ThickRect;
+
+PROCEDURE RectF*(x1, y1, x2, y2: REAL; color: Color);
+BEGIN Al.draw_rectangle(x1, y1, x2, y2, SYSTEM.VAL(Al.Color, color), 1.0)
+END RectF;
+
+PROCEDURE Rect*(x1, y1, x2, y2: INTEGER; color: Color);
+BEGIN
+  Al.draw_rectangle(FLT(x1) + 0.5, FLT(y1) + 0.5,
+    FLT(x2) + 0.5, FLT(y2) + 0.5, SYSTEM.VAL(Al.Color, color), 1.0)
+END Rect;
+
+PROCEDURE NewBitmap*(w, h: INTEGER): Bitmap;
+VAR b: Bitmap;
+BEGIN NEW(b);
+  b.bmp := Al.create_bitmap(w, h);
+  IF b.bmp = NIL THEN b := NIL
+  ELSE b.w := w; b.h := h
+  END
+RETURN b END NewBitmap;
+
+PROCEDURE DrawPartFlip*(bmp: Bitmap; sx, sy, sw, sh, dx, dy: INTEGER;
+    flags: SET);
+BEGIN
+  Al.draw_bitmap_region(bmp.bmp, FLT(sx), FLT(sy), FLT(sw), FLT(sh),
+    FLT(dx), FLT(dy), flags)
+END DrawPartFlip;
+
+PROCEDURE DrawPart*(bmp: Bitmap; sx, sy, sw, sh, dx, dy: INTEGER);
+BEGIN
+  Al.draw_bitmap_region(bmp.bmp, FLT(sx), FLT(sy), FLT(sw), FLT(sh),
+    FLT(dx), FLT(dy), {})
+END DrawPart;
+
+PROCEDURE DrawFlip*(bmp: Bitmap; x, y: INTEGER; flags: SET);
+BEGIN Al.draw_bitmap(bmp.bmp, FLT(x), FLT(y), flags)
+END DrawFlip;
+
+PROCEDURE Draw*(bmp: Bitmap; x, y: INTEGER);
+BEGIN Al.draw_bitmap(bmp.bmp, FLT(x), FLT(y), {})
+END Draw;
+
+PROCEDURE DrawEx*(bmp: Bitmap; sx, sy, sw, sh, dx, dy, dw, dh: INTEGER;
+    flags: SET);
+BEGIN
+  Al.draw_scaled_bitmap(bmp.bmp, FLT(sx), FLT(sy), FLT(sw), FLT(sh),
+    FLT(dx), FLT(dy), FLT(dw), FLT(dh), flags)
+END DrawEx;
+
+PROCEDURE DrawRotated*(bmp: Bitmap; cx, cy, dx, dy: INTEGER;
+    angle: REAL; flags: SET);
+BEGIN
+  Al.draw_rotated_bitmap(bmp.bmp, FLT(cx), FLT(cy),
+    FLT(dx), FLT(dy), angle, flags)
+END DrawRotated;
+
+PROCEDURE DrawScaledRotated*(bmp: Bitmap; cx, cy, dx, dy: INTEGER;
+    xScale, yScale, angle: REAL; flags: SET);
+BEGIN
+  Al.draw_scaled_rotated_bitmap(bmp.bmp, FLT(cx), FLT(cy),
+    FLT(dx), FLT(dy), xScale, yScale, angle, flags)
+END DrawScaledRotated;
+
+PROCEDURE DelayF*(n: REAL);
+BEGIN Al.rest(n)
+END DelayF;
+
+PROCEDURE Delay*(n: INTEGER);
+BEGIN Al.rest(n / 1000)
+END Delay;
+
+PROCEDURE Pause*;
+BEGIN
+
+END Pause;
+
+PROCEDURE SetWindowTitle*(W: Window; title: ARRAY OF CHAR);
+VAR q: ARRAY 256 OF SHORTCHAR;
+BEGIN Utf8.Encode(title, q); Al.set_window_title(W.display, q)
+END SetWindowTitle;
+
+PROCEDURE NewWindow*(x, y, w, h: INTEGER; title: ARRAY OF CHAR;
+    options: SET): Window;
+VAR W: Window;
+  d: Al.Display;
+  q: ARRAY 256 OF SHORTCHAR;
+  opt: SET;
+  n, dw, dh, nw, nh: INTEGER;
+BEGIN NEW(W); W.w := w; W.h := h;
+
+  Utf8.Encode(title, q); Al.set_new_window_title(q);
+  IF software IN options THEN n := 0 ELSE n := 1 END;
+  Al.set_new_display_option(Al.renderMethod, n, Al.suggest);
+  Al.set_new_display_option(Al.vsync, 2, Al.suggest);
+
+  IF smooth IN options THEN n := 1;
+    Al.set_new_display_option(Al.samples, 8, Al.suggest)
+  ELSE n := 0
+  END;
+  Al.set_new_display_option(Al.sampleBuffers, n, Al.suggest);
+
+  IF centered IN options THEN
+    GetDesktopResolution(dw, dh);
+    x := (dw - w) DIV 2;
+    y := (dh - h) DIV 2;
+    IF x < 0 THEN x := 0 END;
+    IF y < 0 THEN y := 0 END;
+    Al.set_new_window_position(x, y)
+  ELSIF (x < 0) OR (y < 0) THEN
+    Al.set_new_window_position(Al.intMax, Al.intMax)
+  ELSE Al.set_new_window_position(x, y)
+  END;
+
+  opt := {};
+  wantW := w; wantH := h;
+  IF fullscreen IN options THEN
+    INCL(opt, Al.fullscreenWindow);
+    IF (wantW <= 0) OR (wantH <= 0) THEN
+      GetDesktopResolution(wantW, wantH);
+      wantW := FLOOR(wantW / scaleX);
+      wantH := FLOOR(wantH / scaleY)
+    ELSIF ~(exact IN options) THEN
+      GetDesktopResolution(w, h);
+      w := FLOOR(w / scaleX); h := FLOOR(h / scaleY);
+      IF ~(smooth IN options) THEN
+        nw := w DIV wantW; nh := h DIV wantH;
+        Out.String('want = '); Out.Int(wantW, 0); Out.String(', '); Out.Int(wantH, 0); Out.Ln;
+        IF nw < nh THEN wantW := w DIV nw; wantH := h DIV nw
+        ELSE wantW := w DIV nh; wantH := h DIV nh
+        END
+;       Out.String('nw, nh = '); Out.Int(nw, 0); Out.String(', '); Out.Int(nh, 0); Out.Ln;
+      END;
+      IF w / h > wantW / wantH THEN wantW := w * wantH DIV h
+      ELSE wantH := h * wantW DIV w
+      END
+    END
+  ELSE INCL(opt, Al.windowed);
+    IF (wantW <= 0) OR (wantH <= 0) THEN wantW := 640; wantH := 400 END
+  END;
+  IF sizeStepX # 1 THEN wantW := wantW DIV sizeStepX * sizeStepX END;
+  IF sizeStepY # 1 THEN wantH := wantH DIV sizeStepY * sizeStepY END;
+
+  IF resizable IN options THEN INCL(opt, Al.resizable) END;
+  IF maximized IN options THEN INCL(opt, Al.maximized) END;
+  IF minimized IN options THEN INCL(opt, Al.minimized) END;
+  IF frameless IN options THEN INCL(opt, Al.frameless) END;
+  Al.set_new_display_flags(opt);
+
+  Out.String('want = '); Out.Int(wantW, 0); Out.String(', '); Out.Int(wantH, 0); Out.Ln;
+
+  W.display := Al.create_display(wantW, wantH);
+  W.winW := Al.get_display_width(W.display);
+  W.winH := Al.get_display_height(W.display);
+
+  Out.String('W. w,h = '); Out.Int(W.w, 0); Out.String(', '); Out.Int(W.h, 0); Out.Ln;
+
+  IF (wantW # W.w) OR (wantH # W.h) THEN
+    W.bmp := Al.create_bitmap(wantW, wantH);
+    W.w := wantW; W.h := wantH
+  ELSE W.bmp := NIL
+  END;
+
+  Out.String('FINAL w h       = '); Out.Int(W.w, 0); Out.String(', '); Out.Int(W.h, 0); Out.Ln;
+  Out.String('FINAL winW winH = '); Out.Int(W.winW, 0); Out.String(', '); Out.Int(W.winH, 0); Out.Ln;
+
+  SetWindowScale(W, 1.0, 1.0); (*!FIXME remove*)
+  Al.register_event_source(queue, Al.get_display_event_source(W.display));
+
+  W.next := windowList; windowList := W
+RETURN W END NewWindow;
+
+PROCEDURE CloseWindow*(W: Window);
+BEGIN Al.destroy_display(W.display)
+END CloseWindow;
+
+PROCEDURE NewTimer*(speed: REAL): Timer;
+VAR T: Timer;
+BEGIN NEW(T); T.tmr := Al.create_timer(speed);
+  Al.register_event_source(queue, Al.get_timer_event_source(T.tmr))
+RETURN T END NewTimer;
+
+PROCEDURE NoEvents*(): BOOLEAN;
+RETURN Al.is_event_queue_empty(queue) END NoEvents;
+
+PROCEDURE GetWindow*(e: Event): Window;
+VAR W: Window;
+  d: Al.Display;
+BEGIN d := e.display; W := windowList;
+  WHILE (W # NIL) & (W.display # d) DO W := W.next END
+RETURN W END GetWindow;
+
+PROCEDURE ApplyResize*(e: Event);
+VAR W: Window;
+BEGIN Al.acknowledge_resize(e.display);
+  W := GetWindow(e);
+  W.w := Al.get_display_width(e.display);
+  W.h := Al.get_display_height(e.display)
+END ApplyResize;
+
+PROCEDURE WaitEvent*(VAR event: Event);
+VAR E: Al.Event;
+  DE: Al.PDisplayEvent;
+  TE: Al.PTimerEvent;
+  KE: Al.PKeyboardEvent;
+  ME: Al.PMouseEvent;
+BEGIN Al.wait_for_event(queue, E);
+  event.time := E.timestamp;
+  IF E.type = Al.eventMouseAxes THEN
+    event.type := mouseMove;
+    ME := SYSTEM.VAL(Al.PMouseEvent, SYSTEM.ADR(E));
+    event.x := ME.x; event.y := ME.y; event.z := ME.z; event.w := ME.w;
+    event.dx := ME.dx; event.dy := ME.dy; event.dz := ME.dz; event.dw := ME.dw;
+    event.button := ME.button;
+    event.display := ME.display
+  ELSIF E.type = Al.eventMouseButtonDown THEN
+    event.type := mouseDown;
+    ME := SYSTEM.VAL(Al.PMouseEvent, SYSTEM.ADR(E));
+    event.x := ME.x; event.y := ME.y; event.z := ME.z; event.w := ME.w;
+    event.button := ME.button;
+    event.display := ME.display
+  ELSIF E.type = Al.eventMouseButtonUp THEN
+    event.type := mouseUp;
+    ME := SYSTEM.VAL(Al.PMouseEvent, SYSTEM.ADR(E));
+    event.x := ME.x; event.y := ME.y; event.z := ME.z; event.w := ME.w;
+    event.button := ME.button;
+    event.display := ME.display
+  ELSIF E.type = Al.eventTimer THEN
+    event.type := timer;
+    TE := SYSTEM.VAL(Al.PTimerEvent, SYSTEM.ADR(E));
+    event.count := TE.count;
+    event.source := SYSTEM.VAL(ADRINT, TE.source)
+  ELSIF E.type = Al.eventKeyDown THEN
+    event.type := keyDown;
+    KE := SYSTEM.VAL(Al.PKeyboardEvent, SYSTEM.ADR(E));
+    event.key := KE.keycode;
+    event.display := KE.display
+  ELSIF E.type = Al.eventKeyUp THEN
+    event.type := keyUp;
+    KE := SYSTEM.VAL(Al.PKeyboardEvent, SYSTEM.ADR(E));
+    event.key := KE.keycode;
+    event.display := KE.display
+  ELSIF E.type = Al.eventKeyChar THEN
+    event.type := char;
+    KE := SYSTEM.VAL(Al.PKeyboardEvent, SYSTEM.ADR(E));
+    event.key := KE.keycode;
+    event.ch := CHR(KE.unichar);
+    event.mod := KE.modifiers;
+    event.repeat := KE.repeat;
+    event.display := KE.display
+  ELSIF E.type = Al.eventDisplayResize THEN
+    event.type := resize;
+    DE := SYSTEM.VAL(Al.PDisplayEvent, SYSTEM.ADR(E));
+    event.x := DE.x; event.y := DE.y;
+    event.w := DE.width; event.h := DE.height;
+    event.display := DE.source
+  ELSIF E.type = Al.eventDisplayClose THEN
+    event.type := quit;
+    event.display := SYSTEM.VAL(Al.Display, E.source)
+  ELSE
+    event.type := 1000 + E.type
+  END
+END WaitEvent;
+
+PROCEDURE StartTimer*(timer: Timer);
+BEGIN Al.start_timer(timer.tmr)
+END StartTimer;
+
+PROCEDURE InitScreen;
+BEGIN
+  IF ~(fullscreen IN settings) & ((wantW <= 0) OR (wantH <= 0)) THEN
+    wantW := 640; wantH := 400
+  END;
+  screen := NewWindow(-1, -1, wantW, wantH, wantScreenTitle, settings);
+  Target(screen)
+END InitScreen;
+
+PROCEDURE Init*;
+BEGIN
+  IF Al.install_system(Al.get_allegro_version(), 0) THEN
+    IF ~Al.install_keyboard() THEN
+      Out.String('Could not install keyboard.'); Out.Ln
+    END;
+
+    IF ~Al.install_mouse() THEN
+      Out.String('Could not install mouse.'); Out.Ln
+    END;
+
+    IF ~Al.init_primitives_addon() THEN
+      Out.String('Could not init primitives addon.'); Out.Ln
+    END;
+
+    IF ~Al.init_image_addon() THEN
+      Out.String('Could not init image addon.'); Out.Ln
+    END;
+
+    queue := Al.create_event_queue();
+    IF queue = NIL THEN
+      Out.String('Could not create queue.'); Out.Ln
+    END;
+
+    Al.register_event_source(queue, Al.get_keyboard_event_source());
+    Al.register_event_source(queue, Al.get_mouse_event_source());
+
+    IF ~(manual IN settings) THEN InitScreen END
+  ELSE Out.String('ERROR'); Out.Ln
+  END
+END Init;
+
+PROCEDURE ResetDefaults;
+BEGIN
+  wantW := 640; wantH := 400; sizeStepX := 1; sizeStepY := 1;
+  scaleX := 1.0; scaleY := 1.0;
+  settings := {fullscreen};
+  wantScreenTitle := 'Oberon'
+END ResetDefaults;
+
+PROCEDURE Close*;
+BEGIN
+  Al.uninstall_system;
+  queue := NIL; windowList := NIL; screen := NIL; target := NIL;
+  ResetDefaults
+END Close;
+
+BEGIN
+  ResetDefaults
+END Graph2.

二進制
src/img.png