Code archives/File Utilities/Compile Blitz3D with Blitz3D

This code has been declared by its author to be Public Domain code.

Download source code

Compile Blitz3D with Blitz3D by Spencer2015
This program stitches files in a "source" and "script" directory together into a single output.bb file, then invokes blitzcc.exe to compile and run output.bb

Update AUG-5-2015 Switched NEW_LN from 10-13 to 13-10 Per RGR's suggestion.

Here is an example layout of how to use. The image references "the code above" , but in this case its the code below. The image was a supplement to a Forum discussion regarding BriskVM See link.

Is BriskVM dead? How do I get hold of?



I should say that this is merely a proof of concept. If you were distributing a program in this fashion you might want to do a couple of things:

1) "Scrub your Inputs" - Parse the user's script files and stop if there are any dangerous commands. File I/O is a good example. You don't want the user to read/write to files. So, you will need to parse and analyze the script files and throw an error on unwanted code. This is totally possible, but the code becomes more complicated and it would muddy up this example.

2) "Protect your Source" - Find a way to obfuscate you source files in the "source" folder. This way users can't easily alter the Game's source code. There are many different ways to do this, but they were omitted from the example code for clarity.
Graphics 640, 480, 0, 2
AppTitle "Blitz3D Game Launcher"

Const SCRIPT_FOLDER$ = "C:\MyGameFolder\scripts\"
Const SOURCE_FOLDER$ = "C:\MyGameFolder\source\"
Const OUTPUT_FILEPATH$ = "C:\MyGameFolder\output.bb"

Const BLITZ_PATH_VAR_NAME$ = "BLITZPATH"
Const BLITZ_PATH_VALUE$ = "C:\MyGameFolder\"
Const BLITZ_COMPILER_PATH$ = BLITZ_PATH_VALUE + "bin\compiler.exe"

Global BLITZ_CMD_TEMPLATE$ = Replace("'" + BLITZ_COMPILER_PATH + "' '{PATH}'","'",Chr(34))
Global NEW_LN$ = Chr(13) + Chr(10)


Function CompileAndRun(CodePath$, ScriptPath$, DestPath$)

    Local FullSource$ = ConcatSource(CodePath,ScriptPath)
    Local Command$ = Replace(BLITZ_CMD_TEMPLATE, "{PATH}", DestPath)
        
    WriteAllText(DestPath,FullSource)
    SetEnv(BLITZ_PATH_VAR_NAME, BLITZ_PATH_VALUE)
    Print GetEnv(BLITZ_PATH_VAR_NAME)
    Print Command
    Input "Press ENTER to run..."
    ExecFile(Command)
    End

End Function


Function ConcatSource$(CodePath$, ScriptPath$)

    Local SourceCodeBlob$ = ConcatFiles(CodePath)
    Local ScriptBlob$ = ConcatFiles(ScriptPath)
    Local FullSource$ = ""
    
    FullSource = SourceCodeBlob
    FullSource = FullSource + String(NEW_LN,2)
    FullSource = FullSource + ";" + String("*",80) + NEW_LN
    FullSource = FullSource + "; SCRIPT SOURCE BEGIN" + NEW_LN
    FullSource = FullSource + ";" + String("*",80) + NEW_LN
    FullSource = FullSource + String(NEW_LN,2)
    FullSource = FullSource + ScriptBlob
    
    Return FullSource

End Function


Function ConcatFiles$(Folder$)

    Local DirStream = ReadDir(Folder)
    Local FileName$ = ""
    Local TextBlob$ = ""
    Local FilePath$ = ""
 
    NextFile(DirStream) ; skip .
    NextFile(DirStream) ; skip ..

    Repeat
    
        FileName = NextFile(DirStream)
    
        If FileName = "" Then
    
            Exit
        Else
            FilePath = Folder + FileName    
            TextBlob = TextBlob + ReadAllText(FilePath)
    
        EndIf
    Forever

    CloseDir(DirStream)
    Return TextBlob

End Function


Function ReadAllText$(Path$)
    
    Local Stream = ReadFile(Path)
    Local Contents$ = ""
    
    While Not Eof(Stream)
        Contents = Contents + ReadLine(Stream) + NEW_LN
    Wend
    
    CloseFile(Stream)
    Return Contents
    
End Function


Function WriteAllText(Path$, Contents$)
    
    Local Stream = WriteFile(Path)
    
    WriteLine(Stream,Contents)
    CloseFile(Stream)
    
End Function



CompileAndRun(SOURCE_FOLDER,SCRIPT_FOLDER,OUTPUT_FILEPATH)

Comments

Blitzplotter2015
Very interesting post Spencer, thank you for sharing.


xlsior2015
2) "Protect your Source" - Find a way to obfuscate you source files in the "source" folder. This way users can't easily alter the Game's source code. There are many different ways to do this, but they were omitted from the example code for clarity.


Just be aware that since the compiler will need to be able to read the code from disk in plain text, as -some- point it will exist in human readable form. Even if you encrypt the source, then decrypt-> compile -> delete , a user can still intercept the code, especially if they 'end task' your program during this window and it has no chance to clean up after itself.


Spencer2015
Yep that's correct. Reading the source would be possible. Encoding it in some fashion, perhaps even bin-packing it, would help to ensure that "clean" source is used each time. But, to xlsior's point: There will always be some way to read the source.


Spencer2015
Here's a version that allows you to block certain keywords. The check will fail if a key word appears anywhere in the script.

These examples will fail
   1:    fs = ReadFile("test.txt")
   2:    a = 400 ;this is a comment ReadFile
   3:    a = "This is a string ReadFile"


These examples will pass
     1:   fx = extReadFile("test.txt")
     2:   a = 400 ;we called extReadFile() above
     3:   a = "This is a string _ReadFile" 






_PJ_2016
Block("Extern")

What is this?


Code Archives Forum