ps2 and lua

Discuss the development of software, tools, libraries and anything else that helps make ps2dev happen.

Moderators: cheriff, Herben

Post Reply
tofuninja
Posts: 3
Joined: Wed Apr 26, 2006 7:30 am

ps2 and lua

Post by tofuninja »

I noticed that psp and lua seems to be growing and that lua for psp, or luaplayer makes it easy to do homebrew games. Is there anything similar lua wise for ps2?
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Re: ps2 and lua

Post by Shine »

You can download the source from http://www.lua.org It is standard C, so it should compile with every C compiler. You could take a look how to build the static libraries in the PSP repository (note: the Lua version in the PSP repository is slightly patched for using floats instead of doubles as the Lua "number" type): http://svn.ps2dev.org/listing.php?repna ... rev=0&sc=0
tofuninja
Posts: 3
Joined: Wed Apr 26, 2006 7:30 am

Post by tofuninja »

so if I compiled all this stuff, it will be the same as the luaplayer on psp? Be able to do the same stuff they are doing, pure lua for a game, and maybe even port their games easily to ps2?
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

Compiling the Lua sources gives you the scripting language Lua. For the graphics, sounds and system functions of Lua Player you need to port the Lua Player source to the PS2, which maybe is a lot of work.
tofuninja
Posts: 3
Joined: Wed Apr 26, 2006 7:30 am

Post by tofuninja »

I am sad now
SSpeare
Posts: 63
Joined: Tue May 23, 2006 11:45 pm
Contact:

Post by SSpeare »

I'm using Lua for development on the PS2 and it is beginning to actually work. I'm not familiar with LuaPlayer, but it should be relatively straightforward to create some kind of Lua-based SDK for the PS2 development (I'm not sure how advanced/mature LuaPlayer is).

It is very easy to expose C functions to Lua. The only difficult part is to map the data structures between the two languages. I have some simple rendering and pad input working, but that is it so far. I'd be happy to post any development if others are interested.

The nice thing about using Lua is that if the Lua SDK is complete enough, then the programmer doesn't have to mess with compiling any C code at all (and the difficulties with cygwin or trying to setup a linux dev box). It is easy to redistribute the .elf binary and then just develop using Lua. However, that would require a lot more sophistication for the SDK.
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

are you using the current 5.0 port made by Pixel (if i'm not wrong) ? or did you made a fresh new port (5.1?)

I would be interested to play a bit with it, and why not start a lua player for the ps2 (some others would be ready as well).
SSpeare
Posts: 63
Joined: Tue May 23, 2006 11:45 pm
Contact:

Post by SSpeare »

I am doing my own port. I didn't know there was any work completed already.

This work is under pretty heavy revision still, and at the moment I'm not really trying to build a "re-useable engine" but just trying to work on my little game.

But, I haven't done anything in the code that is highly custom yet. Most of the engine is actually implemented in Lua at the moment. I'm not sure where to post/host this stuff if you want to look at it. What is convenient for you?
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

just to be sure we are talking of the same thing, i'm speaking of the lua library, not a player.

what did you implement exactly ?
SSpeare
Posts: 63
Joined: Tue May 23, 2006 11:45 pm
Contact:

Post by SSpeare »

First, I got Lua compiling. I switched the datatype to float instead of double and switched the math.* functions to floating point (ie: math.sin calls sinf() instead of sin()).

Then I just began implementing C functions in Lua that allow basic interaction and mapping between the PS2 and Lua. The main.elf loads a file called main.lua and then just sits in a loop executing the "update" global function that is defined by main.lua. That function basically controls all rendering and pad input, etc.

Code: Select all

function setupFullPerspective(aspect)
  lp2MatrixMode(LP2.PROJECTION)
  lp2LoadIdentity()
  lp2Perspective(math.pi/4, aspect, 2, 2000)

  lp2MatrixMode(LP2.MODELVIEW)
  lp2LoadIdentity()

end


function updateObj(obj, pad, millis)
  local offX = normJoyAxis(pad.LJOY_H) * millis/16
  local newX = obj.pos[0] + offX
  local offY = -normJoyAxis(pad.LJOY_V) * millis/16
  local newY = obj.pos[1] + offY
  ............
end

function update(millis)
  lp2BeginScene(0,0,0)
  setupFullPerspective(screenAspect)

  lp2ReadInput()

  for i=1,pads do
    updateObj(obj[i], pad[i], millis)
  end

  lp2LoadIdentity()
  cameraTx(camPos, camRot)

  lp2PushMatrix()
  localWorldTx(obj[1])

  startTimeBlock("drawing chars 1 and 2")

  if (normJoyAxis(pad[1].LJOY_H) ~= 0) or (normJoyAxis(pad[1].LJOY_V) ~= 0) then
    char1.cycle = char1.cycle + 0.2 * millis/16
    char1:moveForward(char1.cycle)
  else
    char1.cycle = 0
    char1:toStandingPose()
  end
  char1:draw()

  lp2PopMatrix()
  --Above code repeats for all inputs--

  -- render walls and floors
  for i=1,#floors do
    floors[i]:draw()
  end
  for i=1,#walls do
    walls[i]:draw()
  end

  lp2WaitVSync()
  lp2EndScene(0,0,0)

end
As far as rendering goes, you can implement some buffers to render or use the "immediate mode" calls like in OpenGL. Obviously, the buffers are faster but a little harder to use.

Buffer example:

Code: Select all

pointCount = 36
cubePoints = lp2CreatePointArray(pointCount)
cubePoints[0]  =  0 cubePoints[1]  =  2 cubePoints[2]  =  1
cubePoints[3]  =  1 cubePoints[4]  =  2 cubePoints[5]  =  3
cubePoints[6]  =  4 cubePoints[7]  =  5 cubePoints[8]  =  6
cubePoints[9]  =  5 cubePoints[10] =  7 cubePoints[11] =  6
cubePoints[12] =  8 cubePoints[13] =  9 cubePoints[14] = 10
cubePoints[15] =  9 cubePoints[16] = 11 cubePoints[17] = 10
cubePoints[18] = 12 cubePoints[19] = 14 cubePoints[20] = 13
cubePoints[21] = 13 cubePoints[22] = 14 cubePoints[23] = 15
cubePoints[24] = 16 cubePoints[25] = 18 cubePoints[26] = 17
cubePoints[27] = 17 cubePoints[28] = 18 cubePoints[29] = 19
cubePoints[30] = 20 cubePoints[31] = 21 cubePoints[32] = 22
cubePoints[33] = 21 cubePoints[34] = 23 cubePoints[35] = 22

vertexCount = 24
vertices = lp2CreateVertexArray(vertexCount)
vertices[0*4] =  6 vertices[0*4+1] = 10 vertices[0*4+2] = 10 vertices[0*4+3]=1
vertices[1*4] =  6 vertices[1*4+1] = 10 vertices[1*4+2] =-10 vertices[1*4+3]=1
vertices[2*4] = 10 vertices[2*4+1] =-10 vertices[2*4+2] = 10 vertices[2*4+3]=1
vertices[3*4] = 10 vertices[3*4+1] =-10 vertices[3*4+2] =-10 vertices[3*4+3]=1
vertices[4*4] =- 6 vertices[4*4+1] = 10 vertices[4*4+2] = 10 vertices[4*4+3]=1
vertices[5*4] =- 6 vertices[5*4+1] = 10 vertices[5*4+2] =-10 vertices[5*4+3]=1
vertices[6*4] =-10 vertices[6*4+1] =-10 vertices[6*4+2] = 10 vertices[6*4+3]=1
vertices[7*4] =-10 vertices[7*4+1] =-10 vertices[7*4+2] =-10 vertices[7*4+3]=1
vertices[8*4] =- 6 vertices[8*4+1] = 10 vertices[8*4+2] = 10 vertices[8*4+3]=1
vertices[9*4] =  6 vertices[9*4+1] = 10 vertices[9*4+2] = 10 vertices[9*4+3]=1
vertices[10*4]=- 6 vertices[10*4+1]= 10 vertices[10*4+2]=-10 vertices[10*4+3]=1
vertices[11*4]=  6 vertices[11*4+1]= 10 vertices[11*4+2]=-10 vertices[11*4+3]=1
vertices[12*4]=-10 vertices[12*4+1]=-10 vertices[12*4+2]= 10 vertices[12*4+3]=1
vertices[13*4]= 10 vertices[13*4+1]=-10 vertices[13*4+2]= 10 vertices[13*4+3]=1
vertices[14*4]=-10 vertices[14*4+1]=-10 vertices[14*4+2]=-10 vertices[14*4+3]=1
vertices[15*4]= 10 vertices[15*4+1]=-10 vertices[15*4+2]=-10 vertices[15*4+3]=1
vertices[16*4]=- 6 vertices[16*4+1]= 10 vertices[16*4+2]= 10 vertices[16*4+3]=1
vertices[17*4]=  6 vertices[17*4+1]= 10 vertices[17*4+2]= 10 vertices[17*4+3]=1
vertices[18*4]=-10 vertices[18*4+1]=-10 vertices[18*4+2]= 10 vertices[18*4+3]=1
vertices[19*4]= 10 vertices[19*4+1]=-10 vertices[19*4+2]= 10 vertices[19*4+3]=1
vertices[20*4]=- 6 vertices[20*4+1]= 10 vertices[20*4+2]=-10 vertices[20*4+3]=1
vertices[21*4]=  6 vertices[21*4+1]= 10 vertices[21*4+2]=-10 vertices[21*4+3]=1
vertices[22*4]=-10 vertices[22*4+1]=-10 vertices[22*4+2]=-10 vertices[22*4+3]=1
vertices[23*4]= 10 vertices[23*4+1]=-10 vertices[23*4+2]=-10 vertices[23*4+3]=1

colours = lp2CreateVertexArray(vertexCount)
for i = 0,vertexCount-1 do
	if &#40;i < 8&#41; then
		colours&#91;i*4&#93; = 1
	else
		colours&#91;i*4&#93; = 0
	end
	if &#40;i >= 8 and i < 16&#41; then
		colours&#91;i*4+1&#93; = 1
	else
		colours&#91;i*4+1&#93; = 0
	end
	if &#40;i >= 16&#41; then
		colours&#91;i*4+2&#93; = 1
	else
		colours&#91;i*4+2&#93; = 0
	end
	colours&#91;i*4+3&#93; = 1
end

lp2RenderBuffers&#40;vertexCount, vertices, colours, pointCount, cubePoints&#41;
Immediate Mode example:

Code: Select all

function drawCubeAt&#40;x, y, z, width, height, depth, r, g, b, a&#41;
	r = r or 1
	g = g or 1
	b = b or 1
	a = a or 1
	x = x or 0
	y = y or 0
	z = z or 0

	width = width or 1
	height = height or 1
	depth = depth or 1

	lp2Begin&#40;LP2.TRIANGLES&#41;
	lp2Color&#40;r, g, b, a&#41;
	lp2Vertex&#40;x,         y + height, z + depth&#41;
	lp2Vertex&#40;x,         y,          z + depth&#41;
	lp2Vertex&#40;x + width, y,          z + depth&#41;

	lp2Vertex&#40;x + width, y,          z + depth&#41;
	lp2Vertex&#40;x + width, y + height, z + depth&#41;
	lp2Vertex&#40;x,         y + height, z + depth&#41;

	lp2Color&#40;r+0.05, g+0.05, b+0.05, a&#41;
	lp2Vertex&#40;x + width, y + height, z + depth&#41;
	lp2Vertex&#40;x + width, y,          z + depth&#41;
	lp2Vertex&#40;x + width, y,          z&#41;

	lp2Vertex&#40;x + width, y,          z&#41;
	lp2Vertex&#40;x + width, y + height, z&#41;
	lp2Vertex&#40;x + width, y + height, z + depth&#41;

	lp2Color&#40;r+0.10, g+0.10, b+0.10, a&#41;
	lp2Vertex&#40;x,         y + height, z&#41;
	lp2Vertex&#40;x + width, y,          z&#41;
	lp2Vertex&#40;x,         y,          z&#41;

	lp2Vertex&#40;x + width, y,          z&#41;
	lp2Vertex&#40;x,         y + height, z&#41;
	lp2Vertex&#40;x + width, y + height, z&#41;

	lp2Color&#40;r+0.15, g+0.15, b+0.15, a&#41;
	lp2Vertex&#40;x,         y + height, z + depth&#41;
	lp2Vertex&#40;x,         y,          z&#41;
	lp2Vertex&#40;x,         y,          z + depth&#41;

	lp2Vertex&#40;x,         y,          z&#41;
	lp2Vertex&#40;x,         y + height, z + depth&#41;
	lp2Vertex&#40;x,         y + height, z&#41;

	lp2Color&#40;r+0.20, g+0.20, b+0.20, a&#41;
	lp2Vertex&#40;x,         y + height, z + depth&#41;
	lp2Vertex&#40;x + width, y + height, z&#41;
	lp2Vertex&#40;x,         y + height, z&#41;

	lp2Vertex&#40;x,         y + height, z + depth&#41;
	lp2Vertex&#40;x + width, y + height, z + depth&#41;
	lp2Vertex&#40;x + width, y + height, z&#41;

	lp2Color&#40;r+0.25, g+0.25, b+0.25, a&#41;
	lp2Vertex&#40;x,         y,          z + depth&#41;
	lp2Vertex&#40;x,         y,          z&#41;
	lp2Vertex&#40;x + width, y,          z&#41;

	lp2Vertex&#40;x,         y,          z + depth&#41;
	lp2Vertex&#40;x + width, y,          z&#41;
	lp2Vertex&#40;x + width, y,          z + depth&#41;

	lp2End&#40;&#41;
end
Obviously, some of this code is silly to write in Lua, but it's quick and easy to write and I'll move it to C for speed later.

All the calls that begin with "lp2" are written in the engine in C. The other calls are implemented as Lua functions elsewhere.

Both rendering modes honor the current MODELVIEW and PROJECTION matrices and you can call lp2PushMatrix() lp2PopMatrix(), lp2Translate(), lp2Rotate(), and lp2MultMatrix().

It isn't too fast and it doesn't support texturing or lighting yet.

Oh, and it also runs in OpenGL on the PC for prototyping.
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

sweeeeeet !

Only a binary version has been released with the patch file for the 5.0.2 sources, if you have the 5.1 patched sources, it's better of course :)
I tried yesterday nigth to compilate the 5.1 but just got a very bad exception and I didn't had the time to found out what was wrong before beeing tired and going to sleep :]

So if you already have the lua interpreter patched, up & running, it could be nice to put it under SVN (here at ps2dev) ?

Just ask oobles for an access, or send me it by email if you prefer and I'll upload it.

Regards.
SSpeare
Posts: 63
Joined: Tue May 23, 2006 11:45 pm
Contact:

Post by SSpeare »

I guess I should just get SVN access at some point as I have run into a few things in the sources to ps2sdk already. How do I go about that? Do I have to pass a double-blind taste test? I haven't used SVN yet, but I've used cvs and perforce plenty.

My code is organized pretty hideously at the moment. I'm not used to straight-C development, have done mostly OO stuff for the past 10 years.

I fixed a few lingering problems last night so now the engine doesn't require 60fps and I fudged the projection matrix a little so the OpenGL and PS2 versions now look identical. I guess I should switch to gsKit instead of libdraw and libgraph, but I probably won't do that until I run into another blocking problem.

Actually, my current most annoying problem is that sometimes I get polygons shearing all over the screen as if the clipping/transform code isn't working right. It's not completely reliable, but it's really annoying.
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

You should ask kindly to Ooble and offer him a candy for that ! then (if he agree) you should have your svn account ready.

Anyway, tonight i'm hoping to have the interpreter running as well :)
SSpeare
Posts: 63
Joined: Tue May 23, 2006 11:45 pm
Contact:

Post by SSpeare »

evilo: what is the problem you are running into? Something to do with the io library? I am building the io library, but I haven't tried using it yet. Are you running a lua script that is using the io library? What does that script look like? If not, then what is the exact error you're seeing?
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

Hi Sspeare,

The problem i'm having is that none of the function in the lua script seems to be recognized by the interpreter. Concerning the IO library, I removed the popen support and I built it successfully, even if i didn't tested it already.

evilo.
SSpeare
Posts: 63
Joined: Tue May 23, 2006 11:45 pm
Contact:

Post by SSpeare »

Ah! Try adding a blank line at the top of the script.

I know that sounds dumb, but I had to modify all of my scripts to always begin with a single blank line and it fixed some strange problem that I never diagnosed.

I was guessing it has something to do with file io settings and maybe the line terminator being 13,10 or just 13 or whatever. I am also suspecting that this is related to the fact that I can't load precompiled lua scripts at runtime on the PS2 either.

Is there something you had to do that was different than the diff I sent you? That is strange...

I just looked at luaL_loadfile() (in lauxlib.c) and it inspects the first character by using getc() and then calls ungetc()... Does anyone know if ungetc() works? I'm a little suspicious of that...
Last edited by SSpeare on Wed Jun 14, 2006 3:15 am, edited 1 time in total.
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

duh... I'll try as soon as I'm back at home !

you sent me a diff ??? where ?
SSpeare
Posts: 63
Joined: Tue May 23, 2006 11:45 pm
Contact:

Post by SSpeare »

ah, I sent it to someone else. I just sent it to you also at your gmail account. I just editted the above post with info about what might be causing the problem.

Using my Makefile might make a difference. It is just based on the makefiles from ps2sdk. It isn't the one that comes with Lua because the Lua version doesn't have a compatibility section for PS2. I guess I could have tried to figure out what that would look like, but I didn't! My Makefile will not specify LUA_USE_POPEN so that won't get compiled in.

Rather, it won't specify LUA_USE_POSIX which then won't specify LUA_USE_POPEN.
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

I've done the same thing but reusing the supplied makefile, just adding necessary stuff specific to the ps2. But on my side, I also made a stub file to add missing function like locale, etc... and kept the io library, so it should be theorically complete !

concerning my gmail account, did you sent it to [email protected] ?
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

So i just got back at home and tested...

and.. It's working.. i will investigate on why that damn blank line is needed.
I ran severals lua scripts and all are working, so it's good :)

In the mean time, I propose you to add our port into svn, so you'll be able to add your changes if you see something else missing ?

do you agree ?
SSpeare
Posts: 63
Joined: Tue May 23, 2006 11:45 pm
Contact:

Post by SSpeare »

I agree. I'm just not sure exactly how best to put it into the SVN here on ps2dev.org. What should the folder be called? I have used perforce and CVS but not SVN and I don't want to mess anything up. I guess it should go under ps2/trunk, right? maybe:

ps2/trunk/lua

or something?

Also, I think I found the problem. ungetc() puts a character back in the putback buffer, but the putback buffer is not checked during fread() so it will be ignored at the next fread(). I believe that the lua will use the fread() call from: getF() in lauxlib.c because that is passed into lua_load which passes it on into the parser.

I think the fix would be to update fread() in stdio.c to something like (just off the top of my head):

Code: Select all

size_t fread&#40;void *buf, size_t r, size_t n, FILE *stream&#41;
&#123;
  size_t ret;

  switch&#40;stream->type&#41; &#123;
    case STD_IOBUF_TYPE_NONE&#58;
    case STD_IOBUF_TYPE_GS&#58;
    case STD_IOBUF_TYPE_SIO&#58;
    case STD_IOBUF_TYPE_STDOUTHOST&#58;
      /* cannot read from stdout or stderr. */
      ret = 0;
      break;
    default&#58;
      /* attempt to read from the stream file. */
      if &#40;stream->has_putback&#41; &#123;
        stream->has_putback = 0;
        buf&#91;0&#93; = stream->putback;
        buf++;
        /* subtract 1 from n to avoid buffer overflow and keep an even record count */
        ret = &#40;_ps2sdk_read&#40;stream->fd, buf, &#40;int&#41;&#40;r * &#40;n-1&#41;&#41;&#41; / &#40;int&#41;r&#41;;
      &#125; else &#123;
        ret = &#40;_ps2sdk_read&#40;stream->fd, buf, &#40;int&#41;&#40;r * n&#41;&#41; / &#40;int&#41;r&#41;;
      &#125;
  &#125;
  return &#40;ret&#41;;
&#125;
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

lua 5.1 is in the box ! under \trunk\ps2sd-port\lua :)

I'll check what you wrote about fread() tomorrow... I need to sleep now !
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

Hi,

I just checked your code and just corrected one thing (1 should be substracted to r*n and not only n), but your correction seems correct to me, i'll test it tonight :)

giving :

Code: Select all

size_t fread&#40;void *buf, size_t r, size_t n, FILE *stream&#41;
&#123;
  size_t ret;

  switch&#40;stream->type&#41; &#123;
    case STD_IOBUF_TYPE_NONE&#58;
    case STD_IOBUF_TYPE_GS&#58;
    case STD_IOBUF_TYPE_SIO&#58;
    case STD_IOBUF_TYPE_STDOUTHOST&#58;
      /* cannot read from stdout or stderr. */
      ret = 0;
      break;
    default&#58;
      /* attempt to read from the stream file. */
      if &#40;stream->has_putback&#41; &#123;
        buf&#91;0&#93; = stream->putback;
        buf++;
        stream->has_putback = 0;
        /* subtract 1 from r * n to avoid buffer overflow and keep an even record count */
        ret = &#40;_ps2sdk_read&#40;stream->fd, buf, &#40;int&#41;&#40;&#40;r * n&#41; -1 &#41;&#41;&#41; / &#40;int&#41;r&#41;;
      &#125; else &#123;
        ret = &#40;_ps2sdk_read&#40;stream->fd, buf, &#40;int&#41;&#40;r * n&#41;&#41; / &#40;int&#41;r&#41;;
      &#125;
  &#125;
  return &#40;ret&#41;;
&#125; 
I also checked in all others IO routines, and that flag is not checked (where it should be) in fwrite, ftell, fgetpos and not reseted in some others (like fsetpos, etc..)

dunno if we need them aswell for the moment, lua/ps2 need some more extensive testing :)

advice from the official libc maintainer ? (Pixel ??? still alive ?)

evilo.
SSpeare
Posts: 63
Joined: Tue May 23, 2006 11:45 pm
Contact:

Post by SSpeare »

Ya. I wrote it that way at first and then changed it. But I think that way is better upon further reflection. I guess fread() will return partial records if your record size is >1. That seems odd to me, but that is the current behavior so I guess we should just leave it alone for the moment.

e.g.
If I ask to read 10 records of size 4, and fread() finds 38 bytes, I would expect it to return 9 records of size 4 (36 bytes), not 38 bytes which is 9 records plus a half record. The return value of fread() will be 9 because it is forced to an int, so it will lie about how much data it read. Then if you fread() again you will have mis-aligned data because you have already read 1/2 of the record, but you didn't know that because the function lied.

I'm not sure what the behavior of fread() is in a standard implementation, though... I haven't used C extensively in a long time. This may be just a caveat.

That being said, it should still probably subtract the 1 from (r * n)... Either way it won't fix the above problem.

EDIT: Moved fread() and ungetc() discussion to a new thread in ps2sdk
Post Reply