Vistas de página en total

viernes, 30 de agosto de 2013

MANEJO FICHEROS

     Hoy voy a crear las instrucciones para manejo de ficheros.
     Como siempre, primero la cabecera con las macros y las constantes asociadas a su manejo.
  Esta cabecera es muy importante, pues sus funciones son utilizadas, junto con las de SYDIO y WINDOW para todos los programas complejos.
     La funciones  open, close y newfile no se implementan en librerías, pues cuando se usan en un programa no se suelen repetir mucho, por lo que no vale la pena el gasto de código extra para paso de parámetros, frente al tamaño de la macro. Por ello lo mantengo como macro.


IO.MAC 
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
; constantes para manejo de unidades
ifndef _unidades
    _unidades equ 1
;unidades
_A equ  0
_B equ 1
_C equ 2
_D equ 3
endif

; constantes para manejo de archivos
ifndef _atributos
   _atributos equ 1
;;atributos de fichero
_O_READ  equ 1
_HIDE    equ 2
_SISTEM  equ 4
_VOL     equ 8
_DIR     equ 16
_ARCHIVO equ 32
_TODOS   equ 00111111B
endif

;posiciones de fseek
_INICIO EQU 0
_FIN    EQU 2
_ULTIMA EQU 3

;; modos de acceso
_R EQU 0
_W EQU 1
_R_W EQU 2

;;Estructuras
_DTA struc
   _RES_DTA DB 21 DUP (?)
   _ATTR    DB ?
   _HORA    DW ?
   _FECHA   DW ?
   _LONG    DD ?
   _NOMBRE  DB 13 DUP (?)
   ENDS

;dispositivos standar
_stdin equ 0
_stdout equ 1
_stderr equ 2
_stdaux equ 3
_stdprn equ 4








;; file direccion cadena ascii fichero
;;handle numero de fichero o codigo de retorno
;;atributo es el tipo de fichero
;;si cf =1 error
;;si cf=0 ax es numero de fichero

newfile macro file,atributo,handle
     mov ah,3ch
     push cx
     push dx
     mov cx,atributo
     lea dx,file
     int 21h
     pop dx
     pop cx
     mov handle,ax
 endm


;abre un fichero. 
; devuelve cf=0 si ok y el handle en la variable handle
;devuelve cf=1 si error y el error en la variable handle
open macro file,atributo,handle

     mov ah,3dh
     mov al,atributo
     push dx
     lea dx,file
     int 21h
     pop  dx
     mov handle,ax
 endm

close macro handle
     mov ah,3eh
     push bx
     mov bx,handle
     int 21h
     pop bx
 endm


;;fichero encontrado esta escrito en la zona DTA
;;      offset descripcion
;;       0      reservado para dos
;;      21      atributo de fichero encontado
;;      22      hora
;;      24      fecha
;;      26      tamaño
;;      30      nombre del fichero y extension
;; devuelve CF=1 si hay error
findfirst macro file,atributo
ifndef _find_first
        extrn _find_first:near
endif
        lea ax,file
        push ax
        mov ax,atributo
        push ax
        call _find_first
  endm


findnext macro
ifndef _find_next
        extrn _find_next:near
endif
        call _find_next
  endm

;; posicion en un fichero el puntero
;; cx marca la parte alta de la direccion
;; para hacerlo mas sencillo nos limitaremos a 65535 bytes por lo que
;; cx=0
;; el metodo es
;;      0    principio fichero
;;      1    desde la posicion actual
;;      2    desde final de fichero
;; devuelve en dx:ax la direccion en que se ha quedado referida al principo del fichero

fseek macro handle,metodo,posicion
ifndef _fseek
        extrn _fseek:near
endif
        mov ax,handle
        push ax        
        mov ax,metodo
        push ax
        mov ax,posicion
        push ax
        call _fseek

 endm

;;obtine direcion de transferencia de disco
;;devuelve en ax un codigo de retorno
;;devuelve en es:bx direccion de DTA
offsetdta macro
      mov ah,2fh
      int 21h
  endm



;READ y WRITE devuelven en ax el número de bytes leidos
;realmente.

read macro handle,n_bytes,buffer
ifndef _read
        extrn _read:near
endif
        mov ax,handle
        push ax
        mov ax,n_bytes
        push AX
        mov ax,offset buffer
        push ax
        call _read

 endm

rseek macro handle,numero,registro

ifndef _rseek
        extrn _rseek:near
endif
        mov ax,handle
        push ax
        mov ax,numero
        push ax
        mov ax,size registro
        push ax
        call _rseek

 endm

setdta macro posicion
      mov ah,1ah
      PUSH DX
      lea dx,posicion
      int 21h
      POP DX
  endm


write macro handle,n_bytes,buffer
ifndef _write
        extrn _write:near
endif
        mov ax,handle
        push ax
        mov ax,n_bytes
        push AX
        lea ax,buffer
        push ax
        call _write

 endm

getpath macro camino,path
ifndef _getpath
      extrn _getpath:near
endif
      lea ax,camino
      push ax
      lea ax,path
      push ax
      call _getpath

endm

miércoles, 28 de agosto de 2013

EJEMPLO DE WINDOW

    Vamos a practicar todo lo anterior.   

    Este es un ejemplo de uso de las ventanas. En este ejemplo vamos a llenar la pantalla con mesajes a través del bucle For...Next. Esperamos pulsación  para luego tomar el fondo de pantalla con getwindow. Posteriormente dibujaremos una ventana con el título "Prueba"mediante draw_win. Esperamos a pulsar y reponemos el fondo original mediante putwindow.




PWINDOW1.MAC 
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
include main.mac
include stdio.mac
include window.mac
include hi_nivel.mac


.model compact,pascal
.stack 200

.data
 ; Tamaño de la ventana  20-5=15 por lo que debemos reservar una mas 16  dw caracter y color
 buffer   dw 16*16 dup (0)   
 valor db 3
 Texto db "Prueba",0
.code

p proc far
        main     
  for valor,0,15
      gotoxy 10,valor
      puts texto
   next valor 
        getch al
        getwindow 5,5,20,20,buffer
        draw_win 5,5,20,20,texto
        getch  al
        putwindow 5,5,20,20,buffer

        exit 0
p endp

end p

lunes, 26 de agosto de 2013

LIBRERIA WINDOW (2/2)

      Esta librería nos va a permitir dibujar una ventana en pantalla de texto con un título de cabecera.
      La función solo dibuja la ventana, No rellena los datos dentro ni la refresca. Tampoco toma el fondo ni lo repone. Esto lo deberá hacer una función de más nivel.
      La impresión se hace en memoria de pantallas para mayor rapidez. Posteriormente esta función se podrá usar en funciones superiores como mover ventana.



DRAW_WIN.MAC 
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
;programa de generacion de ventana con marco y titulo
;macro prototipo en window.mac

include stdio.mac
include string.mac

  
.model compact,pascal
.data
i db 0 .code
        extrn _cls_window:near
        public _draw_win
_draw_win proc near  uses bx cx dx si di, FsCiz,FinCde,Texto,color:byte
        mov ax,FsCiz         ;borra ventana mediante
        push ax              ; implementamos la macro para aprovechar los
        mov ax,FinCde        ;parámetros ya en pareja
        push ax
        mov ah,_color
        mov al,0
        push ax   
        mov al,2
        call _cls_window      
        mov dx,FsCiz
        mov bx,FinCde
        sub bx,dx
for i,0,bh
      push dx
      gotoxy dl,dh
      putchar 186
      add dl,bl
      gotoxy dl,dh
      putchar 186
      pop dx
      inc dh
next i

        mov dx,FsCiz
        gotoxy dl,dh
        putchar 201
        call pline
        putchar 187
        add dh,bh
        gotoxy dl,dh
        putchar 200
        call pline
        putchar 188
        mov di,texto
        strlen [di]
        shr ax,1
        shr bl,1
        mov bh,0     ;un uno en el caso de otra cabecera
        sub bx,ax
        add bx,FsCiz
        gotoxy bl,bh
        puts [di]

        ret
_draw_win endp
pline proc near
        push bx
bucle:
        cmp bl,1
        je salir
        putchar 205
        dec bl
        jmp bucle
salir:
        pop bx
        ret
pline endp
ends
end

sábado, 24 de agosto de 2013

LIBRERIA WINDOW (1/2)

     Voy a ir colocando las funciones de la librería de window.
     Tened en cuenta que se trata de ventanas en modo texto, no de ventanas gráficas. Se manejan como el resto de mis funciones de gestión de pantalla trabajando directamente en memoria de pantalla.

     Estas son las funciones más usadas de la librería.
      _cls_window se apoya en la interrupción 10h para realizar un scroll y borrar la pantalla
      _get_put_window nos permitirá tomar y reponer de la memoria de pantalla el contenido pudiendo con ellas hacer popup de las pantallas y si lo deseamos moverlas y situarlas por el área total de la pantalla.



WINDOW1.MAC 
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.


.model compact,pascal

.code
        public _get_put_window
        public _cls_window
 
;toma el color en dentro de lineas
proc _cls_window uses bx cx dx,FsCiz,FinCde,lineas
        mov ah,6
        cmp al,1  ; up =1 dow=2
        je up
        mov ah,7 
up:       
        mov bx,lineas     
        mov al,bl
        mov cx,FsCiz
        mov dx,FinCde
        int 10h
        ret
_cls_window endp

;esta función realizar tres opciones, según se indique en opcion

; 0 salva pantalla, 1 recoloca pantalla, 2 cambia color
proc _get_put_window  uses es di bx dx cx, FsCiz, FinCde, buffer,opcion
        mov ax,40h
        mov es,ax
        mov dl,es:[4ah]
        mov al,byte ptr FsCiz+1    ;coordenada y inicial
        xor dh,dh
        mul dl
        xor dx,dx
        mov dl,byte ptr FsCiz
        add ax,dx
        shl ax,1
        mov di,ax
        mov al,es:[49h]
        cmp al,7
        jb sb800
        ja sa000
        mov ax,0b000h
        jmp listo

sb800:
        mov ax,0b800h
        jmp listo
sa000:
        mov ax,0a000h
 listo:
        mov es,ax
        mov bx,buffer

        mov cx,FinCde
        sub cx,FsCiz
        inc ch
        inc cl
otralinea:
        push di
        push cx
copia:
        cmp opcion,2   ; opción color
        jne _get_put
        mov es:[di+1],bl
        jmp fin
_get_put:
        cmp opcion,0    ;opción get
        jnz put
        mov ax,es:[di]
        mov [bx],ax
        jmp fin_if

put:    mov ax,[bx]       ;opción put
        mov es:[di],ax

fin_if:
        inc bx
        inc bx
fin:
        inc di
        inc di
        dec cl
        jnz copia
        push es
        mov ax,40h
        mov es,ax
        mov al,es:[4ah]
        pop es
        cbw
        shl ax,1
        pop cx
        pop di
        add di,ax
        dec ch
        jnz otralinea
        ret     
_get_put_window endp

end


jueves, 22 de agosto de 2013

TRABAJO CON VENTANAS (WINDOW.MAC)



  Siguiendo la filosofía de este blog, voy a aumentar el nivel de presentación  generando más opciones para mi librería.
    Seguimos trabajando con TASM 2.0, y bajo DOS. Vuelvo a repetir que sabemos que todo esto está superado si utilizamos MASM 11, o WinASM, esto lo realicé en 1995, pero aquí trato de mostrar como hacer algo de la nada. Ahora se aprovecha lo que ya está hecho.
    Dado que ahora los ordenador han cambiado mucho en hard y soft, muy a menudo me he encontrado  en la necesidad de usar ordenadores antiguos, para manejar ciertos software implantado hace años o comunicar con ciertas máquinas antiguas.
    Por ello seguiré con TASM 2.0 y Dos. En el caso de la reserva de memoria dinámica, que deberíamos de utilizar para el manejo de ventanas, resulta inoperante si trabajamos bajo windows. El servicio 48h de la interrupción 21h no reserva más de 7 bloques en windows. Por lo tanto si queremos usar este servicio el programa tiene que correr en MS-Dos.
    Para compensar esto cuando llegue a este punto, aunque diré como hacerlo con memoria dinámica, lo haré con memoria estática y Swaping.
   
      Ahora vamos a ver la cabecera de Window.mac. Con ella crearé unas pequeñas funciones para trabajo con ventanas en modo texto en dos.
   
     En esta cabecera definimos colores y las siguientes llamadas
   
windowup - Hace scroll de la ventana hacia arriba
windowdown- Hace scroll de la ventana hacia abajo
getwindow - Toma una área de pantalla y la salva en memoria
putwindow - Toma una zona de memoria y la vuelca en pantalla
window - Dibuja una ventana con su testo de cabecera
wincolor - Cambia el color de una ventana
windir - Realiza un dir sobre una ventana emergente, para seleccionar un fichero


WINDOW.MAC 
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.

ifndef _colores
     _colores equ 1
parpadeo equ 80h
intenso equ 0fh
normal equ 7
subrayado equ 1
inverso equ 70h

negro equ 0
azul equ 1
verde equ 2
cian equ 3
rojo equ 4
magenta equ 5
marron equ 6
gris_claro equ 7
gris_obscuro equ 8
Azul_Claro equ 9
verde_claro equ 10
cian_claro equ 11
rojo_claro equ 12
magenta_claro equ 13
amarillo equ 14
blanco equ 15
endif



;scrool down area de pantalla
;windowdown 10,10,50,50,[lineas]
; si lineas no existe se hace un scrool total
windowup macro Fs,Ciz,Fin,Cde,lineas
ifndef _cls_window
        extrn _cls_window:near
endif

        mov al,Ciz
        mov ah,Fs
        push ax
        mov al,Cde
        mov ah,Fin
        push ax
        mov ah,_color
ifb <lineas>
        mov al,0
else
        mov al, lineas
endif
        push ax
        mov al,1
        call _cls_window

endm

;scrool down area de pantalla
;windowdown 10,10,50,50,[lineas]
; si lineas no existe se hace un scrool total
windowdown macro Fs,Ciz,Fin,Cde,lineas
ifndef _cls_window
        extrn _cls_window:near
endif
        mov al,Ciz
        mov ah,Fs
        push ax
        mov al,Cde
        mov ah,Fin
        push ax
        mov ah,_color
ifb <lineas>
        mov al,0
else
        mov al, lineas
endif
        push ax  
        mov al,2
        call _cls_window

endm

;borra la ventana mediante un scroll
clswindow macro   Fs,Ciz,Fin,Cde
    windowup  Fs,Ciz,Fin,Cde
      
endm

;toma el area de una ventana
getwindow macro Fs,Ciz,Fin,Cde,direc
ifndef _get_put_window
        extrn _get_put_window:near
 endif
        mov al,Ciz
        mov ah,Fs
        push ax
        mov al,Cde
        mov Ah,Fin
        push ax
        lea ax,direc
        push ax
        mov ax,0
        push ax          ;opción 0 get 1 put  2 color
        call _get_put_window

  endm

;repone el area de una ventana
putwindow macro Fs,Ciz,Fin,Cde, direc
ifndef _get_put_window
        extrn _get_put_window:near

 endif
        mov al,Ciz
        mov ah,Fs
        push ax
        mov al,Cde
        mov Ah,Fin
        push ax
        lea ax,direc
        push ax
        mov ax,1
        push ax          ;opción 0 get 1 put  2 color     
        call _get_put_window

  endm

draw_win macro Fs,Ciz,Fin,Cde,Texto
ifndef  _window
      extrn _draw_win:near
endif
        mov al,Ciz
        mov Ah,Fs
        push ax
        mov al,cde
        mov ah,Fin
        push ax

        lea ax,texto
        push ax
        mov ax,_color
        push ax
        call _draw_win


endm

wincolor macro Fs,Ciz,Fin,Cde,color
ifndef   _wincolor
        extrn _get_put_window:near
endif
        mov al,Ciz
        mov ah,Fs
        push ax
        mov al,Cde
        mov ah,Fin
        push ax
        mov ax,color
        push ax
        mov ax,2
        push ax          ;opción 0 get 1 put 2 color
        call _get_put_window

  endm

windir macro Fs,Ciz,mascara,fichero
ifndef _windir
        extrn _windir:near
endif
        mov al,ciz
        mov ah,Fs
        push ax
        lea ax,mascara
        push ax
        lea ax,fichero
        push ax
        mov ax,_color
        push ax
        call _windir

endm




martes, 20 de agosto de 2013

USO DE WHILE...ENDWHILE

    Este sería un ejemplo del uso de la macro while....endwhile. Como se ve es idéntico a como sería en basic.
   En este caso imprime 5 veces un mensaje indicando el contador de cada mensaje.




EJEMPLO FOR.MAC
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.

include main.mac
include stdio.mac
include Hi_nivel.mac

.model compact,pascal
.stack 100

.data
valor db 0,0,0,0
msgtexto db "Mensaje ",0

.code
p proc 
          main
         clrscr
     while valor,b,5
          gotoxy 10,valor
          mov ax,word ptr valor
          mov word ptr numero,ax
          puts msgtexto
          printf numero
         inc valor
     endwhile
        exit 0
p endp
end p


lunes, 19 de agosto de 2013

USO DE FOR...NEXT

    Este sería un ejemplo del uso de la macro for....next. Como se ve es idéntico a como sería en basic. No resulta por lo tanto difícil de usar.
   En este caso imprime 5 veces un mensaje indicando el contador de cada mensaje.




EJEMPLO FOR.MAC
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
include main.mac
include stdio.mac
include Hi_nivel.mac

.model compact,pascal
.stack 100

.data

valor db 0,0,0,0
msgtexto db "Mensaje ",0

.code

p proc 
      main
     clrscr
  for valor,0,5
      gotoxy 10,valor
      mov ax,word ptr valor
      mov word ptr numero,ax
      puts msgtexto
      printf numero
  next valor
     exit 0
p endp
end p

sábado, 17 de agosto de 2013

DIRECTIVAS PROGRAMACIÓN ESTRUCTURADA

   Hoy voy a enseñar como podemos crear directivas bucles de alto nivel para simplificar algunos programas.
   En concreto voy a exponer una cabecera donde definiremos directivas para realizar las instrucciones WHILE y FOR.
    Podía hacer la instrucción do..while, pero esta es demasiado simple da realizar directamente en ensamblador, ya que la comparación con salto atrás es directamente esta estructura. por ello no vale pena.
    La idea de estas estructuras de alto nivel es seguir aclarando el programa, de manera que se pueda distinguir de un vistazo la estructura del programa.
    En ensamblador, como todos sabemos, seguir un programa es muy laborioso, incluso para el programador que lo hizo, si ha pasado tiempo desde que lo creó.
     Todas las funciones, macros, y directivas que voy exponiendo, no hacen nada que no se pueda hacer directamente, pero aclaran la estructura, de forma que resulta muy sencilla de seguir, incluso después de 20 años, como estoy haciendo yo ahora.



HI_LEVEL.MAC
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;definiciones de controles de estructuras complejas para
;;programación estructurada

;***** for var=ini to fin*****
for macro var,ini,fin
        mov var,ini
        $salvar
        cmp var,fin
        jb $ + 5
        $salvar
        nop
        nop
        nop
   endm


;***** next var*******
next macro var
        $recup
$hueco = $simbolo
        $recup
$bucle = $simbolo
        inc var
        jmp $bucle
$fin = this near
        org $hueco
        jmp $fin
        org $fin
  endm


;****while op1 (a es >,e es =,b es <,ae es >=,be es <=) op2***********
while macro op1,oper,op2
        $salvar
        cmp op1,op2
        j&oper $ + 5
        $salvar
        nop
        nop
        nop
   endm


;************endwhile
endwhile macro
        $recup
$hueco = $simbolo
        $recup
$bucle = $simbolo
        jmp $bucle
$fin = this near
        org $hueco
        jmp $fin
        org $fin
  endm


$salvar macro
        ifndef $i
           $i = 0
        endif
        $i = $i + 1
        $salvar1 %$i
endm

$salvar1 macro $i
$sim_&$i = this near
endm

$recup macro
      $recup1 %$i
$i = $i - 1
endm

$recup1 macro $i
        ifndef $sim_&$i
         .lall
         .sall
       endif
$simbolo = $sim_&$i
endm

jueves, 15 de agosto de 2013

TIC_TAC_TOE ( TASM 2.0)

      Aquí está el TIC_TAC_TOE hecho usando las directivas TASM 2.0 y la nueva rutina waitmousexy.

    Espero que os guste.

TIC_TAC_TOE.ASM
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.



title tic_tac_toe

include main.mac
include stdio.mac
include string.mac
include time.mac
include mouse.mac

.286  ; para poder usar shr al,3

tablero macro jugador,simbolo
        push bx
        mov bl,jugador
        mov bh,simbolo
        call _tablero
        pop bx
endm

.model compact,pascal

.stack 100

.data
;Mapa de juego
;significado tabla
;     oponente,respuesta,siguiente lista(2 byte)
;significado siguiente lista si
;   offset ->continual el juego en otro nivel
;   0-> ha finalizado el juego
;   1->  si la situación de la máquina es 30h
;   2->  si la situación de la máquina es 90H
;significado respuesta
;   si <>0 es posición de respuesta
;   si =0 no hay respuesta. Son tablas


nivel1  db 80h,20h
            dw offset n2_20h
        db 40h,20h
            dw offset n2_20h
        db 20h,80h
            dw offset n2_80h
        db 10h,80h
            dw offset n2_80h
        db 8,10h
            dw offset n2_10h
        db 4,80h
            dw offset n2_80h
        db 2,40h
            dw offset n2_40h
        db 1,40h
            dw offset n2_40h
       
n2_10h db 9,40h
           dw offset n3_40h
       db 88h,1,0,0
       db 48h,1,0,0
       db 28h,1,0,0
       db 0ch,1,0,0
       db 0ah,1,0,0
       dd 0


n2_20h db 84h,10h
          dw offset n3_10h_1
       db 44h,10h
          dw offset n3_10h_2
       db 0c0h,4,0,0
       db 90h,4,0,0
       db 88h,4,0,0
       db 82h,4,0,0
       db 81h,4,0,0
       db 50h,4,0,0
       db 48h,4,0,0
       db 42h,4,0,0
       db 41h,4,0,0
       dd 0

n2_40h db 82h,10h
            dw offset n3_10h_3
       db 81h,4
            dw offset n3_4h
       db 22h,80h,0,0
       db 21h,80h,0,0
       db 12h,80h,0,0
       db 11h,80h,0,0
       db 0ah,80h,0,0
       db 9,80h,0,0
       db 6,80h,0,0
       db 5,80h,0,0
       db 3,80h,0,0
       dd 0

n2_80h db 60h,10h
            dw offset n3_10h_3
       db 44h,10h
            dw offset n3_10h_3
       db 50h,4
            dw offset n3_4h
       db 30h,40h,0,0
       db 28h,40h,0,0
       db 24h,40h,0,0
       db 22h,40h,0,0
       db 21h,40h,0,0
       db 0ch,40h,0,0
       db 18h,40h,0,0
       db 14h,40h,0,0
       db 12h,40h,0,0
       db 11h,40h,0,0
       db 6,40h,0,0
       db 5,40h,0,0
       dd 0

n3_4h db 70h,8
         dw offset n4_8h
      db 58h,20h,0,0
      db 52h,20h,0,0
      db 51h,20h,0,0
      db 0a1h,10h,0,0
      db 91h,20h,0,0
      db 89h,20h,0,0
      db 83h,20h,0,0
     

n3_10h_1 db 0c4h,8,0,0           
       db 85h,8,0,0 
       db 8ch,1,0,0
       db 86h,8,0,0 
       dd 0

n3_10h_2 db 0c4h,8,0,0
       db 4ch,1,0,0
       db 86h,8,0,0
       db 85,8,0,0
       dd 0

n3_10h_3 db 0c4h,2,0,0
       db 0c2h,1,0,0
       db 0c8h,2,0,0
       db 0c1h,2,0,0
       db 4ch,2,0,0
       db 86h,1,0,0
       db 85h,2,0,0
       db 8ah,4,0,0
       db 83h,4,0,0
       db 0a2h,4,0,0
       db 61h,2,0,0
       db 62h,1,0,0
       db 64h,2,0,0
       db 68h,2,0,0
       db 46h,1,0,0
       db 45h,2,0,0
       dd 0


n3_40h db 89h,4,0,0
       db 29h,80h,0,0 
       db 0dh,80h,0,0
       db 0bh,80h,0,0 
       dd 0
      
n4_8h  db 72h,1,1,0
       db 71h,2,1,0
       dd 0
     
      
nivel_act dw 0 ; almacen de puntero de nivel actual       
maquina db 0 ; situación de la maquina
oponente db 0 ; situación del oponente
ocupados db 0 ; estado ocupados
    
estado db 0; estado partida
posx db 0   ; posicion pulsación del raton
posy db 0
raton dw 0


titulo db "TRES EN LINEA",0
ayuda db "PULSA CON EL RATON EN LA POSICION DESEADA",0
m_gana db "Lo siento has perdido.",0
m_tablas db "Esta partida son tablas",0
m_error db " Ha surgido un error",0

tablero1 db 201,205,203,205,203,205,187,0 ; "╔═╦═╦═╗"
Tablero2 db 186,32,186,32,186,32,186,0      ; "║ ║ ║ ║"
Tablero3 db 204,205,206,205,206,205,185,0   ; "╠═╬═╬═╣"
Tablero4 db 200,205,202,205,202,205,188,0   ; "╚═╩═╩═╝

NW_intento db "Quieres intentarlo de nuevo? S/N",0

.code
tic_tac_toe proc far
        main   ; inicia 
        setcursor off
        resmouse
        mouse off
        putmouse 8,8
nw:
;inicia tablero 
        clrscr
        gotoxy 9,1
        puts titulo
        gotoxy 9,2
        puts ayuda
        gotoxy 9,3   
        puts tablero1
        gotoxy 9,4
        puts tablero2
        gotoxy 9,5
        puts tablero3
        gotoxy 9,6
        puts tablero2
        gotoxy 9,7
        puts tablero3       
        gotoxy 9,8
        puts tablero2       
        gotoxy 9,9
        puts tablero4
        gotoxy 10,4
        putchar 'X'
        mov maquina,0
        mov oponente,0
        mov nivel_act,offset nivel1
        
otra:      
        tablero oponente,'O'
        tablero maquina,'X'


;espera seleccion oponente 
        mouse on
espera:  
        waitmousexy 10,4,4,4
        cmp al,0ffh
        jz espera
        shr ah,1          ; divide por 2 ya que el tablero es de dos caracteres
        mov posx,ah
        shr al,1 ; divide por 2 ya que el tablero es de dos caracteres
        mov posy,al


     ;coloca el bit
        mov al,posy    ; posy*3+posx
        add al,posy
        add al,posy
        add al,posx

        cmp al,8       ; si pulsamos fuera no procesamos
        ja espera

        mov cl,al
        xor al,al   ; borra al
        stc    ; carry a 1
        rcr al,cl      ; situa el bit elegido
        ; comprueba que no esté seleccionada ya
     
        mov ah,oponente
        or ah,maquina
        mov ocupados,ah
        or ah,al     ;montamos nuevo bit
        cmp ah,ocupados   ; ha añadido bit nuevo?
        je  espera ; si no añade bit nuevo la posición está ya estaba ocupada
         
        or oponente,al   ; guarda la jugada
        call ver_respuesta
;presentamos la nueva posición del tablero
         ;si estado = 4 sigue el juego
        cmp estado,4
        jne sig01
        jmp otra  
sig01:
       ;si estado=6 gana
        cmp estado,6 
        je gano
        cmp estado,0ffh
        jne acierto
        gotoxy 10,20         ;error
        puts m_error 
        jmp acabo
      
acierto:
       ;si estado=7 tablas
        gotoxy 10,20         ;ha acertado
        puts m_tablas  
        jmp acabo
gano:
        mouse off
        gotoxy 10,20         ;ha acertado
        puts m_gana  
acabo:       
        tablero oponente,'O'
        tablero maquina,'X'
        gotoxy 10,21
        puts nw_intento
        getch al             ;espera pulsación antes de salir
        upr                   ;convierte al en mayusculas
        cmp al,'S'
        jne  salir
        jmp nw
salir: setcursor on
        mouse off
        exit 0

tic_tac_toe endp


proc ver_respuesta 
; busca la respuesta a la situación del oponente en la tabla correspondiente
; se pasa la dirección de la tabla en si
; devuelve estado=7 si gana, estado=6 si tablas y estado=4 si sigue el juego
;    0ffh= error
        mov si,nivel_act
comprueba:
        mov al,[si]    ;posibilidad
        cmp al,0        ;error fin de lista. No hay acción
        jne n_error
        mov estado,0ffh   ; marca error
        ret
n_error:
        cmp oponente,al  ;es la jugada hecha?
        je encontrado
sig_estado:
        add si,4   ; siguiente estado
        jmp comprueba
encontrado:
        mov al,[si+1]
        or maquina,al    ;añade al tablero de la máquina la jugada correspondiente
        mov ax,[si+2]    ;dato siguiente estado
        cmp ax,0          ;fin de la partida
        je _fin
        cmp ax,1        ;tablas
        je _fin

        mov nivel_act,ax     ;pasamos el puntero del nivel a la lista del siguiente nivel
        xor al,al
        jmp _fin_ver


_fin:   or  al,2      ; devuelve al=6 si gana y al=7 si tablas
_fin_ver:              
        or  al,4      ;devuelve al=4 si sigue el juego
        mov estado,al
ret
ver_respuesta endp

proc _tablero
; oponente viene en bl, y el simbolo a imprimir en bh
        mouse off
        shl bl,1
        jnc c2
        gotoxy 12,4
        putchar bh
c2:
        shl bl,1
        jnc c3
        gotoxy 14,4
        putchar bh
c3:
        shl bl,1
        jnc c4
        gotoxy 10,6
        putchar bh
c4:       
        shl bl,1
        jnc c5
        gotoxy 12,6
        putchar bh
c5:
        shl bl,1
        jnc c6
        gotoxy 14,6
        putchar bh
c6:
        shl bl,1
        jnc c7
        gotoxy 10,8
        putchar bh
c7:
        shl bl,1
        jnc c8
        gotoxy 12,8
        putchar bh
c8:
        shl bl,1
        jnc c9
        gotoxy 14,8
        putchar bh
c9:
        mouse on
        ret
_tablero endp

end tic_tac_toe

martes, 13 de agosto de 2013

GETMOUSEXY

     Hoy toca la segunda parte necesaria para tomar la posición de ratón en una ventana de texto acotada.
     La llamaremos getmousexy.

      La parte correspondiente en el programa TIC_TAC_TOE es:
    ;toma la coordenada
        getmousex  
        shr ax,4 ;divide por 16 para obtener coordenada letra   
        sub ax,5 ;referencia desde cero de la posicion en la matriz
        cmp al,2  ;no valido si pulsamos fuera
        ja espera 
        mov posx,al
        getmousey  
        shr ax,4 ;divide por 16 para obtener coordenada letra   
        sub ax,2 ;referencia desde cero de la posicion en la matriz
        cmp al,2    ;no valido si pulsamos fuera
        ja espera 
        mov posy,al

   Ahora queremos convertirla en una rutina estándar que nos valga para siempre. Para ello en vez de dividir por 16 lo haremos por 8 para que nos de posiciones en carácter de pantalla.
    Para implementarla crearemos una macro a la que le pasaremos hasta 4 parámetros.
    inx e iniy serán las coordenadas de inicio de la ventana
    rangx y rangy será la longitud x e y de la ventana.
    Se podrá no indicar, por parejas, estos parámetros. Si no se indican rangos, se tomará 0,0, 80,24 como ventana.
 
   Como hemos dicho esto está pensado para ser usado junto con waitmouse y analizar una pulsación del ratón. A veces nos interesará hacer waitmouse en un punto del programa y llamar a esta rutina varias veces para analizar varias posibilidades (varias ventanas activas). Otras veces, simplemente tengo activa una ventana válida y solo quiero ver la coordenada pulsada, como es el caso del juego TIC_TAC_TOE.
   Como resulta que para ver si se no pulsó dentro de la ventana debemos verificar si nos ha devuelto 0ffh, en el caso de que solo haya una ventana activa, resulta en este caso un sobrecoste de análisis. Por ello, resulta cómodo tener una función que ya lo implemente y se quede esperando dentro, hasta que la posición sea válida.
   Es por eso que además de la macro getmousexy vamos a crear waitmousexy, que combinará la espera y la toma de posición, para hacer en una sola instrucción las dos cosas.


   IMPLEMENTACIÓN GETMOUSEXY

MOUSE.MAC  ( a añadir a lo que ya existe)
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
;toma la posicion xy del raton en coordenadas texto referidas a inix,iniy
;devuelve la posición en ah=x al=y. Si está fuera de la ventana devueve al=0ffh
;inix e iniy son las coordenadas cero
;rangx,rangy son el rango válido
;ej mousexy 10,10,20,20 devuelve las coordenada pulsada
;si está dentro de la ventana 10,10,20,20 con la coordenada referida al origen 10,10

getmousexy macro inix,iniy,rangx,rangy
ifndef _getmousexy
      extrn _getmousexy:near
endif
  ifnb <rangy>
      mov ax,inix
      push ax
      mov ax,iniy
      push ax
     mov ax,rangx
      push ax
      mov ax,rangy
      push ax
  else
      mov ax,0
      push ax
      push ax
      mov ax,80
      push ax
      mov ax,4
      push ax
  endif
      call _getmousexy
endm


;espera pulsación de ratón y toma la posicion xy del raton en coordenadas texto referidas a inix,iniy
;devuelve la posición en ah=x al=y.

waitmousexy macro   inix,iniy,rangx,rangy
waitmouse 
getmousexy inix,iniy,rangx,rangy
endm



GETMOUSEXY.ASM
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.

title librería getmousexy

.model compact,pascal
     public _getmousexy
.286
.data
.code
proc _getmousexy  uses bx,inix,iniy,rangx,rangy
     ;toma la coordenada
        getmousex  
        shr ax,3               ;divide por 8 para obtener coordenada texto
        sub ax,inix             ;referencia cero de la posicion en la matriz
        cmp ax,rangx           ;no valido si pulsamos fuera
        ja fuera
        mov bh,al
        getmousey  
        shr ax,3             ;divide por 8 para obtener coordenada texto
        sub ax,iniy          ;referencia cero de la posicion en la matriz
        cmp ax,rangy         ;no valido si pulsamos fuera
        ja fuera 
        mov ah,bh
        ret
fuera:
        mov ax,0ffh
       ret
_getmousexy endp
end

domingo, 11 de agosto de 2013

WAITMOUSE

    Como dije en la entrada donde expuse el juego TIC_TAC_TOC completo (TIC_TAC_TOC 5/5),  la parte del programa en donde analizamos la pulsación del ratón, comprobamos que se encuentra dentro de el tablero y la transformamos en coordenadas de texto, puede resultar muy útil en en futuro.
    Este es un caso típico. Mientras programamos aplicaciones, nos damos cuenta que ciertas partes de las funciones pueden resultarnos muy útiles en el futuro. Es ahí cuando debemos crear nuevas instrucciones y librerías. Por esto, es deseable pararnos un momento a pensar, pues esto es lo que nos dará una nueva herramienta, y aumentará nuestro poder informático. Además nos aliviará de carga de trabajo para el futuro.

  Eso sí, hay que pensarlo bien.
  He visto que la función  me ha servido bien, y que es muy útil, si quisiera obtener la posición del ratón en coordenadas de texto y limitar su acción a una sección de pantalla como es el caso de una ventana.
    Esta función sera muy útil para gestión de menús desplegables y ventanas emergentes.
   Si la hiciéramos tal y como está en el juego no nos sirve, pues está pensada para hacer una matriz de 2 caracteres. Además se queda esperando una pulsación, lo cual nos impediría analizar varias ventanas en un mismo programa.
   Si miramos la sección de programa veremos que en realidad tiene dos partes.
   En la primera esperamos el flanco de subida de la pulsación del ratón. Eso ya sería algo útil por si mismo. Incluso, se puede pensar en hacer una función que detecte el flaco de subida o el de bajada. Es decir, detecte "push mouse" y "release mouse".
   En la segunda parte se leen e interpretan como validas las coordenadas, pasándolas a coordenadas relativas a la ventana

ESPERA PULSACIÓN
   La sección de programa es:

 espera:
        getmouse                ;lee el estado del raton
        cmp ax,1
        jnz actual              ;si no se ha pulsado se espera
        cmp bx,ax               ;si se pulso se verifica si ha sido un
        mov bx,ax               ;flanco de subida
        jnz  seleccion           ;si es así se selecciona la opción deseada
actual:
        mov bx,ax
        jmp espera
seleccion:
   
       Este código está hecho para pasar de 0 a 1 en el estado del ratón.
       El código de abajo en cambio detectaría el paso de 1 a 0

 espera:
        getmouse                ;lee el estado del raton
        cmp ax,0
        jnz actual              ;si no se ha pulsado se espera
        cmp bx,ax               ;si se pulso se verifica si ha sido un
        mov bx,ax               ;flanco de bajada
        jnz  seleccion           ;si es si se selecciona la opción deseada
actual:
        mov bx,ax
        jmp espera
seleccion:

    Ya tenemos, por lo tanto definida la función. La vamos a llamar waitmouse. Esta función esperará la pulsación y como parámetro le daremos press o release , para seleccionar el flanco 0->1 0 1->0. Si no se indica nada será press.

    Como se ve no hace falta más que cambiar la primera comparación, por lo que press=1 release=0.
    Para implementarla añadiremos estas constantes y la definición con la llamada a la función en mouse.mac, y crearemos una rutina para almacenar en la librería.


   IMPLEMENTACIÓN WAITMOUSE

MOUSE.MAC  ( a añadir a lo que ya existe)
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.

press=1
release=0

waitmouse macro flanco
ifndef _waitemouse
       extrn  _waitmouse:near
endif

ifb <flanco>
     mov ax,1
else
     mov ax,flanco
endif
     push ax
     call _waitmouse
endm


WMOUSE.ASM
(C) José Angel Moneo Ferdz
include mouse.mac
    public _waitmouse
.modul compact,pascal
.code
proc _waitmouse uses bx,flanco
 espera:
        getmouse                ;lee el estado del raton
        cmp ax,flanco
        jnz actual              ;si no se ha pulsado se espera
        cmp bx,ax               ;si se pulso se verifica si ha sido un
        mov bx,ax               ;flanco de bajada
        jnz  seleccion           ;si es si se selecciona la opción deseada
actual:
        mov bx,ax
        jmp espera
seleccion:
        ret
_waitmouse endp
end




sábado, 10 de agosto de 2013

DELAY

  Esta función se me ha pasado incluirla en su momento, para completar la macro TIME. Por ello la añado ahora.


   Esta función completa la librería Time, añadiendo la función DELAY. Con esta función podremos realizar retardos de tiempo en segundos. Utiliza el reloj del sistema para realizar la espera.



DELAY.ASM
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
.model compact,pascal
.data
ti_min db 0
ti_seg db 0
pausa dw 0
.code
       public _delay

_delay proc near  bx cx, tiempo
     mov ah,2ch
     int 21h
     mov ti_min,cl
     mov ti_seg,dh

        mov al,ti_min
        mov dl,60
        mul dl
        mov dx,ax
        xor ax,ax
        mov al,ti_seg
        add dx,ax
        mov pausa,dx

 espera:
       mov ah,2ch
       int 21h
       mov ti_min,cl
       mov ti_seg,dh
        mov al,ti_min
        mov dl,60
        mul dl
        mov dx,ax
        xor ax,ax
        mov al,ti_seg
        add dx,ax
        mov ax,dx
        sub dx,pausa
        cmp dx,tiempo
        jb espera
        ret
_delay endp

end   _delay