Post Reply 
Xmas Spirit?
12-22-2023, 09:26 PM
Post: #1
Xmas Spirit?
I'm not sure how much Xmas spirit is shared in this group.

Here is a little program, that starts to draw a scene from this time of year.

Please feel free to add something:

Code:
EXPORT Ctree()
  BEGIN 
DIMGROB_P(G1,320,240,1);
DIMGROB_P(G2,320,240,1);
DIMGROB_P(G3,320,240,1);
DIMGROB_P(G4,320,240,RGB(255,0,0));
DIMGROB_P(G5,320,240,RGB(255,0,0));
DIMGROB_P(G6,320,240,RGB(255,0,0));
LOCAL BAUBS:=0;
LOCAL BX:={};
LOCAL BY:={};
LOCAL X:=0;
LOCAL ox:=-18;  //  X-AXIS OFFSET OF TREE
LOCAL Y:=0;
LOCAL COL:=0;
LOCAL R:=0;
LOCAL G:=0;
LOCAL B:=0;
LOCAL A:=0;
LOCAL FR:=0;
LOCAL FG:=0;
LOCAL FB:=0;
LOCAL GO:=0;
RECT_P(G0,0,0,320,240,0);   //   BACKGROUND CLEAR
LINE_P(G0,200,160,140,240,RGB(180,60,0));  //   FIREPLACE LINE L
LINE_P(G0,290,160,320,210,RGB(180,60,0));  //  FIREPLACE LINE R
TRIANGLE_P(120+ox,50,95+ox,92,145+ox,92,RGB(0,255,0));     //  TREE TOP
TRIANGLE_P(120+ox,60,80+ox,130,160+ox,130,RGB(0,255,0));   //  TREE 2
TRIANGLE_P(120+ox,90,70+ox,170,170+ox,170,RGB(0,255,0));   //  TREE 3
TRIANGLE_P(120+ox,130,60+ox,200,180+ox,200,RGB(0,255,0));  //  TREE BOTTOM
RECT_P(G0,110+ox,201,130+ox,225,RGB(150,40,10)); //  TREE TRUNK
RECT_P(G0,200,80,290,160,RGB(255,0,0)); //   FIRE-CENTRE
REPEAT
X:=RANDINT(290,200);
Y:=RANDINT(200,120);
A:=X-245;
B:=Y-160;
IF SQRT(A^2+B^2)<34 AND Y<160 THEN
ARC_P(G5,X,Y,2,0,2*π,{0,0});         //  COALS
T:=T+1;
END;
UNTIL T=250;
BLIT_P(G4,G5,RGB(255,0,0));
BLIT_P(G0,G5,RGB(255,0,0));
BLIT_P(G1,G0);
BLIT_P(G2,G0);

REPEAT
X:=RANDINT(50+ox,165+ox);
Y:=RANDINT(30,220);
GO:=1;

IF BAUBS>0 THEN
FOR T FROM 0 TO BAUBS DO
A:=X-BX(T);
B:=Y-BY(T);
IF SQRT(A^2+B^2)<14 THEN
GO:=0;
END;
END;
END;

IF BAUBS=0 THEN
GO:=1;
END;

IF GO=1 AND GETPIX_P(X,Y)=RGB(0,255,0) THEN
BAUBS:=BAUBS+1;
BX(BAUBS):=X;
BY(BAUBS):=Y;
ARC_P(BX(BAUBS),BY(BAUBS),5,0,2*π,{0,0});
//WAIT(0.3);
END;
UNTIL BAUBS=32;

BLIT(G1,G2);

REPEAT
RECT_P(G6,RGB(RANDINT(70,35),RANDINT(35,1),0));     //   FIRE-SHINE
BLIT_P(G6,G5,RGB(255,0,0));
FOR X FROM 0 to BAUBS-1 DO
R:=RANDINT(255,0);
G:=RANDINT(255,0);
B:=RANDINT(255,0);
FR:=RANDINT(255,200);
FG:=RANDINT(200,0);
FB:=RANDINT(20,0);
ARC_P(G1,BX(X),BY(X),5,0,2*π,{RGB(R,G,B),RGB(R,G,B)});
RECT_P(G1,200,80,290,160,RGB(FR,FG,FB));
END;
WAIT(0.08);
BLIT_P(G1,G5,RGB(255,0,0));
BLIT_P(G6,G1,0);
BLIT_P(G0,G6);

UNTIL ISKEYDOWN(4)=1;

END;

And share again so the next person can add something.
Find all posts by this user
Quote this message in a reply
12-23-2023, 06:37 AM
Post: #2
RE: Xmas Spirit?
Thanks a lot Matalog, I'm not so good to add something to the code but I wish an happy Cristmas to you and your family!! Same for all group readers.
Jean-Guy, F6BGU, from France!
Find all posts by this user
Quote this message in a reply
12-24-2023, 03:38 PM
Post: #3
RE: Xmas Spirit?
Just my 2 cents.

Code:
CONST width=12, height=10;
LOCAL buffer:=MAKEMAT(0, height, width);

EXPORT Ctree()
BEGIN 
DIMGROB_P(G1,320,240,1);
DIMGROB_P(G2,320,240,1);
DIMGROB_P(G3,320,240,1);
DIMGROB_P(G4,320,240,RGB(255,0,0));
DIMGROB_P(G5,320,240,RGB(255,0,0));
DIMGROB_P(G6,320,240,RGB(255,0,0));
DIMGROB_P(G7,width,height,0);
LOCAL BAUBS:=0;
LOCAL BX:={};
LOCAL BY:={};
LOCAL X:=0;
LOCAL ox:=-18;  //  X-AXIS OFFSET OF TREE
LOCAL Y:=0;
LOCAL COL:=0;
LOCAL R:=0;
LOCAL G:=0;
LOCAL B:=0;
LOCAL A:=0;
LOCAL FR:=0;
LOCAL FG:=0;
LOCAL FB:=0;
LOCAL GO:=0;

HAngle:=0;
RECT_P(0);   //   BACKGROUND CLEAR
LINE_P(200,160,140,240,RGB(180,60,0));  //   FIREPLACE LINE L
LINE_P(290,160,320,210,RGB(180,60,0));  //  FIREPLACE LINE R
TRIANGLE_P(120+ox,50,95+ox,92,145+ox,92,RGB(0,255,0));     //  TREE TOP
TRIANGLE_P(120+ox,60,80+ox,130,160+ox,130,RGB(0,255,0));   //  TREE 2
TRIANGLE_P(120+ox,90,70+ox,170,170+ox,170,RGB(0,255,0));   //  TREE 3
TRIANGLE_P(120+ox,130,60+ox,200,180+ox,200,RGB(0,255,0));  //  TREE BOTTOM
RECT_P(110+ox,201,130+ox,225,RGB(150,40,10)); //  TREE TRUNK
RECT_P(200,80,290,160,RGB(255,0,0)); //   FIRE-CENTRE
REPEAT
X:=RANDINT(290,200);
Y:=RANDINT(200,120);
A:=X-245;
B:=Y-160;
IF SQRT(A^2+B^2)<34 AND Y<160 THEN
ARC_P(G5,X,Y,2,0,2*π,{0,0});         //  COALS
T:=T+1;
END;
UNTIL T=250;
BLIT_P(G4,G5,RGB(255,0,0));
BLIT_P(G5,RGB(255,0,0));
BLIT_P(G1,G0);
BLIT_P(G2,G0);

REPEAT
X:=RANDINT(50+ox,165+ox);
Y:=RANDINT(30,220);
GO:=1;

IF BAUBS>0 THEN
FOR T FROM 0 TO BAUBS DO
A:=X-BX(T);
B:=Y-BY(T);
IF SQRT(A^2+B^2)<14 THEN
GO:=0;
END;
END;
END;

IF BAUBS=0 THEN
GO:=1;
END;

IF GO=1 AND GETPIX_P(X,Y)=RGB(0,255,0) THEN
BAUBS:=BAUBS+1;
BX(BAUBS):=X;
BY(BAUBS):=Y;
ARC_P(BX(BAUBS),BY(BAUBS),5,0,2*π,{0,0});
//WAIT(0.3);
END;
UNTIL BAUBS=32;

BLIT(G1,G2);

REPEAT
RECT_P(G6,RGB(RANDINT(70,35),RANDINT(35,1),0));     //   FIRE-SHINE
BLIT_P(G6,G5,RGB(255,0,0));
FOR X FROM 0 to BAUBS-1 DO
R:=RANDINT(255,0);
G:=RANDINT(255,0);
B:=RANDINT(255,0);
FR:=RANDINT(255,200);
FG:=RANDINT(200,0);
FB:=RANDINT(20,0);
ARC_P(G1,BX(X),BY(X),5,0,2*π,{RGB(R,G,B),RGB(R,G,B)});
RECT_P(G1,200,80,290,160,RGB(FR,FG,FB));
END;
IF VERSION(2)>="D" THEN
  WAIT(0.08);
END;
BLIT_P(G1,G5,RGB(255,0,0));
BLIT_P(G6,G1,0);
FIRE();
BLIT_P(G6);

UNTIL ISKEYDOWN(4)=1;

END;

FIRE()
BEGIN
 LOCAL intensity;
 LOCAL x,y;
  FOR x FROM 1 TO width DO
   buffer(height, x) := RANDINT(0, 255);
  END;
  FOR y FROM 1 TO height-1 DO
   FOR x FROM 1 TO width DO
    intensity := (buffer(y+1, x) 
                  + buffer(y+1, IFTE(x==1, width, x-1))
                  + buffer(y+1, IFTE(x==width, 1, x+1))
                  + buffer(IFTE(y+2 > height, y+1, y+2), x)) / 4;
    intensity := MAX(0, intensity - RANDINT(0, 20));
    buffer(y, x) := intensity;
   END;
  END;  
  FOR y FROM 1 TO height DO
   FOR x FROM 1 TO width DO
    intensity := buffer(y, x);
    IF intensity > 180 THEN
     PIXON_P(G7,x, y, RGB(255, 255, intensity));
    ELSE
     IF intensity > 80 THEN
      PIXON_P(G7,x, y, RGB(255, intensity, 0));
     ELSE
      PIXON_P(G7,x, y, RGB(intensity, 0, 0));
     END;
    END;
   END;
  END;
 BLIT_P(G6,210,90,280,152,G7,1,1,width,height,0,223);    
END;

Merry Christmas
Piotr
Find all posts by this user
Quote this message in a reply
12-24-2023, 10:28 PM
Post: #4
RE: Xmas Spirit?
(12-24-2023 03:38 PM)komame Wrote:  Just my 2 cents.



Merry Christmas
Piotr

Wow, that's a nice fire :-).

Did you experiment with making the fire pixels smaller, does it affect the overall speed of the program too much?

Nice work, and Happy Christmas :-).
Find all posts by this user
Quote this message in a reply
12-25-2023, 07:51 AM (This post was last modified: 12-25-2023 10:08 AM by komame.)
Post: #5
RE: Xmas Spirit?
(12-24-2023 10:28 PM)matalog Wrote:  Wow, that's a nice fire :-).

Thanks :-)

(12-24-2023 10:28 PM)matalog Wrote:  Did you experiment with making the fire pixels smaller, does it affect the overall speed of the program too much?

Yes, I experimented with increased resolution, but I encountered performance issues even on the G2 (not to mention the G1, where it was a disaster). Later, I noticed an error in your program that significantly affected performance, and after correcting it, I managed to more than double the number of pixels for the fire effect (exactly 240%) while maintaining the same FPS. Your mistake was that in the loop where you draw "baubs", you were also drawing the fireplace, so it was being drawn as many times as there were "baubs". It was a considerable waste of time in each frame of the animation. After correcting this, I achieved better performance in generating the fire. Not only did I increase the resolution, but I also improved the realism of the fire. Unfortunately, on the G1, I was unable to achieve much better effects, and it is necessary to stick with a resolution of 12x10 to keep the animation smooth. The program after my revisions is below (for G2), but before you paste it into Connectivity Kit, please read the "EDIT" comment at the bottom of the post.

Code:
CONST width=18, height=15;
LOCAL buffer:=MAKEMAT(0, height, width);

EXPORT Ctree()
BEGIN 
 DIMGROB_P(G1,320,240,1);
 DIMGROB_P(G2,320,240,1);
 DIMGROB_P(G3,320,240,1);
 DIMGROB_P(G4,320,240,RGB(255,0,0));
 DIMGROB_P(G5,320,240,RGB(255,0,0));
 DIMGROB_P(G6,320,240,RGB(255,0,0));
 DIMGROB_P(G7,width,height,0);
 LOCAL BAUBS;
 LOCAL BX={},BY={};
 LOCAL X,Y;
 LOCAL ox=-18;  //  X-AXIS OFFSET OF TREE
 LOCAL COL;
 LOCAL GO;
 LOCAL T;

 HAngle:=0;
 RECT_P(0);   //   BACKGROUND CLEAR
 LINE_P(200,160,140,240,RGB(180,60,0));  //   FIREPLACE LINE L
 LINE_P(290,160,320,210,RGB(180,60,0));  //  FIREPLACE LINE R
 TRIANGLE_P(120+ox,50,95+ox,92,145+ox,92,RGB(0,255,0));     //  TREE TOP
 TRIANGLE_P(120+ox,60,80+ox,130,160+ox,130,RGB(0,255,0));   //  TREE 2
 TRIANGLE_P(120+ox,90,70+ox,170,170+ox,170,RGB(0,255,0));   //  TREE 3
 TRIANGLE_P(120+ox,130,60+ox,200,180+ox,200,RGB(0,255,0));  //  TREE BOTTOM
 RECT_P(110+ox,201,130+ox,225,RGB(150,40,10)); //  TREE TRUNK
 RECT_P(200,80,290,160,RGB(255,0,0)); //   FIRE-CENTRE
 REPEAT
  X:=RANDINT(290,200);
  Y:=RANDINT(200,130);
  A:=X-245;
  B:=Y-160;
  IF SQRT(A^2+B^2)<34 AND Y<150 THEN
   ARC_P(G5,X,Y,2,0,2*π,{0,0});         //  COALS
   T:=T+1;
  END;
 UNTIL T=200;
 BLIT_P(G4,G5,RGB(255,0,0));
 BLIT_P(G5,RGB(255,0,0));
 BLIT_P(G1,G0);
 BLIT_P(G2,G0);

 REPEAT
  X:=RANDINT(50+ox,165+ox);
  Y:=RANDINT(30,220);
  GO:=1;

  IF BAUBS>0 THEN
   FOR T FROM 0 TO BAUBS DO
   A:=X-BX(T);
   B:=Y-BY(T);
   IF SQRT(A^2+B^2)<14 THEN
    GO:=0;
   END;
  END;
 END;

 IF BAUBS=0 THEN
  GO:=1;
 END;

 IF GO=1 AND GETPIX_P(X,Y)=RGB(0,255,0) THEN
  BAUBS:=BAUBS+1;
  BX(BAUBS):=X;
  BY(BAUBS):=Y;
  ARC_P(BX(BAUBS),BY(BAUBS),5,0,2*π,{0,0});
  //WAIT(0.3);
  END;
 UNTIL BAUBS=32;

 BLIT(G1,G2);

 T:=TICKS;
 REPEAT
  WHILE TICKS<T DO
  END;
  T:=T+80;
  RECT_P(G6,RGB(RANDINT(70,35),RANDINT(35,1),0));     //   FIRE-SHINE
  BLIT_P(G6,G5,RGB(255,0,0));
  FOR X FROM 0 to BAUBS-1 DO
   COL:=RGB(RANDINT(255,0),RANDINT(255,0),RANDINT(255,0));
   ARC_P(G1,BX(X),BY(X),5,0,2*π,{COL,COL});
  END;
  RECT_P(G1,200,80,290,160,RGB(RANDINT(200,255),RANDINT(0,200),RANDINT(0,20))​);
  BLIT_P(G1,G5,RGB(255,0,0));
  BLIT_P(G6,G1,0);
  FIRE();
  BLIT_P(G6);
 UNTIL ISKEYDOWN(4)=1;

END;

FIRE()
BEGIN
 LOCAL intensity;
 LOCAL x,y;
 buffer := REPLACE(buffer,{height,1},RANDMAT(1,width,255));
 FOR y FROM 2 TO height DO
  FOR x FROM 1 TO width DO
   intensity := IP((buffer(y, x) 
                 + buffer(y, IFTE(x=1, width, x-1)) 
                 + buffer(y, IFTE(x=width, 1, x+1))
                 + buffer(IFTE(y+1 > height, y, y+1), x)) / 4);
   intensity := MAX(0, intensity - RANDINT(0, 20));
   buffer(y-1, x) := intensity;
   CASE
    IF intensity > 160 THEN
     PIXON_P(G7,x, y, RGB(255, 255, intensity));
    END;
    IF intensity > 84 THEN
     PIXON_P(G7,x, y, RGB(255, intensity, 0));
    END;
    PIXON_P(G7,x, y, RGB(intensity*3, 20, 0));
   END;
  END;
 END;  
 BLIT_P(G6,210,90,280,152,G7,1,2,width,height,#FFFFFF,223);
END;

It looks quite nice, doesn't it?

I think that the performance can still be slightly improved because currently in your code, the function ARC_P (which is rather slow) is called 32 times in each iteration and it could be replaced with BLIT_P by referring to the buffered images that were drawn during the program initialization. This should provide an additional 15-20% gain in performance. Unfortunately, the biggest problem is that in calculations on matrices and lists, where you have to iterate over elements, PPL is very weak, and even such a small matrix as 12x10 calculated several times per second eats up all the power of this device. For such tasks, even much slower devices perform much better. This is a very annoying flaw of PPL. In Python, it looks much better. I can try to rewrite this fire effect-generating function in Python and call it from PPL. Then it will be possible to achieve an even better effect.

EDIT: When you paste this program into Connectivity Kit, there's a strange issue because Prime reports a syntax error on line 87:
RECT_P(G1,200,80,290,160,RGB(RANDINT(200,255),RANDINT(0,200),RANDINT(0,20))​);
You can see that after pasting, an additional space (blank character) appears before the last parenthesis on the Prime. This is probably a copy-paste bug in Connectivity Kit. To get the program to compile, you need to remove that space directly on the Prime. I've pasted this program many times into this post, but this error always occurs after copying it into Connectivity Kit, so remember to delete that blank character.

Best wishes,
Piotr
Find all posts by this user
Quote this message in a reply
12-25-2023, 03:13 PM
Post: #6
RE: Xmas Spirit?
That's brilliant.

I wasn't worrying about performance in my program, as you saw, I was even slowing it down with WAIT()

I think there is a lot of room for improvement still. Your fire now looks so real, that it makes the rest of the scen look terrible! Haha.

What do you call the technique you are using to simulate the fire, or if it is something you created from your own imagination, how would you describe it in words?
Find all posts by this user
Quote this message in a reply
12-26-2023, 07:39 AM (This post was last modified: 12-26-2023 07:58 AM by komame.)
Post: #7
RE: Xmas Spirit?
(12-25-2023 03:13 PM)matalog Wrote:  That's brilliant.
Thanks

(12-25-2023 03:13 PM)matalog Wrote:  I wasn't worrying about performance in my program, as you saw, I was even slowing it down with WAIT()
I also use a slowdown, but I do it using a timer (ticks), which gives better results than WAIT, because WAIT does not take into account the drawing time, which can vary in individual frames of animation, causing them to appear at different intervals. By using a timer, you ensure that regardless of the drawing time, the next frame will always start at the same time after the previous one, and thus you also don't need to worry about the hardware speed on which the program is run. For instance, on the real Prime and on the emulator, it will operate at exactly the same speed, which is impossible with WAIT (this is especially noticeable when the calculation time is quite long and the emulator performs them much faster than the real Prime).
In the case of this program, the variable T is responsible for the time after which the next frame should appear, and it is currently set to 80ms, and with each frame, it is increased by another 80ms (T:=T+80). This guarantees the same smoothness of the animation, of course, provided that the computation time is not longer than the time allocated for a single frame.

(12-25-2023 03:13 PM)matalog Wrote:  [...] Your fire now looks so real [...]
Yes, but unfortunately, the resolution is still very low. 18x15 pixels is a comically small size. It would be ideal to generate a fire effect that covers the entire fireplace in a 1:1 pixel ratio. To achieve this, an image would need to be generated over an area of 70x60 pixels, which means that there are 4200 pixels to calculate (which is over 15 times more than so far). With such poor performance of PPL, this is unrealistic.

At the moment, I've made a few more optimizations (attached) that have saved a few additional milliseconds, but that doesn't change much in this sea of needs. I'll try to rewrite it in Python over the weekend, and perhaps then it will be possible to at least reach a size of 36x30, which should significantly improve the quality.

(12-25-2023 03:13 PM)matalog Wrote:  What do you call the technique you are using to simulate the fire, or if it is something you created from your own imagination, how would you describe it in words?
Well, I don't know what to call it, but it's a very simple algorithm. It's certainly safe to say that it works similarly to a cellular automaton (like Conway's Game of Life). Iterating over each pixel for the new frame, the algorithm calculates an average from the neighboring pixels of the previous frame with a slight attenuation, which causes the brightness of the fire to smoothly diminish as it propagates upward.


Attached File(s)
.zip  XMAS.zip (Size: 1.67 KB / Downloads: 18)

Piotr Kowalewski
Find all posts by this user
Quote this message in a reply
12-30-2023, 04:04 PM
Post: #8
RE: Xmas Spirit? (fire effect)
Hi matalog,

I've rewritten the program in Python (just the part that generates the fire effect). I am impressed by how much faster Python is. I was able to achieve a much better effect, and it effortlessly handled the 60x45 resolution (and it seems that even more is possible, but I need to experiment). In the first line of the program, there is a 'full_screen' variable. When it's set to 'False', the fire effect is very smooth in the screen center; when it's set to 'True', the fire effect is displayed across the entire screen, but of course, the pixels are then larger.
All in all, it looks very cool.

Cheers,
Piotr


Attached File(s)
.zip  FIRE_EFFECT.zip (Size: 999 bytes / Downloads: 12)
Find all posts by this user
Quote this message in a reply
12-31-2023, 10:59 AM (This post was last modified: 12-31-2023 12:34 PM by komame.)
Post: #9
RE: Xmas Spirit?
Christmas is long past, so it's time to end this thread Wink
I've managed to introduce additional optimizations, and the currently generated fire effect has a size of 80x60 pixels while maintaining the same animation speed. I've adjusted the color palette slightly to make the fire more yellow at the base. Additionally, you can change the "width" and "height" parameters to experiment (for G1 users?). No matter the values entered, the image will always be displayed in the center of the screen. If you set the "full_screen" parameter to "True", remember to keep the "width" to "height" ratio at 4:3, otherwise the fire will be distorted.

Cheers,
Piotr


Attached File(s)
.zip  FIRE_EFFECT_V2.zip (Size: 1,012 bytes / Downloads: 10)
Find all posts by this user
Quote this message in a reply
01-02-2024, 05:46 AM (This post was last modified: 01-02-2024 05:47 AM by tjurij.)
Post: #10
RE: Xmas Spirit?
(12-31-2023 10:59 AM)komame Wrote:  Christmas is long past, so it's time to end this thread Wink
I've managed to introduce additional optimizations, and the currently generated fire effect has a size of 80x60 pixels while maintaining the same animation speed. I've adjusted the color palette slightly to make the fire more yellow at the base. Additionally, you can change the "width" and "height" parameters to experiment (for G1 users?). No matter the values entered, the image will always be displayed in the center of the screen. If you set the "full_screen" parameter to "True", remember to keep the "width" to "height" ratio at 4:3, otherwise the fire will be distorted.

Cheers,
Piotr

Can you put the Python version here?
Happy new year!
Find all posts by this user
Quote this message in a reply
01-02-2024, 06:39 AM (This post was last modified: 01-02-2024 06:44 AM by komame.)
Post: #11
RE: Xmas Spirit?
(01-02-2024 05:46 AM)tjurij Wrote:  Can you put the Python version here?
Happy new year!

In my last three posts, there are downloadable attachments (ZIP files). I see the download counters, so it seems that other people have already downloaded these attachments.
If you have any problem downloading these files, let me know.
Find all posts by this user
Quote this message in a reply
01-03-2024, 12:16 AM (This post was last modified: 01-03-2024 12:19 AM by StephenG1CMZ.)
Post: #12
RE: Xmas Spirit?
The zip files include a .hpprgm, which I guess works well with a PC and a connectivity kit.
On a Chromebook, python text that can be cut-and-pasted would be more readable (the Chromebook and modern Androids do not have hpprime apps that can read .hpprgm - Or do I just need to change the extension to .html?).
When I can read it I can discover whether the graphics in that Python are portable...
Hopefully by next Xmas there will be a new HP Prime App that can read .hpprgm
Happy New Year to you all

Stephen Lewkowicz (G1CMZ)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 1 Guest(s)