• Dear Cerberus X User!

    As we prepare to transition the forum ownership from Mike to Phil (TripleHead GmbH), we need your explicit consent to transfer your user data in accordance with our amended Terms and Rules in order to be compliant with data protection laws.

    Important: If you accept the amended Terms and Rules, you agree to the transfer of your user data to the future forum owner!

    Please read the new Terms and Rules below, check the box to agree, and click "Accept" to continue enjoying your Cerberus X Forum experience. The deadline for consent is April 5, 2024.

    Do not accept the amended Terms and Rules if you do not wish your personal data to be transferred to the future forum owner!

    Accepting ensures:

    - Continued access to your account with a short break for the actual transfer.

    - Retention of your data under the same terms.

    Without consent:

    - You don't have further access to your forum user account.

    - Your account and personal data will be deleted after April 5, 2024.

    - Public posts remain, but usernames indicating real identity will be anonymized. If you disagree with a fictitious name you have the option to contact us so we can find a name that is acceptable to you.

    We hope to keep you in our community and see you on the forum soon!

    All the best

    Your Cerberus X Team

File Directory [Solved]

Wingnut

Well-known member
3rd Party Module Dev
Tutorial Author
Joined
Jan 2, 2020
Messages
1,414
I feel stupid for asking but I've been trying to find example how to load and save json files that sits beside the app file itself on the desktop on Windows and MacOS, how do you do that? Is there a path defined for this?

I don't want to refer to the absolute desktop path but I want to access files wherever the app itself happens to be on macOS/Windows, is that possible?
 
Simple: Look in the trans source code. You'll find your answer there.
Clue, check out the os mdule.
 
Thanks, okay so I was reading up and found this nugget :

# Function AppPath:String()
Returns the file system path of the currently running application.

# Function RealPath:String(path:String)
Returns the real, or 'absolute', file system path corresponding to the given path.

Parameters:
path - a file system path.


I quickly threw this together :

Cerberus:
Local path:String = AppPath() ' import os
Local path2:String =  RealPath("")
Print path
Print path2

The first one did work but it gives you something like this

. . . .. /Desktop/gamefix/test.buildv2020-11-15/glfw3/xcode/build/Release/CerberusGame.app/Contents/MacOS/CerberusGame

The app-level is CerberusGame.app, everything after that is "inside" the executable icon.
How can I chop it off at .app? Is it just a matter of string manipulation?
 
Last edited:
Okay so I failed to read the json file so I went for something simpler and load image but I can't even do that the app just closes down.

Here's a simple current example :

Cerberus:
Import mojo2
Import os

Function Main()
    New MyApp
End

Class MyApp Extends App

    Field canvas:Canvas   
    Field readonlyimage:Image       
    Field paint2:Canvas
    Field paint3:Canvas
    Field image2:Image   
    Field image3:Image
    Field size:Int=32
    Field wx:Int, wy:Int
    Field tilemap:Int[512*512]
    Field path:String
    Field path2:String
    
    Method OnCreate()
        
        For Local y :=0 To 511
            For Local x := 0 To 511
                tilemap[x + y * 512] = Int(Rnd(127))
            Next
        Next





' -------------------------------------------------------------------------------------------------
        path = AppPath()
        path2 =  RealPath("")
        ' Print path
        ' Print path2
        
        ' Example of path
        ' . . .. /Desktop/gamefix/test.buildv2020-11-15/glfw3/xcode/build/Release/CerberusGame.app/Contents/MacOS/CerberusGame
        
        path=path+"/"+"betatestsprites.png" ' Get path where application is
        readonlyimage = Image.Load(path,0,0,0) '  Try load beta-sprites placed inside the application at correct spot inside the app.
' -------------------------------------------------------------------------------------------------




        
        ' readonlyimage = Image.Load("512x512sprites2.png",0,0,0)
        
        image3 = New Image(readonlyimage.Width,readonlyimage.Height,,,0)
        image2 = New Image(256,256,0,0,0)
        paint2 = New Canvas(image2)
        paint3 = New Canvas(image3)   
        canvas = New Canvas
        SetSwapInterval 1
        SetUpdateRate 0   
    End

     Method OnRender()
    
        Local w=DeviceWidth, h=DeviceHeight       
        canvas.SetViewport 0,0,w,h ; canvas.SetScissor 0,0,w,h ; canvas.SetProjection2d 0,w,0,h ; canvas.Clear 0,0,0
          paint3.SetViewport 0,0,w,h ; paint3.SetScissor 0,0,w,h ; paint3.SetProjection2d 0,w,0,h
          paint3.Clear ;    paint3.DrawImage readonlyimage,0,0 ; paint3.Flush
        paint2.SetViewport 0,0,w,h ; paint2.SetScissor 0,0,w,h ; paint2.SetProjection2d 0,w,0,h ; paint2.Clear 0,0,0
        paint2.DrawImage readonlyimage,0,0
        paint2.DrawImage image3,256,256
        paint2.Flush

        Local scrx := wx Mod size, scry:=wy Mod size
        Local mapx := wx / size, mapy:=wy / size   
        Local cnty := -scry
        For Local y := mapy To mapy+((h/size)+1)
            Local cntx := -scrx
            For Local x:=mapx To mapx+((w/size)+1)
                Local char:= tilemap[x + y * 512] ; Local tilex := char & 15 ; Local tiley := char Shr 4
                canvas.DrawRect cntx,cnty,size,size,image2,tilex Shl 5,tiley Shl 5,32,32
                cntx=cntx+size
            Next
            cnty = cnty + size
        Next   
        
        canvas.DrawText path,-450,100
        wx = wx + 1       
        canvas.Flush
    End
 
End
 
I can however get the path correctly, I construct the path correctly, so far so good.

Maybe the the load command needs some extra time or something to load when the file is so far away?
 
Okay but even with the path being correct I can't seem to be able to use it with LoadImage yet.

Will solve this later and post the solution when I find it.
I need to check this more tonight.


Cerberus:
Function Main()
    Local tcc:=New TransCC
    #If CONFIG="debug"
        SetEnv "CERBERUS_DIR",RealPath( ExtractDir( AppPath )+"/../../../../" )
        SetEnv "CXS_FILE",GetEnv( "CERBERUS_DIR" )+TEST_PATH+"/"+TEST_FILE+"/"+TEST_FILE+".cxs"
     
        Local str:String, args$[]=[ GetEnv( "CERBERUS_DIR" )+"/bin/transcc_"+HostOS(),
                                    "-target="+TEST_TARGET,
                                    "-config="+TEST_CONFIG,
                                    TEST_BUILD,
                                    GetEnv( "CXS_FILE" ) ]
        For Local i:=Eachin args
            str+=i+" "
        Next
        DebugLog "~nRunning in debug mode:~n"+str
        tcc.Run args
    #Else
        SetEnv "CERBERUS_DIR",RealPath( ExtractDir( AppPath )+"/.." )
        tcc.Run AppArgs
    #Endif
End
 
haha I found the problem I think
. . .. /Desktop/gamefix/test.buildv2020-11-15/glfw3/xcode/build/Release/CerberusGame.app/Contents/MacOS/CerberusGame

the name of the app itself is included in the path!

I have to take away CerberusGame for the "internal" (manually placed by the animator inside the Mac app file) for the file to work
. . .. /Desktop/gamefix/test.buildv2020-11-15/glfw3/xcode/build/Release/CerberusGame.app/Contents/MacOS/

And to have an external file that lays beside the actual app will be simple deleteon of a few more characters so it becomes this
(in other workds I should not save filename.app)
. . .. /Desktop/gamefix/test.buildv2020-11-15/glfw3/xcode/build/Release/
 
So as I see it the simplest way is simply to import os and use AppPath() and manipulate that string it gives you
so you save only up to .. ."Release/". Everything after that should be deleted.

And that will be the path of your executable on macOS!

With Windows my guess without trying is that is iit too gives you the name that includes the app (but .exe instead of .app) and it it does not go "inside" the exe, it probably stops there, so you have less to take away.

But the recipe becomes the same :
Use AppPath() to get the full path and save everything of that string until you reach .... ....Release/" and the snip the rest.

and this will get you the path of your executable on any desktop probably.
 
But if you move the file, there's no Release..

**** okay I need to go back to the drawing board.
 
I can do the ugly way, if I don't change the name of the app I can hardcode this :
Take away from string from the right side "CerberusGame.app/Contents/MacOS/CerberusGame"

And that would work on macOS alone.
 
Try this.
Cerberus:
Strict

Import os

Function Main:Int()
    Local appRoot:="", contentsRoot:="", resourceRoot:="", jsonFile:="", exeRoot:=RealPath( ExtractDir( AppPath() ) ) ' Extracting the directory removes the last part. In other words the executable name.

    Print""

    #If HOST="macos"
        appRoot = RealPath( exeRoot+"/../../" )    ' MacOS go back two directories. Should set you to the bundle root directory aka .app
        contentsRoot = RealPath( exeRoot+"/../" )    ' MacOS go back one directory. Should set you to the Contents directory
        resourceRoot = contentsRoot+"/Resource"    ' From the Contents directory, construct the path to the files
        jsonFile = resourceRoot+"/myJson.json"       ' If the json file was located in the resource directory. Else if the json was with the executable, then use exeRoot instead of resourceRoot.
        Print contentsRoot+"~n the Contents direcory~n"
    #Else
        jsonFile = exeRoot+"/myJson.json"
    #End

    Print "The executable directory~n"+exeRoot+"~n"
    Print "The path to the json file~n"+jsonFile

    Return 0
End
 
Last edited:
Thanks so much!

I will try to understand this tonight, is it possible to see the console PRINTs when you execute
actual desktop binarys or do you need create a window with Drawtext?
 
Thanks Dawnlane and Mike, got it working now perfectly
 
Here's a working example that saves a file just beside the game executable on macOS.
:D
Am really happy having this working as it will truly make the development so much faster!

MacOS version
Screenshot.png


Cerberus:
Strict
Import mojo2
Import brl.filestream
Import os

Function Main:Int()
    New Game()
    Return 0
End

Class Game Extends App

    Field canvas:Canvas
 
    Method OnCreate:Int()
        canvas=New Canvas
        canvas.Clear
        
        ' Create data
        Local numbers:Int[] = [10,20,30,40,50,60,70,80,90,100]

        ' Find directory
        Local exeRoot := RealPath(ExtractDir(AppPath()))
        Local besideapp := RealPath(exeRoot+"/../../../")

        ' Save data
        Local dump := New FileStream(besideapp+"/"+"numbers.dat","w")
        For Local i:Int = EachIn numbers
            dump.WriteString(i+ ",") ' as (8-bit) strings, totally 31 bytes.
            ' dump.WriteInt(i) ' as (32-bit) integers, totally 40 bytes.
        Next
        dump.Close
        
        Return 0
    End
    
    Method OnRender:Int()
        ' DebugStop
        Return 0
    End 

End
 
Last edited:
Back
Top Bottom