Jump to content
IGNORED

MAME and Geneve emulation issue with Video mode


9640News

Recommended Posts

Michael,

 

I tracked down the issue and I am attaching a diskette image to you. I can reproduce the error within 6 lines of code, and fix it with another 3 lines of code. If I had my suspicion, it is a timing issue likely in the 9938 code.

 

Setting graphics mode 7 via the geneve XOP's and immediately setting to Text mode 2 (80 columns) with another XOP, I get a messed up screen. When I am dumped back to the CLI, I can do a MODE 80 and the screen is restored. I searched mode 80 code looking for hints, and saw nothing that should have been an issue.

​I then did two back to back Text Mode 2 calls in code with the XOP's, and the problem disappeared. It looks like the 9938 has not completed processing everything in Graphics Mode 7 and then the call to Text Mode probably interrupts that call. That is my 2 cents since I am not that familiar with the 9938 code. However, a second call and everything is then setup properly in the registers.

 

The file TEST-S is my code, and I have a couple of other files from the Geneve VID XOP.

 

Hope this helps.

 

Beery

 

DSDD.DSK

post-62580-0-27703900-1514152133.png

Link to comment
Share on other sites

What happens iwhen you add a delay between the mode 7 and mode 2 calls? If this is a timing issue, a delay should resolve the problem.

 

I would also question why a program is calling two video modes in succession, as a secondary curiosity.

 

Tim,

 

I ran that test. Adding a decrementing loop from >FFFF to >0000 between calling graphics mode 7 and then calling text mode 2, it works fine. There is a timing issue with something with the 9938. Whether it is with the 9995 talking to the 9938 in emulation or the 9938 too slow or being interrupted with the next call, that is beyond me to know.

 

The code I had was purely an example of calling text mode twice that fixed the issue. That was not in the stock program, just something I tested to see if it was a timing issue "somewhere".

 

Beery

Link to comment
Share on other sites

I measured the required delay as 12ms (4400 loop iterations). I have to look into the code of the v9938.

 

If you want to have a look for yourself: https://github.com/mamedev/mame/blob/master/src/devices/video/v9938.cpp

 

Unfortunately, I never contributed anything for this chip, so this is largely terra incognita (apart from the comment "MZ:" and the small fix related to it).

Link to comment
Share on other sites

I measured the required delay as 12ms (4400 loop iterations). I have to look into the code of the v9938.

 

If you want to have a look for yourself: https://github.com/mamedev/mame/blob/master/src/devices/video/v9938.cpp

 

Unfortunately, I never contributed anything for this chip, so this is largely terra incognita (apart from the comment "MZ:" and the small fix related to it).

 

Michael,

 

I looked at the file. Other than around line 2001 with notes on parallel processing, I would have no idea where/how timing could be handled. It is over my head!

 

Beery

Link to comment
Share on other sites

OK, I'll check. Maybe it is not so difficult to find as it looks. I notice that the graphics 7 switch takes some perceivable time to complete, which means that the switch is not instantaneous, and so the call must be asynchronous. There is some chance that the new switch breaks the state machine.

Link to comment
Share on other sites

Here is a sequence of log outputs that should show us the actual issue. It starts with the execution of the test program.

 

 

[:vdp] v9938: Write 88 to R#8
[:vdp] v9938: Write a0 to R#1
[:vdp] v9938: mode = GRAPHIC 3
[:vdp] v9938: Write 00 to R#0
[:vdp] v9938: mode = GRAPHIC 1
[:vdp] v9938: Write 0e to R#0
[:vdp] v9938: mode = GRAPHIC 7
[:vdp] v9938: Write a0 to R#1
[:vdp] v9938: Write 80 to R#9
[:vdp] v9938: Write 04 to R#7
[:vdp] v9938: Write a0 to R#1
[:vdp] v9938: Write 1f to R#2
[:vdp] v9938: Write f7 to R#5
[:vdp] v9938: Write 01 to R#11
[:vdp] v9938: Write 1e to R#6
[:vdp] v9938: Write 24 to R#17
[:vdp] v9938: Write 00 to R#36
[:vdp] v9938: Write 00 to R#37
[:vdp] v9938: Write 00 to R#38
[:vdp] v9938: Write 00 to R#39
[:vdp] v9938: Write 00 to R#40
[:vdp] v9938: Write 01 to R#41
[:vdp] v9938: Write d4 to R#42
[:vdp] v9938: Write 00 to R#43
[:vdp] v9938: Write 04 to R#44
[:vdp] v9938: Write 00 to R#45
[:vdp] v9938: Write 80 to R#46
[:vdp] V9938: Opcode 80h  LMMV-SET  (0,0)->(0,0),4 [256,212]
[:vdp] Command started
[:vdp] v9938: Write e0 to R#1
[:vdp] v9938: mode = GRAPHIC 7
[:vdp] v9938: Write e0 to R#1
[:vdp] v9938: Write 88 to R#8
[:vdp] v9938: Write a0 to R#1
[:vdp] v9938: mode = GRAPHIC 7
[:vdp] v9938: Write 00 to R#0
[:vdp] v9938: mode = GRAPHIC 1
[:vdp] v9938: Write 04 to R#0
[:vdp] v9938: mode = GRAPHIC 3
[:vdp] v9938: Write b0 to R#1
[:vdp] v9938: mode = TEXT 2
[:vdp] v9938: Write 00 to R#9
[:vdp] v9938: Write 04 to R#7
[:vdp] v9938: Write b0 to R#1
[:vdp] v9938: Write 03 to R#2
[:vdp] v9938: Write 2f to R#3
[:vdp] v9938: Write 00 to R#10
[:vdp] v9938: Write 02 to R#4
[:vdp] v9938: Write f0 to R#1
[:vdp] v9938: mode = TEXT 2
[:vdp] v9938: Write f0 to R#1
[:vdp] v9938: Write f4 to R#7
[:vdp] LMMV command done

 

[Edit: Changed position of register write logging]

Edited by mizapf
Link to comment
Share on other sites

So, if I understand things from the log file you posted, the LMMV-SET is still processing while other register commands are being sent to the 9938 as well, interfering with the LMMV-SET?

 

Will that be a 9938 issue in it's core requiring a fix, or is that doing something a bit different in the TI and/or Geneve emulation with the 9938 access?

​Beery

Link to comment
Share on other sites

As it seems, the XOP in MDOS not only switches modes but also executes a v9938 command (LMMV) to clear the screen. This takes some time to complete, and if you switch modes in the meantime, the command will continue to plough through the VRAM.

 

I think I should consult the other devs, particular those who wrote the code. The code states that the commands may only be invoked in the higher graphics modes, so you cannot initiate a command within text mode, but they obviously did not abort the command when the switch is done before the command has completed. The question is: What is the real thing doing? If we consider this program on the Geneve, it may be considered a proof that the command is aborted. To make sure, we should probably write a program that fills the VRAM with some byte, switch modes, and check where the overwrite ends. However, if I remember correctly, the video RAM is organized differently between the modes.

 

At least we can now explain the symptoms: Depending on how early we switch modes, the pattern table in text 2 mode is affected or not. The delay of 12 ms that I mentioned above does not suffice to let the command terminate, but it seems to save the patterns.

Link to comment
Share on other sites

I've extracted the routine framework for reference. It starts with VR#8 (which agrees with your trace) by doing some housekeeping and eventually winds up in a routine to set the mode, reset the character table, and clear the screen. There are two routines to clear the screen: one for 'text' mode and one for graphics mode. The latter uses LMMV, as shown above, to clear the screen with a scroll via GRCLR. (Is a scroll faster than writing to the screen? This routine might need to be looked at).

 

VDCMD1 and VDCMD2 are the routines that write the registers for the LMMV command. They both appear to test the status /before/ setting up the registers. I suspect that if you set video mode to graphics 6 then graphics 7 in succession, the VDCMD1/2 routines would pause for completion of the commands before setting and executing the next. However, since Text mode scrolling is not managed via VDCMD1/2, there is no command test, and the setup continues during LMMV execution. It is NOT clear to me why this is a problem for emulation or $$CRASH$$.

 

On a related note it seems strange that MDOS is using a scroll routine to clear the screen during a mode set; there should be better ways to handle this, unless the routines are manipulating the scrollback buffer for the CLI at the same time and/or performing other housekeeping. I did not investigate this any further.

 

 

 

 

X900VC
X900L1  LI      R0,>0888                * mouse must be on! -pc 9/23/89
        BLWP    @VWTR                   * Mode register 8 (MOUSE OFF <- hic)
        MOVB    @VIDREG+1,R0
        ANDI    R0,>E700                * Kill text, & multicolor modes
        ANDI    R0,>BFFF                (SCREEN OFF)
        SRL     R0,8
        ORI     R0,>0100
        BLWP    @VWTR
        MOVB    @VIDREG,R0
        ANDI    R0,>F100                * Kill graphics modes
        SRL     R0,8
        BLWP    @VWTR
        MOV     @2(R13),R1
        LI      R2,5
        MPY     R1,R2
        MOVB    @VIDREG,R0
        SOCB    @X900TB(R3),R0
        SRL     R0,8
        BLWP    @VWTR                   * Mode register 0
        MOVB    @VIDREG+1,R0
        SOCB    @X900TB+1(R3),R0
        SRL     R0,8
        ORI     R0,>0100
        BLWP    @VWTR                   * Mode register 1
        MOVB    @X900TB+2(R3),R0
        SRL     R0,8
        ORI     R0,>0900
        BLWP    @VWTR                   * Mode register 9
        MOV     @2(R13),@VIDMOD
        MOV     @2(R13),@VIDUSR         CP 94/03/02
        MOVB    @X900TB+3(R3),R0
        SRL     R0,8
        MOV     R0,@CHCOLS              * Set number of columns
        MOVB    @X900TB+4(R3),R0
        SRL     R0,8
        MOV     R0,@CHROWS              * Set number of rows
        LI      R1,80
        MPY     R1,R0
        MOV     R1,@SCRADD
        AI      R1,SCRBUF
        MOV     R1,@SCREND
        MOV     @VIDMOD,R3
        SLA     R3,2

File:HDS2.MDOS.L6.VX0003S   Page: 4 Date: 10-30-04  Time: 01:51:50
        MOV     @X900TC(R3),@GXCOLS
        MOV     @X900TC+2(R3),@GXROWS
        MOV     @VIDMOD,R3
        CI      R3,10
        JNE     X900S1
        LI      R3,1
        MOV     R3,@VIDMOD
X900S1  CLR     R1
X900L2  MOV     @CHCOLS,@CURXMX+2(R1)
        MOV     @CHROWS,@CURYMX+2(R1)
        DEC     @CURXMX+2(R1)
        DEC     @CURYMX+2(R1)
        CLR     @CURXMN+2(R1)
        CLR     @CURYMN+2(R1)
        CLR     @CURX+2(R1)
        CLR     @CURY+2(R1)
        INCT    R1
        CI      R1,32*2
        JNE     X900L2
        CLR     R1
        CLR     R2
        LWPI    LOWWP1
        MOV     @CURWS,R13
        BL      @X902VC    **SET CURSOR POSITION
        DATA    >009D
        LI      R0,8
        MOV     R0,@GRPHLF
        MOV     @CHCOLS,R0
        CI      R0,40
        JEQ     X900L4
        LI      R0,16
        MOV     R0,@GRPHLF
X900L4  CLR     R1
        CLR     R2
        CLR     R3
        MOV     @BRDCOL,R1
        ANDI    R1,>FF
        LWPI    LOWWP1
        MOV     @CURWS,R13
        BL      @X90CVC    *SET BORDER COLOR
        DATA    >009D
        CLR     R1
        CLR     R2
        LWPI    LOWWP1
        MOV     @CURWS,R13
        LI      R0,LOWWP1
        MOV     R0,@CURWS
        BL      @X904L1  *Sets page number,resets character set, and clears display  (GRCLR is graphics mode clear; TMCLR for text modes; both seem to clear using a scroll)
        MOV     R13,@CURWS
        DATA    >009D

File:HDS2.MDOS.L6.VX0003S   Page: 5 Date: 10-30-04  Time: 01:51:50
        MOVB    @VIDREG+1,R0
        ORI     R0,>4000
        SRL     R0,8
        ORI     R0,>0100
        BLWP    @VWTR                   * Mode register 1 (SCREEN ON)
        CLR     @SPRACT
        RT
 
GRCLR   CLR     R1
        CLR     R2
        CLR     R3
        MOV     @GXROWS,R4
        MOV     @GXCOLS,R5
        DEC     R4
        DEC     R5
        MOV     @STDCLR,R6
        SLA     R6,8
        LWPI    LOWWP2
        MOV     @CURWS,R13
        BL      @X916L1    **scrollup
        DATA    >009D
        RT
 
 
* FILENAME: VX161CS
*
* BScrollUp
*
* R1x = Number of pixels to scroll
* R2x = Row number of upper left corner
* R3x = Column number of upper left corner
* R4x = Row number of lower right corner
* R5x = Column number of lower right corner
* R6h = Pixel color for blank pixels
*
X916VC
X916L1  C       @4(R13),@8(R13)
        JH      X916RT
        C       @6(R13),@10(R13)
        JH      X916RT
        MOV     @VIDMOD,R1
        CI      R1,6
        JHE     X916L2
X916RT  RT
X916L2  MOV     @2(R13),R10             * R10 increment
        MOV     @4(R13),R3
        A       @PAGEPX,R3
        MOV     @6(R13),R2
        MOV     R2,R0
        MOV     R3,R1
        A       R10,R1                  * R10 increment, # of lines to blank
        MOV     @8(R13),R5
        A       @PAGEPX,R5
        MOV     R5,R9
        S       R3,R9                   * R9 # of rows
        INC     R9
        MOV     @10(R13),R4
        S       R0,R4
        S       R1,R5
        INC     R4
        INC     R5
        CLR     R6
        MOV     @VIDMOD,R8
        LI      R7,>90
        LI      R12,>80
X916L3  C       R10,R9
        JHE     X916L4
        MOV     R10,R10
        JNE     X916L5
X916L4  MOV     R9,R10
        JMP     X916L6
X916L5  BLWP    @VDCMD2
X916L6  MOV     R4,R2
        CI      R8,6

File:HDS2.MDOS.L6.VX161CS   Page: 2 Date: 10-30-04  Time: 01:51:50
        JEQ     X916L7
        CI      R8,8
        JEQ     X916L7
        CI      R8,7
        JEQ     X916L8
        MOV     @12(R13),R4
        SRL     R4,8
        JMP     X916L9
X916L7  MOV     @12(R13),R5             *
        ANDI    R5,>FF00                *
        MOV     R5,R4                   * Calculate color for
        SLA     R5,4                    * blank pixels
        SOCB    R5,R4                   *
        SRL     R4,8                    *
        JMP     X916L9
X916L8  MOV     @12(R13),R5
        ANDI    R5,>FF00
        MOV     R5,R4
        SLA     R5,2
        SOCB    R5,R4
        MOVB    R4,R5
        SLA     R5,4
        SOCB    R5,R4
        SRL     R4,8
X916L9  MOV     @8(R13),R1
        A       @PAGEPX,R1
        INC     R1
        MOV     R10,R3
        S       R10,R1                  * R1 starting line to blank
        MOV     R12,R5
        BLWP    @VDCMD1
        RT
 
* VDCMD1
*
* R0x = Registers #36, #37
* R1x = Registers #38, #39
* R2x = Registers #40, #41
* R3x = Registers #42, #43
* R4x = Registers #44, #45
* R5l = Register #46
*
VDCMD1  DATA    LOWWP0,$+2
VDCM11  LI      R0,>8F02                * Read status register #2
        SWPB    R0
        MOVB    R0,@VDPWA
        SWPB    R0
        MOVB    R0,@VDPWA
        MOVB    @VDPSTA,R1
        ANDI    R1,>0100

File:HDS2.MDOS.L6.VX-INTS   Page: 5 Date: 10-30-04  Time: 01:51:50
        JNE     VDCM11
        LI      R0,>2491                * Set multiple register start
        MOVB    R0,@VDPWA
        SWPB    R0
        MOVB    R0,@VDPWA
        LI      R10,11
        MOV     R13,R12
VDCM12  MOV     *R12+,R0
        SWPB    R0
        MOVB    R0,@VDPPT3
        DEC     R10
        JEQ     VDCM13
        SWPB    R0
        MOVB    R0,@VDPPT3
        DEC     R10
        JEQ     VDCM13
        JMP     VDCM12
VDCM13  RTWP
 
* VDCMD2
*
* R0x = Registers #32, #33
* R1x = Registers #34, #35
* R2x = Registers #36, #37
* R3x = Registers #38, #39
* R4x = Registers #40, #41
* R5x = Registers #42, #43
* R6x = Registers #44, #45
* R7l = Register #46
*
VDCMD2  DATA    LOWWP0,$+2
VDCM21  LI      R0,>8F02                * Read status register #2
        SWPB    R0
        MOVB    R0,@VDPWA
        SWPB    R0
        MOVB    R0,@VDPWA
        MOVB    @VDPSTA,R1
        ANDI    R1,>0100
        JNE     VDCM21
        LI      R0,>2091                * Set multiple register start
        MOVB    R0,@VDPWA
        SWPB    R0
        MOVB    R0,@VDPWA
        LI      R10,15
        MOV     R13,R12
VDCM22  MOV     *R12+,R0
        SWPB    R0
        MOVB    R0,@VDPPT3
        DEC     R10
        JEQ     VDCM23

File:HDS2.MDOS.L6.VX-INTS   Page: 6 Date: 10-30-04  Time: 01:51:50
        SWPB    R0
        MOVB    R0,@VDPPT3
        DEC     R10
        JEQ     VDCM23
        JMP     VDCM22
VDCM23  RTWP
 
 

 

 

Link to comment
Share on other sites

However, since Text mode scrolling is not managed via VDCMD1/2, there is no command test, and the setup continues during LMMV execution. It is NOT clear to me why this is a problem for emulation or $$CRASH$$.

 

 

Because the command continues to write values into VRAM after the tables have been rearranged?

 

 

[:vdp] v9938: Write 00 to R#45
[:vdp] v9938: Write 80 to R#46
[:vdp] V9938: Opcode 80h  LMMV-SET  (0,0)->(0,0),4 [256,212]
[:vdp] Command started
[:vdp] addr=000000 <- 04
[:vdp] addr=010000 <- 04
[:vdp] addr=000001 <- 04
[:vdp] addr=010001 <- 04
[:vdp] addr=000002 <- 04
[:vdp] addr=010002 <- 04
...
[:vdp] addr=0004bf <- 04
[:vdp] addr=0104bf <- 04
[:vdp] addr=0004c0 <- 04
[:vdp] addr=0104c0 <- 04
[:vdp] addr=0004c1 <- 04
[:vdp] addr=0104c1 <- 04
[:vdp] addr=0004c2 <- 04
[:vdp] addr=0104c2 <- 04
[:vdp] addr=0004c3 <- 04
[:vdp] addr=0104c3 <- 04
[:vdp] addr=0004c4 <- 04
[:vdp] addr=0104c4 <- 04
[:vdp] addr=0004c5 <- 04
[:vdp] addr=0104c5 <- 04
[:vdp] addr=0004c6 <- 04
[:vdp] addr=0104c6 <- 04
[:vdp] v9938: Write 00 to R#0
[:vdp] v9938: mode = GRAPHIC 1
[:vdp] addr=0004c7 <- 40
[:vdp] addr=0004c7 <- 44
[:vdp] addr=0004c8 <- 40
[:vdp] addr=0004c8 <- 44
[:vdp] addr=0004c9 <- 40
[:vdp] addr=0004c9 <- 44
[:vdp] addr=0004ca <- 40
[:vdp] addr=0004ca <- 44
Link to comment
Share on other sites

 

Because the command continues to write values into VRAM after the tables have been rearranged?

 

Agreed, I was musing about the successive use of the mode select XOP. I understand the reason for the tables being re-arranged but I don't understand why a programmer would call the video mode settings back-to-back. That isn't normal, IMHO. I wonder if the command is aborted when a mode change occurs, or if the current command executes using the table settings made when the command was triggered?

Link to comment
Share on other sites

  • 2 weeks later...

So I have come to some conclusions now, after days of working with a number of machine language programs that wrote for that purpose.

 

Summary: I patched the v9938.cpp file in MAME to abort a command when the video mode is changed before completion.This is available from Github right now, or on Jan 31 with the next release. This will make the program BEURS usable, at least concerning that reported issue. (Remember to add "-mouse" as a command line argument to capture the mouse.)

 

In detail: I tried to figure out what happens when we switch the mode before the command has completed its execution. For that purpose, I wrote a program that switches to Graphics7, starts drawing a filled box with LMMV, then switches to another mode - a) after waiting for completion, and b) immediately (just by commenting out the JOC instruction). Also, it creates fingerprints of the VRAM by calculating the CRC16 for 1k blocks, once at the start, then again after switching. Later I refined these fingerprints to blocks of 64 bytes.

 

Results:

  1. In Graphics6/7 modes, address line A16 takes the role of the LSB of the VRAM address. (This is well-known, but I could see it directly here.) This means that subsequent pixels of the box drawn at (0,0) change VRAM at locations >00000, >10000, >00001, >10001, >00002, >10002, and so on. This is true for G6 and G7, not for G4 and G5. I wonder whether this is a glitch of the v9938 design.
  2. (already found before) The LMMV command does not immediately stop after the switch. This is obvious by watching the CE bit (command executing); it seems as if the CE bit is 1 just a little bit shorter than in the case where the command is allowed to complete (17000 iterations vs. 19000 iterations).
  3. When the switch occurs, writing to high memory locations (>10000 and higher) stops immediately.
  4. Writing to low memory locations stops at the point when the switch occured, then some isolated bytes are written to VRAM. This means that the BEURS program can cope with the early switch because the pattern tables do not get damaged, or only at isolated locations which may be seen as broken characters. This was not correctly emulated before, where the command continued to write to VRAM, overwriting the Text2 tables.
  5. The locations of the single, isolated bytes that are changed after the switch are not fully predictable. They change for repeated test runs, and they depend on the time of the switch.

From these results, I decided that it should be sufficient to abort the command when the switch occurs. This is certainly not precise in terms of timing behavior and the fact that some few bytes are sputtered over the VRAM, but since that behavior is not fully predictable and reproducible, and I do not know more about the v9938 internals, I cannot emulate it better. I do not believe that any application for a v9938-based system seriously relies on that behavior.

  • Like 1
Link to comment
Share on other sites

Thanks for the update. I ran your timing tests on one computer and I got different results greater than your 17,000 and 19,000 iterations. It was a few days ago, but I got something in the 23,000 range as I recall.

 

I do not know your system, but I could believe the randomness of the few bytes sputtered over the VRAM could be related to any other tasks running separate of the emulation. That is just a guess, no evidence one way or the other.

 

For BEURS, I spent yesterday taking the disassembled code and modifying some instructions. I have bypassed the title screen causing the graphics issue so no matter what version of MESS or MAME someone is using, it will not be a problem. I have identified the code for the menus and submenus and working through it now to identify the precise piece of code I need to insert to be able to save files.

 

In all reality, I seriously doubt anyone will use this program when one can no go to Yahoo Financials or their 401K website manager and pull up the data without taking the time to ever type in any data into a spreadsheet. What I may offer is some graphing opportunities if someone wants to see other data plotted out on the screen. I have not dug into graphing routines, but it does not appear those routines are causing an issue in the flipping between them and text mode so I believe he is using another mode.

 

Right now, I am waiting on my AT&T guy to come out right now and check my internet line. As luck would have it, it has been working fine since Friday except for one small timeframe. I just hope I did not exceed my Verizon Wireless data limit as it is $15/GB.

 

 

Beery

Link to comment
Share on other sites

I do not know your system, but I could believe the randomness of the few bytes sputtered over the VRAM could be related to any other tasks running separate of the emulation. That is just a guess, no evidence one way or the other.

 

 

No, I refer to the real iron. Running on the emulation to be fixed does not make too much sense. ;)

Link to comment
Share on other sites

Thanks for the update. I ran your timing tests on one computer and I got different results greater than your 17,000 and 19,000 iterations. It was a few days ago, but I got something in the 23,000 range as I recall.

 

Is this the current version? I fixed a speed issue of the 9995 in one release, which became obvious with my Christmas song program that ran far too slowly.

 

If you log the output (add the -log switch), there should be a line

[:maincpu] RESET; automatic wait state creation is disabled
Edited by mizapf
Link to comment
Share on other sites

 

 

Is this the current version? I fixed a speed issue of the 9995 in one release, which became obvious with my Christmas song program that ran far too slowly.

 

If you log the output (add the -log switch), there should be a line

[:maincpu] RESET; automatic wait state creation is disabled

 

No, it was not with the current version. It was MESS that I had on another system.

 

Beery

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...