Jump to content
IGNORED

High score cart source code


GroovyBee

Recommended Posts

Is there a binary or the source code floating around for the 7800's high score cart? I've looked at Curt's site and downloaded the Desert Falcon high score cart accessing source code, but I'd like a look at what the cart actually does. I've searched the forums here but not found anything (maybe I'm not using the right search terms). Thanks in advance.

Link to comment
Share on other sites

Is there a binary or the source code floating around for the 7800's high score cart? I've looked at Curt's site and downloaded the Desert Falcon high score cart accessing source code, but I'd like a look at what the cart actually does. I've searched the forums here but not found anything (maybe I'm not using the right search terms). Thanks in advance.

 

You can snag the BIN off of my website here. I don't think source code has been found (yet). If you do a disassembly I'm sure people would love to see it. That and a PAL version. :)

 

Mitch

Link to comment
Share on other sites

I've started working on this. There are 7 entry points into the ROM at the following addresses :-

 

0x3FEB - HSCSETRS (some form of initialisation?)

0x3FEE - ??

0x3FF1 - ??

0x3FF4 - ??

0x3FF7 - HSCSTAT (??)

0x3FFA - HSCATRCT (Attract mode)

0x3FFD - HSCENTER (Enter high score)

 

The names are taken from Beefdrop. What do the unknown ones do? Does anybody have any notes on the format of the data passed to/from these functions? Its in various games source code but maybe folks have some notes lying around they could share here.

Link to comment
Share on other sites

Status update...

 

High score cart ROM dissassembled.

All h/w addresses fixed up to documented names.

Found jump vectors.

Found font data (just needs converting to byte data directives).

Found watkins string data (already converted).

Added some comments.

 

Just need to...

Find DLL and DL data and convert to assembler byte directives.

Rebuild and compare as needed until it matches the original.

Post the commented source code.

 

No "easter egg" strings found so far :lol:.

 

It looks to be tightly packed code. It might be hard to wedge PAL support in there :(.

Link to comment
Share on other sites

  • 3 weeks later...

Heres the latest version. I haven't reverse engineered much at the moment, but it builds an exact copy of the original. You'll need DASM to build it.

 

High_Score_Cart.29_04_09.v1.00.zip

Any help from the high score cart using gurus would be much appreciated. Basically I'm looking to document the ins and outs of the functions called using the entry points at the end of the ROM.

Link to comment
Share on other sites

Here ya go...

 

 

* 1415 280384

*

** HISCORE.S

** ASTEROIDS FOR THAT DAMN ATARI 3600, OR IS IT 7000, I FORGET. *

** WRONG!! IT'S THE ATARI 7800 PRO SYSTEM. TA DA! *

** THIS FILE CONTAINS THE HANDLERS FOR THE INTERFACE TO THE HISCORE CART *

** UPDATED TO HSC REV 7.X *

 

* HSCINIT -- INITIALIZE HIGH SCORE CART DATA. DOES HSCSTAT.

* RETURNS > 0 IF NO HSC EXISTS, < 0 IF ENTRY NOT FOUND, ZERO IF OK

HSCINIT:

JSR HSCSETDM ;SET UP DIFF/MODE LEVEL ARGUMENT

HSCINIT2:

LDA #$C6 ;CHECK EXISTANCE.

CMP $3900

BNE NOHSC

LDA #$FE

CMP $3904

BNE NOHSC

 

LDX #$0E ;COPY HSC ROM INTO RAM ARGUMENT BLOCK

HSCCOPY:

LDA HSCROM,X

STA HSCRAM,X

DEX

BPL HSCCOPY

 

LDA TEMP ;INSTALL LEVEL ARGUMENT

ASL

ASL

STA HSCRAM+2

 

; LDX #L(HSCRAM) ;WHY BOTHER; HSC TRASHES X ANYWAY

LDY #HSCRAM >> 8

JMP HSCSTAT

 

NOHSC:

LDA #1 ;POSITIVE NUMBER = NO HIGH SCORE

RTS

 

* HSSUCK -- SUCK IN HIGH SCORE, IF AVAILABLE. IF NOT ZAP IT OUT.

HSCSUCK:

JSR ZEROHS ;FIRST ZAP IT OUT

JSR HSCINIT ;SUCK IN HIGH SCORE, IF AVAILABLE

BNE NOHSC

LDX #3

SUCKHSIN:

LDA HSCRAM+$F,X

STA HISCORE,X

DEX

BPL SUCKHSIN

RTS

 

* HSCSHOW -- DISPLAY ONE DIFF/MODE LEVEL

HSCSHOW:

JSR HSCINIT2 ;USE INIT2 SO NOT TO DISTURB TEMP VAL

BNE NOHSC

 

LDX HSCRAM+4 ;COMPUTE DISPLAY TIMES FOR EACH LEVEL

CPX #5 ;USE MINIMUM TIME IF >= 5 ENTRIES

BCC ZNHSOK

LDX #5

ZNHSOK:

LDA HSTIME,X ;TABLE LOOKUP FOR DISPLAY TIME

STA HSCRAM+$E

 

LDA TEMP ;TEMP CONTAINS THE DIFF/MODE LEVEL

ASL ; SHIFT UP FOR ARG FORMAT

ASL

STA HSCRAM+2

 

JSR HSCDM ;PUT UP OUR OWN DIFFICULTY/MODE NAMES

JSR ONTITLE ;PUT UP THE LOGO

 

JSR WAITLOAD ;WAIT FOR LOADER TO UPDATE

LDA #$60 ;TURN OFF DMA NOW, SO WE DON'T GET

STA CTRL ; A GLITCHY SCREEN IN BETWEEN

LDA #$40 ;TELL NMI HANDLER TO DO FANCY

STA NMICTRL ; ALTERNATING READ MODES ON CTRL

 

; JSR OLDBUTON ;GO BACK TO ONE BUTTON MODE

; LDX #L(HSCRAM)

LDY #HSCRAM>>8

JSR HSCATRCT

; JSR NEWBUTON ;REVERT TO WHATEVER MODE WAS BEFORE

 

RTS

 

* HSCDOENT -- DO CALLS TO HSCENTER FOR ALL PLAYERS WHAT NEEDS IT

HSCDOENT:

JSR HSCINIT ;SET UP HSC

BEQ ZHSENTOK ;DOES THE HSC EXIST?

BPL NOHSC ;NO. DO NOTHING.

ZHSENTOK:

LDA HSCRAM+2 ;SET UP TEMP TO DM VALUE

LSR

LSR

STA TEMP

 

JSR HSCDM ;PUT UP DIFF/MODE INDICATORS

JSR ONTITLE ;PUT UP THE LOGO

 

LDA MODE ;SET UP ENTER DELAY FOR THIS MODE

LSR

BCC ZNOWAIT ;ON EVEN MODES, DON'T WAIT HERE.

LDA #10 ;ON ODD MODES, WAIT 10 SECONDS. THERE

STA HSCRAM+$E ; IS ONLY ONE SCORE BEING ENTERED.

ZNOWAIT:

LDA MODE ;IF IN ONE PLAYER MODE JUST

BMI ZHSCENT ; DO THIS ONE.

 

LDX #0 ;PICK HIGHER OF THE TWO FIRST!

ZCOMPLOP:

LDA SCORE,X ; COMPARE EACH DIGIT OF P1 SCORE

CMP SCORE+4,X ; AGAINST EACH DIGIT OF P2 SCORE

BEQ ZP2EQU ; P1 EQUALS P2, MOVE ON TO NEXT DIGIT

BCS ZPNGO ; P1 > P2, LET P1 ENTER

ZP2GO: ; P2 > P1, LET P2 ENTER

INC HSCRAM+2 ; TOGGLE PLAYER BIT TO P2

LDA #SCORE2 & 255 ; CHANGE TO P2 SCORE

STA HSCRAM+8

ZPNGO:

 

LDA MODE ;IN TEAMPLAY MODE, USE COMBINED SCORE

CMP #1

BNE ZHSCENT

LDA #COMBSCOR & 255

STA HSCRAM+8 ;LOW ADDR OF SCORE PTR. HI ADDR = 0 ZP

 

ZHSCENT:

JSR WAITLOAD ;WAIT FOR LOADER TO UPDATE

LDA #$60 ;TURN OFF DMA NOW, SO WE DON'T GET

STA CTRL ; A GLITCHY SCREEN IN BETWEEN

LDA #$40 ;TELL NMI HANDLER TO DO FANCY

STA NMICTRL ; ALTERNATING READ MODES ON CTRL

 

; JSR OLDBUTON ;GO BACK TO ONE BUTTON MODE

; LDX #L(HSCRAM)

LDY #HSCRAM >> 8

JSR HSCENTER

; JSR NEWBUTON ;REVERT TO WHATEVER MODE WAS BEFORE

 

LDA HSCRAM+$E ;CHECK DELAY TIME:

BNE ZHSCRTS ; IF NOT ZERO, WE'RE DONE.

 

LDA #10 ;SET DELAY TIME TO FINAL DELAY.

STA HSCRAM+$E

 

LDA HSCRAM+2 ;CHECK PLAYER BIT TO SEE WHICH PLAYER

LSR

BCC ZP2GO ;IF WE JUST DID P1, THEN DO P2

ZP1GO:

LDA #SCORE & 255 ;GO BACK TO P1 SCORE

STA HSCRAM+8

DEC HSCRAM+2 ;GO BACK TO P1 JOYSTICK

JMP ZHSCENT

 

ZP2EQU:

INX ; MOVE ON TO NEXT DIGIT

CPX #4 ; 4 DIGITS OF SCORE TO COMPARE

BEQ ZPNGO ; IF WE HAVE DONE ALL COMPARES, DFLT P1

BNE ZCOMPLOP ; IF NOT, DO NEXT COMPARE

 

* HSCDM -- PUT UP DIFF/MODE ICONS ACCORDING TO VALUE OF TEMP

HSCDM:

LDA TEMP

AND #$03 ;GET DIFF BITS

CLC

ADC #10

TAY

LDX #10

JSR DOICON

LDA TEMP

LSR ;GET MODE BITS

LSR

BEQ HSCZAPM ;ONLY DISPLAY TEAM AND COMPETITVE PLAY

CLC

ADC #15

TAY

INX ;10+1=11

JSR DOICON

ZHSCRTS:

RTS

 

HSCZAPM:

LDA #$FF ;ZAP OUT STATUS OF MODE ICON

STA STATUS+11

RTS

 

* HSCSETDM -- SET DIFF/MODE LEVEL ARGUMENT BASED ON DIFF AND MODE

HSCSETDM:

LDA MODE ;COMPUTE DIFF/MODE LEVEL VALUE BYTE

BPL ZHSCMOK

LDA #0

ZHSCMOK:

ASL

ASL

CLC

ADC DIFF

STA TEMP ;SAVE IT WHERE WE CAN INSERT LATER

RTS

 

* GO TO OLD ONE-BUTTON MODE FOR WAT'S HISCORE CART

;OLDBUTON LDA #$FF

;ZOLDSTOR STA SWCHB

; RTS

* GO BACK TO PREVIOUS STATE

;NEWBUTON LDA ONEBUT

; BPL ZOLDSTOR

 

; THIS TABLE IS COPIED INTO RAM WHEN HSC IS CALLED. IT'S THE ARGUMENT BLOCK

; NEEDED BY THE HSC.

 

HSCROM:

.DC.B $49,$6C ; CARTRIDGE ID NUMBER

 

.DC.B $00 ; DIFFICULTY LEVEL

; + PLAYER NUMBER (BOTTOM 2 BITS)

 

.DC.B $01 ; CONTROLLER TYPE

 

.DC.B $00,$00 ; GAME NAME; WE USE OUR OWN LOGO.

 

.DC.B $00,$00 ; DIFFICULTY NAME; WE USE OUR OWN.

 

.DC.W SCORE ; POINTER TO THE SCORE

 

.DC.W HSCDLL ; POINTER TO DLL

 

.DC.W LOGOBARS ;SOUND ROUTINE. WE USE THIS TO TWINKLE

; OUR LOGO BARS WHILE OFF SCREEN.

 

.DC.B $00 ; SECONDS TO WAIT BEFORE RETURNING

; (FOR EACH DIFFICULTY LEVEL)

 

* HSCDLL -- DLL FOR HSC DISPLAY. MERELY A RE-ARRANGED VERSION OF DLLTAB W/DLIS

HSCDLL:

.DC.B $8F

.DC.B BLANKDL>>8,BLANKDL&255 ;DLI + 16 BLANK LINES

 

.DC.B $4F

.DC.B (GAMEDL07+4)>>8,(GAMEDL07+4)&255 ;NO DLI + MODE

 

.DC.B $4F

.DC.B (GAMEDL04+4)>>8,(GAMEDL04+4)&255 ;NO DLI + TOP OF LOGO

 

.DC.B $4F

.DC.B (GAMEDL05+4)>>8,(GAMEDL05+4)&255 ;NO DLI + BOTTOM OF LOGO

 

.DC.B $4F

.DC.B (GAMEDL11+4)>>8,(GAMEDL11+4)&255 ;NO DLI + DIFF LEVEL

 

* HSTIME -- TIME TO DISPLAY EACH ENTRY FOR A GIVEN TOTAL NUMBER OF ENTRIES.

HSTIME:

.DC.B 0,10,6,5,4,3

Link to comment
Share on other sites

A couple of things I noticed when using the HSC from within games:

 

1) In the two bytes for the Game ID, the left-most bit of the first byte has a meaning: it is '0' if it displays the score as-is, and '1' if it adds a zero to the end (like in the case of Ms. Pac-Man).

2) When calling any of the routines, you *must* initialize the joystick ports, or the entry can either crash, or get some invalid values in your variables (I found this out the hard way). :( i.e.:

LDA #$00

STA CTLSWA ;(CTLSWA is set to $281)

STA CTLSWB ;(CTLSWB is set to $283)

 

Here is a list of all of the games that use the HSC and their values:

http://www.atariage.com/forums/index.php?showtopic=128432

 

To date, I've only used the three routines you've documented: HSCSTAT which also brings in the current scores for whatever skill level you call it with (third byte). This is useful for showing the High Score just after booting the cart (I do this in Space Invaders), HSCATRCT (shows the current list of High Scores), and HSCENTER (Enters the high score)

 

I did notice some interesting TEXT in there though... something about deleting a score or re-initializing - that may be useful. I may play around with the other three 'undocumented' entry points to see what they do... :)

 

Thanks!

Bob

Edited by PacManPlus
Link to comment
Share on other sites

@PacManPlus

 

Thanks for the information.

 

When you get some free time could you make some notes regarding the data input/output format/layout that the High Score Cart subroutines expect? Just some notes along the lines of :-

 

Offset 0x?? Description

 

I know I could extract it from the source code out there (Beef Drop, Desert Falcon, etc.) but it would only be assumptions on my part because I don't have the hardware to try it out.

Link to comment
Share on other sites

No Problem :)

 

This is the template I use now for my HSC setup:

 

 

;  TEMPLATE FOR HSC TABLE
HSCTEMP
	 .byte	 $80,$00			   ;TRASILING ZERO [BIT 7 OF FIRST BYTE],  AND ID NUMBER
	 .byte	 $00				   ;DIFFICULTY [BITS 4..2] AND PLAYER [1..0] - PLAYER IS *REQUIRED*
	 .byte	 $01				   ;CONTROLLER TYPE
	 .byte	 $00,$00			   ;POINTER TO GAME NAME (IF LOGO IS USED, MAKE $00,$00)
	 .byte	 <(HSCDIF),>(HSCDIF)   ;POINTER TO DIFFICULTY NAME
	 .byte	 $00,$00			   ;POINTER TO SCORE
	 .byte	 <(HSCDLL),>(HSCDLL)   ;POINTER TO DLL FOR LOGO
	 .byte	 <(HSCSOUND),>(HSCSOUND);POINTER TO SOUND ROUTINE
	 .byte	 $00				   ;TIME TO WAIT TILL RETURN

;<---------------------------------------------HIGH SCORE CART RPD SECTION--------------------------------------------------->
; HIGH SCORE DISPLAY LIST LIST
HSCDLL
	 .byte	$8F,>(HSCNLDL),<(HSCNLDL);16 BLANK LINES
	 .byte	$47,>(HSCNLDL),<(HSCNLDL);8  BLANK LINES
	 .byte	$45,>(HSCDLS0),<(HSCDLS0)
	 .byte	$45,>(HSCDLS1),<(HSCDLS1)
	 .byte	$45,>(HSCDLS2),<(HSCDLS2)
	 .byte	$45,>(HSCDLS3),<(HSCDLS3)
	 .byte	$45,>(HSCDLS4),<(HSCDLS4)
	 .byte	$45,>(HSCDLS5),<(HSCDLS5)
	 .byte	$45,>(HSCDLS6),<(HSCDLS6)
	 .byte	$45,>(HSCDLS7),<(HSCDLS7)
	 .byte	$00,$00,$00

; HIGH SCORE DISPLAY LIST (ONLY USES CHARACTER MODE)
HSCDLS0  .byte  <(HLIST00),$60,>(HLIST00),$00+$04,$14,$00,$00,$00
HSCDLS1  .byte  <(HLIST01),$60,>(HLIST01),$00+$04,$14,$00,$00,$00
HSCDLS2  .byte  <(HLIST02),$60,>(HLIST02),$00+$04,$14,$00,$00,$00
HSCDLS3  .byte  <(HLIST03),$60,>(HLIST03),$00+$04,$14,$00,$00,$00
HSCDLS4  .byte  <(HLIST04),$60,>(HLIST04),$00+$04,$14,$00,$00,$00
HSCDLS5  .byte  <(HLIST05),$60,>(HLIST05),$00+$04,$14,$00,$00,$00
HSCDLS6  .byte  <(HLIST06),$60,>(HLIST06),$00+$04,$14,$00,$00,$00
HSCDLS7  .byte  <(HLIST07),$60,>(HLIST07),$00+$04,$14,$00,$00,$00
;			   CHAR MODE DATA-DON'T CHNG,PAL+LNG,POS,END MARKER
HSCNLDL  .byte	$00,$00,$00

; HIGH SCORE SCREEN MEMORY - THIS IS WHERE THE CHARACTER MODE LOGO IS STORED
HLIST00  .byte	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
HLIST01  .byte	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
HLIST02  .byte	$00,$00,$00,$00,$00,$00,$00,$83,$88,$8D,$92,$97,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
HLIST03  .byte	$00,$00,$00,$00,$00,$00,$00,$84,$89,$8E,$93,$98,$9C,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
HLIST04  .byte	$00,$00,$00,$00,$00,$00,$00,$85,$8A,$8F,$94,$99,$9D,$A0,$00,$A4,$A7,$AA,$AD,$AF,$A4,$B2,$B3,$00,$00,$00,$00,$00,$00
HLIST05  .byte	$00,$00,$00,$00,$00,$00,$00,$86,$8B,$90,$95,$9A,$9E,$A1,$A3,$A5,$A8,$AB,$AE,$95,$B0,$A8,$AB,$00,$00,$00,$00,$00,$00
HLIST06  .byte	$00,$00,$00,$00,$00,$00,$00,$87,$8C,$91,$96,$9B,$9F,$A2,$00,$A6,$A9,$AC,$91,$96,$B1,$A9,$AC,$00,$00,$00,$00,$00,$00
HLIST07  .byte	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00

 

The numbers in the SCREEN MEMORY (HLIST00-HLIST07) refer to the characters on the screen ($00 = blank, logo stored in $80-$C0)

All of this is held in ROM. I then have a byte in the DLI which switches to this display mode when in high score mode.

 

Hope this helps!

Bob

Link to comment
Share on other sites

  • 1 year later...

Another thing I recently found out while making Super Circus AtariAge:

 

* ANOTHER IMPORTANT NOTE - If you change the fourth byte of the HSC (the controller type byte) to anything greater than $01, the HSC crashes.

 

I really need to look at the disassembly to see what it does with this byte :ponder:

Link to comment
Share on other sites

  • 2 years later...

In my development of Donkey Kong XM, I have been playing around with the HSC cart in prosystem under PAL and have learned a few things.

 

I'll first start with how I got HSC to work with Prosystem. Since prosystem incorrectly treats everything up to $4000 as continuous ram, I simply copied a 2k saved RAM binary to $1000 and copied the HSC ROM to $3000. I did this by assembling my code with the binary data in an unused ROM bank. When the game is being initialized, I switch to that bank and copy the binary data to RAM. It then looks to prosystem like the HSC is present. The only drawback is that I can't easily save the HSC data before exiting Prosystem. I have to use a save state and hex editor to get the HSC data back into a binary file. But for game debugging purposes, this works fine.

 

Here's what I learned.

 

1) HSC ram should at a minium be cleared before calling hsettemp. I was having problems with my top and bottom DLI's getting out of sync. I found it was due to garbage data at the end of the HSC DLL that was generating unwanted DLI's. This is also what causes the garbage at the bottom of the screen when using HSC on PAL systems.

 

2) This may be old news for some, but I only just realized that only the 1st 7 DLL's for the game logo get used. I had a few more, but they would never appear. When the HSC creates the DLL in HSCRAM, it copies the LOGODLL in and then writes it's own DLL starting with number 8.

 

3) The HSC only creates enough DLL's for NTSC scan lines and they are always in the same location relative to HSCRAM. If HSCRAM=$1800, then the last HSC DLL entry will be at $19e1 or $19d9, depending on which function is running on the HSC. So if you write some dll's pointing to a null dl, starting at $19de, prior to calling the HSC routine, you can fill in the remaining PAL scan lines. I just wrote enough DLL's to reach the end of HSCRAM. This eliminates the garbage at the bottom of the screen using valid DLL/DL's.

 

So now my PAL HSC seems to be working cleanly without garbage at the bottom of the screen. :)

  • Like 3
Link to comment
Share on other sites

  • 6 months later...
  • 10 months later...

I worked GroovyBee's disassembly a fair bit more...

 

High_Score_Cart.06_12_14.v1.10.zip

 

Here's the new details on the jump vectors. I made up the names for HSCCPYFM and HSCCPYTO, since no game that we have the source code to actually uses them.

 

0x3feb - HSCSETRS ... set P#C2 and CHARBASE registers for HSC

0x3fee - HSCCPYFM ... copy from game's high score entry to (8F)

0x3ff1 - HSCCPYTO ... copy to game's high score entry from (8F)

0x3ff4 - HSCENTER2 ... just HSCENTER with a different Entry ID

0x3ff7 - HSCSTAT ... check status of HSC

0x3ffa - HSCATRCT ... show HSC table for attract mode

0x3ffd - HSCENTER ... enter high scores for users

 

I believe the values for 8F and 90 are populated with the 2 HSCRAM values after your 15 bytes of argument data, though I haven't tested that.

  • Like 2
Link to comment
Share on other sites

  • 4 weeks later...

That would be easy, just like a POKEY passthrough cart, the problem is the stupid cartridge ports. I managed to get my hands on a virgin original, but quantities are not easy. I suppose someone with the right contacts could get them made in China, by just sending them one to copy.

Link to comment
Share on other sites

Yeah, I hear that.

 

Just the same, if someone were to sell bare bones boards and PLD, I'd still be in. I imagine there would be console resellers that would fill the gap for those who couldn't do the mod, similar to what happens now with consoles modded for video.

 

But I'm not pressuring you for your buy-in, bud. I know I couldn't, even if I wanted to. :P Just some spitballing.

Link to comment
Share on other sites

Just the same, if someone were to sell bare bones boards and PLD, I'd still be in. I imagine there would be console resellers that would fill the gap for those who couldn't do the mod, similar to what happens now with consoles modded for video.

Indeed. Best Electronics and Electronic Sentimentalities perhaps would see a NICE spike in business, to say the least of any those with a similar reputation for quality and delivery here on AtariAge.

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