0 Members and 1 Guest are viewing this topic.
Option ExplicitPublic Sub writeByte(filenumber As Integer, value As Byte)  Put #filenumber, , valueEnd SubPublic Sub writeInteger(filenumber As Integer, value As Integer)  Put #filenumber, , valueEnd SubPublic Sub writeLong(filenumber As Integer, value As Long)  Put #filenumber, , valueEnd SubPublic Sub writeSingle(filenumber As Integer, value As Single)  Put #filenumber, , valueEnd SubPublic Sub writeDelphiString(filenumber As Integer, value As String)  writeByte filenumber, CByte(Len(Trim(value)))  Put #filenumber, , valueEnd SubPublic Function getDelphiString(ByVal filenumber As Integer, ByVal maxSize As Byte) As String  getDelphiString = Space(maxSize + 1) 'include length byte  Get #filenumber, , getDelphiString  getDelphiString = Mid(getDelphiString, 2, Asc(Left(getDelphiString, 1))) 'use length byte to cut off endEnd FunctionPublic Function getByte(ByVal filenumber As Integer) As Byte  Get #filenumber, , getByteEnd FunctionPublic Function getInteger(ByVal filenumber As Integer) As Integer  Get #filenumber, , getIntegerEnd FunctionPublic Function getLong(ByVal filenumber As Integer) As Long  Get #filenumber, , getLongEnd FunctionPublic Function getSingle(ByVal filenumber As Integer) As Single  Get #filenumber, , getSingleEnd FunctionPublic Sub Skip(ByVal filenumber As Integer, ByVal numBytes As Long)  Seek #filenumber, Loc(filenumber) + numBytes + 1End Sub
'D3DVECTOR2 is defined as a type with X as single, Y as singlePublic Type tColor  blue As Byte  green As Byte  red As Byte  alpha As ByteEnd TypePublic Type tHeader  version As LongEnd TypePublic Type tCollider  Active As Byte  x As Single  y As Single  'Coords As D3DVECTOR2  translation As D3DVECTOR2  radius As Single  Scale As D3DVECTOR2End TypePublic Type tOptions  MapName As String * MAPNAME_SIZE  TextureName As String * TEXTURENAME_SIZE  BackgroundColor As tColor  BackgroundColor2 As tColor  StartJet As Long  GrenadePacks As Byte  Medikits As Byte  Weather As Byte  Steps As Byte  RandomID As LongEnd TypePublic Type tProp  Active As Byte  Style As Integer  width As Long  height As Long  'Corner As Point  x As Single  y As Single  'Coords As D3DVECTOR2  translation As D3DVECTOR2  rotation As Single  ScaleX As Single  ScaleY As Single  'OriginalScale As D3DVECTOR2  Scale As D3DVECTOR2  color As tColor  level As ByteEnd TypePublic Type tScenery  SceneryName As String * SCENERY_SIZE  lDate As LongEnd TypePublic Type tSector  PolyCount As Integer  Polys() As IntegerEnd TypePublic Type tSpawnpoint  Active As Byte  x As Long  y As Long  team As LongEnd TypePublic Type tWaypoint  Active As Byte  id As Long  x As Long  y As Long  Left As Byte  Right As Byte  up As Byte  down As Byte  m2 As Byte  PathNum As Byte  C1 As Byte  C2 As Byte  C3 As Byte  ConnectionsNum As Long  connections(MAX_CONNECTIONS) As LongEnd TypePublic Type tVertex  x As Single  y As Single  Z As Single  RHW As Single '// Position for the vertex.  color As tColor ' // Diffuse color.  tu As Single  tv As SingleEnd TypePublic Type tPolygon  vertices() As tVertex  Perp(1 To 3) As D3DVECTOR  PolyType As ByteEnd Type
'with this code, I chose to, instead of padding the types, to load them all manually. While it means slower loading times, it means much clearer code and less useless variables.Public Function getWaypoint(filenumber As Integer) As tWaypoint  Dim j As Byte  With getWaypoint    .Active = getByte(filenumber)    Skip filenumber, 3    .id = getLong(filenumber)    .x = getLong(filenumber)    .y = getLong(filenumber)    .Left = getByte(filenumber)    .Right = getByte(filenumber)    .up = getByte(filenumber)    .down = getByte(filenumber)    .m2 = getByte(filenumber)    .num = 1 + .up + .down * 2 + .Left * 4 + .Right * 8 + .m2 * 16    .PathNum = getByte(filenumber)    .C1 = getByte(filenumber)    .C2 = getByte(filenumber)    .C3 = getByte(filenumber)    Skip filenumber, 3    .ConnectionsNum = getLong(filenumber)    For j = 1 To MAX_CONNECTIONS      If j <= .ConnectionsNum Then        .connections(j) = getLong(filenumber)      Else        Skip filenumber, 4      End If    Next j  End WithEnd FunctionPublic Function getSpawnpoint(filenumber As Integer) As tSpawnpoint  With getSpawnpoint    .Active = getByte(filenumber)    Skip filenumber, 3    .x = getLong(filenumber)    .y = getLong(filenumber)    .team = getLong(filenumber)  End WithEnd FunctionPublic Function getCollider(filenumber As Integer) As tCollider  With getCollider    .Active = getByte(filenumber)    Skip filenumber, 3    .x = getSingle(filenumber)    .y = getSingle(filenumber)    .radius = getSingle(filenumber)  End WithEnd FunctionPublic Function getScenery(filenumber As Integer) As tScenery  With getScenery    .SceneryName = getDelphiString(filenumber, SCENERY_SIZE)    .lDate = getLong(filenumber)  End WithEnd FunctionPublic Function getProp(filenumber As Integer) As tProp  Dim alpha As Byte  With getProp    .Active = getByte(filenumber)    Skip filenumber, 1    .Style = getInteger(filenumber)    .width = getLong(filenumber)    .height = getLong(filenumber)    .x = getSingle(filenumber)    .y = getSingle(filenumber)    .rotation = getSingle(filenumber)    .ScaleX = getSingle(filenumber)    .ScaleY = getSingle(filenumber)    alpha = getByte(filenumber)    Skip filenumber, 3    .color = getColor(filenumber)    .color.alpha = alpha    .level = getByte(filenumber)    Skip filenumber, 3  End WithEnd FunctionPublic Function getPolygon(filenumber As Integer) As tPolygon  Dim k As Long  With getPolygon    'loop through vertices    ReDim .vertices(4)    ReDim .basevertices(3)    For k = 1 To 3      'deal with this vertice      .vertices(k) = getVertex(filenumber)      .basevertices(k).x = .vertices(k).x      .basevertices(k).y = .vertices(k).y      'Debug.Print .vertices(k).x      '.Vertex(k) = tempVertex      'done with this vertice    Next k    .vertices(k) = .vertices(1)    'next vertice    'loop through the perps    For k = 1 To 3      'load each perp      .Perp(k) = getVector(filenumber)      'Debug.Print i, .Perp(k).x, .Perp(k).y, .Perp(k).Z    Next k    'next perp    'get the type of this polygon        .PolyType = getByte(filenumber)  End WithEnd FunctionPublic Function getOptions(filenumber As Integer) As tOptions  With getOptions    ' convert map name string    .MapName = getDelphiString(filenumber, MAPNAME_SIZE)    ' convert texture string    .TextureName = getDelphiString(filenumber, TEXTURENAME_SIZE)    'load top background color a byte at a time    .BackgroundColor = getColor(filenumber)    .BackgroundColor2 = getColor(filenumber)    'load bottom background color a byte at a time    .StartJet = getLong(filenumber)    .GrenadePacks = getByte(filenumber)    .Medikits = getByte(filenumber)    .Weather = getByte(filenumber)    .Steps = getByte(filenumber)    .RandomID = getLong(filenumber)  End WithEnd FunctionPublic Function getColor(filenumber As Integer) As tColor  With getColor    .blue = getByte(filenumber)    .green = getByte(filenumber)    .red = getByte(filenumber)    .alpha = getByte(filenumber)  End WithEnd FunctionPublic Function getVector(ByVal filenumber As Integer) As D3DVECTOR  Get #filenumber, , getVectorEnd FunctionPublic Function getVertex(ByVal filenumber As Integer) As tVertex  Get #filenumber, , getVertexEnd Function
Public Sub openFile(rFilePath As String)  If rFilePath = "" Then Exit Sub  filePath = rFilePath  'Counters for array access  Dim i As Integer  Dim k As Integer  Dim j As Integer  Dim tempVector As D3DVECTOR  Dim tempVertex As tVertex  Dim tempLong As Long  Dim FN As Integer  FN = FreeFile  ' open map  Open rFilePath For Binary Access Read Lock Write As #FN  with Header    .version = getLong(FN)  End With  Options = getOptions(FN)  ReDim Polygon(getLong(FN))  For i = 1 To UBound(Polygon)    Polygon(i) = getPolygon(FN)  Next i  SectorDivision = getLong(FN)  Skip FN, 4  'this is a 50x50 array in essence, -25 to 25  For i = -NUM_SECTORS To NUM_SECTORS    For j = -NUM_SECTORS To NUM_SECTORS      'In my original code, I skipped sector data; when saving it was useless because it had to be regenerated to account for changes. I've included some code in here for your benefit.      'Skip FN, getInteger(FN) * 2      Sector(i,j).Polycount = getInteger(FN)      redim Sector(i,j).Polys(Sector(i,j).Polycount)      For k = 1 To Sector(i,j).Polycount        sector(i,j).Polys(k) = getInteger(FN) 'this is the index of the poly in that sector      Next k    Next j  Next i  tempLong = getLong(FN)  If tempLong > 0 Then    ReDim Prop(tempLong)  Else    ReDim Prop(0 To 0)  End If  For i = 1 To UBound(Prop)    Prop(i) = getProp(FN)  Next i  tempLong = getLong(FN)  If tempLong > 0 Then    ReDim Scenery(tempLong)  Else    ReDim Scenery(0 To 0)  End If  For i = 1 To UBound(Scenery)    Scenery(i) = getScenery(FN)  Next i  tempLong = getLong(FN)  If tempLong > 0 Then    ReDim Collider(tempLong)  Else    ReDim Collider(0 To 0)  End If  For i = 1 To UBound(Collider)    Collider(i) = getCollider(FN)  Next i  tempLong = getLong(FN)  If tempLong > 0 Then    ReDim Spawnpoint(tempLong)  Else    ReDim Spawnpoint(0 To 0)  End If  For i = 1 To UBound(Spawnpoint)    Spawnpoint(i) = getSpawnpoint(FN)  Next i  tempLong = getLong(FN)  If tempLong > 0 Then    ReDim Waypoint(tempLong)  Else    ReDim Waypoint(0 To 0)  End If  For i = 1 To UBound(Waypoint)    Waypoint(i) = getWaypoint(FN)  Next i  Close #FNEnd Sub
<?php// create the object to help us read from the PMS data$pmshandle = new PMSHandle('someMap.pms');// read the first 3 bytes (byte 0, 1, and 2) of the file into $first3bytes$first3bytes = $pmshandle->read(3);// read the second and third bytes (1 and 2) into the $twobytes$twobytes = $pmshandle->back(2);?>
Here's also a link to EditPro, which is mapmaker coded in VB6, you can download the source too: http://koti.mbnet.fi/meitzi/EditPro/Though im not sure if it's made for the new map format, it seems to be a few years old.
If I have some time, I'll try to write a code snippet for PHP that shows a good way to work through the file using offsets.What I would probably do is this:Write a small class that is created with a filename as its only argument. The class would then have a few methods to move forwards (and backwards, just so that you can re-read stuff) through the file by specifying offsets. Example:Code: [Select]<?php// create the object to help us read from the PMS data$pmshandle = new PMSHandle('someMap.pms');// read the first 3 bytes (byte 0, 1, and 2) of the file into $first3bytes$first3bytes = $pmshandle->read(3);// read the second and third bytes (1 and 2) into the $twobytes$twobytes = $pmshandle->back(2);?>I would have the class object keep track of where it is in the file, and use whatever php functions are available read and move the specified offset in either direction, returning the data stored between the current position and that offset.Now that I think of it, just $pmshandle->read() would be enough if it was made in such a way that it could handle negative offsets, but it couldn't hurt to have a separate method just for added clarity.Yes something like this is small and stupidly simple, but it is small things like this that helped me make my PHP ASE parser so efficient and easy to code. If someone is going to be doing this in PHP, it'd probably help to create a tiny-ass wrapper like this just to make it much easier to do.
<?php    $filehandle = fopen($filename, "rb");    $polygonoffset = 92;    fseek($filehandle, 88);    fseek($filehandle, (((int)fread($filehandle, 4)) * 79) + 4, SEEK_CUR); //skip polygon data and pixel size of sectors    $sectoroffset = ftell($filehandle) + 4;    $numsectors = (int)fread($filehandle, 4)    for ($i = -$numsectors; $i <= $numsectors; $i++) {      for ($j = -$numsectors; $j <= $numsectors; $j++) {        //$polysinsector = (int)fread($filehandle, 2);        //for ($k = 0; $k < $polysinsector; $k++) {        //  $polyindex = (int)fread($filehandle, 2);        //}        fseek($filehandle, ((int)fread($filehandle, 2)) * 2, SEEK_CUR); //skips over sector data      }    }    $propoffset = ftell($filehandle) + 4;    fseek($filehandle, (((int)fread($filehandle, 4)) * 44), SEEK_CUR); //skip over prop data    $sceneryoffset = ftell($filehandle) + 4;    fseek($filehandle, (((int)fread($filehandle, 4)) * 55), SEEK_CUR); //skip over scenery data    $collideroffset = ftell($filehandle) + 4;    fseek($filehandle, (((int)fread($filehandle, 4)) * 16), SEEK_CUR); //skip over collider data    $spawnpointoffset = ftell($filehandle) + 4;    fseek($filehandle, (((int)fread($filehandle, 4)) * 16), SEEK_CUR); //skip over spawnpoint data    $waypointoffset = ftell($filehandle) + 4;    //waypoint data is last section, don't need to skip it