Changeset 14:0047b364b6d9

Show
Ignore:
Timestamp:
03/07/08 12:51:02 (10 months ago)
Author:
Diggory Hardy <diggory.hardy@gmail.com>
branch:
default
convert_revision:
d82c68b347390eb6bb28020500056e0060b36de6
Message:

Changed much of the mergetag structure and some functionality. First tests on windows.

Changes to mergetag Reader methods. New functionality allowing a dataSecCreator to cause sections to be skipped.
Moved several of the mergetag modules and some of their contents around. Moved all interfaces to separate modules in iface/ .
IReader & IWriter interfaces exist; MTTReader, MTBReader, MTTWriter, MTBWriter & DualWriter? all now exist and implement IReader/IWriter (although the MTB variants are dummy classes); makeReader & makeWriter should both be fully functional.

Tested building on windows with partial success (works but window won't open).
Included a temporary hack from windows to get supported resolutions information.

committer: Diggory Hardy <diggory.hardy@gmail.com>

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • conf/input.mtt

    r10 r14  
    11{MT01} 
    2 <char[][]|Configs=["Std"]> 
    3 <char[]|Test="1"> 
     2!<char[][]|Configs=["Default"]> 
    43{Default} 
    54<uint[][uint]|B=[ 0x8800001B : [[0x1000, 0x0]] ]> 
  • conf/options.mtt

    r12 r14  
    11{MT01} 
    22{Default} 
    3 <char[]|greeting="Hi − options now work!"> 
    43<char[]|L10n="en-GB"> 
    54 
  • doc/jobs

    r12 r14  
    22 
    33To do: 
    4 *   Submit new version of parseTo 
    5 *   Why doesn't input.config filtering via headers "Configs" work? 
     4*   Control logging level/output via options. 
     5*   Read config from system and user paths. 
     6*   Windows building/compatibility (currently partial) 
     7*   gdc building/compatibility (wait for tango 0.99.5 release?) 
     8*   Config loaded from correct places 
    69*   OutOfMemoryException is not currently checked for − it should be at least in critical places (use high-level catching of all errors?). 
    710*   Sensitivity adjustments. From es_a_out: 
     
    3437 
    3538Done (for git log message): 
    36 *   Implemented i18n.I18nTranslation class to load strings and descriptions from files (with unittest). 
    37 *   MTUnknownTypeException removed: its pointless since it's always ignored without even any message. 
    38 *   A few fixes to mde.mergetag.read.Reader regarding partial reading. 
     39Changes to mergetag Reader methods. New functionality allowing a dataSecCreator to cause sections to be skipped. 
     40Moved several of the mergetag modules and some of their contents around. Moved all interfaces to separate modules in iface/ . 
     41Mergetag: IReader & IWriter interfaces exist; MTTReader, MTBReader, MTTWriter, MTBWriter & DualWriter all now exist and implement IReader/IWriter (although the MTB variants are dummy classes); makeReader & makeWriter should both be fully functional. 
     42Tested building on windows with partial success (works but window won't open). 
     43Included a temporary hack from windows to get supported resolutions information. 
  • dsss.conf

    r11 r14  
    1 defaulttargets = mde/mde.d 
     1version (Posix) { 
     2    defaulttargets = mde/mde.d 
     3} else version (Win32) { 
     4    defaulttargets = mde\mde.d 
     5
    26 
    37[*] 
    48version (Posix) { 
    59    buildflags=-L-ldl 
    6 } else { 
    7     warn Only posix builds have been tested; elsewhere other libraries will probably need to be linked. 
    810} 
    911 
    1012[mde/mde.d] 
    1113target=bin/mde 
     14 
     15#[mde\mde.d] 
     16#target=bin\mde 
    1217 
    1318[test/mdeTest.d] 
     
    1722version (Posix) { 
    1823    buildflags+=-L-ldl 
    19 } else { 
    20     warn Only posix builds have been tested; elsewhere other libraries will probably need to be linked. 
    2124} 
  • mde/i18n.d

    r12 r14  
    2727import mde.exception; 
    2828 
    29 import mde.mergetag.dataset; 
    30 import mde.mergetag.read
     29import mde.mergetag.DataSet; 
     30import mde.mergetag.Reader
    3131import mde.mergetag.exception; 
    3232 
     
    4040* Encoding used is UTF-8. 
    4141*/ 
    42 class I18nTranslation : DataSection 
     42class I18nTranslation : IDataSection 
    4343{ 
    4444    final char[] name;      /// The module/package/... which the instance is for 
     
    8585        */ 
    8686        FilePath filePath = new FilePath ("conf/L10n/"~name~".mtt"); 
    87         // If it's not a file or an empty file stop. 
    88         if (!filePath.exists || filePath.fileSize == 0u) { 
     87        // If it doesn't exist, stop. 
     88        // Don't bother checking it's not a folder, because it could still be a block or something. 
     89        if (!filePath.exists) { 
    8990            throw new L10nLoadException ("No database file conf/L10n/"~name~".mtt exists!"); 
    9091        } 
    9192         
    92         Reader reader; 
     93        IReader reader; 
    9394        try { 
    94             reader = new Reader(filePath); 
     95            reader = new MTTReader(filePath); 
    9596            /* Note: we don't want to load every translation section depended on to its own class 
    9697            * instance, since we want to merge them. So make every mergetag section use the same 
    9798            * instance. */ 
    98             reader.dataSecCreator = delegate DataSection(ID) { 
     99            reader.dataSecCreator = delegate IDataSection(ID) { 
    99100                return transl; 
    100101            }; 
  • mde/init.d

    r12 r14  
    1919import tango.util.log.Log : Log, Logger; 
    2020import tango.util.log.ConsoleAppender : ConsoleAppender; 
    21 import tango.stdc.stringz : fromUtf8z; 
     21import tango.stdc.stringz : fromStringz; 
    2222 
    2323import derelict.sdl.sdl; 
     
    3636        // For now, just log to the console: 
    3737        Logger root = Log.getRootLogger(); 
    38         root.setLevel(root.Level.Trace); 
     38        debug root.setLevel(root.Level.Trace); 
     39        else root.setLevel(root.Level.Info); 
    3940        root.addAppender(new ConsoleAppender); 
    4041    } 
     
    9394                return; 
    9495            } 
    95             logger.info ("Derelict: loaded SDL"); 
     96            logger.trace ("Derelict: loaded SDL"); 
    9697             
    9798            if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_JOYSTICK /+| SDL_INIT_EVENTTHREAD+/)) { 
    9899                logger.fatal ("SDL initialisation failed:"); 
    99100                char* msg = SDL_GetError (); 
    100                 logger.fatal (msg ? fromUtf8z(msg) : "no reason available"); 
     101                logger.fatal (msg ? fromStringz(msg) : "no reason available"); 
    101102                 
    102103                setFailure ();      // abort 
     
    104105            } 
    105106             
    106             SDL_SetVideoMode (800, 600, 0, 0); 
    107              
    108107            addCleanupFct (&cleanupSDL); 
    109             logger.info ("SDL initialised"); 
     108            logger.trace ("SDL initialised"); 
     109             
     110            // Print a load of info: 
     111            logger.info ("Available video modes:"); 
     112            char[128] tmp; 
     113            SDL_Rect** modes = SDL_ListModes (null, SDL_FULLSCREEN); 
     114            if (modes is null) logger.info ("None!"); 
     115            else if (modes is cast(SDL_Rect**) -1) logger.info ("All modes are available"); 
     116            else { 
     117                for (uint i = 0; modes[i] !is null; ++i) { 
     118                    logger.info (logger.format (tmp, "\t{}x{}", modes[i].w, modes[i].h)); 
     119                } 
     120            } 
     121             
     122            SDL_VideoInfo* vi = SDL_GetVideoInfo (); 
     123            if (vi !is null) { 
     124                logger.info ("Video info:"); 
     125                logger.info ("Hardware surface support: "~ (vi.flags & SDL_HWSURFACE ? "yes" : "no")); 
     126                logger.info (logger.format (tmp, "Video memory: {}", vi.video_mem)); 
     127                 
     128                if (vi.vfmt !is null) { 
     129                    logger.info ("Best video mode:"); 
     130                    logger.info (logger.format (tmp, "Bits per pixel: {}", vi.vfmt.BitsPerPixel)); 
     131                } 
     132            } 
     133             
     134            // FIXME: make this non-fatal and provide a way to re-set video mode 
     135            if (SDL_SetVideoMode (800, 600, 0, 0) is null) {   // Can't open in windows!! 
     136                logger.fatal ("Unable to set video mode:"); 
     137                char* msg = SDL_GetError (); 
     138                logger.fatal (msg ? fromStringz(msg) : "no reason available"); 
     139                 
     140                setFailure (); 
     141                return; 
     142            } 
    110143             
    111144            openJoysticks ();       // after SDL init 
     
    164197            try { 
    165198                t.join (true); 
    166             /+ Will only catch thread exceptions; but even so something still went badly wrong so we want the same functionality. 
     199            /+ We might as well catch and report any exception, rather than just ThreadExceptions: 
    167200            } catch (ThreadException e) {   // Any threading exception 
    168201            +/ 
     
    195228    { 
    196229        if (!initFailure) { 
    197             logger.info ("Cleaning up..."); 
     230            logger.trace ("Cleaning up..."); 
    198231            runCleanupFcts();   // if threading, note not all functions can be called simultaeneously 
    199             logger.info ("Done!"); 
     232            logger.trace ("Done!"); 
    200233        } 
    201234    } 
  • mde/input/config.d

    r12 r14  
    66import mde.input.exception; 
    77 
    8 import MT = mde.mergetag.read
     8import MT = mde.mergetag.Reader
    99import tango.scrapple.text.convert.parseTo : parseTo; 
    1010 
     
    1717 * Class extends DataSection so that it can be loaded by mergetag easily. 
    1818 */ 
    19 class Config : MT.DataSection 
     19class Config : MT.IDataSection 
    2020{ 
    2121    alias uint[] outQueue;      // This is the type for the out queue config data. 
     
    118118        loadedFiles.add (filename); 
    119119         
    120         MT.Reader file; 
     120        MT.IReader file; 
    121121         
    122122        try { 
    123             file = new MT.Reader(filename, null, true);   // open and read header 
     123            file = new MT.MTTReader(filename, null, true);    // open and read header 
    124124            // TODO: also load user-config file 
    125125             
    126126            file.dataSecCreator = 
    127             delegate MT.DataSection (MT.ID) { return new Config;  }; 
     127            delegate MT.IDataSection (MT.ID) {    return new Config;  }; 
    128128             
    129129            // D2.0: enum MT.ID CONFIGS = "Configs"; 
    130130            const MT.ID CONFIGS = cast(MT.ID)"Configs"; 
    131             MT.ID[] file_configs;   // active config sections (may not exist) 
    132             MT.ID[]* file_configs_p = cast(MT.ID[]*) (CONFIGS in file.dataset.header._charAA); 
    133             debug foreach (i,d; file.dataset.header._charAA) logger.trace ("ID: "~cast(char[])i); 
    134             debug foreach (i,d; file.dataset.header._charA) logger.trace ("ID: "~cast(char[])i); 
    135                          
    136             if (file_configs_p) file.read(*file_configs_p); // restrict to this set IF a restriction was given 
     131            // Restrict config sections if this tag exists: 
     132            auto file_configs_p = CONFIGS in file.dataset.header._charAA; 
     133            MT.ID[] file_configs = null; 
     134            if (file_configs_p) { 
     135                file_configs = cast(MT.ID[]) *file_configs_p; 
     136            } 
     137             
     138            if (file_configs)   file.read(file_configs);    // restrict to this set IF a restriction was given 
    137139            else        file.read();            // otherwise read all 
    138140        } 
  • mde/input/input.d

    r12 r14  
    123123    /** Feed an SDL_Event struct (only uses if it's a key, mouse or joystick event). 
    124124    * 
    125     * Other types of event functions may be added. Returns true if the event was used, false if not. 
     125    * Other types of event functions may be added. Returns true if the event was used, false if not 
     126    * or no config was available. Hmm... doesn't seem very useful, but has practically no cost. 
    126127    * 
    127128    * May throw InputClassExceptions (on configuration errors). Catching the exception and continuing should 
     
    129130    */ 
    130131    bool opCall (ref SDL_Event event) { 
     132        /* Non-config events. 
     133        * 
     134        * Mouse events don't need config for the GUI. Handle them first so that if no config exists 
     135        * some functionality at least is retained. 
     136        */ 
     137        switch (event.type) { 
     138            case SDL_MOUSEBUTTONDOWN: 
     139            case SDL_MOUSEBUTTONUP: 
     140                foreach (dg; mouseClickCallbacks) 
     141                    dg (event.button.x, event.button.y, event.button.button, event.button.state == SDL_PRESSED); 
     142                break; 
     143             
     144            case SDL_MOUSEMOTION: 
     145                mouse_x = event.motion.x; 
     146                mouse_y = event.motion.y; 
     147                break; 
     148             
     149            default: 
     150        } 
     151         
     152        /* No config available, so don't try to access it and segfault. 
     153        * Don't log a message because this function is called per-event (i.e. frequently). 
     154        * A message should already have been logged by loadConfig anyway. 
     155        */ 
     156        if (!config) return false; 
     157         
    131158        switch (event.type) { 
    132159            // Keyboard events: 
     
    142169            case SDL_MOUSEBUTTONDOWN: 
    143170            case SDL_MOUSEBUTTONUP: 
    144                 // Mouse clicks: 
    145                 foreach (dg; mouseClickCallbacks) 
    146                     dg (event.button.x, event.button.y, event.button.button, event.button.state == SDL_PRESSED); 
    147                  
    148171                // Button events: 
    149172                outQueue[]* p = (Config.B.MOUSE | event.button.button) in config.button; 
     
    154177             
    155178            case SDL_MOUSEMOTION: 
    156                 // Screen coordinates (set here since relMotion is also used for joystick balls): 
    157                 mouse_x = event.motion.x; 
    158                 mouse_y = event.motion.y; 
    159                  
    160179                // Relative motion: 
    161180                outQueue[]* p = (Config.M.WMMOUSE) in config.relMotion; 
     
    268287            return false; 
    269288        } 
    270         debug logger.warn ("Config \""~profile~"\" not found."); 
     289        logger.warn ("Config profile \""~profile~"\" not found: input won't work unless a valid profile is loaded!"); 
    271290        return true; 
    272291    } 
  • mde/mergetag/doc/file-format-binary.txt

    r0 r14  
    44BOM  ---  a Byte Order Mark should be used to determin endianness (MT01 (or other version) in bytes, but converted to two ushorts to detect endianness?) 
    55 
     6 
     7File should then consist of sections: 
     8 
     9Header data including an address for the header section data if included. 
     10 
     11Sections list. Include a list of sections with identifiers and addresses, sorted by identifier and in a suitible format to easily be converted to a D hash-map. Addresses for each section should consist of both a start and an end address; the end address should be checked upon reading the section. In addition the start address must be checked against the end of file to avoid security vulnerabilities with reading other memory blocks. 
  • mde/mergetag/exception.d

    r12 r14  
    4545} 
    4646 
    47 /** Thrown by addTag (in classes implementing dataset.DataSection) when a data parsing error occurs 
     47/** Thrown by addTag (in classes implementing IDataSection) when a data parsing error occurs 
    4848* (really just to make whoever called addTag to log a warning saying where the error occured). */ 
    4949class MTaddTagParseException : MTException { 
     
    6666    } 
    6767} 
     68 
     69/// Thrown when attempting to use an unimplemented part of the package 
     70/// Really, just until MTB stuff is implemented 
     71class MTNotImplementedException : MTException { 
     72    this () { 
     73        super ("Functionality not implemented!"); 
     74    } 
     75} 
  • mde/mergetag/mtunittest.d

    r10 r14  
    22module mde.mergetag.mtunittest; 
    33 
    4 import mde.mergetag.read; 
    5 import mde.mergetag.write; 
    6 import mde.mergetag.defaultdata; 
     4import mde.mergetag.Reader; 
     5import mde.mergetag.Writer; 
     6import mde.mergetag.DataSet; 
     7import mde.mergetag.DefaultData; 
    78 
    89import tango.scrapple.text.convert.parseTo : parseTo; 
     
    1415    private Logger logger; 
    1516    static this() { 
    16         logger = Log.getLogger ("mde.mergetag.unittest"); 
     17        logger = Log.getLogger ("mde.mergetag.mtunittest"); 
    1718    } 
    1819 
     
    2122        * Thus it provides some basic testing for the whole mergetag package. */ 
    2223         
    23         const file = "unittest.mtt"; 
     24        const file = "unittest"; 
    2425        const ID UT_ID = cast (ID) "mdeUT"; 
    2526        const headInfo = "mde Unit Test"; 
     
    4243        mixin (genUTCode());    // Add an entry to dd for each type 
    4344         
    44         // FIXME: if/when binary writing is available, write in both formats 
    45         IWriter w = makeWriter (file, dsW); 
     45        IWriter w = makeWriter (file, dsW, WriterMethod.Both); 
    4646        w.write(); 
    4747         
    48         Reader r = new Reader (file, null, true); 
     48        // FIXME: when binary writing is supported, read both formats and check 
     49        IReader r = makeReader (file~".mtt", null, true); 
    4950        r.read(); 
    5051         
     
    5758        assert (*p == headInfo); 
    5859                 
    59         DataSection* sec_p = (UT_ID in dsR.sec); 
     60        IDataSection* sec_p = (UT_ID in dsR.sec); 
    6061        assert (sec_p); 
    6162        DefaultData secR = cast(DefaultData) *sec_p; 
  • mde/options.d

    r12 r14  
    88import mde.exception; 
    99 
    10 import mde.mergetag.read
    11 import mde.mergetag.write
    12 import mde.mergetag.dataset; 
     10import mde.mergetag.Reader
     11import mde.mergetag.Writer
     12import mde.mergetag.DataSet; 
    1313import mde.mergetag.exception; 
    1414 
     
    3131* All options and handling should be non-static to allow possibility of profiles later. 
    3232*/ 
    33 class Options : DataSection 
     33class Options : IDataSection 
    3434{ 
    3535    /* The options. 
     
    3939    * They can be read and set directly by other code (so not thread-safe for writing currently). 
    4040    */ 
    41     char[] greeting;    // just a testing message 
    4241    char[] L10n;        // locale, e.g. en-GB 
     42     
     43    /* Have any options been changed? Only bother writing if true. 
     44    * 
     45    * Maybe update this in the future to save if the last file edit was not made by mde. */ 
     46    bool changed = false; 
    4347     
    4448    /* The code to load/save the values. 
     
    4852    void addTag (char[] tp, ID id, char[] dt) { 
    4953        if (tp == "char[]") { 
    50             if (id == cast(ID)"greeting") greeting = parseTo!(char[]) (dt); 
    51             else if (id == cast(ID)"L10n") L10n = parseTo!(char[]) (dt); 
     54            if (id == cast(ID)"L10n") L10n = parseTo!(char[]) (dt); 
    5255        } 
    5356    } 
    5457    void writeAll (ItemDelg dlg) { 
    55         dlg ("char[]", cast(ID)"greeting", parseFrom!(char[]) (greeting)); 
    5658        dlg ("char[]", cast(ID)"L10n", parseFrom!(char[]) (L10n)); 
    5759    } 
     
    6668    static void load () { 
    6769        FilePath filePath = new FilePath (fileName); 
    68         // If it's not a file or an empty file stop. It should still be created on exit (assuming 
    69         // it's not a folder). 
    70         if (!filePath.exists || filePath.fileSize == 0u) return; 
    7170         
    72         Reader reader; 
     71        // Check it exists (if not it should still be created on exit). 
     72        // Don't bother checking it's not a folder, because it could still be a block or something. 
     73        if (!filePath.exists) return; 
     74         
     75        IReader reader; 
    7376        try { 
    74             reader = new Reader(filePath); 
    75             reader.dataSecCreator = delegate DataSection(ID) { 
     77            reader = new MTTReader(filePath); 
     78            reader.dataSecCreator = delegate IDataSection(ID) { 
    7679                return new Options; 
    7780            }; 
     
    8386        } 
    8487         
    85         DataSection* secP = secName in reader.dataset.sec; 
     88        IDataSection* secP = secName in reader.dataset.sec; 
    8689        options = cast(Options) *secP; 
    8790        if (options is null) { 
     
    9194    } 
    9295    static void save () { 
     96        if (!options.changed) return;   // skip 
     97 
    9398        DataSet ds = new DataSet(); 
    9499        ds.sec[secName] = options; 
  • mde/scheduler.d

    r4 r14  
    99// FIXME: support delegates or not? 
    1010/// This class can run scheduled functions per frame or every t seconds (sim-time). 
    11 class Scheduler 
     11abstract class Scheduler 
    1212{ 
    1313    /** The type of function pointer to be passed to the scheduler. 
  • test/mdeTest.d

    r12 r14  
    55// This module should import all mde modules containing unittests: 
    66import mde.input.input; 
    7 import mde.mergetag.dataset; 
     7import mde.mergetag.DataSet; 
    88import mde.mergetag.mtunittest; 
    99import mde.exception;