Jump to content
IGNORED

XEX2CAS 2.0 - Modernized XEX2CAS


baktra

Recommended Posts

Hello,

I've decided to put together several updates of the XEX2CAS utility that have been discussed on this forum in the past. The result is XEX2CAS 2.0 - modernized XEX2CAS. You can download it from here: http://www.baktra.wz.cz/software/xex2casv2.html

If you still use cassettes, you may find it useful.

Notable new features

  • Ported to Microsoft Windows, compilable under Linux and possibly other operating systems
  • You can choose from 4 binary loaders (STDBLOAD 2, Exclamation mark loader, Exclamation mark loader updated for XL/XEs, and binary loader used by certain L.K. Avalon games)
  • You can elongate inter-record-gaps (IRGs) after records that hold INIT segments
  • You can use shorter leader (12 s instead of 20 s) or increase transfer speed to 720 bd
  • You can process plain files
  • Completely new processing of command line arguments

Original XEX2CAS bugs that have been fixed

  • XEX2CAS no longer elongates the converted files by up to 127 bytes

Command line

 

XEX2CAS 2.0 - Convert Atari DOS 2 Binary File to standard tape records
Usage:
xex2cas [option1] [option2] ... infile.xex [outfile.cas]
Options:
-r Overwrite output file
-s Use a shorter leader (12 s)
-i<n> Elongate IRGs after INIT segments to n seconds (0 to 99)
-n'<name>' Set program name displayed by the binary loader (STDBLOAD 2 only)
The name can be up to 34 characters long
-l<n> Binary loader selection
n=0 STDBLOAD 2 (default, XL/XE only, displays program name)
n=1 Exclamation mark (!) loader updated for XL/XE computers
n=2 Exclamation mark (!) loader
n=3 Binary loader from L.K. Avalon
-b Do not prepend any binary loader
-f Faster transfer speed (720 bd)
-g Generate longer (350 ms) IRGs
-e Generate empty FUJI tape image chunk
-p Convert the input file as a plain file
-pe Same as -p with usage of the "Data in EOF record trick"
-h,-help,-? Display usage instructions

  • Like 7
Link to comment
Share on other sites

Another update is available - version 2.4.

 

The changes are the following:

  • Included "Fancy loader" from XEX2CAS 1.5.
  • Included SIECOD verbose loader
  • Included BAS2CAS functionality

Command line arguments have been slightly changed. Refer to the readme.txt for more details.

Link to comment
Share on other sites

I have updated the default loader to STDBLOAD 2a. The loader uses the IOCB 0 opened for the E: device to display the program name and the inverse exclamation mark. There are no illegal OS jumps.

 

The signalization of errors has also changed. If an I/O error occurs, the screen becomes red. If the input file is not a binary file, the screen becomes light gray. Although this can look bit sloppy, there is a reason for it - the programs being loaded can do many things to prevent a text message from being displayed but cannot do much to prevent changes of the screen background color (GTIA COLBK register).

 

The updated version of XEX2CAS is available at http://www.baktra.wz.cz/software/xex2casv2.html.

Re-download the distribution archive.

Link to comment
Share on other sites

Thanks. I noticed that there were a few things that could be size-optimized in the loader, such as JSR+RTS -> JMP, and also an unnecessary load of ICSTA,X after JSR CIOV. CIO already returns the status code Y register and flags (OS manual, page 39).

 

Could the same be done for the BASIC loader? I maintain a replacement for Atari BASIC, and while it's source and binary compatible, it can't support internal entry points. XEX2CAS's BASIC loader appears to be pushing this onto the screen:

DIM X$(40)$="<asm>":POKE 842,12:POKE 764,12:GR.0:X=USR(ADR(X$))

where <asm>:
0878: A2 FD             LDX #$FD
087A: 9A                TXS
087B: A9 B7             LDA #$B7     ;>XRUN.NOFILE
087D: 48                PHA
087E: A9 54             LDA #$54     ;<XRUN.NOFILE
0880: 48                PHA
0881: A9 04             LDA #$04
0883: 20 B6 BB          JSR $BBB6    ;COPEN
0886: A9 FF             LDA #$FF
0888: 4C 04 BB          JMP $BB04    ;XLOAD

This uses internal entry points within Atari BASIC, so it fails on BASIC XE, etc. I'm not sure why all of this is done instead of just using RUN "C".

 

Finally, regarding the screen-stuffing routine that the BASIC loader uses:

053D: AD 30 02          LDA SDLSTL
0540: 85 80             STA $80
0542: AD 31 02          LDA SDLSTH
0545: 85 81             STA $81
0547: A0 04             LDY #$04
0549: B1 80             LDA ($80),Y
054B: 85 82             STA $82
054D: C8                INY
054E: B1 80             LDA ($80),Y
0550: 85 83             STA $83

The screen memory base is pointed to by SAVMSC ($58), as documented in p.222 of the OS manual. There's no need to pull it from the LMS instruction in the display list.

 

Link to comment
Share on other sites

I will try to fix the Atari BASIC initializer even though I haven't written it; it is worth the effort. The remaining loaders, however, will remain as they are - it really is not my ambition to fix all cassette binary loaders in the universe.

 

suppawer - Do we happen to have a source code for it? If not, it doesn't matter - I'll be looking forward to another friendly encounter with my favorite disassembler.

Link to comment
Share on other sites

Actually, after thinking about it a bit more, I'm not sure why the BASIC loader even does all of the direct manipulation of the screen and screen editor variables that it does -- all it should need to do is print RUN "C"<EOL><UpArrow> through CIOV and then push an ENTER key into CH, the way many AUTORUN.SYS loaders work. Should make it a bit smaller than it currently is.

 

I do recognize that this program has a collection of existing loaders and there is value in keeping the originals, even if they are hardcoded to a particular OS. However, it shouldn't encourage creation of new tapes that have unnecessary OS internal dependencies for silly reasons, as some of these loaders do. That's why I asked for at least the default loaders to be fixed.

Link to comment
Share on other sites

I do recognize that this program has a collection of existing loaders and there is value in keeping the originals, even if they are hardcoded to a particular OS. However, it shouldn't encourage creation of new tapes that have unnecessary OS internal dependencies for silly reasons, as some of these loaders do. That's why I asked for at least the default loaders to be fixed.

 

Yes, that is exactly why I hapilly agreed to fix the default STDBLOAD 2 loader. It is agreeable to have a good loader with source code available. Other loaders are present for "hisorical and nostalgia reasons."

 

I am not sure whether RUN"C:" will do the job. I was thinking about something like CLOAD followed by RUN. I'd like to avoid long 3000-ms inter-record-gaps.

Link to comment
Share on other sites

Hmm, yeah, forgot about that. BASIC won't run statements on the same line after a CLOAD, though, and you can't push more than one key at a time. That's a problem because you need two: one to start the cassette load and another to run the RUN command after it. It also won't work if the BASIC program is protected as the interpreter will crash trying to insert the RUN command.

 

It's probably easier to shim the C: device to force short IRGs. This would require: searching HATABS for the C: device table (normally at CASETV), copying the 12 byte device table to RAM, and then changing the OPEN routine. The new OPEN routine would force AUX2=$80, restore the old C: device table entry, and then chain to the original OPEN handler. Should work regardless of BASIC or OS, and even if someone loads a custom turbo C: handler first.

  • Like 1
Link to comment
Share on other sites

Perhaps we can try a different approach - the one used by BCOM and JBXEX utilities that embed basic to binary file

 

I can try to create a bootable machine language program that will pefrom the following:

1. Switch on the BASIC ROM

2. Load the tokenized BASIC (short IRGs) using CIO

2. Update 7 BASIC related pointers

3. Run the BASIC program

 

The question that remains to be answered is if there is an entry point that must be the same for all BASICs intended to be replacements of Atari BASIC ROM.

Link to comment
Share on other sites

Not that I know of. Some loaders hardcode $A000 as the Atari BASIC start vector, but I just checked Basic XE and it uses $B000 and $BFF3 as its init/run vectors due to bank switching. JMP ($BFFA) and ($BFFE) will get to those portably, but at best it only inits BASIC. There are no other official entry points for BASIC.

 

Doing a manual load is not hard, and may work, but step 3 is problematic. The only portable way to start a BASIC program is to inject a RUN command, and that will fail if the program is protected with a broken line 32768. No immediate mode commands can be run after a protected program loads, which is why they can only be run by a RUN "filename" command that combines both the LOAD and the RUN. In the end, this sounds less portable and more code than letting BASIC do the load.

Link to comment
Share on other sites

Hello Baktra,

Can you tell me if this PC software can rescue the dying and badly damaged real tapes ? I have a few badly damaged tapes , that it is not longer to be loading a games into memory of Atari. I am not sure if it is BASIC or machine language software. I do remember 1 thing, "Flash Spelling Bee" is in BASIC loading. I would be appreciating if it is any help to rescue of my old tapes.

Link to comment
Share on other sites

Hello Baktra,

Can you tell me if this PC software can rescue the dying and badly damaged real tapes ? I have a few badly damaged tapes , that it is not longer to be loading a games into memory of Atari. I am not sure if it is BASIC or machine language software. I do remember 1 thing, "Flash Spelling Bee" is in BASIC loading. I would be appreciating if it is any help to rescue of my old tapes.

 

It cannot. The purpose of this XEX2CAS software was, is, and always will be data transfer from PC to Atari. A software that can help you is A8CAS - http://a8cas.sourceforge.net/. In my opinion, the best one for recovering data from tapes. Still, I don't have to mention that recovering old tapes can turn out to be laborious and time consuming job that requires a lot of dedication.

Link to comment
Share on other sites

I've made certain progress, especially with the unprotected Atari BASIC files. It is possible to force CLOAD followed by RUN without usage of any "unofficial" entry points and the user still does not need to press any keys.

 

Now I'll try to create the modified C: handler that will force short IRGs

;Simple ATARI BASIC Initializer

           *=1536
          CIO0_OP   =$0342
          CIO0_STAT =$0343
          CIO0_BUFLO=$0344
          CIO0_BUFHI=$0345
          CIO0_LENLO=$0348
          CIO0_LENHI=$0349
          CIO0_AUX1 =$034A
          CIO0_AUX2 =$034B
                      
          CIOV      = 58454          
          SAVMSC      = 88
          BUFRLO      = 50
          BUFRHI      = 51
          CH          = 764
          RAMTOP      = 106
          BASICF      = 1016
          PTABW       = 201
          BOOT        = 9
          PORTB       = 54017
;-------------------------------------------------------------------------------
; Initialize BASIC values
;-------------------------------------------------------------------------------      
            lda #253             ;Switch ON BASIC ROM (XL/XE only)
            sta PORTB               

            ldx #0               ;No BOOT
            stx BOOT
            
            lda #10              ;Tab stops
            sta PTABW
            
            lda #0
            sta BASICF
            
            lda #160             ;Set RAMTOP right below BASIC ROM
            sta RAMTOP
            
GOBASIC     jsr INIBAS           ;Initialize BASIC cartridge   

;-------------------------------------------------------------------------------
;Initialize the screen editor
;-------------------------------------------------------------------------------
;Close the screen editor - it is using screen memory of BASIC ROM
ECLOSE      ldx #0
            lda #12
            sta CIO0_OP
            jsr CIOV
          
;Open the screen editor - screen memory will now be below BASIC ROM
EOPEN       ldx #0                ;IOCB 0
            lda #3                ;Requesting CIO OPEN operation with code 3
            sta CIO0_OP
            lda #12               ;Auxiliary value 12 - R/W access
            sta CIO0_AUX1
            lda #0                ;Auxiliary value  0 
            sta CIO0_AUX2
            lda #<EDEV            ;Buffer- DEVICE:FILENAME ("E:")
            sta CIO0_BUFLO
            lda #>EDEV
            sta CIO0_BUFHI
            jsr CIOV              ;Call CIO
            
;-------------------------------------------------------------------------------
; Prepare certain commands
;-------------------------------------------------------------------------------
            lda SAVMSC            ;Copy SAVMSC to BUFRLO,BUFRHI
            sta BUFRLO
            lda SAVMSC+1
            sta BUFRHI
            clc  
            lda BUFRLO
            adc #[3*40+2]
            sta BUFRLO
            lda BUFRHI
            adc #0
            sta BUFRHI        
            
            ldy  #0               ;Copy the CLOAD command
CMD1_L      lda  CMD1,Y     
            sta  (BUFRLO),Y  
            iny
            cpy  #5
            bne  CMD1_L
            
            lda  BUFRLO           ;Move 6 lines below
            adc  #[6*40-1]
            sta  BUFRLO
            lda  BUFRHI
            adc  #0
            sta  BUFRHI
            
            ldy  #0               ;Copy the POKE and RUN commands             
CMD2_L      lda  CMD2,Y     
            sta  (BUFRLO),Y  
            iny
            cpy  #15
            bne  CMD2_L
            
            lda  #12              ;Force RETURN key
            sta  CH               
            
            lda  #13              ;Set E: to forced reading
            sta CIO0_AUX1
;-------------------------------------------------------------------------------
;Run BASIC
;-------------------------------------------------------------------------------
;Run BASIC cartridge                     
            jmp (49146)           ;General cartridge RUN vector
INIBAS      jmp (49150)           ;General cartridge INIT vector                        
          
;-------------------------------------------------------------------------------
; Data area
;-------------------------------------------------------------------------------            
EDEV      .BYTE "E:",155

CMD1      .SBYTE "CLOAD"
CMD2      .SBYTE "POKE 842,12:RUN"

Link to comment
Share on other sites

I've updated XEX2CAS 2.4 : http://www.baktra.wz.cz/software/xex2casv2.html

Now it allows you to select the BASIC initializer using a new command line argument.

 

Options valid for the BOOTBASIC mode:

-bi<n> BASIC initializer selection:
n=0 LAUNCHBAS (default). This initializer has been written from
scratch. This initializer does not use any undocumented entry
points or routines and automatically attaches BASIC ROM on XL/XE
machines. On pre-XL/XE machines, BASIC must be attached.

n=1 BAS2CAS Initializer. Initializer from the BAS2CAS utility.

 

The LAUNCHBAS initializer utilizes all tricks proposed by phaeron.

 

In a nutshell, it initializes BASIC, forces the C: handler to use short IRGs (only once, of course) and forces execution of the RUN"C:" command. The source code of the LAUNCHBAS initializer is in the distribution archive, so it can be judged or blown to bits.

 

I am open to suggestions and bug reports.

Link to comment
Share on other sites

Don't forget to clear the carry flag before the second addition to BUFRLO/HI (this is why you're having to add 40-1, because carry is set). You can also add the first buffer offset while loading the pointer and count backwards in copying loops to save space, if space is a concern (although it may not be):

	lda SAVMSC	;Copy SAVMSC to BUFRLO,BUFRHI
	clc
	adc #[3*40]+2
	sta BUFRLO
	lda SAVMSC+1
	adc #0
	sta BUFRHI
           
	ldy  #4		;Copy the CLOAD command
CMD1_L	lda  CMD1,Y     
	sta  (BUFRLO),Y  
	dey
	bpl CMD1_L
            
	lda  BUFRLO	;Move 6 lines below
	clc
	adc  #[6*40]
	sta  BUFRLO
	bcc  *+2
	inc  BUFRHI
            
	ldy  #14	;Copy the POKE and RUN commands             
CMD2_L	lda  CMD2,Y     
	sta  (BUFRLO),Y  
	dey
	bpl  CMD2_L
It might be quicker to simply use the CIO to print the strings to the screen, however? Edited by flashjazzcat
Link to comment
Share on other sites

Thank you for spotting the missing CLC. The size of the loader is not a big concern (unless it gets one block longer), so I'll keep the loop as it is, counting forward. I am not going to use CIO to print the BASIC commands, now when it is only one line.

 

The latest version has more polished display. Instead of displaying the BASIC commands, it just displays B (as BASIC) in the top corner of the screen. The trick with the RUN"C:" and IRGs is crude, but appears to be working. This will allow the "protected programs" to run.

;Simple ATARI BASIC Initializer
;
;This program executes a tokenized ATARI BASIC program saved with short
;IRGs by forcing a RUN"C:" command

           *=16384
                      
          CIO0_OP   =$0342
          CIO0_STAT =$0343
          CIO0_BUFLO=$0344
          CIO0_BUFHI=$0345
          CIO0_LENLO=$0348
          CIO0_LENHI=$0349
          CIO0_AUX1 =$034A
          CIO0_AUX2 =$034B
                      
          CIOV      = 58454          
          SAVMSC      = 88
          BUFRLO      = 50
          BUFRHI      = 51
          BFENLO      = 52
          BFENHI      = 53
          CH          = 764
          RAMTOP      = 106
          BASICF      = 1016
          PTABW       = 201
          BOOT        = 9
          PORTB       = 54017
          HATABS      = 794
          ICAX2Z      = 43
          COLDSV      = 58487
          PACTL       = 54018

;-------------------------------------------------------------------------------
; Boot header
;-------------------------------------------------------------------------------          
.IF LDRTYPE=0
BOOTHEAD  .BYTE 0                 ;Boot mark
          .BYTE 3                 ;3 records
          .WORD [16384]           ;Program start
          .WORD CXORTS            ;Simple RTS
          lda  #60                ;Motor off
          sta  PACTL
          ldx  #255               ;Clear pushdown store
          txs
.ENDIF          
;-------------------------------------------------------------------------------
; Initialize BASIC values
;-------------------------------------------------------------------------------      
            lda #253             ;Switch ON BASIC ROM (XL/XE only)
            sta PORTB               

            ldx #0               ;No BOOT
            stx BOOT
            
            lda #10              ;Tab stops
            sta PTABW
            
            lda #0
            sta BASICF
            
            lda #160             ;Set RAMTOP right below BASIC ROM
            sta RAMTOP
            
GOBASIC     jsr INIBAS           ;Initialize BASIC cartridge   

;-------------------------------------------------------------------------------
;Initialize the screen editor
;-------------------------------------------------------------------------------
;Close the screen editor - it is using screen memory of BASIC ROM
ECLOSE      ldx #0
            lda #12
            sta CIO0_OP
            jsr CIOV
          
;Open the screen editor - screen memory will now be below BASIC ROM
EOPEN       ldx #0                ;IOCB 0
            lda #3                ;Requesting CIO OPEN operation with code 3
            sta CIO0_OP
            lda #12               ;Auxiliary value 12 - R/W access
            sta CIO0_AUX1
            lda #0                ;Auxiliary value  0 
            sta CIO0_AUX2
            lda #<EDEV            ;Buffer- DEVICE:FILENAME ("E:")
            sta CIO0_BUFLO
            lda #>EDEV
            sta CIO0_BUFHI
            jsr CIOV              ;Call CIO
            
;-------------------------------------------------------------------------------
; Hack the C: handler open routine to force short IRGs for just one OPEN
; operation
;-------------------------------------------------------------------------------

;Find the routine table for the C: device. Start from the end of HATABS
            ldx #33                ;Point to the beginning of HATABs
FDEVICE_L   lda HATABS,X           ;Get device letter 
            cmp #67                ;Is it C ?
            beq FDEV_Y             ;Yes, we found it
            cpx #0                 ;All entries searched?
            beq FDEVICE_NF         ;Yes, then cold start
            dex                    ;Decrease X by 3
            dex
            dex                     
FDEVICE_E   jmp FDEVICE_L          ;And continue loop
FDEVICE_NF  jmp COLDSV             ;No C handler found - cold start           

;Copy the routine table             
FDEV_Y      inx                    ;Get address of the original routine table 
            lda HATABS,X
            sta BUFRLO
            inx
            lda HATABS,X
            sta BUFRHI
            
            lda #<RTABLECPY        ;Get address of a copy of the I/O table
            sta BFENLO
            lda #>RTABLECPY
            sta BFENHI
            
            ldy #0                 ;Copy the I/O table
FDEV_C_L    lda (BUFRLO),Y
            sta (BFENLO),Y
            iny
            cpy #13
            bne FDEV_C_L
            
;Change HATABS entry so it points to the copy of the I/O table
            lda #>RTABLECPY
            sta HATABS,X
            dex
            lda #<RTABLECPY
            sta HATABS,X            
            stx HATABS_OFFSET      ;We keep the HATABS offset for later use
            
;Keep original table address and original OPEN routine address
            lda BUFRLO            
            sta ORIGTABLE
            lda BUFRHI
            sta ORIGTABLE+1
            
            lda RTABLECPY
            sta ORIGOPEN
            lda RTABLECPY+1
            sta ORIGOPEN+1

;Introduce our new OPEN routine to the copy of the I/O table            
            lda #<[CXOPEN-1]
            sta RTABLECPY
            lda #>[CXOPEN-1]
            sta RTABLECPY+1
            
;-------------------------------------------------------------------------------
; Prepare forced BASIC commands
;-------------------------------------------------------------------------------
            lda SAVMSC            ;Copy SAVMSC to BUFRLO,BUFRHI
            sta BUFRLO
            lda SAVMSC+1
            sta BUFRHI
            clc  
            lda BUFRLO
            adc #[3*40+2]
            sta BUFRLO
            lda BUFRHI
            adc #0
            sta BUFRHI        
            
            ldy  #0               ;Copy the POKE and RUN commands
CMD1_L      lda  CMD1,Y     
            sta  (BUFRLO),Y  
            iny
            cpy  #34
            bne  CMD1_L
            
            lda  #13              ;Enable forced reading 
            sta CIO0_AUX1
            lda  #12              ;Force key pressed
            sta  CH
            
;-------------------------------------------------------------------------------
;Run BASIC
;-------------------------------------------------------------------------------
;Run BASIC cartridge                     
            jmp (49146)           ;General cartridge RUN vector
INIBAS      jmp (49150)           ;General cartridge INIT vector                        
          
;-------------------------------------------------------------------------------
; OPEN routine that forces short IRGs and cascades to the original one 
;-------------------------------------------------------------------------------
CXOPEN      lda #128              ;Force short IRGs on channel 7       
            sta CIO0_AUX2+[7*16]
            sta ICAX2Z
            
            stx SAVEX
            ldx HATABS_OFFSET     ;Restore HATABS entry to the original
            lda ORIGTABLE
            sta HATABS,X
            lda ORIGTABLE+1
            inx
            sta HATABS,X
            ldx SAVEX
            
            lda ORIGOPEN+1        ;Jump to the original OPEN routine by
            pha                   ;forcing entries in the pushdown store
            lda ORIGOPEN          ;and using rts
            pha
 CXORTS     rts
;-------------------------------------------------------------------------------
; Data area
;-------------------------------------------------------------------------------            
EDEV          .BYTE "E:",155                  ;Screen editor device string
CMD1          .SBYTE "POKE 842,12:?CHR$(125);"B":RUN"C:""    ;Forced BASIC commands
ORIGTABLE     .BYTE 0,0                       ;Address of the original I/O table
ORIGOPEN      .BYTE 0,0                       ;Address of the original OPEN
HATABS_OFFSET .BYTE 0                         ;C: HATABS offset
SAVEX         .BYTE 0                         ;Storage for X register
RTABLECPY     .REPT 12                        ;Copy of the I/O table
              .BYTE 0
              .ENDR

 

 

 

 

 

 

 

 

 

 

Link to comment
Share on other sites

I did some tweaks to the loader. Changes:

  • Changed to build under MADS for testing -- hopefully shouldn't be hard to convert back.
  • Shrunk from 3 blocks to 2 blocks.
  • Now works in 16K -- changed load address from $4000 to $0600 and made RAMTOP adjustment conditional.
  • Moved second ENTER push to C: open handler and shrunk BASIC command line.
  • Removed unnecessary PTABW write -- BASIC init does this.
  • Clear WARMST to ensure proper BASIC init.
  • Clear COLDST so BASIC program is preserved on System Reset.
  • C: open shim no longer assumes IOCB #7.
  • Moved BASIC init after screen init just in case (although I believe this is just RTS on all BASICs).

 

basicboot.s

  • Like 1
Link to comment
Share on other sites

I have embedded the new BASIC initializer to the XEX2CAS 2.4 and re-released the archive. The old BAS2CAS initializer is still an option.

 

As I don't plan any new features, it would appear that the work has been done and we have yet another tape-oriented utility. If you find any defects, you can add a post to this thread.

 

I am grateful for all your help.

Link to comment
Share on other sites

For those of you who don't want go back to the dark ages of the command line, there is a new version of Turgen System.

The new version brings an equivalent of the -bootbasic function and the STDBLOAD 2a binary loader.

http://turgen.sourceforge.net/

You can see it in action here: http://youtu.be/NHxlpKppbz8

Edited by baktra
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...