BlitzMax on iOS
BlitzMax Forums/Brucey's Modules/BlitzMax on iOS
| ||
Hot-on-the-heels of getting DX9 working in bmx-ng, I thought I'd have a bash at iOS. Getting code to compile correctly turned out to be the easier part of the mission. As far as can see there are three possible targets for iOS : armv7, arm64 and x86 (simulator). Apparently armv7 will work on all devices since the iPhone4... But for now I've been concentrating on the simulator, as it doesn't require me to pay for a dev license to test it. Dynamically building the xcode project has been a trickier part to get right, involving a bit of trial and error and looking at other's project files for inspiration. We're pretty much there now though, and it is happily populating things in the right place. There are lots of possibilities for customisation though, which can be looked into at a later date (like folders of stuff you want auto-packaged into the bundle, etc) The biggest hurdle so far has been SDL.GL2SDLMax2D, which has refused to render *any* graphics whatsoever, and since there's so much going on in there, it's hard to work out where it actually isn't working. :-( However, I knocked together a small test program which renders a coloured rectangle on the screen, and it is working as expected ! :-) Which proves that, in theory at least, iOS is definitely a viable target. SDL.GL2SDLMax2D is already known to work on the Pi and Android so it's a bit of a puzzle why it's not rendering anything on iOS... If anyone has any wild or crazy ideas, I'm more than happy to listen to them. |
| ||
Since XCode 7 beta you no longer need an apple dev membership to test on the device. http://bouk.co/blog/sideload-iphone/ |
| ||
Interesting! Thanks ;-) |
| ||
It's all a bit like some mysterious magic stuff... when everything just seems to work...![]() (running on iOS simulator, *with sound*!) One has to be somewhat impressed with Skid's freeaudio module, which so far has played on every platform without issue. Go Skid! :-D |
| ||
That's pretty awesome... |
| ||
Wow! |
| ||
Magical indeed :) But I guess user input will be a lot more difficult than just getting MouseHit(), MouseX() etc? |
| ||
But I guess user input will be a lot more difficult than just getting MouseHit(), MouseX() etc? Depends if you want to support multi-touch or not? Otherwise, MouseX() and co reflect the "first" touch input. For the breakout sample, when your finger touches the screen and move the bat across it, you are effectively holding down the mouse button while you move - think, click-and-drag. So yes, you may need to adapt your mouse input stuff, but it's not so hard. You can catch the initial "down" when the user touches the screen and do something then if you like. Unlike moving your mouse cursor around the screen, the cursor will appear to "jump" around from place to place as the user touches different parts of the screen. I added some new events for BlitzMax to help with multi-touch stuff (on top of the mouse handling which already works) : Const EVENT_TOUCHMASK=$40000 Const EVENT_TOUCHDOWN=$40001 Const EVENT_TOUCHUP=$40002 Const EVENT_TOUCHMOVE=$40003 Rather than a button number in the event you will get a touch id, which you can use to track multiple fingers at the same time. |
| ||
I can only synopsize some of the earlier comments: Wow, that's pretty awesome! |
| ||
Very interesting! |
| ||
Great ! |
| ||
Thanks to the generosity of some members of the community, I can now work directly with iOS hardware, rather than just the simulator... (donations generally go directly towards improving the tools and environment I have at my disposal for creating all this stuff I churn out. ;-) Nice to see my virtual joystick stuff actually seems to work! :-D SuperStrict Framework sdl.gl2sdlmax2d Import sdl.virtualjoystick Local joy:TRenderedJoystick = TRenderedJoystick(New TRenderedJoystick.Create("VJ", 100, 680, 50, 20)) joy.AddButton(900, 680, 30) joy.AddButton(970, 620, 30) Graphics 1024, 768, 0 SetBlend alphablend SetClsColor 255, 255, 255 SetColor 0, 0, 0 While Not KeyDown(key_escape) Cls ' draw joystick joy.Render() ' get some stats SetColor 0, 0, 0 Local x:Float = JoyX() DrawText "JoyX : " + x, 100, 300 DrawLine 150, 330, 150, 360, False DrawRect 150, 330, x * 50, 30 Local y:Float = JoyY() DrawText "JoyY : " + y, 300, 300 DrawLine 260, 310, 290, 310, False DrawRect 260, 310, 30, y * 50 If JoyDown(0) Then DrawText "Button 0 : DOWN", 100, 380 Else DrawText "Button 0 : UP", 100, 380 End If If JoyDown(1) Then DrawText "Button 1 : DOWN", 100, 400 Else DrawText "Button 1 : UP", 100, 400 End If Flip Wend Type TRenderedJoystick Extends TVirtualJoystick Method Render() If touchId <> -1 Then SetColor 200, 200, 100 Else SetColor 100, 200, 100 End If DrawOval centerX - radius, centerY - radius, radius * 2, radius * 2 SetColor 100, 100, 200 DrawOval xPos - knobRadius, yPos - knobRadius, knobRadius * 2, knobRadius * 2 For Local i:Int = 0 Until buttons.length Local button:TVirtualButton = buttons[i] If JoyDown(i) Then SetColor 255, 100, 100 Else SetColor 100, 100, 100 + i * 50 End If DrawOval button.centerX - button.radius, button.centerY - button.radius, button.radius * 2, button.radius * 2 Next End Method End Type |
| ||
Brucey, I must admit I feel 'joy'seeing the simple&dear&old BlitzMax syntax of the source code and the result running on an 'alien' device like iOS. In MX this feeling is still missing... |
| ||
Is the iOS simulator available on Mac? Nice video demo - I thought it was better with no sound though - sort of distracting. I didn't know you could do "Typename( New Typename.Create(arg) )". How is that better than a Create function? Anyway great progress! It's all looking very cool. |
| ||
Is the iOS simulator available on Mac? Yes. I was developing against that until recently (x86/x64 targets). However, building for the devices themselves raised different issues that I was unaware of until now. How is that better than a Create function? This way I am creating an instance of my subclass and initialising it. The Create method itself is part of the superclass. A create function would define a particular Type to create an instance of. This way, I am free to subclass and instantiate as I please, which is much more flexible. Of course, you could also do the following if you aren't using any subclass-specific functionality : Local joy:TVirtualJoystick = New TRenderedJoystick.Create("VJ", 100, 680, 50, 20) |
| ||
Anyhoo, here's Digesteroids running on the iPad Mini with the virtual joystick for input ... As you can probably see, there's some potential for getting BlitzMax games on iOS ;-) |
| ||
Very Nice and keep good work up :-) |
| ||
Awesome! What's next? BMax on XBone and PS4!? :D |
| ||
@brucey: it's doable a patron page(or like) for supporting BMX.NG or there could be a potential conflict with BRL? |
| ||
TBH I cant see a patron page conflicting with BRL as its not their code its Bruceys, also Mark has abandoned this forum ages ago so I dont see it as a issue anymore. |
| ||
Why not have doable a patron page for Brucey Win to win situation for Brucey :-) |
| ||
What's next? BMax on XBone and PS4!? Of those, more likely PS4, but unlikely just the same (although PS4 is running on top of BSD which isn't too far away from Linux) :-p I will probably add support for nacl (Chrome OS/Chrome browser) at some point since SDL already supports it. iOS is coming along. Did some work on lib and framework importing today, which made BASS useable, so I made a little app streaming internet radio on the iPad. Very cool how you can build and run your app for desktop, then re-compile for iOS and it *just works* :-) It's something I've always enjoyed with BlitzMax - the ability to switch platform and see your app running the same. And is more-or-less what I demand of NG - that you shouldn't need to change much (platform specific caveats aside), if anything, to run your stuff on the "new" platforms. |
| ||
I was (mostly) kidding, but I'm surprised PS4 is more likely. Out of curiosity, is it possible to make a stand-alone NG compiler? One that requires no other installs (MinGW, SDL, etc.)? |
| ||
Out of curiosity, is it possible to make a stand-alone NG compiler? One that requires no other installs (MinGW, SDL, etc.)? MinGW is only necessary to (re)compile modules, so if you have a compiled version of the mods and don't intent to add any others then you shouldn't need MinGW I'd think. |
| ||
I'm surprised PS4 is more likely. PS4 builds with Clang/LLVM, as does Apple's OSX and iOS. is it possible to make a stand-alone NG compiler? One that requires no other installs (MinGW, SDL, etc.)? Yes, one could probably drop a copy of MinGW into BlitzMax/MinGW32, and add some of the other modules to it for some kind of basic Windows distribution. |
| ||
one could probably drop a copy of MinGW into BlitzMax/MinGW32 Ah, cool. Wasn't sure if that was a legal distribution method. What about other platforms? Would that be Clang/LLVM instead? |
| ||
Wasn't sure if that was a legal distribution method. BlitzMax already ships with MinGW components. What about other platforms? Would that be Clang/LLVM instead? No. Unless you go to the trouble of creating your own custom distro of clang/gcc then it's easier just to use the compiler tools available on the system (XCode on Mac, GCC (or perhaps clang/llvm) on Linux. |
| ||
BlitzMax already ships with MinGW components Oh? I couldn't see anything obvious (no MinGW directory), but I'll take your word for it.How difficult would it be to add true first class functions to Blitz? |
| ||
How difficult would it be to add true first class functions to Blitz? I've no idea. Ask Yasha :-) |
| ||
I've no idea. Ask Yasha Bah! |
| ||
It's all rather exciting as the various parts come together :-) Wake/sleep handling is now working. The on-screen keyboard interacts well with BlitzMax's key stuff. Fixed some 64-bit lua issues over the weekend, so it's running well now on iOS - I've been using Derron's TVTower game (https://github.com/GWRon/TVTower) as a testbed since it's huge, complex, has lua support, etc. The code only requires a couple of minor tweaks to run on iOS (graphics driver, logging), but it's now running very stable. Of course, the UI/interaction will need some work to be more touch friendly, but that is to be expected really. I was surprised it runs at a solid 60fps, considering how inefficient Max2D generally is. One really nice thing XCode gives you is a fantastic depth of profiling information. You can snapshot the app any time and it will flood you with warnings (and detailed explanations) about the code, highlighting the lines of code, and ways you might want to change it to make it better... |
| ||
Well, this IS interesting. I'm hoping that this will make porting my game engine to the major platforms...less painful, anyway. All along, I've assumed that I'd have to translate everything to C or C++, but I would love to be wrong about that! I'm using LuaJIT for scripting and have recently learned how to get better performance - Yasha's right when he sings its praises. So I'd have to get Zeke's module working. Is there a page somewhere that has a list of things to watch out for (for those of us used to standard BMX)? Did I read something earlier about Byte Ptr not working with 64-bit? I use them often... |
| ||
(a modified) LuaJIT appears to work fine in 64-bit BlitzMax. I'll add it to the bmx-ng repo at some point. |
| ||
(a modified) LuaJIT appears to work fine Modified in what way? |
| ||
I meant the module, rather than luajit itself :-) |
| ||
I know, that was what I meant. What has to change in standard BMX code in order to use it with NG? |
| ||
Oh :-) Anything that refers to size_t in the API should be Long for 64-bit platforms. Also, externed Types should be wrapped instead. Otherwise, it should work as normal. Lugi, on the otherhand, would probably require a major rewrite - as it accesses BlitzMax Objects at a very low level, and I've rewritten the object internals for NG to use a different GC. (A modified) MaxLua does work though (see paragraph 2 above) :-) |
| ||
Hmm, okay. I am not using Lugi, but I am using BBObject and the like for exposing objects. I suppose I'd have to know how the new GC works. My current garbage collection function for exposed Lua userdata: int __gc_object( lua_State *state ) { BBObject **obj = (BBObject**)lua_touserdata( state, 1 ); BBRELEASE(*obj); *obj = NULL; return 0; } I've minimized the C code required and there are no instances of size_t (and no externed types), but I am using int - am I right to assume that doesn't matter? |
| ||
There's no need for your Null set there, unless you are specifically checking for it somewhere else? Ints are fine, as long as you aren't using them for pointers. For specific 64-bit changes, look for ?ptr64 here : https://github.com/bmx-ng/zeke.mod |
| ||
unless you are specifically checking for it somewhere else? BBRELEASE works for BlitzMax GC, but Lua's GC also needs to release it. It's a metatable function.Thanks for the link; I'll definitely want to look into this stuff soon. Just wish I had all the hardware for testing... |
| ||
Lua's GC also needs to release it. I thought that was why this function would be called? - because Lua was GC'ing anyway. |
| ||
Perhaps you're right; don't think it's hurting anything, either. I've put a comment by it to check into when I run through gc testing again. :) |
| ||
Should the modified LuaJIT be working with original BlitzMax? Since the link you posted had a later version of LuaJIT (and one that might actually solve an issue I'm having), I decided to give it a try. The module built just fine, but when I tried to make an executable, I got some undefined references. C:/BlitzMax/mod/zeke.mod/luajit.mod/lib/win32/libluajit_x86.a(lib_os.o):lib_os.c:(.text+0x10e): undefined reference to `_difftime32' C:/BlitzMax/mod/zeke.mod/luajit.mod/lib/win32/libluajit_x86.a(lib_os.o):lib_os.c:(.text+0x548): undefined reference to `_time32' C:/BlitzMax/mod/zeke.mod/luajit.mod/lib/win32/libluajit_x86.a(lib_os.o):lib_os.c:(.text+0x600): undefined reference to `_localtime32' C:/BlitzMax/mod/zeke.mod/luajit.mod/lib/win32/libluajit_x86.a(lib_os.o):lib_os.c:(.text+0x8ab): undefined reference to `_gmtime32' C:/BlitzMax/mod/zeke.mod/luajit.mod/lib/win32/libluajit_x86.a(lib_os.o):lib_os.c:(.text+0x8e8): undefined reference to `_time32' What should I do about this? I'm using TDM 4.7 - could that be the problem? EDIT: Tried updating TDM to 5.1 and still not working. EDIT2: I'm guessing that the .a just needs to be recompiled. |
| ||
It's built with TDM 5.1 64-bit. Yes, a recompile with a different version would probably sort it. |
| ||
Well, I guess I don't know how to do that. Thought "gcc -o Makefile luajit.c" from the terminal would do it... :( EDIT: "mingw32-make", by itself, generates a .dll and .exe, but no static libs. Keep finding sources that say it should be spitting out .a libs. :/ |
| ||
Just edit the makefile. Look for the line : BUILDMODE= mixed And change it to static. Or comment out that line and uncomment the following one... |
| ||
Hmm, guess I read that wrong. I thought "mixed" meant it would create both. I did as you suggested and got another error message related to making the exe...however...it DID build the static lib. Unfortunately, the undefined references from above are still there. :( |
| ||
As far as I am aware, if you build everything with the 32-bit TDM, you shouldn't have an issue as it won't suffix those functions with 32. |
| ||
EDIT: Wtf moment...rescinded! EDIT 2: Compiling problem resolved, but I think I'm getting too old for this... EDIT 3: Finding lots of instances of size_t in luajit.mod - what has been "modified?" |
| ||
what has been "modified?" See post #39 above. |
| ||
I did see that post, but it was unclear to me what you meant. I thought there were changes in the luajit C source. Anyhoo, the luajit ffi stuff is not 100% working and now I'm trying to track down why... |
| ||
Nah, there are no changes to the library itself. The examples were working fine, so I assumed it was okay. |
| ||
I've learned somewhat recently that FFI (not used in the examples, I think) allows you to directly call C functions and they get inlined with the JIT. It's very fast and better, in theory, than using the C API. In the process of switching over, I ran into an issue that I thought updating to the most recent version of LuaJIT (I was still using 2.0.1) would fix - but the issue is still there. I have to assume I'm still doing something wrong... EDIT: Think I've just confirmed the ffi part is not fully functional, but I'll post an update tomorrow. |
| ||
Okay, I'm almost sure that ffi in the module is not working - at least not for cdata and ctype. LuaJIT allows you to create cdata objects and work with them directly and attach metamethods to them, just like userdata. Unfortunately, I've discovered that the ctypes are not recognized and that means the __index and __newindex metamethods are not getting called properly. Just in case you're curious, here's an example Lua script... local ffi = require( "ffi" ) ffi.cdef[[ struct foo { int a, b; }; ]] local tt = ffi.new( "foo", 5, 8 ) print( " ----- " ) print( tt.a ) print( type( tt ) ) print( ffi.typeof( tt ) ) print( " ----- " )I am expecting the result to be... > ----- > 5 > cdata > foo <-- or maybe "struct foo" > ----- Instead, the lines above and below "cdata" are blank. Sorry for diverging from the thread topic. The truth is that JIT is turned off on iOS (and consoles). It may not be the best option for all platforms, but I'm not aware of a better one. It's too bad because except for these caveats, LuaJIT is pretty awesome. |
| ||
What happens when you declare your struct like this? :typedef struct { int a, b; } foo; |
| ||
Same thing... I've tried many combinations and have been following working examples from the LuaJIT forums. I don't know how the mod could be responsible for this - I don't see any connection. This is a simple example, of course. What I was trying to do was use BBArray directly and was pleasantly surprised when the __len meta method worked. Then, of course, I was deflated when the __index meta method did not. :/ The type is not getting recognized, so that explains it, but it would be nice to find a solution. |
| ||
Oh, that's interesting. When I tried it with the above def I got this on OS X :----- 5 cdata ctype<struct 95> ----- ... and the same result on Windows 7. |
| ||
Ugh. Okay, I'll look elsewhere... Thanks for looking into it, though. EDIT: I'm embarrassed to say this was just my replacement "print" function. Not related to my original problem at all. |
| ||
So your problem is this? What I was trying to do was use BBArray directly... In case you hadn't noticed, the BBArray struct does not actually define the whole of the contents of your array. 'scales' is a variable size, and the data comes somewhere after that. Unfortunately, I don't understand much of the innards of lua (like what are all these double-underscore variables), to be of too much help. |
| ||
That's okay. I appreciate what you have done and just by testing it (and exposing my blunder), you steered me away from spending too much time looking in the wrong place. So your problem is this? Sort of. There's a bit more to it.-- All of this is already working using the C API and userdata, but I wanted best possible performance and that's where ffi came in. However, ffi is incompatible with the stack and you need the stack to make userdata. Another option is just to push every single object as userdata, but I'd prefer to avoid that. Certain objects (table, userdata, and cdata) can have metatables/methods attached to them with double-underscore-prefixed keys that are accessors. x = foo.bar ..... triggers __index, if it exists foo.bar = x ..... triggers __newindex, .. #a .............. triggers __len, .. a + b ........... triggers __add, .. etc.The BBArray was another test case. This works right now, with the correct typedefs in ffi.cdef... local arrayMT = { __len = function( self ) return self.scales[0] end } local arrayType = ffi.metatype( "BBArray", arrayMT ) The __index metamethod wasn't triggering properly, but I have made some steps in the right direction and am no longer convinced the mod is the issue. |
| ||
Got it sorted now, thanks for your help (and sorry for the noise)! |
| ||
Wow, simply amazing! |
| ||
Brucey, you rock! |