TMSS

From MegaDrive Development Wiki
Jump to: navigation, search

The TMSS (Trade Mark Security Software) is the little rom inside the console who will verify if the game is licenced by SEGA.

At startup the console with execute the TMSS code and not the cart one.

The TMSS will check if the string at 0x100 is either 'SEGA' or ' SEGA'. If it is, it will display "PRODUCED BY OR UNDER LICENCE FROM SEGA ENTERPRISES LTD" on the screen for about 2 seconds then start the game. If not it will simply display a black screen.

The code use two register, $A14000 and $A14101. The first it used to lock/unlock the VDP by writing either "SEGA" to unlock it or anything else to lock it. The second control the bankswitching between the cart and the TMSS rom.

Setting the first bit to 1 enable the cart, and setting it to 0 enable the TMSS.

Here is the code disassembled and commented.

		.long 0xFFFF00
		.long START
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.long INT
		.ascii "SEGA GENESIS    "
		.ascii "(C)SEGA 1990.MAY"
		.ascii "GENESIS OS                                      "
		.ascii "GENESIS OS                                      "
		.ascii "OS 00000000-00"
		.word 0x5B74
		.ascii "                "
		.long 0
		.long 0x7FF
		.long 0xFF0000
		.long 0xFFFFFF
		.ascii "            "
		.ascii "                                                    "
		.ascii "U               "


INT:
		bra.s	INT

START:		lea	reg_data_1, a5
		movem.l	(a5)+, d5-a4
		move.b	-0x10FF(a1), d0	| Read version register	(0xA10001)
		andi.b	#0xF, d0
		beq.s	_version_00
		move.l	#'SEGA', 0x2F00(a1) | Enable VDP

_version_00:
		move.w	(a4), d0	| Read VDP control port	???
		moveq	#0, d0
		movea.l	d0, a6
		move	a6, usp		| Set stack to 0x0
		moveq	#0x17, d1

_setup_vdp_reg:
		move.b	(a5)+, d5
		move.w	d5, (a4)
		add.w	d7, d5
		dbf	d1, _setup_vdp_reg
		move.l	#0x40000080, (a4) | VRAM Fill command
		move.w	d0, (a3)	| FIll VRAM with 0x00

_wait_for_dma:
		move.w	(a4), d4
		btst	#1, d4
		bne.s	_wait_for_dma
		move.l	#0x81048F02, (a4) | DMA	disable, autoinc to 2
		move.l	#0xC0000000, (a4) | Write to CRAM command
		moveq	#0x1F, d3

_clr_cram:
		move.l	d0, (a3)
		dbf	d3, _clr_cram
		move.l	#0x40000010, (a4) | Write to VSRAM command
		moveq	#0x13, d4

_clr_vsram:
		move.l	d0, (a3)
		dbf	d4, _clr_vsram
		moveq	#3, d5

_write_to_psg:
		move.b	(a5)+, 0x11(a3)
		dbf	d5, _write_to_psg
		bra.s	loc_2AA

reg_data_1:	.long 0x8000		| d5
		.long 0x3FFF		| d6
		.long 0x100		| d7
		.long 0xA00000		| a0
		.long 0xA11100		| a1
		.long 0xA11200		| a2
		.long 0xC00000		| a3
		.long 0xC00004		| a4
		.byte 4			| VDP Reg #0, Disable INT, Disable HV counter
		.byte 0x14		| VDP Reg #1, Enable DMA
		.byte 0x30		| VDP Reg #2, Scroll A at 0xC000
		.byte 0x3C		| VDP Reg #3, Window at	0xF000
		.byte 7			| VDP Reg #4, Scroll B at 0xE000
		.byte 0x6C		| VDP Reg #5, Sprites at 0xD800
		.byte 0			| VDP Reg #6
		.byte 0			| VDP Reg #7
		.byte 0			| VDP Reg #8
		.byte 0			| VDP Reg #9
		.byte 0xFF		| VDP Reg #10
		.byte 0			| VDP Reg #11, Full scroll
		.byte 0x81		| VDP Reg #12, 40 H-Cell mode
		.byte 0x37		| VDP Reg #13, H-Scroll	data at	0xDC00
		.byte 0			| VDP Reg #14
		.byte 1			| VDP Reg #15, Autoinc to 1
		.byte 1			| VDP Reg #16, H Scroll	64 Cell
		.byte 0			| VDP Reg #17, Window at 0
		.byte 0			| VDP Reg #18, Window at 0
		.byte 0xFF		| VDP Reg #19
		.byte 0xFF		| VDP Reg #20, DMA Counter to 0xFFFF
		.byte 0			| VDP Reg #21
		.byte 0			| VDP Reg #22
		.byte 0x80		| VDP Reg #23, DMA source addr at 0x800000
		.byte 0x9F
		.byte 0xBF
		.byte 0xDF
		.byte 0xFF

loc_2AA:
		lea	(0xFFFFC000).w,	a0
		lea	reg_data_2, a1
		movem.l	(a1)+, d4-d7/a2-a6
		move.w	#0x3F, d0

_copy_code_to_ram:
		move.w	(a1)+, (a0)+
		dbf	d0, _copy_code_to_ram
		jsr	0xFFFFC000

loc_2C4:
		bra.s	loc_2C4


reg_data_2:	.long 0x20534547	| d4
		.long 0x45940003	| d5
		.long 0xF7		| d6
		.long 0x53454741	| d7
		.long 0xA14000		| a2
		.long 0xA14101		| a3
		.long 0xC00004		| a4
		.long 0xC00000		| a5
		.long 0xA10001		| a6


test_cart:
		bset	#0, (a3)	| a3 = 0xA14101, Disable TMSS rom and enable cart
		cmp.l	(0x100).w, d7	| Compare ROM offset 0x100 with	'SEGA'
		beq.s	_cart_ok
		cmp.l	(0x100).w, d4	| Compare ROM offset 0x100 with	' SEG'
		bne.s	loc_302
		cmpi.b	#0x41, (0x104).w | 'A' | Look for the missing 'A'
		beq.s	_cart_ok

loc_302:
		bclr	#0, (a3)	| Disable cart and enable TMSS rom
		move.b	(a6), d0
		andi.b	#0xF, d0
		beq.s	locret_314
		move.l	#0, (a2)

locret_314:
		rts

_cart_ok:
		bclr	#0, (a3)	| Disable cart and enable TMSS rom
		jsr	(write_palette).l
		move.l	#0x4C200000, (a4) | Write to VRAM at 0xC20

_write_map:
		move.l	(a1)+, (a5)
		dbf	d6, _write_map
		jsr	(write_licence).l
		move.w	#0x8144, (a4)	| Enable display
		move.w	#0x3C, d0
		bsr.s	delay
		move.w	#0x8104, (a4)	| Disable display
		move.b	(a6), d0	| Read version register
		andi.b	#0xF, d0
		beq.s	loc_34E
		move.l	#0, (a2)	| Write	0x0 to 0xa14000

loc_34E:
		bset	#0, (a3)	| Disable TMSS rom and enable cart
		moveq	#0, d0
		movea.l	d0, a0
		movea.l	(a0)+, sp	| Set stack pointer to (0x0).l
		movea.l	(a0)+, a0	| Set a0 to (0x4).l
		jmp	(a0)		| Jump to cart START vector


delay:
		move.w	#0x95CE, d1

loc_360:
		dbf	d1, loc_360
		dbf	d0, delay
		rts


		.word 1			| PAL size
		.word 0xEEE		| PAL #0 color #1 = white
		.word 0xEE8
		.long 0x1111100
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11111110
		.long 0x11000110
		.long 0x11000110
		.long 0
		.long 0x11111100
		.long 0x11000110
		.long 0x11000110
		.long 0x11111100
		.long 0x11000110
		.long 0x11000110
		.long 0x11111100
		.long 0
		.long 0x11111110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000000
		.long 0x11000110
		.long 0x11000110
		.long 0x11111110
		.long 0
		.long 0x11111100
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11111100
		.long 0
		.long 0x11111110
		.long 0x11000000
		.long 0x11000000
		.long 0x11111100
		.long 0x11000000
		.long 0x11000000
		.long 0x11111110
		.long 0
		.long 0x11111110
		.long 0x11000000
		.long 0x11000000
		.long 0x11111100
		.long 0x11000000
		.long 0x11000000
		.long 0x11000000
		.long 0
		.long 0x11111110
		.long 0x11000110
		.long 0x11000000
		.long 0x11001110
		.long 0x11000110
		.long 0x11000110
		.long 0x11111110
		.long 0
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11111110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0
		.long 0x111000
		.long 0x111000
		.long 0x111000
		.long 0x111000
		.long 0x111000
		.long 0x111000
		.long 0x111000
		.long 0
		.long 0x110
		.long 0x110
		.long 0x110
		.long 0x110
		.long 0x110
		.long 0x1100110
		.long 0x1111110
		.long 0
		.long 0x11000110
		.long 0x11001100
		.long 0x11111000
		.long 0x11111000
		.long 0x11001100
		.long 0x11000110
		.long 0x11000110
		.long 0
		.long 0x1100000
		.long 0x1100000
		.long 0x1100000
		.long 0x1100000
		.long 0x1100000
		.long 0x1100000
		.long 0x1111110
		.long 0
		.long 0x11000110
		.long 0x11101110
		.long 0x11111110
		.long 0x11010110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0
		.long 0x11000110
		.long 0x11100110
		.long 0x11110110
		.long 0x11011110
		.long 0x11001110
		.long 0x11000110
		.long 0x11000110
		.long 0
		.long 0x11111110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11111110
		.long 0
		.long 0x11111110
		.long 0x11000110
		.long 0x11000110
		.long 0x11111110
		.long 0x11000000
		.long 0x11000000
		.long 0x11000000
		.long 0
		.long 0x11111110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11001110
		.long 0x11001110
		.long 0x11111110
		.long 0
		.long 0x11111110
		.long 0x11000110
		.long 0x11000110
		.long 0x11111100
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0
		.long 0x11111110
		.long 0x11000110
		.long 0x11000000
		.long 0x11111110
		.long 0x110
		.long 0x11000110
		.long 0x11111110
		.long 0
		.long 0x11111110
		.long 0x111000
		.long 0x111000
		.long 0x111000
		.long 0x111000
		.long 0x111000
		.long 0x111000
		.long 0
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11111110
		.long 0
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x1101100
		.long 0x111000
		.long 0x10000
		.long 0
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x11010110
		.long 0x11111110
		.long 0x11101110
		.long 0x11000110
		.long 0
		.long 0x11000110
		.long 0x11000110
		.long 0x11101110
		.long 0x1111100
		.long 0x11101110
		.long 0x11000110
		.long 0x11000110
		.long 0
		.long 0x11000110
		.long 0x11000110
		.long 0x11000110
		.long 0x1101100
		.long 0x111000
		.long 0x111000
		.long 0x111000
		.long 0
		.long 0x11111110
		.long 0x1110
		.long 0x11100
		.long 0x111000
		.long 0x1110000
		.long 0x11100000
		.long 0x11111110
		.long 0
		.long 0
		.long 0
		.long 0
		.long 0
		.long 0
		.long 0x1100000
		.long 0x1100000
		.long 0
		.long 0x2222200
		.long 0x22000220
		.long 0x22000000
		.long 0x2222200
		.long 0x220
		.long 0x22000220
		.long 0x2222200
		.long 0
		.long 0x2222220
		.long 0x22000000
		.long 0x22000000
		.long 0x22222200
		.long 0x22000000
		.long 0x22000000
		.long 0x2222220
		.long 0
		.long 0x2222200
		.long 0x22000220
		.long 0x22000000
		.long 0x22002220
		.long 0x22000220
		.long 0x22000220
		.long 0x2222220
		.long 0
		.long 0x22000
		.long 0x222200
		.long 0x222200
		.long 0x2200220
		.long 0x2200220
		.long 0x22000022
		.long 0x22022222
		.long 0
line_1:		.ascii "   produced by or"
		.byte 0xFF		| End of first line
line_2:		.ascii " under license from"
		.byte 0xFF		| End of second	line
line_3:		.ascii "sega,enterprises ltd{"
		.byte 0			| End of data


write_palette:
		move.w	(a1)+, d0	| Get palette size
		move.l	#0xC0020000, (a4) | Write to CRAM at 0x2

_write_palette:
		move.w	(a1)+, (a5)
		dbf	d0, _write_palette
		rts
| End of function write_palette


write_licence:
		move.l	d5, (a4)	| Write	to VRAM	at 0xC594

loc_79E:
		moveq	#0, d1
		move.b	(a1)+, d1
		bmi.s	loc_7AC
		bne.s	loc_7A8
		rts

loc_7A8:
		move.w	d1, (a5)
		bra.s	loc_79E

loc_7AC:
		addi.l	#0x1000000, d5
		bra.s	write_licence