Jump to content
IGNORED

Assembly under emulation


Vorticon

Recommended Posts

OK, it turned out that using END START instead of END somehow corrupts the GPLLNK utility. It took me a while to figure out why perfectly good code was misbehaving, until I remembered that I had a similar issue while coding the Chaos programs. I still don't have a clear explanation as to why this is the case, and I would love for someone here to enlighten me.

 

I am having a similar issue and cannot find an answer anywhere. Have you been enlightened? I will eventually figure it out; but, I would rather short-circuit that painful process!

 

...lee

 

I'm afraid not :(

Link to comment
Share on other sites

OK, it turned out that using END START instead of END somehow corrupts the GPLLNK utility. It took me a while to figure out why perfectly good code was misbehaving, until I remembered that I had a similar issue while coding the Chaos programs. I still don't have a clear explanation as to why this is the case, and I would love for someone here to enlighten me.

 

I am having a similar issue and cannot find an answer anywhere. Have you been enlightened? I will eventually figure it out; but, I would rather short-circuit that painful process!

 

...lee

 

I'm afraid not :(

 

Bummer. I saw something in Bruce Harrison's The Art of Assembly Series relating to saving the GPL return, but I did not think it was explained very well; and, I could not find any other reference to it---finding anything useful in Harrison's stream-of-consciousness tome is well nigh impossible, even when you are sure you have read it before. The Harrison quote below from "1.6. The Art Of Assembly — Part 6. The Ins And Outs" gives us a handle on the problem, I guess; but, it seems a little too much like magic:

 

The second program uses a slightly more exotic way of entering and leaving. At the opening, it stashes away the value from R11 of whatever workspace the computer was using, then restores that to R11 of the GPL workspace before doing an RT. Early in our experiences with the TI Assembly language, we discovered that when you enter your program, the computer has essentially performed a BL operation to get into your program, so register 11 contains the return address you can use to exit. There are exceptions to this when you entered from Extended Basic, and this method from Program 2 will not always work for XB entry. The first method (B @>006A) will always work, provided only that you first load the workspace pointer with the GPL workspace (>83E0).

 

That brings us to a very minor point, but one that might be important in some of your programming efforts. In our music programs, we discovered that, for some reason we've not discovered, if one does NOT move R11 to someplace on entry, as in Program 2, the sending of bytes directly to the sound generator at >8400 will not work properly. We have no idea why that's so, or whether other functions might be affected, but in our music programs we use the entry method of Program 2 and the exit method of Program 1. That keeps everything working.

 

Thoughts?

 

...lee

Link to comment
Share on other sites

I asked a similar question on this thread: <http://tech.groups.yahoo.com/group/ti99-4a/message/44814>.

 

Paolo Bagnaresi suggested " I seem to remember that the loader of an END START program doesn't load the UTILITIES in low memory. The Utilities include, among others, GPLLNK. We are talking about E/A module, of course. As a test, and assuming your program is fully relocatable (no AORG in it) you can try loading first another normally relocatable program first (no END START in it) and then your END START program. This time your program

should find the GPLLNK among the Utilities, which will be loaded by the first program."

 

Never did get round to trying Paolo's suggestion ...

 

Stuart.

Link to comment
Share on other sites

I asked a similar question on this thread: <http://tech.groups.y...a/message/44814>.

 

Paolo Bagnaresi suggested " I seem to remember that the loader of an END START program doesn't load the UTILITIES in low memory. The Utilities include, among others, GPLLNK. We are talking about E/A module, of course. As a test, and assuming your program is fully relocatable (no AORG in it) you can try loading first another normally relocatable program first (no END START in it) and then your END START program. This time your program

should find the GPLLNK among the Utilities, which will be loaded by the first program."

 

Never did get round to trying Paolo's suggestion ...

 

Stuart.

 

Yes, this may be the issue, but Paolo's method will require having to manually load more than one file which is inconvenient. Can one manually load the EA utilities into low memory from within the program?

Link to comment
Share on other sites

I asked a similar question on this thread: <http://tech.groups.y...a/message/44814>.

 

Paolo Bagnaresi suggested " I seem to remember that the loader of an END START program doesn't load the UTILITIES in low memory. The Utilities include, among others, GPLLNK. We are talking about E/A module, of course. As a test, and assuming your program is fully relocatable (no AORG in it) you can try loading first another normally relocatable program first (no END START in it) and then your END START program. This time your program

should find the GPLLNK among the Utilities, which will be loaded by the first program."

 

Never did get round to trying Paolo's suggestion ...

 

Stuart.

 

Yes, this may be the issue, but Paolo's method will require having to manually load more than one file which is inconvenient. Can one manually load the EA utilities into low memory from within the program?

 

I think they probably do get loaded and that it is really a link issue. That should not be difficult to check using Tursi's debugger to dump >2000 -- >267B, where the utilites and their vectors are supposed to be loaded; and, possibly the DEF table at >3F38+ for the program assembled with END and with END START.

 

...lee

Link to comment
Share on other sites

OK, it turned out that using END START instead of END somehow corrupts the GPLLNK utility. It took me a while to figure out why perfectly good code was misbehaving, until I remembered that I had a similar issue while coding the Chaos programs. I still don't have a clear explanation as to why this is the case, and I would love for someone here to enlighten me.

 

I am having a similar issue and cannot find an answer anywhere. Have you been enlightened? I will eventually figure it out; but, I would rather short-circuit that painful process!

 

...lee

 

I'm afraid not :(

 

Bummer. I saw something in Bruce Harrison's The Art of Assembly Series relating to saving the GPL return, but I did not think it was explained very well; and, I could not find any other reference to it---finding anything useful in Harrison's stream-of-consciousness tome is well nigh impossible, even when you are sure you have read it before. The Harrison quote below from "1.6. The Art Of Assembly — Part 6. The Ins And Outs" gives us a handle on the problem, I guess; but, it seems a little too much like magic:

 

The second program uses a slightly more exotic way of entering and leaving. At the opening, it stashes away the value from R11 of whatever workspace the computer was using, then restores that to R11 of the GPL workspace before doing an RT. Early in our experiences with the TI Assembly language, we discovered that when you enter your program, the computer has essentially performed a BL operation to get into your program, so register 11 contains the return address you can use to exit. There are exceptions to this when you entered from Extended Basic, and this method from Program 2 will not always work for XB entry. The first method (B @>006A) will always work, provided only that you first load the workspace pointer with the GPL workspace (>83E0).

 

That brings us to a very minor point, but one that might be important in some of your programming efforts. In our music programs, we discovered that, for some reason we've not discovered, if one does NOT move R11 to someplace on entry, as in Program 2, the sending of bytes directly to the sound generator at >8400 will not work properly. We have no idea why that's so, or whether other functions might be affected, but in our music programs we use the entry method of Program 2 and the exit method of Program 1. That keeps everything working.

 

Thoughts?

 

...lee

 

When calling a routine from XB via CALL LINK, the programmer is "expected" to set up a workspace for the routine. The programmer may then return to XB by restoring the WS to 0x83E0 and executing a RT. However... in practice, the called routine may destroy the GPLWS R11 and may even make it impossible to return to the interpreter. for example, DSRLNK and DSR code have a habit of mucking around with GPLWS registers. By saving R11, then clearing the status byte and restoring R11, he can either return or force a return via the interpreter. Bruce is mixing lessons learned from EA and XB assembly programs, hence early confusion when working between envirionments. I think he works out the kinks in later parts. :)

As for the direct sound problem, I cannot think of any reason such trickery would have any bearing on his sound routine, unless he was somehow intefering with the interrupt routines or inadvertently turning sound off.

 

(Reminded me of something -- check out post #150 for the XB assembly language programmers guide)

 

http://www.atariage....t/page__st__125

Edited by InsaneMultitasker
Link to comment
Share on other sites

...

Bruce is mixing lessons learned from EA and XB assembly programs, hence early confusion when working between envirionments. I think he works out the kinks in later parts. :)

 

I would love to find the worked-out kinks; but, like I said, mucking through almost 700 pages of Harrison's SOC writing is torture.

 

...lee

Link to comment
Share on other sites

Using 16 bit wide RAM instead of 8 bit wide improves execution speed by 105-110%, even with the original crystal, provided that both code and workspace is in this RAM. If you already had the workspace in the console RAM (8300H), then the difference is smaller.

 

So twice is no overstatement, under these conditions.

Link to comment
Share on other sites

  • 1 month later...

HELP!

 

I am having trouble using WinAsm99 (Asm994A) to assemble some of the original TI Forth code, namely, ASMSRC. It works just fine with the E/A Assembler. I am calling the object file FORTH2. The source code for ASMSRC is

 

 COPY "DSK2.ASMSRC1"
 COPY "DSK2.ASMSRC2"
 COPY "DSK2.ASMSRC3"
 END

 

Obviously, this will not work in WinAsm99, so I loaded the individual files as DOS text files asmsrc1.a99, asmsrc2.a99, asmsrc3.a99 and asmsrc_end.a99, which are zipped up in this file: asmsrc.zip The last file contains only the END directive. When I attempt to assemble the program, WinAsm99 blows up. This happens even if I put all the files into one source file. Windows 7 pops up a window that tells me the program has stopped working. It cannot be that the program is too big because I can assemble Mark Wills' TurboForth (almost 4X larger) just fine.

 

I tried to assemble the program minus asmsrc3.a99. That worked! It gave lots of errors, of course; but, the assembler did not blow up. So, it would appear there is something in asmsrc3.a99 that WinAsm99 does not like. I have no clue what that might be. Any ideas?

 

...lee

Link to comment
Share on other sites

It's the label "ELSE" on line 388 that's crashing it, it must be looking for some kind of conditional assembly operation. (Found by binary search - delete half the lines each time, see if it gets through assembly ;) ).

 

You can't even change it to something like "ELSE2", you have to change the word. Changing the first letter works, though, I tested as 'QELSE' ;) It's not referenced anywhere at all, so removing the label seems to let it build too.

 

It also doesn't like the RORG on line 330 of asmsrc2.a99 (though it tells you sort of why but puts the error on like 333). I had to put a number after it (RORG 0). that is definately not the right answer, since it started counting from 0 again and there was already data at zero. Might want to double check the usage of RORG and DORG in this one and then make sure the Asm994A output is what you expect (use the listing file).

Link to comment
Share on other sites

It's the label "ELSE" on line 388 that's crashing it, it must be looking for some kind of conditional assembly operation. (Found by binary search - delete half the lines each time, see if it gets through assembly ;) ).

 

You can't even change it to something like "ELSE2", you have to change the word. Changing the first letter works, though, I tested as 'QELSE' ;) It's not referenced anywhere at all, so removing the label seems to let it build too.

 

It also doesn't like the RORG on line 330 of asmsrc2.a99 (though it tells you sort of why but puts the error on like 333). I had to put a number after it (RORG 0). that is definately not the right answer, since it started counting from 0 again and there was already data at zero. Might want to double check the usage of RORG and DORG in this one and then make sure the Asm994A output is what you expect (use the listing file).

 

Thanks for your input, Tursi!

 

I did discover the problem with RORG. Asm994A is wrong. RORG does not require an operand. However, if I put a label "_rlast equ $" just ahead of the "DORG 0" and then use "RORG _rlast", it gets the right value when it continues.

 

I have no choice regarding ELSE. That is the definition of the eponymous TI Forth word.

 

...lee

Link to comment
Share on other sites

It's the label "ELSE" on line 388 that's crashing it, it must be looking for some kind of conditional assembly operation. (Found by binary search - delete half the lines each time, see if it gets through assembly ;) ).

 

You can't even change it to something like "ELSE2", you have to change the word. Changing the first letter works, though, I tested as 'QELSE' ;) It's not referenced anywhere at all, so removing the label seems to let it build too.

 

It also doesn't like the RORG on line 330 of asmsrc2.a99 (though it tells you sort of why but puts the error on like 333). I had to put a number after it (RORG 0). that is definately not the right answer, since it started counting from 0 again and there was already data at zero. Might want to double check the usage of RORG and DORG in this one and then make sure the Asm994A output is what you expect (use the listing file).

 

Thanks for your input, Tursi!

 

I did discover the problem with RORG. Asm994A is wrong. RORG does not require an operand. However, if I put a label "_rlast equ $" just ahead of the "DORG 0" and then use "RORG _rlast", it gets the right value when it continues.

 

I have no choice regarding ELSE. That is the definition of the eponymous TI Forth word.

 

...lee

 

If I use "else" instead of "ELSE", it works. If the object file stores it as uppercase only, I'm OK. Otherwise, I will have to think of something else. :_(

 

...lee

Link to comment
Share on other sites

It's the label "ELSE" on line 388 that's crashing it, it must be looking for some kind of conditional assembly operation. (Found by binary search - delete half the lines each time, see if it gets through assembly ;) ).

 

You can't even change it to something like "ELSE2", you have to change the word. Changing the first letter works, though, I tested as 'QELSE' ;) It's not referenced anywhere at all, so removing the label seems to let it build too.

 

It also doesn't like the RORG on line 330 of asmsrc2.a99 (though it tells you sort of why but puts the error on like 333). I had to put a number after it (RORG 0). that is definately not the right answer, since it started counting from 0 again and there was already data at zero. Might want to double check the usage of RORG and DORG in this one and then make sure the Asm994A output is what you expect (use the listing file).

 

Thanks for your input, Tursi!

 

I did discover the problem with RORG. Asm994A is wrong. RORG does not require an operand. However, if I put a label "_rlast equ $" just ahead of the "DORG 0" and then use "RORG _rlast", it gets the right value when it continues.

 

I have no choice regarding ELSE. That is the definition of the eponymous TI Forth word.

 

...lee

 

If I use "else" instead of "ELSE", it works. If the object file stores it as uppercase only, I'm OK. Otherwise, I will have to think of something else. :_(

 

...lee

 

Hm-m-m-m... Forth does not use the Assembly label to find the word. It uses the name in the DATA statement above it. It appears, as you say, Tursi, to be an idle label! :)

 

...lee

Link to comment
Share on other sites

Hee, I was going to say! It's not referenced anywhere else, not even in a DEF, so it never appears in the object file.

 

But yeah. Win994a didn't get quite enough development time. it's a shame, because with a few tweaks and bugfixes it would be truly amazing. It's still my assembler of choice, but I carefully study the listing file anytime anything wierd happens (that's not always enough either.)

Link to comment
Share on other sites

Not that I am a Assembly Langauge guru but in RXB I always use BLWP and in Scratch Pad so the Registers are loaded before the switch.

That way a GPLLNK has no effect on return.

Now I know every one says use BL and RT and fix R11 but it is running from Scratch Pad so some speed is there.

Doing this that way in RXB solved many problems in one fell swoop.

Link to comment
Share on other sites

Hee, I was going to say! It's not referenced anywhere else, not even in a DEF, so it never appears in the object file.

 

But yeah. Win994a didn't get quite enough development time. it's a shame, because with a few tweaks and bugfixes it would be truly amazing. It's still my assembler of choice, but I carefully study the listing file anytime anything wierd happens (that's not always enough either.)

 

Indeed. I remember literally tearing my hair out trying to figure why my program was bombing until someone here pointed out that I was using the non-patched version of asm99...There is something to be said here about using real hardware because at least you know that when your program bombs, it's likely your code and not the assembler at fault. You just need more patience and maybe a handy book to read while the assembler toils away :D

Link to comment
Share on other sites

Not that I am a Assembly Langauge guru but in RXB I always use BLWP and in Scratch Pad so the Registers are loaded before the switch.

That way a GPLLNK has no effect on return.

Now I know every one says use BL and RT and fix R11 but it is running from Scratch Pad so some speed is there.

Doing this that way in RXB solved many problems in one fell swoop.

 

There's definately a place for BLWP, especially in very complex systems. Anytime you see people saying "avoid blahblah" and "use blahblah" instead, they are usually just talking about maximum performance. Doesn't mean you'll be ostracized for doing it. ;) But I think the issue they are seeing is that the Loader itself is corrupting the code for GPLLNK.

 

Wouldn't be too hard to test that in the Classic99 debugger, I guess? Just save a copy of the code for GPLLNK, load and run, and see if it got changed.

 

Indeed. I remember literally tearing my hair out trying to figure why my program was bombing until someone here pointed out that I was using the non-patched version of asm99...There is something to be said here about using real hardware because at least you know that when your program bombs, it's likely your code and not the assembler at fault. You just need more patience and maybe a handy book to read while the assembler toils away :D

 

Heh.. well, I used Editor/Assembler under Classic99 for a long time. With the keyboard paste option I just set up a notepad with all the keypresses needed to assemble, link, save and run, then just copy and paste into the emulator to get it done. But Asm994A is still more convenient.

Link to comment
Share on other sites

There's definitely a place for BLWP, especially in very complex systems. Anytime you see people saying "avoid blahblah" and "use blahblah" instead, they are usually just talking about maximum performance. Doesn't mean you'll be ostracized for doing it. ;) But I think the issue they are seeing is that the Loader itself is corrupting the code for GPLLNK.

 

Well, I tried recently to figure out what was different between the GPLLNK used by E/A and the one that is part of TI Forth. The LINKer flag of >20 at >8349 is set by the E/A routine but not, as far as I could tell, by the TI Forth version. It also appeared that the GPL routine to execute was pushed onto the subroutine stack in PAD one word deeper by the E/A routine than by the TI Forth routine before they both took a B *R11 to >061C in the console. When using an END START, the E/A routine pops you back into the LOADer waiting for another program to load as though you had given no label for the program to autostart. If, however, you tap <enter> twice, the program actually starts at the proper label :? . During my research, such as it was, the E/A GPLLNK routine's code did not appear to get clobbered. I kind of gave up on it because I implemented the Millers Graphics GPLLNK routine that @Willsy used (modified) in TurboForth, which works just fine!

 

...lee

Link to comment
Share on other sites

There is nothing wrong with liking modern tools. Back in the day, we did what we could, but computers advanced and so did the tools. Denying the modern stuff out of "purism" is just unjustified stubbornness IMO. I always wanted better graphics from my 99/4A, but it only has 16 colors and a fixed resolution, however I don't condemn my PC from having 24-bit color.

 

There is a lot about the 99/4A that was a pain in the ass to do on the console, especially the assembly development cycle. And the keyboard (all the keyboards on the early 80's "home computers") is not adequate for programming, again IMO.

 

I like hacking on my real gear every now and then just for the fun of it, but for any code more than a few lines, I'll do it on the PC and test with emulation. Once it is all working, then test it on the metal. Since this is a hobby for me (and most everyone), the time spent waiting for floppy disks, assemblers, loading, saving, etc. is just wasted time.

 

ITT: Heretics ;)

Link to comment
Share on other sites

It's the label "ELSE" on line 388 that's crashing it, it must be looking for some kind of conditional assembly operation. (Found by binary search - delete half the lines each time, see if it gets through assembly ;) ).

 

You can't even change it to something like "ELSE2", you have to change the word. Changing the first letter works, though, I tested as 'QELSE' ;) It's not referenced anywhere at all, so removing the label seems to let it build too.

 

It also doesn't like the RORG on line 330 of asmsrc2.a99 (though it tells you sort of why but puts the error on like 333). I had to put a number after it (RORG 0). that is definately not the right answer, since it started counting from 0 again and there was already data at zero. Might want to double check the usage of RORG and DORG in this one and then make sure the Asm994A output is what you expect (use the listing file).

 

Thanks for your input, Tursi!

 

I did discover the problem with RORG. Asm994A is wrong. RORG does not require an operand. However, if I put a label "_rlast equ $" just ahead of the "DORG 0" and then use "RORG _rlast", it gets the right value when it continues.

 

I have no choice regarding ELSE. That is the definition of the eponymous TI Forth word.

 

...lee

 

If I use "else" instead of "ELSE", it works. If the object file stores it as uppercase only, I'm OK. Otherwise, I will have to think of something else. :_(

 

...lee

 

Hm-m-m-m... Forth does not use the Assembly label to find the word. It uses the name in the DATA statement above it. It appears, as you say, Tursi, to be an idle label! :)

 

...lee

 

Yeah. That label will only come into play if you want to write Forth code in assembly. That is to say, pre-compiled Forth code, which is a list of entry points:

 

DATA OVER,DUP,LIT,42,ADD

 

etc...

 

In the case of ELSE, I would imagine pre-compiled Forth words are going to be written in terms of 0BRANCH rather than IF...ELSE...THEN, as that is how they would be compiled (having been translated by the immediate words IF...ELSE etc).

Link to comment
Share on other sites

Hee, I was going to say! It's not referenced anywhere else, not even in a DEF, so it never appears in the object file.

 

But yeah. Win994a didn't get quite enough development time. it's a shame, because with a few tweaks and bugfixes it would be truly amazing. It's still my assembler of choice, but I carefully study the listing file anytime anything wierd happens (that's not always enough either.)

 

Yeah. It's a great assembler, especially when you consider it was just an 'add on' to the main-course!

 

There are some undocumented features in the assembler. For example, IIRC, it supports conditional assembly and macros; they're just undocumented (and maybe unstable) so we don't know how to use them. If you look at the ASM994A exe in a hex editor you'll find references (IIRC) to IF THEN ELSE et al, so they're actually reserved key-words/directives in ASM994A, hence the full on tilt when encountered in your source code!

Link to comment
Share on other sites

There's definitely a place for BLWP, especially in very complex systems. Anytime you see people saying "avoid blahblah" and "use blahblah" instead, they are usually just talking about maximum performance. Doesn't mean you'll be ostracized for doing it. ;) But I think the issue they are seeing is that the Loader itself is corrupting the code for GPLLNK.

 

Well, I tried recently to figure out what was different between the GPLLNK used by E/A and the one that is part of TI Forth. The LINKer flag of >20 at >8349 is set by the E/A routine but not, as far as I could tell, by the TI Forth version. It also appeared that the GPL routine to execute was pushed onto the subroutine stack in PAD one word deeper by the E/A routine than by the TI Forth routine before they both took a B *R11 to >061C in the console. When using an END START, the E/A routine pops you back into the LOADer waiting for another program to load as though you had given no label for the program to autostart. If, however, you tap <enter> twice, the program actually starts at the proper label :? . During my research, such as it was, the E/A GPLLNK routine's code did not appear to get clobbered. I kind of gave up on it because I implemented the Millers Graphics GPLLNK routine that @Willsy used (modified) in TurboForth, which works just fine!

 

...lee

 

Yep. A nice routine. I always give credit when I use/shamelessly steal others code ;-)

 

I just had to make some small mods to allow it to run from ROM IIRC. That would have been back in 2009, and I never needed to change it, so I call that 'production code' ;-)

Link to comment
Share on other sites

Hee, I was going to say! It's not referenced anywhere else, not even in a DEF, so it never appears in the object file.

 

But yeah. Win994a didn't get quite enough development time. it's a shame, because with a few tweaks and bugfixes it would be truly amazing. It's still my assembler of choice, but I carefully study the listing file anytime anything wierd happens (that's not always enough either.)

 

Yeah. It's a great assembler, especially when you consider it was just an 'add on' to the main-course!

 

There are some undocumented features in the assembler. For example, IIRC, it supports conditional assembly and macros; they're just undocumented (and maybe unstable) so we don't know how to use them. If you look at the ASM994A exe in a hex editor you'll find references (IIRC) to IF THEN ELSE et al, so they're actually reserved key-words/directives in ASM994A, hence the full on tilt when encountered in your source code!

 

The IF/THEN/ELSE does work. I've used it in Cortex BASIC for conditional compilation for the TI-99 and my TM990 system. Note that the "IF", "THEN" and "ELSE" need to be indented by two spaces.

 

 
*************
TM990   EQU 1		    **** Set to 1 to assemble for the TM990
*************		    **** Set to 0 to assemble for the TI-99
 IF TM990
 ELSE *TI-99
    DEF START	    For the TI-99 so program can be run from E/A option 3.
    REF KSCAN	    TI-99 key scan routine.
    REF DSRLNK	   File I/O operations.
 ENDIF

*CRU definitions.
EIA02   EQU >0040	    Main 9902 hardware base address.

*Memory mapped I/O definitions.
 IF TM990
VRAMW   EQU >E400	    VDP VRAM data write address.
VDPREG  EQU >E402	    VDP VRAM address and register access address.
VRAMR   EQU >E404	    VDP VRAM data read address.
VDPSTTS EQU >E406	    VDP status read address.
 ELSE *TI-99
VRAMW   EQU >8C00	    VDP VRAM data write address.
VDPREG  EQU >8C02	    VDP VRAM address and register access address.
VRAMR   EQU >8800	    VDP VRAM data read address.
VDPSTTS EQU >8802	    VDP status read address.
 ENDIF

 

Stuart.

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...