Convert pictures of a Turbo Pascal program ported to ptcGraph lazarus / 39-Graphics ---------------------------------------------------------------------- Roland57 · 2021-05-08 07:42 Hello! I am trying to port to ptcGraph a Turbo Pascal game, a Pacman clone (by George M. Tzoumas) that I found here. My code compiles and runs, but the screen is black. I think that pictures need to be converted. I wrote a little program to convert one picture, but the result is bad. Could you help me to find what I am doing wrong? Regards. Roland ---------------------------------------------------------------------- retronick · 2021-05-15 18:19 Hi Roland, That looks like an interesting version of ms pac man. I would like to see you port it to freepascal/lazarus.  Turbo Pascal 16 color modes store bitmaps in a planar mode. Just like EGA\VGA hardware specs describe. Also Turbo Pascal and Turbo C remap the plane/color order to make it even more confusing. Freepascal stores the bitmaps for putimage slightly different.  I have modified the advance unit to do an on the fly conversion when you BLoad the image. This way you don't need to convert every single image. You can if you like - just bsave the new converted image. Code: [Select]unit Advanced; { Advanced Routines Unit, Version 1.0, Copyright 1996 by George M. Tzoumas } interface procedure BSave(FN: String; P: Pointer; Length: Word); procedure BLoad(FN: String; var P: Pointer); implementation const   MaxWidth = 2047; type    BLine       = Array [0..MaxWidth]  of Byte;    WLine       = Array [0..MaxWidth]  of Word;  TPImgRec = Record             width,height : word;             Buf : array[0..10000] of byte;           end;  FPImgRec = Record             width,height,reserved : longint;             Buf : array[0..10000] of word;           end; var   BorlandColorMap : array[0..15] of Word = (0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15); Function BitOn(Position,Testbyte : Byte) : Boolean; Var   Bt : Byte; Begin   Bt :=$01;   Bt :=Bt Shl Position;   Biton :=(Bt And Testbyte) > 0; End; Function BytesPerRow(width : word) : Word; begin  BytesPerRow :=(width+7) div 8; end; Procedure mpTOsp(Var mPlane : bLine;Var splane : wLine;BPR : Word); Var  i,j    : Word;  xpos : Word;  Col  : Word;  ImgOff2,ImgOff3,ImgOff4 : Word; begin  ImgOff2:=BPR;  ImgOff3:=BPR*2;  ImgOff4:=BPR*3;  xpos:=0;  FillChar(splane,SizeOf(sPlane),0);  For i:=0 to ImgOff2-1 do  begin    For j:=7 downto 0 do    begin      Col:=0;      if biton(j,mPlane[i]) then      begin        Inc(Col,1);      end;      if biton(j,mPlane[i+ImgOff2]) then      begin        Inc(Col,2);      end;      if biton(j,mPlane[i+ImgOff3]) then      begin        Inc(Col,4);      end;      if biton(j,mPlane[i+ImgOff4]) then      begin        Inc(Col,8);      end; //     Splane[xpos]:=Col;      Splane[xpos]:=BorlandColorMap[Col];      Inc(xpos);    end;  end; end; procedure BSave(FN: String; P: Pointer; Length: Word); var   F: File; begin   Assign(F, FN);   Rewrite(F, Length);   BlockWrite(F, P^, 1);   Close(F); end; Procedure TPImageToFPImage(var P : Pointer;PSize : LongInt); var  FPImgPtr : ^FPImgRec;  TPImgPtr : ^TPImgRec;  bbuf     : bline;  wbuf     : wline;  pos,pos2      : word;  width,height : word;  BPR : word;  NP : Pointer;  NPSize : longint;  i,j : word; begin  TPImgPtr:=P;  width:=TPImgPtr^.width+1;  height:=TPImgPtr^.height+1;  BPR:=BytesPerRow(width);  NPSize:=12+ (BPR*4*2)*height;  GetMem(NP, NPSize);  FPImgPtr:=NP;  FPImgPtr^.width:=width;  FPImgPtr^.height:=height;  FPImgPtr^.reserved:=0;  pos:=0;  pos2:=0;  For i:=1 to height do  begin    Move(TPImgPtr^.Buf[pos],bbuf,BPR*4);    mpTosp(bbuf,wbuf,BPR);    Move(wbuf,FPImgPtr^.Buf[pos2],width*2);    inc(pos,BPR*4);    inc(pos2,width);  end;  FreeMem(P,PSize);  P:=NP;  end; procedure BLoad(FN: String; var P: Pointer); var   F: File;   FSize : LongInt; begin   Assign(F, FN);   Reset(F, 1);   FSize:= FileSize(F);   GetMem(P, FSize );   BlockRead(F, P^, FSize);   Close(F);   TPImageToFPImage(P,FSize); end; end. ---------------------------------------------------------------------- lucamar · 2021-05-15 18:45 For gods sake, please use code tags or learn to share larger pieces of code! ---------------------------------------------------------------------- Roland57 · 2021-05-15 19:16 @retronick Thank you for your message and for your adaptation of the Advanced unit. I had to modify this line to compile the code. I don't know if my modification has sense. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i      if biton(j,mPlane[i]) then // <--- After that the program can be compiled but here, it crashes. QuoteLoading ...An unhandled exception occurred at $0000000000422608: EAccessViolation: Access violation $0000000000422608 $0000000000474991  BLOAD,  line 155 of advanced.pas Did you manage, on your side, to run the program? ASAP I will try to use your code for the little test program, which is made for displaying a single (strawberry) image. Regards. Roland ---------------------------------------------------------------------- retronick · 2021-05-15 19:38 I think it got mangled - I have attached a zip version. I was also calculating the memory size wrong. I was able to compile the original TP code to the point where it was displaying the pacman and ghost properly but the maze was messed up. Try it with just a small test program to see if this code works better. ---------------------------------------------------------------------- Roland57 · 2021-05-16 13:43 Quote from: retronick on May 15, 2021, 09:38:21 pmI was able to compile the original TP code to the point where it was displaying the pacman and ghost properly but the maze was messed up. Same thing for me with your latest code, integrated in the ptcGraph project. The pictures are correctly loaded. Thank you very much for your help. Now I will try to find why the maze is messed up. I will come back to this discussion as soon as I find something. ---------------------------------------------------------------------- retronick · 2021-05-16 22:12 that's great I am glad I could help. If you ever finish this let me know i would like to see the final version. ---------------------------------------------------------------------- Roland57 · 2021-05-17 11:25 Fixed loading of maze data. The game works now.  It crashes in the middle of the game when compiled with -dDEBUG. There must be errors somewhere. Help welcome. ---------------------------------------------------------------------- retronick · 2021-05-17 13:58 Wow! I didn't think you would be so quick. Try compiling with ${mode TP} and PACKRECORDS 1 Sometimes this easily make some of my old code just work. ---------------------------------------------------------------------- dseligo · 2021-05-17 16:26 Quote from: Roland57 on May 17, 2021, 01:25:30 pmFixed loading of maze data. The game works now.  Very nice ---------------------------------------------------------------------- Roland57 · 2021-05-18 07:00 Quote from: dseligo on May 17, 2021, 06:26:21 pmVery nice Indeed.  I really do not regret my efforts. It's a very nice little game. The source code is surprisingly short. Congratulations to the author. Quote from: retronick on May 17, 2021, 03:58:17 pmWow! I didn't think you would be so quick. It was easy. The solution was to use the original BLoad procedure for loading the maze data. Thank you for the hints about compilation mode. It seems that the game crashes when the range checking is on. With patience I should be able to find the errors. ---------------------------------------------------------------------- retronick · 2021-05-18 15:07 The issue probably also exists in the original code except no errors are thrown. probably just accessing the contents of one of the arrays limit. you can try increasing the array sizes and see if the error goes away. ---------------------------------------------------------------------- Roland57 · 2021-05-19 05:24 I found the error. It's here: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i // mspacman.pas line 604  Inc(cwf); LogLn(Format({$I %LINE%} + ' cwf = %d', [cwf])); The error happens when cwf = 255. I still have to figure how to fix it. To compile and run the game, you can do this: make make run If you wish to run the game without error: make release make run ---------------------------------------------------------------------- retronick · 2021-05-19 16:34 that variable is declared as a byte. in turbo pascal if var   c  : byte; ... c:=255; inc(255); writeln(c);    <-- will display 0 the variable will be set to 0 in freepascal it will not - it will generate an error so if you want to make your code compatible with turbo pascal you should check if it is 255 and set to 0 - if not inc(cwf) or turn off range checking before you inc {$R-} inc(cwf); {$R+} I think your release compiler options turn off range checking so that's why it works. make sense? ---------------------------------------------------------------------- Roland57 · 2021-05-20 08:50 @retronick Yes, all what you say makes sense. Thank you for your help. So I made this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   if cwf < High(byte) then    Inc(cwf)  else    cwf := 0; but it seems that there still are other errors. But it isn't really an issue, since (as you said) we can simply turn the range checking off. If I have time, I will add some sound effects. ---------------------------------------------------------------------- winni · 2021-05-20 09:10 Hi! The overflow of bytes or words to roll to zero was widely used in Turbo Pascal apps - most of speed reasons. Disabling Range Check did the job. If you did not want this behaviour we had some functions like Range2Byte - the same like math.ensureRange does today. Winni ---------------------------------------------------------------------- Roland57 · 2021-05-20 09:26 @Winni Thanks for the informations. Yes, I understand what you say: there aren't really errors in the program, but it's rather a programming style. Indeed the program works well when range checking is off. Tracking the errors was a way for me to study the program and try to understand how it works. But for now I think I will let it as it is. By the way, I tested the program on Windows (on two different machines). It works, but is very slow. ---------------------------------------------------------------------- retronick · 2021-05-20 15:23 As long as you know it's not really a bug and just the behavior of the compiler i think it's save t o turn off range checking. its just a game and not some kind of medical device. I notice when you reach Act 1 the screen doesn't clear. I never got to act 2 so i don't know what happens there. Anyway good job on porting this! ---------------------------------------------------------------------- retronick · 2021-05-20 19:24 It looks like you commented out all the cleardevice statements in the act procedures when you were debugging. You need to uncomment them for the act scenes to look right. ---------------------------------------------------------------------- Roland57 · 2021-05-21 05:57 Quote from: retronick on May 20, 2021, 09:24:08 pmIt looks like you commented out all the cleardevice statements in the act procedures when you were debugging. You need to uncomment them for the act scenes to look right. Indeed. And also here, in the main program: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     ClearDevice;    CurLevel^.Draw; Quote from: retronick on May 20, 2021, 05:23:34 pmAnyway good job on porting this! Thank you. You did the most difficult. For my part, I did not do much. ---------------------------------------------------------------------- Roland57 · 2021-05-21 06:18 So, here is the current version of the project. Later I will create a git repository. I have not really tested the level editor. It is on my to-do list. I wonder what are the keys for cheating. Here are the values:  #251 : score up by 1000 pts  #252 : bonus pacman (life)  #253 : eat a power pill  #254 : toggle visible/invisible mode  #255 : skip level What are the keys for those values? ---------------------------------------------------------------------- retronick · 2021-05-21 17:08 if you have a numeric keypad on your computer hold down the Alt key and type the number on the numeric key pad. i believe same values as ascii / chr(number) ---------------------------------------------------------------------- Roland57 · 2022-08-01 13:16 Hello! With the holidays I came back to this project. I could fix range check errors and all memory leaks.  So I decided to create a repository on GitLab: Ghost Invasion The next step would be to add music and sound effects. ---------------------------------------------------------------------- Fred vS · 2022-08-01 15:43 Quote from: Roland57 on August 01, 2022, 03:16:06 pmSo I decided to create a repository on GitLab: Ghost Invasion WoW, superbe and out-of-the-box. Fre;D ---------------------------------------------------------------------- Handoko · 2022-08-01 15:47 Thank you for sharing it. But I can't compile it using Lazarus GTK2, Ubuntu Mate 22.04. ---------------------------------------------------------------------- Fred vS · 2022-08-01 15:53 Quote from: Handoko on August 01, 2022, 05:47:09 pmThank you for sharing it. But I can't compile it using Lazarus GTK2, Ubuntu Mate 22.04. Hello. It was the same here with Debian 11. The fixes: First: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i sudo apt- get install libxxf86dga1 And then: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i sudo ln -s /usr/lib/x86_64-linux-gnu/libXxf86dga.so.1 /usr/lib/x86_64-linux- gnu/libXxf86dga.so Fre;D ---------------------------------------------------------------------- Handoko · 2022-08-01 15:55 Thank you for the reply. Maybe that should be documented on the project readme.txt. ---------------------------------------------------------------------- Roland57 · 2022-08-01 17:50 Thanks for your feedback guys. @Fred Thank you for the solution. Link added in this discussion.