Jump to content
Sign in to follow this  
Colex

[ASM] SpriteAsm

Recommended Posts

Colex    0
Colex

SpriteAsm

Extrator de Sprites

 

Programador: Alex Santos (Colex)

Linguagem de Programação: Assembly (Compilado em GCC 4.2.2)

 

Como funciona:

Basta colocar o ficheiro Tibia.spr na pasta do SpriteAsm.exe, abrir o programa e esperar que extraia para a pasta Sprites.

 

Detalhes da Aplicação:

Esta aplicação não tem o objetivo de substituir outras aplicações (e.g.: a ferramenta feita por blackdemon). O SpriteAsm foi feito com o objetivo de alcançar um tempo de extração rapido para o disco (e não para a memoria volátil). Por esse motivo foi desenvolvido em Assembly.

Para testar comparei com a ferramente desenvolvida por Troopers (que extrai para o disco). A ferramenta do troopers demorou 3 minutos e 30 segundos a extrair enquanto que o SpriteAsm demorou 1 minuto. Ainda é algum tempo, porém foi 3.5 vezes mais rápido.

O código poderia ser optimizado, mas por ser apenas uma "brincadeira" para estudo fiquei satisfeito.

As sources estão disponiveis, deixei alguns comentários no código

 

Sources:

##################################
##	       SpriteAsm	    	##
##	Developed by Alex Santos    ##
##			(Colex)				##
##################################

.data
READ_FLAG:
.asciz "rb"
WRITE_FLAG:
.asciz "wb"
SPRITES_DIR:
.asciz "Sprites"
SPRITES_FILE:
.asciz "Tibia.spr"
EMPTY_FILE:
.asciz "%d.bmp"
PREVIOUS_DIR:
.asciz "cd .."
BITMAP_HEADER_INFO:
.long	0x4D42, 150, 0, 54, 40, 32, 32, 1, 24, 0, 96, 2835, 2835, 0
BITMAP_HEADER_SIZE:
.long	2, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 4, 4, 8, 0
START_STRING:
.asciz "SpriteAsm (Developed by Alex Santos)\n\n-- Started Extracting... "
END_STRING:
.asciz "[Done]\n\nEnded Extraction\n"

.globl _main


##################################
##	       WRITE_BYTES	    	##
##################################
_write_bytes:	#paramaters: file pointer, value, size
#Epilogue
pushl	%ebp
movl	%esp, %ebp
#########

pushl	8(%ebp)
pushl 	$1
pushl	16(%ebp)
leal	12(%ebp), %eax
pushl	%eax
call	_fwrite
addl	$16, %esp

#Prologue
leave
ret
##################################





##################################
##		CREATE_EMPTY_SPRITE		##
##################################
_create_empty_sprite:	#parameter: sprite number
#Epilogue
pushl	%ebp
movl	%esp, %ebp
pushl	%ebx
pushl	%esi
pushl	%edi
subl	$255, %esp
########


leal	-255(%ebp), %eax

#Generate the sprite name
pushl	8(%ebp)
pushl	$EMPTY_FILE
pushl	%eax
call	_sprintf
addl	$12, %esp


#Open the file in write mode
pushl	$WRITE_FLAG
leal	-255(%ebp), %eax
pushl	%eax
call	_fopen
addl	$8, %esp
movl	%eax, %ebx

#Write the BMP header
leal 	BITMAP_HEADER_SIZE, %esi
leal 	BITMAP_HEADER_INFO, %edi
write_header:
movl	(%esi), %eax
cmp		%eax, 0
je		write_header_end
pushl	%eax
pushl	(%edi)
pushl	%ebx
call	_write_bytes
addl	$12, %esp
addl	$4, %edi
addl	$4, %esi
jmp		write_header
write_header_end:	

#Fill the sprite with transparent color
movl	$0, %esi
pushl	$3
pushl	$0xFF00FF
pushl	%ebx
write_pixels:
call	_write_bytes
addl	$1, %esi
cmp		$1024, %esi
jne		write_pixels
addl	$12, %esp

pushl	$2
pushl	$-96
pushl	%ebx
call	_fseek
#addl	$12, %esp

#Return the file pointer (through %eax)
movl	%ebx, %eax


#Prologue
movl	%ebp, %esp
subl	$12, %esp
popl	%edi
popl	%esi
popl	%ebx	
leave
ret 
##################################




##################################
##		   READ_SPRITES     	##
##################################	
_read_sprites:	#parameter:	file pointer
#Epilogue
pushl	%ebp
movl	%esp, %ebp
subl	$32, %esp
pushl	%edi
pushl	%esi
pushl	%ebx
#########

#Ignore header informations (except the sprites count)
pushl	$0	
pushl	$4	
pushl	8(%ebp)
call	_fseek	
addl	$12, %esp


#Read how many sprites are in the file
pushl	8(%ebp)
pushl	$1
pushl 	$2
leal	-4(%ebp), %eax
pushl	%eax
call	_fread
addl	$16, %esp
movl	-4(%ebp), %edi


#Read all the sprites to a file
movl	$1, -32(%ebp)
read_sprite:
	pushl	-32(%ebp)
	call 	_create_empty_sprite
	addl	$4, %esp
	movl	%eax, %ebx

	#pushl	%esi
	#pushl	$TEST_STRING1
	#call	_printf

	#Read the next sprite's pointer
	movl	-32(%ebp), %eax
	imull	$4, %eax
	addl	$6, %eax

	pushl	$0	
	pushl	%eax
	pushl	8(%ebp)
	call	_fseek	
	addl	$12, %esp

	pushl	8(%ebp)
	pushl	$1
	pushl 	$4
	leal	-4(%ebp), %eax
	pushl	%eax
	call	_fread
	addl	$16, %esp

	movl	-4(%ebp), %eax
	addl	$3,	%eax
	pushl	$0	
	pushl	%eax
	pushl	8(%ebp)
	call	_fseek	
	addl	$12, %esp


	#Read the sprites size (number of bytes)
	pushl	8(%ebp)
	pushl	$1
	pushl 	$2
	leal	-8(%ebp), %eax
	pushl	%eax
	call	_fread
	addl	$16, %esp

	#Read the pixels
	subl	%esi, %esi
	read_pixels:		

		movl	-8(%ebp), %eax
		cmp		%eax, 0
		je		close_sprite



		#Read the number of transparent pixels
		pushl	8(%ebp)
		pushl	$1
		pushl 	$2
		leal	-12(%ebp), %eax
		pushl	%eax
		call	_fread
		addl	$16, %esp

		#Ignore the transparent pixels
		movl	-12(%ebp), %eax
		addl	%eax, %esi
		imull	$3, %eax
		pushl	$1
		pushl	%eax
		pushl	%ebx
		call	_fseek
		addl	$12, %esp

		#Read the number of colored pixels
		pushl	8(%ebp)
		pushl	$1
		pushl 	$2
		leal	-16(%ebp), %eax
		pushl	%eax
		call	_fread
		addl	$16, %esp


		movl	-8(%ebp), %eax
		subl	$4, %eax
		movl	%eax, -8(%ebp)

		######################################################
		#Bitmap "mirror's" the image, so we need to calculate#
		#the original position of the pixel					 #
		#######  y = (32 - (P / 32)) * 96  ###################
		calculate_pos:
		movl	%esi, %eax
		subl	%edx, %edx
		movl	$32, %ecx
		idiv	%ecx
		addl	$1, %eax
		subl	%eax, %ecx
		imull	$96, %ecx
		movl	%ecx, -4(%ebp)

		#######  x = (P % 32) * 3  #######	
		movl	%esi, %eax
		subl	%edx, %edx
		movl	$32, %ecx
		idiv	%ecx
		imull	$3, %edx

		#######  pos = x + y + 54  #######	
		addl	%edx, -4(%ebp)
		addl	$54, -4(%ebp)

		pushl	$0
		pushl	-4(%ebp)
		pushl	%ebx
		call	_fseek
		addl	$12, %esp
		###################################	###################


		#Write the colored pixels to the file		
		write_colored_pixels:
			movl	-16(%ebp), %eax
			cmp		%eax, 0
			je		read_pixels


			#Read RGB bytes
			read_rgb:
			pushl	8(%ebp)
			pushl	$1
			pushl 	$1
			leal	-20(%ebp), %eax
			pushl	%eax
			call	_fread
			addl	$4, %esp
			leal	-24(%ebp), %eax
			pushl	%eax
			call	_fread
			addl	$4, %esp
			leal	-28(%ebp), %eax
			pushl	%eax
			call	_fread
			addl	$16, %esp
			#Write RGB bytes to the file
			pushl	$1
			pushl	-28(%ebp)
			pushl	%ebx
			call	_write_bytes
			addl	$8, %esp
			pushl	-24(%ebp)
			pushl	%ebx
			call	_write_bytes
			addl	$8, %esp
			pushl	-20(%ebp)
			pushl	%ebx
			call	_write_bytes
			addl	$12, %esp

			addl	$1, %esi

			movl	-8(%ebp), %eax
			subl	$3, %eax
			movl	%eax, -8(%ebp)

			movl	-16(%ebp), %eax
			subl	$1, %eax
			movl	%eax, -16(%ebp)

			#Verify if needs to recalculate the position
			movl	%esi, %eax
			subl	%edx, %edx
			movl	$32, %ecx
			idiv	%ecx
			cmp		%edx, 0
			je		calculate_pos

			jmp		write_colored_pixels


	#Close the sprite's file
	close_sprite:
	pushl	%ebx
	call	_fclose
	addl	$4, %esp

	addl	$1, -32(%ebp)	
	cmp		-32(%ebp), %edi
	jne		read_sprite


#Prologue
movl	%ebp, %esp
subl	$12, %esp
popl	%ebx
popl	%esi
popl	%edi
leave
ret
##################################	



##############################
##			MAIN			##
##############################	
_main:
#Epilogue
pushl 	%ebp
movl 	%esp, %ebp
#########

pushl	$START_STRING
call	_printf

#Open the Tibia.Spr
pushl 	$READ_FLAG
pushl	$SPRITES_FILE
call	_fopen
#Exit if couldn't open the Tibia.spr
cmp		%eax, 0
je		prologue
mov		%eax, %ebx


#Create the Sprites directory
pushl 	$SPRITES_DIR
call 	_chdir
#If it already exists, don't create
cmp 	%eax, 0
je 		do_no_create
call 	_mkdir
call 	_chdir
do_no_create:

pushl	%ebx
call	_read_sprites	

#Close the Tibia.spr
pushl	%ebx
call	_fclose

pushl	$END_STRING
call	_printf

pushl	$PREVIOUS_DIR
call	_system

#Prologue
prologue:
leave
ret
##################################

 

 

Download (executável):

http://www.4shared.com/file/Dn5sMsiL/SpriteAsm.html

 

Recapitulando: Isto foi apenas objeto de estudo, pode ser usado por quem quiser da forma que quiser.

 

Cumprimentos,

Alex Santos

Edited by Colex

Share this post


Link to post
Share on other sites
River    3
River

Prefiro o editor do Black Demon!

 

BRINKS!

 

kkkkkkkk

 

 

Muito rox, cara! Sempre ajudando a galera ai!

E tudo com código aberto! XD

 

Valeu pelo post!

 

Abraço

Share this post


Link to post
Share on other sites
Baxnie    8
Baxnie

Assembly sempre me atraiu, mas é baixo o nível. Ao mesmo tempo que te da maior liberdade e controle, é bem mais trabalhoso de se programar.

 

Não entendi muito bem qual a grande otimização de seu código.

 

Mas já pensou se o motivo do seu código ser 3 vezes mais rápido do que o do Troopers não é devido a algum 'defeito' no código dele?

Share this post


Link to post
Share on other sites
Colex    0
Colex

@Up

 

A razão é pela que voce mesmo citou, é de baixo nivel, da um maior liberdade de controlo. Assim eu posso optmizar o código para ser mais rápido.

Porem, normalmente, assembly não compensa. C é rápido e mais facil de programar, então por uma diferença de segundos (dependendo do código) mais vale programar em C. (ou outra linguagem)

Eu só fiz isto porque acho interessante a linguagem, oferece um desafio.

Share this post


Link to post
Share on other sites
Fixthow    33
Fixthow

Grande Utilitário, vai ajudar muitas pessoas

Share this post


Link to post
Share on other sites
Baxnie    8
Baxnie

Já brinquei um pouco com ASM, copiando código dos outros, para meu benefício. É bem divertido. :X

 

Porém realmente não compensa, não consigo imaginar utilidade no dia-a-dia de um programador. Somente acho que é útil para compreender como realmente funciona a rotina de um programa, entender para evitar bugs como de buffer overflow.

Share this post


Link to post
Share on other sites
Dark Skyllen    7
Dark Skyllen
Já brinquei um pouco com ASM, copiando código dos outros, para meu benefício. É bem divertido. :X

 

Porém realmente não compensa, não consigo imaginar utilidade no dia-a-dia de um programador. Somente acho que é útil para compreender como realmente funciona a rotina de um programa, entender para evitar bugs como de buffer overflow.

 

Na verdade quando se pensa em desempenho é muito util na vida de um programador. O preço a se pagar por isso é essa linguagem tão cheia de nós.

Share this post


Link to post
Share on other sites
EcL    3
EcL

Muito bom, assembly rula mesmo, e pra quem disse que não serve pra nada, está totalmente errado. Principalmente quando se fala em exploits.

Share this post


Link to post
Share on other sites
Anywhere    0
Anywhere

Engraçado, esses dias eu estava lendo tutoriais de Assembly, como o Colex disse oferece um desafio =D

 

Quem sabe em breve eu não me aventure em algum utilitário AOEKOAKEAE

Mas creio que irei me apronfundar em C++ msm '-'

 

Obrigado pelo tópico Colex, isso gera até um incentivo *-*

Share this post


Link to post
Share on other sites
flipagenor    0
flipagenor

Até hoje, não consegui entender um simples código em Assembly, sequer!

Share this post


Link to post
Share on other sites
haxyy    0
haxyy

Muito bom!

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×