瀏覽代碼

Merge branch 'develop' into develop-tmp

Mark Sibly 7 年之前
父節點
當前提交
fc94d79972
共有 34 個文件被更改,包括 589 次插入295 次删除
  1. 1 0
      bananas/assetstest/assets/test1.txt
  2. 1 0
      bananas/assetstest/assets/test2.txt
  3. 73 0
      bananas/assetstest/assetstest.monkey2
  4. 57 0
      modules/android/android.monkey2
  5. 6 0
      modules/android/module.json
  6. 3 0
      modules/emscripten/emscripten.monkey2
  7. 3 1
      modules/emscripten/module.json
  8. 4 0
      modules/miniz/miniz.monkey2
  9. 3 3
      modules/mojo/audio/audio.monkey2
  10. 3 51
      modules/mojo/audio/native/bbmusic.cpp
  11. 3 1
      modules/mojo/audio/native/bbmusic.h
  12. 3 0
      modules/mojo/graphics/shader.monkey2
  13. 10 3
      modules/mojo3d/assets/shaders/imports/pbr.glsl
  14. 1 1
      modules/mojo3d/loader/gltf2loader.monkey2
  15. 3 2
      modules/mojo3d/mojo3d.monkey2
  16. 44 0
      modules/mojo3d/scene/entities/pivot.monkey2
  17. 16 7
      modules/mojo3d/scene/native/collisiondetect.cpp
  18. 2 0
      modules/mojo3d/tests/room.monkey2
  19. 8 8
      modules/monkey/newdocs/language/arrays.md
  20. 17 40
      modules/monkey/newdocs/language/enums.md
  21. 23 12
      modules/monkey/newdocs/language/strings.md
  22. 42 26
      modules/monkey/newdocs/language/types.md
  23. 5 3
      modules/monkey/newdocs/language/variants.md
  24. 3 1
      modules/stb-image/stb-image.monkey2
  25. 118 46
      modules/std/filesystem/filesystem.monkey2
  26. 53 0
      modules/std/filesystem/native/filesystem.cpp
  27. 4 2
      modules/std/filesystem/native/filesystem.h
  28. 1 2
      modules/std/graphics/pixmaploader.monkey2
  29. 11 4
      modules/std/misc/zipfile.monkey2
  30. 1 1
      modules/std/module.json
  31. 19 52
      modules/std/std.monkey2
  32. 4 12
      modules/std/stream/filestream.monkey2
  33. 36 16
      products/android/Monkey2Game/app/src/main/java/org/libsdl/app/SDLActivity.java
  34. 8 1
      products/android/Monkey2Game/build.gradle

+ 1 - 0
bananas/assetstest/assets/test1.txt

@@ -0,0 +1 @@
+Test One

+ 1 - 0
bananas/assetstest/assets/test2.txt

@@ -0,0 +1 @@
+Test Two - a bit longer.

+ 73 - 0
bananas/assetstest/assetstest.monkey2

@@ -0,0 +1,73 @@
+Namespace myapp
+
+#Import "<std>"
+#Import "<mojo>"
+
+Using std..
+Using mojo..
+
+#Import "assets/"
+
+Class MyWindow Extends Window
+
+	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=Null )
+
+		Super.New( title,width,height,flags )
+		
+		Print "AssetsDir()=~q"+AssetsDir()+"~q"
+		
+#If __DESKTOP_TARGET__
+		Print "DesktopDir()=~q"+DesktopDir()+"~q"
+		
+		Print "HomeDir()=~q"+HomeDir()+"~q"
+#endif
+		
+#If __MOBILE_TARGET__
+		Print "InternalDir()=~q"+InternalDir()+"~q"
+		DeleteFile( "internal::test.txt" )
+		SaveString( "Some Test Internal Text!","internal::test.txt" )
+		Print "LoadString(~qinternal::test.txt~q)=~q"+LoadString( "internal::test.txt" )+"~q"
+		
+		Print "ExternalDir()=~q"+ExternalDir()+"~q"
+		DeleteFile( "external::test.txt" )
+		SaveString( "Some Test External Text!","external::test.txt" )
+		Print "LoadString(~qexternal::test.txt~q)=~q"+LoadString( "external::test.txt" )+"~q"
+		
+#endif
+	
+		Print "LoadDir(~qasset::~q):"
+		PrintDir( "asset::" ) 
+		
+		Print "LoadDir(AssetsDir())"
+		PrintDir( AssetsDir() )
+		
+		Print "RealPath(AssetsDir())=~q"+RealPath( AssetsDir() )+"~q"
+		
+		Print "RealPath(~qasset::~q)=~q"+RealPath( "asset::" )+"~q"
+		
+	End
+	
+	Method PrintDir( dir:String,indent:String=" " )
+
+		For Local file:=Eachin LoadDir( dir )
+			Print indent+"file=~q"+file+"~q size="+GetFileSize( dir+file )+" type="+Int( GetFileType( dir+file ) )
+		Next
+	End		
+
+	Method OnRender( canvas:Canvas ) Override
+	
+		App.RequestRender()
+	
+		canvas.DrawText( "Hello World!",Width/2,Height/2,.5,.5 )
+	End
+	
+End
+
+Function Main()
+
+	New AppInstance
+	
+	New MyWindow
+	
+	App.Run()
+End

+ 57 - 0
modules/android/android.monkey2

@@ -0,0 +1,57 @@
+
+Namespace android
+
+#If __TARGET__="android"
+
+#Import "<libc>"
+#Import "<sdl2>"
+#Import "<jni>"
+
+#Import "<sdl2/SDL/src/core/android/SDL_android.h>"
+'#Import "<asset_manager.h>"
+'#Import "<SDL.h>"
+
+Extern Private
+
+'this is actually in SDL...
+Function Android_JNI_GetAssetManager:Void Ptr()
+
+Extern
+
+Const AASSET_MODE_UNKNOWN:Int	'0
+Const AASSET_MODE_RANDOM:Int	'1
+Const AASSET_MODE_STREAMING:Int	'2
+Const AASSET_MODE_BUFFER:Int	'3
+ 
+Class AAssetManager Extends Void
+End
+
+Class AAssetDir Extends Void
+End
+
+Class AAsset Extends Void
+End
+
+Function AAssetManager_open:AAsset( mgr:AAssetManager,filename:CString,mode:Int )
+Function AAssetManager_openDir:AAssetDir( mgr:AAssetManager,dirName:CString )
+	
+Function AAssetDir_getNextFileName:CString( assetDir:AAssetDir )
+Function AAssetDir_rewind( assetDir:AAssetDir )
+Function AAssetDir_close( assetDir:AAssetDir )
+	
+Function AAsset_getLength:Int( asset:AAsset )
+Function AAsset_getRemainingLength:Int( asset:AAsset )
+Function AAsset_read:Int( asset:AAsset,buf:Void Ptr,count:Int )
+Function AAsset_seek:Int( asset:AAsset,offset:Int,whence:Int )
+Function AAsset_close( asset:AAsset )
+	
+Public
+
+Function GetAssetManager:AAssetManager()
+	
+	Return Cast<AAssetManager>( Android_JNI_GetAssetManager() )
+End
+
+#endif
+
+

+ 6 - 0
modules/android/module.json

@@ -0,0 +1,6 @@
+{
+	"module":"android",
+	"version":"1.0.0",
+	"support":"http://monkeycoder.co.nz",
+	"depends":["libc","sdl2","jni"]
+}

+ 3 - 0
modules/emscripten/emscripten.monkey2

@@ -3,6 +3,9 @@ Namespace emscripten
 
 #If __TARGET__="emscripten"
 
+#Import "<libc>"
+#Import "<sdl2>"
+
 #Import "<emscripten.h>"
 
 Extern

+ 3 - 1
modules/emscripten/module.json

@@ -1,4 +1,6 @@
 {
 	"module":"emscripten",
-	"version":"1.0.0"
+	"version":"1.0.0",
+	"support":"http://monkeycoder.co.nz",
+	"depends":["libc","sdl2"]
 }

+ 4 - 0
modules/miniz/miniz.monkey2

@@ -91,6 +91,10 @@ Function mz_zip_reader_locate_file:Int( pZip:mz_zip_archive Ptr,pName:CString,pC
 'Returns detailed information about an archive file entry.
 Function mz_zip_reader_file_stat:Int( pZip:mz_zip_archive Ptr,file_index:Int,pStat:mz_zip_archive_file_stat Ptr )
 
+'Determines if an archive file entry is a directory entry.
+Function mz_zip_reader_is_file_a_directory:Int( pZip:mz_zip_archive Ptr,file_index:Int )
+Function mz_zip_reader_is_file_encrypted:Int( pZip:mz_zip_archive Ptr,file_index:Int )
+
 'Extracts a archive file to a memory buffer.
 Function mz_zip_reader_extract_to_mem:Int( pZip:mz_zip_archive Ptr,file_index:Int,pBuf:Void Ptr,buf_size:Int,flags:Int )
 Function mz_zip_reader_extract_file_to_mem:Int( pZip:mz_zip_archive Ptr,pFilename:CString,pBuf:Void Ptr,buf_size:Int,flags:Int )

+ 3 - 3
modules/mojo/audio/audio.monkey2

@@ -12,7 +12,7 @@ Namespace mojo.audio
 
 Extern Private
 
-Function playMusic:Int( path:CString,callback:Int,source:Int )="bbMusic::playMusic"
+Function playMusic:Int( file:libc.FILE ptr,callback:Int,source:Int )="bbMusic::playMusic"
 Function getBuffersProcessed:Int( source:Int )="bbMusic::getBuffersProcessed"
 Function endMusic:Void( source:Int )="bbMusic::endMusic"
 	
@@ -72,9 +72,9 @@ Class AudioDevice
 			finished()
 		End,True )
 		
-		path=filesystem.RealPath( path )
+		Local file:=filesystem.OpenCFile( path,"rb" )
 		
-		Local sampleRate:=playMusic( path,callback,channel._alSource )
+		Local sampleRate:=playMusic( file,callback,channel._alSource )
 	
 		If Not sampleRate
 			async.DestroyAsyncCallback( callback )

+ 3 - 51
modules/mojo/audio/native/bbmusic.cpp

@@ -13,9 +13,7 @@
 #include "../../../std/async/native/async_cb.h"
 #include "../../../stb-vorbis/native/stb-vorbis.h"
 
-#if __ANDROID__
-#include "../../../sdl2/SDL/src/core/android/SDL_android.h"
-#endif
+#include <std/filesystem/native/filesystem.h>
 
 #include <atomic>
 
@@ -25,7 +23,7 @@ namespace{
 
 	Counter *counters;
 	
-	//Yikes! We have to make a little atomic counter class!
+	//little atomic counter class...
 	//
 	struct Counter{
 		
@@ -57,59 +55,13 @@ namespace{
 		return 0;
 	}
 }
-	
 
 namespace bbMusic{
 
-#if __ANDROID__
-	
-	int android_read( void *cookie,char *buf,int size ){
-	
-	  return AAsset_read( (AAsset*)cookie,buf,size );
-	}
-	
-	int android_write( void *cookie,const char* buf,int size ){
-	
-	  return EACCES; // can't provide write access to the apk
-	}
-	
-	fpos_t android_seek( void *cookie,fpos_t offset,int whence ){
-	
-	  return AAsset_seek( (AAsset*)cookie,offset,whence );
-	}
-	
-	int android_close(void* cookie) {
-	
-	  AAsset_close( (AAsset*)cookie );
-	  return 0;
-	}
-	
-#endif
-	
-	FILE *fopen( const char *path,const char *mode ){
-	
-#if __ANDROID__
-		if( !strncmp( path,"asset::",7 ) ){
-			
-			AAssetManager *assetManager=Android_JNI_GetAssetManager();
-			if( !assetManager ) return 0;
-			
-	  		AAsset* asset=AAssetManager_open( assetManager,path+7,0 );
-			if( !asset ) return 0;
-	
-	  		return funopen( asset,android_read,android_write,android_seek,android_close );
-		}
-#endif
-		return ::fopen( path,mode );
-	}
-
-	int playMusic( const char *path,int callback,int alsource ){
+	int playMusic( FILE *file,int callback,int alsource ){
 	
 		const int buffer_ms=100;
 			
-		FILE *file=fopen( path,"rb" );
-		if( !file ) return false;
-	
 		int error=0;
 		stb_vorbis *vorbis=stb_vorbis_open_file( file,0,&error,0 );
 		if( !vorbis ) return false;

+ 3 - 1
modules/mojo/audio/native/bbmusic.h

@@ -1,7 +1,9 @@
 
+#include <std/filesystem/native/filesystem.h>
+
 namespace bbMusic{
 
-	int playMusic( const char *path,int callback,int source );
+	int playMusic( FILE *file,int callback,int source );
 	
 	int getBuffersProcessed( int source );
 	

+ 3 - 0
modules/mojo/graphics/shader.monkey2

@@ -423,6 +423,9 @@ Class Shader
 		
 			Local defs:="#define MX2_RENDERPASS "+rpass+"~n"
 			
+'			Print "~n~n*************** Vertex Shader ***************~n"+defs+vs
+'			Print "~n~n*************** Fragment Shader ****************~n"+defs+fs
+			
 			Local vshader:=glCompile( GL_VERTEX_SHADER,defs+vs )
 			Local fshader:=glCompile( GL_FRAGMENT_SHADER,defs+fs )
 				

+ 10 - 3
modules/mojo3d/assets/shaders/imports/pbr.glsl

@@ -7,9 +7,12 @@
 
 float pointAtten( float d,float r ){
 
-	float atten=max( 1.0-d*d/(r*r),0.0 );atten*=atten;
+//	Doesn't work on ANGLE!
+//	float atten=1.0-min( (d*d)/(r*r),1.0 );atten*=atten;
+
+	float atten=1.0-min( d/r,1.0 );atten*=atten;
 	
-//	float d=length( lvec ),atten=1.0/(1.0+d*d);
+//	float atten=1.0/(1.0+d*d);
 
 	return atten;
 }
@@ -34,7 +37,11 @@ void emitPbrFragment( vec3 color,float metalness,float roughness,vec3 position,v
 	vec3 lvec=r_LightViewMatrix[3].xyz-position;
 
 	float atten=pointAtten( length( lvec ),r_LightRange );
-
+	
+#ifdef GL_ES
+	if( atten!=atten ) return;
+#endif
+	
 	lvec=normalize( lvec );
 	
 #elif MX2_SPOTLIGHT

+ 1 - 1
modules/mojo3d/loader/gltf2loader.monkey2

@@ -149,7 +149,7 @@ Class Gltf2Loader
 			Local start:=ULong( GetData( source.bufferView ) )
 			Local length:=source.bufferView.byteLength
 			
-			Local path:="memblock::("+start+","+length+")"
+			Local path:="memory::("+start+","+length+")"
 			If source.mimeType.StartsWith( "image/" ) path+="."+texture.source.mimeType.Slice( 6 )
 				
 			tex=Texture.Load( path,flags )

+ 3 - 2
modules/mojo3d/mojo3d.monkey2

@@ -38,12 +38,13 @@ Using reflection..
 
 #Import "scene/entities/camera"
 #Import "scene/entities/light"
+#Import "scene/entities/pivot"
+#Import "scene/entities/renderable"
 #Import "scene/entities/model"
+#Import "scene/entities/sprite"
 #Import "scene/entities/particlebuffer"
 #Import "scene/entities/particlematerial"
 #Import "scene/entities/particlesystem"
-#Import "scene/entities/renderable"
-#Import "scene/entities/sprite"
 
 #Import "scene/materials/pbrmaterial"
 #Import "scene/materials/spritematerial"

+ 44 - 0
modules/mojo3d/scene/entities/pivot.monkey2

@@ -0,0 +1,44 @@
+
+Namespace mojo3d
+
+#rem monkeydoc The Pivot class.
+#end
+Class Pivot Extends Entity
+
+	#rem monkeydoc Creates a new pivot.
+	#end	
+	Method New( parent:Entity=Null )
+		
+		Super.New( parent )
+		
+		Visible=True
+		
+		AddInstance()
+	End
+
+	#rem monkeydoc Copies the pivot.
+	#end
+	Method Copy:Pivot( parent:Entity=Null ) Override
+		
+		Local copy:=OnCopy( parent )
+		
+		CopyTo( copy )
+		
+		Return copy
+	End
+	
+	Protected
+
+	Method New( pivot:Pivot,parent:Entity )
+		
+		Super.New( pivot,parent )
+		
+		AddInstance( pivot )
+	End
+	
+	Method OnCopy:Pivot( parent:Entity ) Override
+		
+		Return New Pivot( Self,parent )
+	End
+	
+End

+ 16 - 7
modules/mojo3d/scene/native/collisiondetect.cpp

@@ -14,15 +14,24 @@ void collisionCallback( btDynamicsWorld *world,btScalar timeStep ){
 	
 	for( int i=0;i<numManifolds;++i ){
 
-		btPersistentManifold *manifold=world->getDispatcher()->getManifoldByIndexInternal( i );
+		btPersistentManifold *contactManifold=world->getDispatcher()->getManifoldByIndexInternal( i );
         
-		const btCollisionObject *body0=manifold->getBody0();
-		const btCollisionObject *body1=manifold->getBody1();
-       
-//		printf( "Collision! body0=%p body1=%p\n",body0,body1 );fflush( stdout );
+		const btCollisionObject *body0=contactManifold->getBody0();
+		const btCollisionObject *body1=contactManifold->getBody1();
 		
-		*_collp++=body0->getUserPointer();
-		*_collp++=body1->getUserPointer();
+        int numContacts=contactManifold->getNumContacts();
+        
+        for( int j=0;j<numContacts;++j ){
+        
+            btManifoldPoint &pt=contactManifold->getContactPoint(j);
+            
+            if( pt.getDistance()<0.0f ){
+	            
+				*_collp++=body0->getUserPointer();
+				*_collp++=body1->getUserPointer();
+				break;
+			}
+        }
 	}
 }
 

+ 2 - 0
modules/mojo3d/tests/room.monkey2

@@ -13,6 +13,8 @@ Using mojo3d..
 
 Function Main()
 	
+	SetConfig( "MOJO_OPENGL_PROFILE","es" )
+	
 	New AppInstance
 	
 	New MyWindow

+ 8 - 8
modules/monkey/newdocs/language/arrays.md

@@ -5,13 +5,13 @@
 
 An array is a linear sequence of values that can be addressed using one or more integer indices.
 
-Each array has an associated element type. That is, the type of the values actually stored in the array. An array's element type is a purely static property. It is only known at compile time so arrays cannot be 'downcast' at runtime.
+Each array has an associated element type. That is, the type of the values actually stored in the array. An array's element type is a purely static property. It is only known at compile time so arrays cannot be 'cast' to different array types at runtime.
 
-The syntax used for declaring values and variables of array type is: 
+Array variables are declared using the syntax:
 
-_ElementType_ `[` [`,`...] `]`
+_ElementType_`[`[`,`...]`]`
 
-An array can also be multidimensional, in which case the '[]' will contain 1 or more commas.
+An array can be multidimensional, in which case the '[]' will contain 1 or more commas.
 
 Here are some example of declaring array variables:
 
@@ -24,13 +24,13 @@ Local stacks:Stack<Int>[]	'One dimensional array of stacks of type Int.
 
 @#### Creating arrays
 
-Declaring an array does not actually create an array. To do that you must use `New`.
+Declaring an array does not actually create an array. To do that you must use the `New` operator.
 
 `New` can be used to create either a null intialized or value initialized array. The syntax for creating a null initialized array is:
 
 `New` _ElementType_ `[` _Sizes_ `]`
 
-...where sizes is a comma separated sequence of dimension size.
+...where sizes is a comma separated sequence of dimension sizes.
 
 The syntax for creating a value initialized array is:
 
@@ -80,8 +80,8 @@ Local ints:=New Int[]( 1,2,3 )
 ints=ints.Resize( 5 )	'ints now contains 1,2,3,0,0
 ```
 
-(Note that resize does not actually resize the array! It actually returns a resized *copy* of the array.)
+Note that resize actually returns a resized *copy* of the input array. The input array is not modified in any way.
 
-Note that mutidimensional arrays cannot currently be sliced or resized, and you cannot create an initialized multidimensional arrays. These features are planned for the future though.
+Multidimensional arrays cannot currently be sliced or resized.
 
 For more information, see the [[types.Array.Resize|Array.Resize]] API documentation.

+ 17 - 40
modules/monkey/newdocs/language/enums.md

@@ -3,56 +3,33 @@
 
 ### Enums
 
-`Enum` is a data type containing a set of Int constants.
+An enum is a user defined data type that contains a set of named integer constants. Enums are frequently used to implement typesafe 'flags' or 'bitmasks'.
 
-By default the members will receive values starting from zero and incemented by one for each new member. You can assign a chosen value to each member when declaring them.
+Unintialized enum members are automatically assigned constant integer values starting with 0 and increasing by 1 for each successive enum member:
 
 ```
-Enum myBasicEnum
-	a,b,c 'a=0, b=1, c=2
+Enum MyEnum
+	A,B,C			'A, B, C will be assigned the values 0, 1, 2.
+	D,E,F			'D, E, F will be assigned the values 4, 5, 6.
 End
 ```
-```
-Enum myCustomEnum
-	a=7
-	b=31,c,d 'c=32, d=33
-End
-```
-The values can be accessed with the postfix member acces operator (`.`).
-Enums values are implicitly converted to integral values when assigned to it.
-```
-Local i:UInt=myCustomEnum.b
-```
-
-You can also create `Enum` variables. An `Enum` variable contains an Int variable in addition to it's constant members (default value is zero).
 
-Bitwise operators (|,&,~) can be used with Enums variables and Enums members to compute combinations. Such Enums most often contain powers of 2 numbers as members! (1,2,4,8,16,32,64,... and 0 if needed).
+You can also initialize enum members with a constant integer value:
 
-A bitmask Enum example:
-```
-Enum Flags 'a classic Enum. (4 bits bitmask)
-	None=0
-  A=$0001 'bin OOOI dec 1
-  B=$0002 'bin OOIO dec 2
-  C=$0004 'bin OIOO dec 4
-  D=$0008 'bin IOOO dec 8
-End
-```
-An enum with modifiers example (in this case the bitwise operators should be used with at least one modifier):
 ```
-Enum Foo '(modifiers on 5th and 6th bit)
-	None=0
-	A=1,B,C,D,E,F,G,H,J,K,L,M ' max 15 because the 5th bit is used for modifier
-	Modifier_A=$0010 'bin IOOOO dec 16
-	Modifier_B=$0020 'bin IOOOOO dec 32
+Enum MyEnum
+	A=10,B=20,C=30	'A, B, C will be assigned the values 10,20,30
+	D,E,F			'D, E, F will be assigned the values 31, 32, 33.
 End
 ```
 
-For now enums don't accept negative number literals. To assign a negative number you'll have to type a substraction until the bug is resolved.
+Enum members are accessed using the 'dot' operator:
+
 ```
-Enum Foo '(with a negative member)
-	Negative=0-1 'instead of -1
-	None=0
-	A=1,B,C,D,E,F,G,H,J,K,L,M
-End
+Local e:MyEnum=MyEnum.A
 ```
+
+Enum values can be implictly converted to any integer type, and can be used with the `&` (bitwise 'and'), `|` (bitwise 'or') and `~` (bitwise 'exclusive-or') binary operators. This allows you to use enums to represent 'bitmasks'.
+
+Enum values can also be compared with enum values of the same type, or with a `Null` which represents an enum value with the integer value 0.
+

+ 23 - 12
modules/monkey/newdocs/language/strings.md

@@ -3,15 +3,9 @@
 
 ### Strings
 
-Values of type String are used to represent sequences of characters, such as text. The exact size of each character in a string value is target dependent, but is at least 8 bits.
+A String is an immutable sequence of 16 bit characters that is usually used to represent text.
 
-String variables are declared using the type name `String`, for example:
-
-```
-Local test:String="Hello World"
-```
-
-String literals are sequences of characters enclosed in "" (quotation marks). String literals may also include escape sequences, special sequences of characters used to represent unprintable characters.
+String literals are sequences of characters enclosed in `"``"` (quotation marks). String literals may also include escape sequences, special sequences of characters used to represent unprintable characters.
 
 You can use the following escape sequences in string literals:
 
@@ -24,13 +18,30 @@ You can use the following escape sequences in string literals:
 |~z					| 0 (null)
 |~~	 				| 126 (tilde ~)
 
-For example, to include literal quotation marks in a string...
+For example, to include literal quotation marks in a string:
 
 ```
 Local test:="~qHello World~q" 
 ```
 
-You can index a string using the `[]' operator, eg:
+Strings can also be declared across multiple lines:
+
+```
+Const multiLine:="
+Multi Line String
+"
+```
+
+In this case, each newline inside the quote marks is simply included in the string, so the above example string actually contains 2 'hidden' newlines.
+
+String variables are declared using the type name `String`, for example:
+
+```
+Local test:String="Hello World"
+```
+
+You can index a string using the `[]' operator:
+
 ```
 Local str:="Hello World"
 For Local i:=0 Until str.Length
@@ -40,7 +51,7 @@ Next
 
 Indexing a string will return the character code at a given string index as an int.
 
-You can iterate through the characters in a string using `Eachin`, eg:
+You can iterate through the characters in a string using `Eachin`:
 
 ```
 For Local chr:=Eachin "Hello World"
@@ -48,4 +59,4 @@ For Local chr:=Eachin "Hello World"
 Next
 ```
 
-For more information on strings, please see the [[types.String|String]] API reference.
+Strings have a number of useful methods including [[types.String.Slice|Slice]], [[types.String.Find|Find]] and [[types.String.Split|Split]]. For more information on strings, please see the [[types.String|String]] API reference.

+ 42 - 26
modules/monkey/newdocs/language/types.md

@@ -7,7 +7,7 @@
 
 The following primtive types are supported:
 
-| Type		| Description
+| Type Name	| Description
 |:----------|:-----------
 | `Void`	| No type.
 | `Bool`	| Boolean type.
@@ -24,32 +24,35 @@ The following primtive types are supported:
 | `String`	| String of 16 bit characters.
 | `Object`	| Base type of all objects.
 
+
 @#### Compound types
 
 The following compound types are supported:
 
-| Type						| Description
-|:--------------------------|:-----------
-| _Type_ `[` [,...] `]`		| Array type
-| _Type_ `Ptr`				| Pointer type
-| _Type_ `(` _Types_ `)`	| Function type
+| Type Syntax							| Description
+|:--------------------------------------|:-----------
+| _ElementType_`[]`						| Array type.
+| _PointeeType_ `Ptr`					| Pointer type.
+| _ReturnType_`(`_ParameterTypes_`)`	| Function type.
+
+Array types can have more than one dimension, for example: `[,]` declares a 2D array, `[,,]` declares a 3D array and so on.
+
+The parameter types for a function type can optionally include an identifier prefix, for example: `MyFunction:Int( arg:Int )`. The prefix must be a valid identifier but is otherwise ignored.
 
 
 @#### Implicit type conversions
 
 These type conversions are performed automatically:
 
-| Source type					| Destination type
-|:------------------------------|:-----------------
-| Any numeric type	 			| `Bool`
-| String or array type 			| `Bool`
-| Class or interface type	 	| `Bool`
-| Any numeric type				| Any numeric type
-| Any numeric type or `Bool`	| `String`
-| Any pointer type				| `Void Ptr`
-| Any enum type					| Any integral type
-| Class or interface type		| Base class type or implemented interface type
-| Class, interface or struct type | `Bool`
+| Source type						| Destination type
+|:----------------------------------|:-----------------
+| `Bool`							| `String`
+| Any numeric type					| `Bool`, `String` or any numeric type.
+| `String` or any array type 		| `Bool`
+| Any pointer type					| `Void Ptr`
+| Class, interface or struct type	| `Bool`
+| Class or interface type			| Base class or implemented interface type
+| Enum type							| `Bool` or any integral type.
 
 When numeric values are converted to bool, the result will be true if the value is not equal to 0.
 
@@ -57,24 +60,37 @@ When strings and arrays are converted to bool, the result will be true if the le
 
 When class or interface instances are converted to bool, the result will be true if the instance is not equal to null.
 
-When struct values are converted, the result will be true if the struct value is not equal to null.
+When struct values are converted to bool, the result will be true if the struct value is not equal to null.
+
+When floating point values are converted to integral values, the fractional part of the floating point value is chopped off - no rounding is performed.
 
-When floating point values are converted to integral values, the fractional part of the floating point value is simply chopped off - no rounding is performed.
+When bools are converted to strings, the result will be either "True" or "False".
 
-When Bools are converted to strings, the result will be either "True" or "False".
 
+@#### Explicit type conversions 
 
-@#### Explicit type conversions
+Some type conversions must be explicitly performed using the 'cast' operator. The cast operator has the syntax:
 
-The `Cast` `<` _dest-type_ `>` `:` _dest-type_ `(` _expression_ `)` operator must be used for these type conversions:
+`Cast<`_DestinationType_`>:`_DestinationType_`(`_SourceExpression_`)`
+
+You must use the cast operator to perform the following type conversions:
 
 | Source type			| Destination type
 |:----------------------|:-----------------
 | `Bool`				| Any numeric type
 | `String`				| Any numeric type
-| Any pointer type		| Any pointer type, any integral type
-| Any integral type		| Any pointer type, any enum type
-| Class type			| Derived class type, any interface type
-| Interface type		| Any class type, any interface type
+| Any pointer type		| Any pointer type or any integral type
+| Any integral type		| Any pointer type or any enum type.
+| Class type			| Derived class or any interface type.
+| Interface type		| Any class or interface type.
+
+When using the cast operator to dynamically downcast an object or interface instance, the result will be `Null` if the cast failed.
 
 When casting bool values to a numeric type, the result will be 1 for true, 0 for false.
+
+You can also use 'function syntax' to explictly cast values to primitive types:
+
+```
+Local floatValue:Float=3.14
+Local intValue:=Int( floatValue )
+```

+ 5 - 3
modules/monkey/newdocs/language/variants.md

@@ -3,7 +3,7 @@
 
 ### Variants
 
-The Variant type is a primitive type that can be used to 'box' values of any type.
+A Variant is a special value that can be used to 'box' values of any other type.
 
 The easiest way to create a variant is to cast a value to Variant (much like casting an Int to String etc), eg:
 
@@ -17,7 +17,7 @@ v=10				'variant now contains an int 10.
 v="hello"			'variant now contains a string "hello".
 ```
 
-A variant is 'true' if it contains any value with a non-void type (including a bool false value!) and 'false' if it is uninitialized and has no (void) type.
+A variant is true if it is initialized (even if it contains a bool 'false' value) and false if it is uninitialized. There is currently no way to uninitialize a variant, so once a variant is initialized it will always be 'true'.
 
 Any type of value can be implicitly converted to a variant, so you can easily pass anything to a function with variant parameters:
 
@@ -47,4 +47,6 @@ Local v:=Variant( 10 )
 Print Cast<String>( v )	'Runtime error! Variant contains an Int not a String!
 ```
 
-The one exception to this is if the Variant contains a class object, in which case you can cast the variant to any valid base class of the object.
+The one exception to this is if the variant contains a instance of an object, in which case you can cast the variant to any valid base class of the object's actual type.
+
+Variants also have a number of useful methods including...

+ 3 - 1
modules/stb-image/stb-image.monkey2

@@ -1,6 +1,8 @@
 
 Namespace stb.image
 
+#Import "<libc>"
+
 #Import "native/stb_image.cpp"
 #Import "native/stb_image.h"
 
@@ -18,5 +20,5 @@ End
 Function stbi_load:UByte Ptr( filename:CString,x:Int Ptr,y:Int Ptr,comp:Int Ptr,req_comp:Int )
 Function stbi_load_from_memory:UByte Ptr( buffer:UByte Ptr,len:Int,x:Int Ptr,y:Int Ptr,comp:Int Ptr,req_comp:Int )
 Function stbi_load_from_callbacks:UByte Ptr( clbk:stbi_io_callbacks Ptr,user:Void Ptr,x:Int Ptr,y:Int Ptr,comp:Int Ptr,req_comp:Int )
-
+Function stbi_load_from_file:UByte Ptr( f:libc.FILE Ptr,x:Int Ptr,y:Int Ptr,comp:Int Ptr,req_comp:Int )
 Function stbi_image_free( data:Void Ptr )

+ 118 - 46
modules/std/filesystem/filesystem.monkey2

@@ -7,9 +7,23 @@ Using libc
 #Import "native/filesystem.cpp"
 
 #If __TARGET__="android"
+
 #Import "native/Monkey2FileSystem.java"
+
+Using android
+
 #Elseif __TARGET__="ios"
+
 #Import "native/filesystem.mm"
+
+#endif
+
+#If __TARGET__="android"
+
+Extern Private
+
+Function fopenAsset:FILE Ptr( asset:AAsset )="bbFileSystem::fopenAsset"
+	
 #endif
 
 Extern
@@ -63,8 +77,6 @@ Function FixPath:String( path:String )
 	
 	Select root
 	Case "asset::" return AssetsDir()+path
-	Case "desktop::" Return DesktopDir()+path
-	Case "home::" Return HomeDir()+path
 #If __MOBILE_TARGET__
 	Case "internal::" Return InternalDir()+path
 	Case "external::" Return ExternalDir()+path
@@ -226,13 +238,13 @@ Note that only the desktop and web targets have an assets directory. Other targe
 Function AssetsDir:String()
 	If Not _assetsDir
 #If __TARGET__="macos"
-		_assetsDir=ExtractDir( AppDir() )+"Resources/"	'enable me!
+		_assetsDir=ExtractDir( AppDir() )+"Resources/"
 #Else If __DESKTOP_TARGET__ Or __WEB_TARGET__
 		_assetsDir=AppDir()+"assets/"
 #Else If __TARGET__="ios"
 		_assetsDir=GetSpecialDir( "assets" )
 #Else
-		_assetsDir="asset::"
+		_assetsDir="${ASSETS}/"	'"asset::"
 #Endif
 	Endif
 	Return _assetsDir
@@ -261,7 +273,7 @@ Function DesktopDir:String()
 #Else If __DESKTOP_TARGET__
  	Return GetEnv( "HOME" )+"/Desktop/"
  #Else
- 	Return "desktop::"
+ 	Return "${DESKTOP}/"
 #Endif
 End
 
@@ -278,7 +290,7 @@ Function HomeDir:String()
 #Else if __DESKTOP_TARGET__
 	Return GetEnv( "HOME" )+"/"
 #Else
-	Return "home::"
+	Return "${HOME}/"
 #Endif
 End
 
@@ -333,19 +345,20 @@ Function ExtractRootDir:String( path:String )
 	
 	If path.StartsWith( "//" ) Return "//"
 	
+	If path.StartsWith( "/" ) Return "/"
+
 	Local i:=path.Find( "/" )
-	If i=0 Return "/"
 	
-	If i=-1 i=path.Length
+	If path.StartsWith( "$" ) And i<>-1 Return path.Slice( 0,i+1 )
 	
-	Local j:=path.Find( "://" )
-	If j>0 And j<i Return path.Slice( 0,j+3 )
+	Local j:=path.Find( ":" )
+	If j=-1 Or (i<>-1 And j>i) Return ""
 	
-	j=path.Find( ":/" )
-	If j>0 And j<i Return path.Slice( 0,j+2 )
+	If path.Slice( j,j+3 )="://" Return path.Slice( 0,j+3 )
 	
-	j=path.Find( "::" )
-	If j>0 And j<i Return path.Slice( 0,j+2 )
+	If path.Slice( j,j+2 )=":/" Return path.Slice( 0,j+2 )
+	
+	If path.Slice( j,j+2 )="::" Return path.Slice( 0,j+2 )
 	
 	Return ""
 End
@@ -359,26 +372,9 @@ End
 #end
 Function IsRootDir:Bool( path:String )
 	
-	path=path.Replace( "\","/" )
-	
-
-	If path="//" Return True
-	
-	If path="/" Return True
-	
-	Local i:=path.Find( "/" )
-	If i=-1 i=path.Length
-	
-	Local j:=path.Find( "://" )
-	If j>0 And j<i Return j+3=path.Length
-	
-	j=path.Find( ":/" )
-	If j>0 And j<i Return j+2=path.Length
-	
-	j=path.Find( "::" )
-	If j>0 And j<i Return j+2=path.Length
+	Local root:=ExtractRootDir( path )
 	
-	Return False
+	Return root And root.Length=path.Length
 End
 
 #rem monkeydoc Gets the process current directory.
@@ -418,30 +414,30 @@ Function RealPath:String( path:String )
 	
 	path=FixPath( path )
 	
-	Local rpath:=ExtractRootDir( path )
-	If rpath 
-		path=path.Slice( rpath.Length )
+	Local root:=ExtractRootDir( path )
+	If root 
+		path=path.Slice( root.Length )
 	Else
-		rpath=CurrentDir()
+		root=CurrentDir()
 	Endif
 	
 	While path
 		Local i:=path.Find( "/" )
-		If i=-1 Return rpath+path
+		If i=-1 Return root+path
 		Local t:=path.Slice( 0,i )
 		path=path.Slice( i+1 )
 		Select t
 		Case ""
 		Case "."
 		Case ".."
-			If Not rpath rpath=CurrentDir()
-			rpath=ExtractDir( rpath )
+			If Not root root=CurrentDir()
+			root=ExtractDir( root )
 		Default
-			rpath+=t+"/"
+			root+=t+"/"
 		End
 	Wend
 	
-	Return rpath
+	Return root
 	
 	#rem Not working on macos!
 	
@@ -593,6 +589,21 @@ End
 Function GetFileType:FileType( path:String )
 	
 	path=FixFilePath( path )
+	
+#If __TARGET__="android"
+	If path.StartsWith( "${ASSETS}/" )
+		
+		path=path.Slice( 10 )
+		
+		Local asset:=AAssetManager_open( GetAssetManager(),path,0 )
+		If Not asset Return FileType.Unknown
+		
+		Local length:=AAsset_getLength( asset )
+		AAsset_close( asset )
+		
+		Return length<>0 ? FileType.File Else FileType.Unknown
+	End
+#Endif
 
 	Local st:stat_t
 	If stat( path,Varptr st )<0 Return FileType.None
@@ -630,9 +641,24 @@ End
 
 #end
 Function GetFileSize:Long( path:String )
-
+	
 	path=FixFilePath( path )
 
+#If __TARGET__="android"
+	If path.StartsWith( "${ASSETS}/" )
+		
+		path=path.Slice( 10 )
+		
+		Local asset:=AAssetManager_open( GetAssetManager(),path,0 )
+		If Not asset Return 0
+		
+		Local length:=AAsset_getLength( asset )
+		AAsset_close( asset )
+		
+		Return length
+	End
+#Endif
+
 	Local st:stat_t
 	If stat( path,Varptr st )<0 Return 0
 
@@ -664,13 +690,33 @@ Does not return any '.' or '..' entries in a directory.
 #end
 Function LoadDir:String[]( path:String )
 	
+	Local files:=New StringStack
+	
 	path=FixFilePath( path )
-
+	
+#If __TARGET__="android"
+	If path.StartsWith( "${ASSETS}/" )
+		
+		path=path.Slice( 10 )
+		
+		Local assetDir:=AAssetManager_openDir( GetAssetManager(),path )
+		
+		If assetDir
+			Repeat
+				Local file:=AAssetDir_getNextFileName( assetDir )
+				If Not file Exit
+				files.Add( file )
+			Forever
+			AAssetDir_close( assetDir )
+		Endif
+		
+		Return files.ToArray()
+	Endif
+#endif
+	
 	Local dir:=opendir( path )
 	If Not dir Return Null
 	
-	Local files:=New StringStack
-	
 	Repeat
 		Local ent:=readdir( dir )
 		If Not ent Exit
@@ -851,3 +897,29 @@ Function CopyDir:Bool( srcDir:String,dstDir:String,recursive:Bool=True )
 	Return True
 
 End
+
+#rem monkeydoc Opens a 'C' file.
+
+Opens a file that can be used with the 'C' calls fopen, fread, fwrite and fclose. Similar to plain libc.fopen, except that it can also handle assets on android.
+
+`mode` should be one of: "r", "w" or "rw". When opening a file using "r" or "rw", the file must already exist or the function will fail and null will be returned. When opening a file using "w", any existing file at the same path will be overwritten.
+
+#end
+Function OpenCFile:FILE Ptr( path:String,mode:String )
+	
+	path=FixFilePath( path )
+	
+#If __TARGET__="android"
+	If path.StartsWith( "${ASSETS}/" )
+		
+		path=path.Slice( 10 )
+		
+		Local asset:=AAssetManager_open( GetAssetManager(),path,0 )
+		If Not asset Return Null
+		
+		Return fopenAsset( asset )
+	Endif
+#Endif
+	
+	Return libc.fopen( path,mode )
+End

+ 53 - 0
modules/std/filesystem/native/filesystem.cpp

@@ -37,6 +37,12 @@
 
 #endif
 
+#if BB_ANDROID
+
+#include <sdl2/SDL/src/core/android/SDL_android.h>
+
+#endif
+
 namespace bbFileSystem{
 
 	bbString _appDir;
@@ -172,4 +178,51 @@ namespace bbFileSystem{
 #endif
 	}
 	
+#if BB_ANDROID
+	int android_read( void *cookie,char *buf,int size ){
+	
+	  return AAsset_read( (AAsset*)cookie,buf,size );
+	}
+	
+	int android_write( void *cookie,const char* buf,int size ){
+	
+	  return EACCES; // can't provide write access to the apk
+	}
+	
+	fpos_t android_seek( void *cookie,fpos_t offset,int whence ){
+	
+	  return AAsset_seek( (AAsset*)cookie,offset,whence );
+	}
+	
+	int android_close(void* cookie) {
+	
+	  AAsset_close( (AAsset*)cookie );
+	  return 0;
+	}
+
+	FILE *fopenAsset( void *asset ){
+
+		return funopen( asset,android_read,android_write,android_seek,android_close );
+	}
+
+#endif
+
+/*	
+	FILE *fopen( const char *path,const char *mode ){
+
+#if BB_ANDROID
+		if( !strncmp( path,"asset::",7 ) ){
+			
+			AAssetManager *assetManager=Android_JNI_GetAssetManager();
+			if( !assetManager ) return 0;
+			
+	  		AAsset* asset=AAssetManager_open( assetManager,path+7,0 );
+			if( !asset ) return 0;
+			
+			return fopenAsset( asset );
+		}
+#endif
+		return ::fopen( path,mode );
+	}
+*/	
 }

+ 4 - 2
modules/std/filesystem/native/filesystem.h

@@ -16,9 +16,11 @@ namespace bbFileSystem{
 	bbBool copyFile( bbString srcPath,bbString dstPath );
 	
 #if BB_IOS
-	
 	bbString getSpecialDir( bbString name );
-	
+#endif
+
+#if BB_ANDROID
+	FILE *fopenAsset( void *asset );
 #endif
 
 }

+ 1 - 2
modules/std/graphics/pixmaploader.monkey2

@@ -72,9 +72,8 @@ Public
 Function LoadPixmap:Pixmap( path:String,format:PixelFormat )
 	
 	If ExtractExt( path )=".hdr"
-		path=RealPath( path )
 		
-		Local file:=libc.fopen( path,"rb" )
+		Local file:=filesystem.OpenCFile( path,"rb" )
 		If Not file Return Null
 		
 		Local width:=0,height:=0

+ 11 - 4
modules/std/misc/zipfile.monkey2

@@ -63,7 +63,7 @@ Class ZipFile
 	#rem monkeydoc @hidden
 	#end	
 	Method Extract:Bool( dir:String,prefix:String="" )
-	
+		
 		If Not dir.EndsWith( "/" ) dir+="/"
 		
 		Local result:=True
@@ -75,13 +75,20 @@ Class ZipFile
 			
 			If prefix And Not name.StartsWith( prefix ) Continue
 			
+			Local path:=dir+name
+				
+			If mz_zip_reader_is_file_a_directory( _zip,i )
+				
+				filesystem.CreateDir( path )
+				
+				Continue
+			Endif
+			
 			Local size:=_sizes[i]
 
 			Local buf:=New DataBuffer( size )
-		
-			If mz_zip_reader_extract_to_mem( _zip,i,buf.Data,size,0 ) 
 			
-				Local path:=dir+name
+			If mz_zip_reader_extract_to_mem( _zip,i,buf.Data,size,0 ) 
 				
 				filesystem.CreateDir( ExtractDir( path ) )
 				

+ 1 - 1
modules/std/module.json

@@ -4,5 +4,5 @@
 	"author":"Mark Sibly",
 	"version":"1.0.0",
 	"support":"http://monkeycoder.co.nz",
-	"depends":["libc","emscripten","jni","sdl2","miniz","stb-image","stb-image-write","stb-vorbis","zlib"]
+	"depends":["libc","sdl2","jni","android","emscripten","zlib","miniz","stb-image","stb-image-write","stb-vorbis"]
 }

+ 19 - 52
modules/std/std.monkey2

@@ -1,23 +1,20 @@
 
 Namespace std
 
-#Import "<libc.monkey2>"
+#Import "<libc>"
+#Import "<zlib>"
+#Import "<miniz>"
 #Import "<stb-image>"
 #Import "<stb-image-write>"
 #import "<stb-vorbis>"
-#Import "<miniz>"
-#Import "<zlib>"
 
-#If __MOBILE_TARGET__
-#Import "<sdl2>"
-#If __TARGET__="android"
-#Import "<jni>"
-#Endif
-#Endif
-
-#If __WEB_TARGET__
+#If __TARGET__="emscripten"
 #Import "<emscripten>"
-#endif
+#ElseIf __TARGET__="android"
+#Import "<android>"
+#ElseIf __TARGET__="ios"
+'#Import "<ios>"
+#Endif
 
 #Import "collections/container"
 #Import "collections/stack"
@@ -30,9 +27,9 @@ Namespace std
 #Import "stream/stream"
 #Import "stream/filestream"
 
-#If __MOBILE_TARGET__
-#Import "stream/sdl_rwstream.monkey2"
-#Endif
+'#If __MOBILE_TARGET__
+'#Import "stream/sdl_rwstream.monkey2"
+'#Endif
 
 #Import "memory/byteorder"
 #Import "memory/databuffer"
@@ -107,9 +104,9 @@ Function Main()
 		Return FileStream.Open( path,mode )
 	End
 	
-	Stream.OpenFuncs["memblock"]=Lambda:Stream( proto:String,path:String,mode:String )
+	Stream.OpenFuncs["asset"]=Lambda:Stream( proto:String,path:String,mode:String )
 	
-		Return DataStream.Open( path,mode )
+		Return FileStream.Open( filesystem.AssetsDir()+path,mode )
 	End
 	
 #If __MOBILE_TARGET__
@@ -126,46 +123,16 @@ Function Main()
 
 #endif
 	
-#If __DESKTOP_TARGET__
-
-	Stream.OpenFuncs["process"]=Lambda:Stream( proto:String,path:String,mode:String )
-
-		Return std.process.ProcessStream.Open( path,mode )
-	End
-	
-	Stream.OpenFuncs["desktop"]=Lambda:Stream( proto:String,path:String,mode:String )
+	Stream.OpenFuncs["memory"]=Lambda:Stream( proto:String,path:String,mode:String )
 	
-		Return FileStream.Open( filesystem.DesktopDir()+path,mode )
-	End
-
-	Stream.OpenFuncs["home"]=Lambda:Stream( proto:String,path:String,mode:String )
-	
-		Return FileStream.Open( filesystem.HomeDir()+path,mode )
-	End
-	
-#Endif
-
-#If __DESKTOP_TARGET__ Or __WEB_TARGET__
-
-	'note: ios and android asset proto is implemented using SDL and implemented in mojo...
-	'
-	Stream.OpenFuncs["asset"]=Lambda:Stream( proto:String,path:String,mode:String )
-	
-		Return FileStream.Open( filesystem.AssetsDir()+path,mode )
+		Return DataStream.Open( path,mode )
 	End
-
-#Else If __TARGET__="android"
-
-	Stream.OpenFuncs["asset"]=Lambda:Stream( proto:String,path:String,mode:String )
 	
-		Return SDL_RWStream.Open( path,mode )
-	End
+#If __DESKTOP_TARGET__
 
-#Else If __TARGET__="ios"
+	Stream.OpenFuncs["process"]=Lambda:Stream( proto:String,path:String,mode:String )
 
-	Stream.OpenFuncs["asset"]=Lambda:Stream( proto:String,path:String,mode:String )
-	
-		Return SDL_RWStream.Open( "assets/"+path,mode )
+		Return std.process.ProcessStream.Open( path,mode )
 	End
 	
 #Endif

+ 4 - 12
modules/std/stream/filestream.monkey2

@@ -92,9 +92,6 @@ Class FileStream Extends Stream
 	
 	When opening a file using "w", any existing file at the same path will be overwritten.
 	
-	Note: This method should not be used to open an 'asset stream' because assets are not always files. You should instead use 
-	[[Stream.Open]] for streams that have a stream path prefix such as `asset::`, `internal::`, `external::` etc.
-	
 	@param path The path of the file to open.
 	
 	@param mode The mode to open the file in: "r", "w" or "rw".
@@ -105,19 +102,14 @@ Class FileStream Extends Stream
 	Function Open:FileStream( path:String,mode:String )
 	
 		Select mode
-		Case "r"
-			mode="rb"
-		Case "w"
-			mode="wb"
-		Case "rw"
-			mode="r+b"
+		Case "r" mode="rb"
+		Case "w" mode="wb"
+		Case "rw" mode="r+b"
 		Default
 			Return Null
 		End
 		
-		path=RealPath( path )
-		
-		Local file:=fopen( path,mode )
+		Local file:=OpenCFile( path,mode )
 		If Not file Return Null
 		
 		Return New FileStream( file )

+ 36 - 16
products/android/Monkey2Game/app/src/main/java/org/libsdl/app/SDLActivity.java

@@ -546,6 +546,7 @@ public class SDLActivity extends Activity {
      * This method is called by SDL using JNI.
      */
     public static int audioOpen(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) {
+/*
         int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
         int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
         int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
@@ -575,7 +576,7 @@ public class SDLActivity extends Activity {
         }
 
         Log.v(TAG, "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + (mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
-
+*/
         return 0;
     }
 
@@ -583,6 +584,7 @@ public class SDLActivity extends Activity {
      * This method is called by SDL using JNI.
      */
     public static void audioWriteShortBuffer(short[] buffer) {
+/*
         for (int i = 0; i < buffer.length; ) {
             int result = mAudioTrack.write(buffer, i, buffer.length - i);
             if (result > 0) {
@@ -598,12 +600,14 @@ public class SDLActivity extends Activity {
                 return;
             }
         }
+*/
     }
 
     /**
      * This method is called by SDL using JNI.
      */
     public static void audioWriteByteBuffer(byte[] buffer) {
+/*
         for (int i = 0; i < buffer.length; ) {
             int result = mAudioTrack.write(buffer, i, buffer.length - i);
             if (result > 0) {
@@ -619,12 +623,14 @@ public class SDLActivity extends Activity {
                 return;
             }
         }
+*/
     }
 
     /**
      * This method is called by SDL using JNI.
      */
     public static int captureOpen(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) {
+/*
         int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
         int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
         int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
@@ -652,41 +658,51 @@ public class SDLActivity extends Activity {
         }
 
         Log.v(TAG, "SDL capture: got " + ((mAudioRecord.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioRecord.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + (mAudioRecord.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
-
+*/
         return 0;
     }
 
     /** This method is called by SDL using JNI. */
     public static int captureReadShortBuffer(short[] buffer, boolean blocking) {
+/*
         // !!! FIXME: this is available in API Level 23. Until then, we always block.  :(
         //return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
         return mAudioRecord.read(buffer, 0, buffer.length);
+*/
+        return 0;
     }
 
     /** This method is called by SDL using JNI. */
     public static int captureReadByteBuffer(byte[] buffer, boolean blocking) {
+/*
         // !!! FIXME: this is available in API Level 23. Until then, we always block.  :(
         //return mAudioRecord.read(buffer, 0, buffer.length, blocking ? AudioRecord.READ_BLOCKING : AudioRecord.READ_NON_BLOCKING);
         return mAudioRecord.read(buffer, 0, buffer.length);
+*/
+        return 0;
     }
 
 
     /** This method is called by SDL using JNI. */
     public static void audioClose() {
+/*
         if (mAudioTrack != null) {
             mAudioTrack.stop();
             mAudioTrack.release();
             mAudioTrack = null;
         }
+*/
     }
 
     /** This method is called by SDL using JNI. */
     public static void captureClose() {
+/*
         if (mAudioRecord != null) {
             mAudioRecord.stop();
             mAudioRecord.release();
             mAudioRecord = null;
         }
+*/
     }
 
 
@@ -834,7 +850,7 @@ public class SDLActivity extends Activity {
             final int[] buttonIds,
             final String[] buttonTexts,
             final int[] colors) {
-
+/*
         messageboxSelection[0] = -1;
 
         // sanity checks
@@ -875,10 +891,12 @@ public class SDLActivity extends Activity {
         }
 
         // return selected value
-
         return messageboxSelection[0];
+*/
+        return -1;
     }
 
+/*
     @Override
     protected Dialog onCreateDialog(int ignore, Bundle args) {
 
@@ -957,7 +975,7 @@ public class SDLActivity extends Activity {
                     mapping.put(KeyEvent.KEYCODE_ENTER, button);
                 }
                 if ((buttonFlags[i] & 0x00000002) != 0) {
-                    mapping.put(111, button); /* API 11: KeyEvent.KEYCODE_ESCAPE */
+                    mapping.put(111, button);
                 }
             }
             button.setText(buttonTexts[i]);
@@ -1012,6 +1030,7 @@ public class SDLActivity extends Activity {
 
         return dialog;
     }
+    */
 }
 
 /**
@@ -1088,7 +1107,8 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
     @Override
     public void surfaceCreated(SurfaceHolder holder) {
         Log.v("SDL", "surfaceCreated()");
-        holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
+        //deprecated in API5!
+        //holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
     }
 
     // Called when we lose the surface
@@ -1109,23 +1129,27 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
 
         int sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565 by default
         switch (format) {
-        case PixelFormat.A_8:
-            Log.v("SDL", "pixel format A_8");
+        case 8://PixelFormat.A_8:
+          Log.v("SDL", "pixel format A_8");
             break;
-        case PixelFormat.LA_88:
+        case 10://PixelFormat.LA_88:
             Log.v("SDL", "pixel format LA_88");
             break;
-        case PixelFormat.L_8:
+        case 9://PixelFormat.L_8:
             Log.v("SDL", "pixel format L_8");
             break;
-        case PixelFormat.RGBA_4444:
+        case 7://PixelFormat.RGBA_4444:
             Log.v("SDL", "pixel format RGBA_4444");
             sdlFormat = 0x15421002; // SDL_PIXELFORMAT_RGBA4444
             break;
-        case PixelFormat.RGBA_5551:
+        case 6://PixelFormat.RGBA_5551:
             Log.v("SDL", "pixel format RGBA_5551");
             sdlFormat = 0x15441002; // SDL_PIXELFORMAT_RGBA5551
             break;
+        case 11://PixelFormat.RGB_332:
+            Log.v("SDL", "pixel format RGB_332");
+            sdlFormat = 0x14110801; // SDL_PIXELFORMAT_RGB332
+            break;
         case PixelFormat.RGBA_8888:
             Log.v("SDL", "pixel format RGBA_8888");
             sdlFormat = 0x16462004; // SDL_PIXELFORMAT_RGBA8888
@@ -1134,10 +1158,6 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
             Log.v("SDL", "pixel format RGBX_8888");
             sdlFormat = 0x16261804; // SDL_PIXELFORMAT_RGBX8888
             break;
-        case PixelFormat.RGB_332:
-            Log.v("SDL", "pixel format RGB_332");
-            sdlFormat = 0x14110801; // SDL_PIXELFORMAT_RGB332
-            break;
         case PixelFormat.RGB_565:
             Log.v("SDL", "pixel format RGB_565");
             sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565

+ 8 - 1
products/android/Monkey2Game/build.gradle

@@ -8,7 +8,7 @@ buildscript {
     }
     
     dependencies {
-	    classpath 'com.android.tools.build:gradle:3.1.0'
+	    classpath 'com.android.tools.build:gradle:3.1.2'
     }
 }
 
@@ -19,3 +19,10 @@ allprojects {
         google()
     }
 }
+
+allprojects {
+ 
+    tasks.withType(JavaCompile) {
+        options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
+    }
+}