;*                                                                           */
 ;*                                                                           */
 ;*                                                                           */
-;* (C) 2002-2009, Ullrich von Bassewitz                                      */
+;* (C) 2002-2012, Ullrich von Bassewitz                                      */
 ;*                Roemerstrasse 52                                           */
 ;*                D-70794 Filderstadt                                        */
 ;* EMail:         uz@cc65.org                                                */
         TGI_ERR_INV_FONT        ; Font file is invalid
         TGI_ERR_NO_RES          ; Out of resources (memory, handles, ...)
         TGI_ERR_UNKNOWN         ; Unknown error
+        TGI_ERR_INSTALLED       ; A driver is already installed
 
         TGI_ERR_COUNT           ; Special: Number of error messages
 .endenum
 
 ;*                                                                           */
 ;*                                                                           */
 ;*                                                                           */
-;* (C) 2002-2009, Ullrich von Bassewitz                                      */
+;* (C) 2002-2012, Ullrich von Bassewitz                                      */
 ;*                Roemerstrasse 52                                           */
 ;*                D-70794 Filderstadt                                        */
 ;* EMail:         uz@cc65.org                                                */
 ;------------------------------------------------------------------------------
 ; ASM functions
 
+        .global tgi_clear_ptr
         .global tgi_clippedline
         .global tgi_curtoxy
         .global tgi_getset
 
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2009, Ullrich von Bassewitz                                      */
+/* (C) 2002-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
 #define TGI_ERR_INV_FUNC       6       /* Function not supported */
 #define TGI_ERR_INV_FONT        7       /* Font file is invalid */
 #define TGI_ERR_NO_RES          8       /* Out of resources */
+#define TGI_ERR_INSTALLED       9       /* A driver is already installed */
 
 
 
 
 # Object files
 
 C_OBJS =        tgi_arc.o               \
-                tgi_load_driver.o       \
                 tgi_load_vectorfont.o   \
                 tgi_pieslice.o
 
                 tgi_line.o              \
                 tgi_linepop.o           \
                 tgi_lineto.o            \
+                tgi_load.o              \
                 tgi_outcode.o           \
                 tgi_outtext.o           \
                 tgi_outtextxy.o         \
 
 
 ; Clear driver pointer and error code
 
+tgi_clear_ptr:
         lda     #$00
         sta     _tgi_drv
         sta     _tgi_drv+1
 
         .byte   <(msg7-msgtab)
         .byte   <(msg8-msgtab)
         .byte   <(msg9-msgtab)
+        .byte   <(msg10-msgtab)
 
 msgtab:
 msg0:   .asciiz         "No error"
 msg7:   .asciiz         "Invalid font file"
 msg8:   .asciiz         "Out of resources"
 msg9:   .asciiz         "Unknown error"
+msg10:  .asciiz         "A driver is already installed"
 
+.assert (*-msgtab) < 256, error, "Message table too large"
 
--- /dev/null
+;
+; Ullrich von Bassewitz, 2012-07-22
+;
+; void __fastcall__ tgi_load_driver (const char* name);
+; /* Load and install the given driver. */
+
+
+        .include        "tgi-kernel.inc"
+        .include        "tgi-error.inc"
+        .include        "modload.inc"
+        .include        "fcntl.inc"
+
+        .import         pushax
+        .import         pusha0
+        .import         incsp2
+        .import         _open
+        .import         _read
+        .import         _close
+
+
+
+;----------------------------------------------------------------------------
+; Variables
+
+.data
+
+ctrl:   .addr   _read
+        .res    2                       ; CALLERDATA
+        .res    2                       ; MODULE
+        .res    2                       ; MODULE_SIZE
+        .res    2                       ; MODULE_ID
+
+;----------------------------------------------------------------------------
+; Code
+
+.code
+
+.proc   _tgi_load_driver
+
+; Check if we do already have a driver loaded. This is an error. Do not
+; touch A/X because they contain the file name.
+
+        ldy     _tgi_drv
+        bne     @L0
+        ldy     _tgi_drv+1
+        beq     @L1
+@L0:    lda     #TGI_ERR_INSTALLED
+        bne     @L3
+
+; Push the name onto the C stack and open the file. The parameter will get
+; removed by open().
+; ctrl.callerdata = open (name, O_RDONLY);
+
+@L1:    jsr     pushax
+        lda     #<O_RDONLY
+        jsr     pusha0
+        ldy     #4                      ; Argument size
+        jsr     _open
+        sta     ctrl + MOD_CTRL::CALLERDATA
+        stx     ctrl + MOD_CTRL::CALLERDATA+1
+
+; if (ctrl.callerdata >= 0) {
+
+        txa
+        bmi     @L2
+
+; /* Load the module */
+; Res = mod_load (&ctrl);
+
+        lda     #<ctrl
+        ldx     #>ctrl
+        jsr     _mod_load
+        pha
+
+; /* Close the input file */
+; close (ctrl.callerdata);
+
+        lda     ctrl + MOD_CTRL::CALLERDATA
+        ldx     ctrl + MOD_CTRL::CALLERDATA+1
+        jsr     _close
+
+; /* Check the return code */
+; if (Res == MLOAD_OK) {
+
+        pla
+        beq     @L5
+@L2:    lda     #TGI_ERR_CANNOT_LOAD
+
+; Set an error and exit
+
+@L3:    sta     _tgi_error
+@L4:    rts
+
+; Check the driver signature, install the driver. c is already on stack and
+; will get removed by ser_install().
+; Res = ser_install (ctrl.module);
+
+@L5:    lda     ctrl + MOD_CTRL::MODULE
+        ldx     ctrl + MOD_CTRL::MODULE+1
+        jsr     _tgi_install
+
+; If tgi_install was successful, we're done
+
+        lda     _tgi_error
+        beq     @L4
+
+; The driver didn't install correctly. Remove it from memory. The error code
+; will be retained.
+
+        lda     _tgi_drv
+        ldx     _tgi_drv+1
+        jsr     _mod_free               ; Free the driver memory
+        jmp     tgi_clear_ptr           ; Clear tgi_drv and return
+
+.endproc
+
+
+   
 
+++ /dev/null
-/*****************************************************************************/
-/*                                                                           */
-/*                             tgi_load_driver.c                             */
-/*                                                                           */
-/*                       Loader module for TGI drivers                       */
-/*                                                                           */
-/*                                                                           */
-/*                                                                           */
-/* (C) 2002-2009, Ullrich von Bassewitz                                      */
-/*                Roemerstrasse 52                                           */
-/*                D-70794 Filderstadt                                        */
-/* EMail:         uz@cc65.org                                                */
-/*                                                                           */
-/*                                                                           */
-/* This software is provided 'as-is', without any expressed or implied       */
-/* warranty.  In no event will the authors be held liable for any damages    */
-/* arising from the use of this software.                                    */
-/*                                                                           */
-/* Permission is granted to anyone to use this software for any purpose,     */
-/* including commercial applications, and to alter it and redistribute it    */
-/* freely, subject to the following restrictions:                            */
-/*                                                                           */
-/* 1. The origin of this software must not be misrepresented; you must not   */
-/*    claim that you wrote the original software. If you use this software   */
-/*    in a product, an acknowledgment in the product documentation would be  */
-/*    appreciated but is not required.                                       */
-/* 2. Altered source versions must be plainly marked as such, and must not   */
-/*    be misrepresented as being the original software.                      */
-/* 3. This notice may not be removed or altered from any source              */
-/*    distribution.                                                          */
-/*                                                                           */
-/*****************************************************************************/
-
-
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <modload.h>
-#include <tgi.h>
-#include <tgi/tgi-kernel.h>
-
-
-
-/*****************************************************************************/
-/*                                   Code                                    */
-/*****************************************************************************/
-
-
-
-void __fastcall__ tgi_load_driver (const char* name)
-/* Install the given driver. This function is identical to tgi_load with the
- * only difference that the name of the driver is specified explicitly. You
- * should NOT use this function in most cases, use tgi_load() instead.
- */
-{
-    static struct mod_ctrl ctrl = {
-        read            /* Read from disk */
-    };
-    unsigned Res;
-
-    /* Check if we do already have a driver loaded. If so, remove it. */
-    if (tgi_drv != 0) {
-        tgi_unload ();
-    }
-
-    /* Now open the file */
-    ctrl.callerdata = open (name, O_RDONLY);
-    if (ctrl.callerdata >= 0) {
-
-        /* Load the module */
-        Res = mod_load (&ctrl);
-
-        /* Close the input file */
-        close (ctrl.callerdata);
-
-        /* Check the return code */
-        if (Res == MLOAD_OK) {
-
-            /* Check the driver signature, install the driver */
-            tgi_install (ctrl.module);
-            return;
-
-        }
-    }
-
-    /* Error loading the driver */
-    tgi_error = TGI_ERR_CANNOT_LOAD;
-}