home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 1 / PC Actual CD 01.iso / trucos / pascal / pascal.wri < prev   
Encoding:
Text File  |  1995-02-10  |  38.4 KB  |  2,292 lines

  1.  
  2. PASCAL
  3.  
  4. GRABAR Y RECUPERAR PANTALLAS DE TEXTO
  5.  
  6. Programando en Turbo Pascal, hay ocasiones en las que se necesita
  7. ½salvar╗ la pantalla con la que estamos trabajando, y restaurarla
  8. despuΘs de hacer algo (mostrar un peque±o men· de ayuda, hacer una
  9. pregunta, etc). Esta es la utilidad de estas dos rutinas, la primera
  10. de ellas, llamado ½Savescreen╗, se encarga de guardar la memoria de
  11. video directamente en un archivo. Su formato es el siguiente:
  12.  
  13. Savescreen(Nombre);
  14.  
  15. donde ½Nombre╗ es el nombre del archivo con el que se guardarß la
  16. pantalla.
  17.  
  18. El segundo procedimiento se encarga de 'restaurar' la pantalla. Su
  19. formato es el siguiente:
  20.  
  21. Restscreen(Nombre);
  22.  
  23. donde ½Nombre╗ es el nombre del archivo a restaurar.
  24.  
  25. Estos procedimientos estßn probados, y funcionan para pantallas del tipo
  26. 80 x 25, 16 Colores, es decir para pantallas de texto. El tama±o que se
  27. graba es de 4000 bytes, porque la pantalla es de 80 columnas x 25 filas
  28. = 2000 bytes, pero como cada caracter lleva asociado un atributo, esto
  29. hace un total de 2000 x 2 = 4000 bytes.
  30.  
  31.  
  32. procedure savescreen(__name:string);
  33.  
  34. var
  35.  
  36.  f :file;
  37.  
  38.  p :pointer;
  39.  
  40. begin
  41.  
  42.  assign(f,__name);
  43.  
  44.  rewrite(f);
  45.  
  46.  { abre el fichero. si existe, lo destruye. }
  47.  
  48.  close(f);
  49.  
  50.  { cierra el fichero. }
  51.  
  52.  reset(f,1);
  53.  
  54.  { abre el fichero otra vez. }
  55.  
  56.  p:=ptr($b800,$0000);
  57.  
  58.  { el puntero p^ apunta a la direcci≤n $b800:0000 }
  59.  
  60.  blockwrite(f,p^,4000);
  61.  
  62.  { guarda la pantalla }
  63.  
  64.  close(f);
  65.  
  66. end;
  67.  
  68.  
  69. procedure restscreen(__name:string);
  70.  
  71. var
  72.  
  73.  f :file;
  74.  
  75.  p :pointer;
  76.  
  77. begin
  78.  
  79.  {$i-}
  80.  
  81.  assign(f,__name);
  82.  
  83.  reset(f);
  84.  
  85.  { comprueba si exite el fichero especificado. }
  86.  
  87.  close(f);
  88.  
  89.  {$i+}
  90.  
  91.  if ioresult=0 then begin
  92.  
  93.  assign(f,__name);
  94.  
  95.  reset(f,1);
  96.  
  97.  p:=ptr($b800,$0000);
  98.  
  99.  { el puntero p^ apunta a la direcci≤n $b800:0000 }
  100.  
  101.  blockread(f,p^,4000);
  102.  
  103.  { lee los datos y los pone en pantalla }
  104.  
  105.  close(f);
  106.  
  107.  end;
  108.  
  109. end;
  110.  
  111. Daniel Sßnchez Teodoro
  112.  
  113. Granada
  114.  
  115.  
  116.  
  117. NUMEROS CON PUNTOS
  118.  
  119. Estas dos funciones escritas en Pascal permiten la escritura de un
  120. n·mero con los puntos de separaci≤n de millares. Este tipo de
  121. funciones tienen gran utilidad en aplicaciones (por ejemplo de
  122. contabilidad) en las que se deseen presentar resultados de cantidades
  123. con cierta calidad.
  124.  
  125. La primera (UsingLong) sirve para n·meros ½LongInt╗ y la segunda
  126. (Usingreal) para n·meros reales y hace uso de la anterior.
  127.  
  128. Function UsingLong (n:LongInt):string;
  129.  
  130. Const
  131.  
  132.  Punto='.';
  133.  
  134. Var
  135.  
  136.  f,Largo : byte;
  137.  
  138.  s : String;
  139.  
  140.  Signo : String[1];
  141.  
  142. Begin
  143.  
  144.  If n<0 Then Signo := '-'
  145.  
  146.  Else
  147.  
  148.  Signo := '';
  149.  
  150.  n:=Abs(n);
  151.  
  152.  Str(n,s);
  153.  
  154.  For f := 1 to 3 do
  155.  
  156.  If Length(s) >= 4*f Then
  157.  
  158.  Insert (Punto,s,Length(s)-f*4+2);
  159.  
  160.  UsingLong:=Signo+s;
  161.  
  162. End;
  163.  
  164. Function UsingReal(r:Real; deci:byte): String;
  165.  
  166. Var
  167.  
  168.  m : Real;
  169.  
  170.  n : LongInt;
  171.  
  172.  s,t : String;
  173.  
  174. Begin
  175.  
  176.  n := Trunc(r);
  177.  
  178.  s := UsingLong(n);
  179.  
  180.  m := Frac(r);
  181.  
  182.  m := Abs(m);
  183.  
  184.  If deci >0 Then
  185.  
  186.  Begin
  187.  
  188.  Str (m:deci+2:deci,t);
  189.  
  190.  t := Copy (t,2,length(t)-1);
  191.  
  192.  s := s+t;
  193.  
  194.  End;
  195.  
  196.  UsingReal := s;
  197.  
  198. End;
  199.  
  200.  
  201. JosΘ M. Serrano
  202.  
  203. LΘrida
  204.  
  205.  
  206.  
  207. CAMBIAR LA TABLA DE CARACTERES
  208.  
  209. El procedimiento ½xchr╗ permite transformar un carßcter en cualquier
  210. otro que nosotros dise±emos. Para ello nos crearemos una tabla de 8
  211. columnas por 16 filas como la del ejemplo y calcularemos los valores
  212. teniendo en cuenta que para cada una de las columnas de una fila son
  213. 128, 64, 32, 16, 8, 4, 2 y 1. Para cada fila sumamos los valores
  214. correspondientes a las columnas que tachemos para crear el carßcter.
  215. Un ejemplo:
  216.  
  217.  ........ 00
  218.  
  219.  ........ 00
  220.  
  221.  ..****.. 60
  222.  
  223.  ..****.. 60
  224.  
  225.  ..*..... 32
  226.  
  227.  ..**.... 48
  228.  
  229.  ...**... 24
  230.  
  231.  ....**.. 12
  232.  
  233.  ........ 00
  234.  
  235.  ..****.. 60
  236.  
  237.  ..****.. 60
  238.  
  239.  ........ 00
  240.  
  241.  ...**... 24
  242.  
  243.  ...**... 24
  244.  
  245.  ........ 00
  246.  
  247.  ........ 00
  248.  
  249. Una vez que hemos calculado los bytes correspondientes a las 16 filas
  250. (las cifras representadas a la derecha), los colocamos en un
  251. array de la siguiente forma:
  252.  
  253. MIO :array [0..15] of BYTE= (00, 00, 60, 60, 32, 48, 24, 12, 00, 60,
  254. 60, 00, 24, 24, 0, 0 );
  255.  
  256. Con todos estos datos podemos generar el siguiente programa para
  257. cambiar el juego de caracteres.
  258.  
  259. uses dos;
  260.  
  261. type font16 = array [ 0..15] of byte;
  262.  
  263. const
  264.  
  265.  ONDAS :font16 =
  266.  
  267.  ($94, $84, $48, $30, $00, $C1, $22, $14, $94, $84, $48, $30, $00, $C1,
  268.  $22, $14);
  269.  
  270.  MIO :font16=
  271.  
  272.  (00, 00, 60, 60, 32, 48, 24, 12, 00, 60, 60, 00, 24, 24, 0, 0);
  273.  
  274. procedure xchr(CH:CHAR ;VAR s);
  275.  
  276. var regs:registers;
  277.  
  278. { La variable s no tiene tipo declarado para que usemos bien matrices
  279.  de 16 bytes o de 8 seg·n el tipo de fuente actual }
  280.  
  281. begin
  282.  
  283. regs.dx:=ord(ch);
  284.  
  285. with regs do
  286.  
  287. begin
  288.  
  289.  ah:=$11;
  290.  
  291.  al:=$00;
  292.  
  293.  bh:=16;
  294.  
  295.  bl:=8;
  296.  
  297.  cx:=1;
  298.  
  299.  es:=seg (S);
  300.  
  301.  bp:=ofs (S);
  302.  
  303. end;
  304.  
  305. intr ($10,regs);
  306.  
  307. { S≤lo es soportada por EGA, MCGA y VGA (y no CGA o MDA) }
  308.  
  309. end;
  310.  
  311. begin
  312.  
  313.  xchr ('A',ondas);
  314.  
  315.  writeln ('AAAA');
  316.  
  317. end.
  318.  
  319.  
  320. Nota del L.T.: Este programa s≤lo cambia el c≤digo de un carßcter,
  321. pero no es difφcil (aunque sφ laborioso) cambiar totalmente el juego
  322. de caracteres. Simplemente deberemos generar un array para cada uno
  323. de los 255 caracteres. Una buena idea es ponerlo todo de forma que
  324. cargue la tabla de caracteres desde un bucle, para automatizar el
  325. proceso.
  326.  
  327. Alberto Vallejo Martφnez
  328.  
  329. Burgos
  330.  
  331.  
  332. DIRECTORIOS ½DIRECTOS╗
  333.  
  334. A pesar de que el Borland Pascal incluye una orden para crear
  335. directorios (½MKDir╗), esta rutina incorpora la interesante novedad de
  336. que permite crear m·ltiples directorios a la vez, unos dentro de
  337. otros, sin tener que crearlos uno por uno.
  338.  
  339. A este procedimiento se le pasa un ½string╗ con el directorio completo
  340. (podemos a±adir al resultado de ½getdir╗ el directorio a crear), y dos
  341. variables booleanas que indican si el directorio es imposible de crear
  342. por ser incorrecto sintßcticamente, unidad inexistente o bien si ya
  343. existφa. Hay que advertir que dichas variables deben estar
  344. inicializadas a ½false╗.
  345.  
  346. PROCEDURE Creardir (dir:String; VAR error, existe:BOOLEAN);
  347.  
  348. VAR dir2:String;
  349.  
  350.  ind,io:Integer;
  351.  
  352.  faux:File;
  353.  
  354. BEGIN
  355.  
  356.  {$i-}
  357.  
  358.  ind:=Length(dir);
  359.  
  360.  dir2:=dir;
  361.  
  362.  IF (ind<>0) AND (dir[ind]<>':') THEN
  363.  
  364.  BEGIN
  365.  
  366.  WHILE (dir2[Length(dir2)] <>'\') AND (Length(dir2)<>0) DO
  367.  
  368.  Delete(dir2,Length(dir2),1);
  369.  
  370.  Delete(dir2,Length(dir2),1);
  371.  
  372.  IF Length(dir2)>0 THEN Creardir(dir2,error,existe)
  373.  
  374.  ELSE error:=true
  375.  
  376.  END
  377.  
  378.  ELSE IF ind=0 THEN error:=true
  379.  
  380.  ELSE BEGIN
  381.  
  382.  Assign(faux,dir+'\prueba.dat');
  383.  
  384.  Rewrite(faux);
  385.  
  386.  IF ioresult=0 THEN BEGIN
  387.  
  388.  Close(faux);
  389.  
  390.  Erase(faux)
  391.  
  392.  END
  393.  
  394.  ELSE error:=true
  395.  
  396.  END;
  397.  
  398.  IF not(error) THEN error:=ind=0;
  399.  
  400.  IF (ind<>0) AND (dir[ind]<>':') AND NOT (error) THEN
  401.  
  402.  BEGIN
  403.  
  404.  IF NOT error THEN mkdir(dir);
  405.  
  406.  io:=ioresult;
  407.  
  408.  IF existe THEN existe:= io=5;
  409.  
  410.  IF NOT (error) THEN error:= (io<>0) AND (io<>5)
  411.  
  412.  END;
  413.  
  414. END;
  415.  
  416. Julio Maiques Pena
  417.  
  418. Valencia
  419.  
  420.  
  421.  
  422. BITES SIGNIFICATIVOS
  423.  
  424. En Pascal no hay ninguna funci≤n estßndar que nos traduzca los bites
  425. significativos de un valor de tipo binario, algo de gran utilidad si
  426. nos interesa, por ejemplo, manejar los atributos de un fichero. Con
  427. una funci≤n en ensamblador, sin embargo, resolvemos el problema en tan
  428. solo unas cuantas lφneas. La funci≤n es como sigue:
  429.  
  430. Function BiteActivo(BiteBuscado, Lugar:Word):boolean;assembler;
  431.  
  432. asm
  433.  
  434. mov ax, BiteBuscado
  435.  
  436. and ax, Lugar
  437.  
  438. cmp ax,0 {si es 0, no se haya activo}
  439.  
  440. je @1 {false =0}
  441.  
  442. mov ax,1 {true=1}
  443.  
  444. @1:
  445.  
  446. end;
  447.  
  448. Fco. Javier Delgado Martφnez
  449.  
  450. Madrid
  451.  
  452.  
  453. SONIDO POR INTERRUPCIONES
  454.  
  455. Este es un truco residente que hace sonar el teclado de forma curiosa.
  456. Con las teclas ½+╗, ½-╗, y con los n·meros 1 al 9, se puede variar el
  457. tono y duraci≤n del sonido respectivamente. S≤lo suena cuando se
  458. pulsa alguna tecla, para ello el programa mira directamente la tecla
  459. pulsada en el buffer.
  460.  
  461. program sonido;
  462.  
  463. {$M 1024,0,0}
  464.  
  465. uses crt,dos;
  466.  
  467.  var progr:procedure;
  468.  
  469.  regs:registers;
  470.  
  471.  ofs,entrada:word;
  472.  
  473.  mul,mul2:integer;
  474.  
  475. {$F+}
  476.  
  477.  procedure rutina;interrupt;
  478.  
  479.  var b,d:integer;
  480.  
  481. begin
  482.  
  483.  entrada:=memw[$40:$1c];
  484.  
  485.  if entrada<>30 then
  486.  
  487.  begin
  488.  
  489.  entrada:=entrada-2; { letra -2 bytes es tu letra }
  490.  
  491.  end
  492.  
  493.  else entrada:=60;
  494.  
  495.  ofs:=memw[$40:entrada];
  496.  
  497.  b:=lo(ofs); { n·mero de letra }
  498.  
  499.  if b=43 then mul:=mul+1;
  500.  
  501.  if b=45 then mul:=mul-1 ;
  502.  
  503.  if (b>=49) and (b<=57) then mul2:=b-48;
  504.  
  505.  mul:=abs(mul);
  506.  
  507.  for d:=b*100 downto 0 do sound((d*mul div 2)+b);
  508.  
  509.  nosound;
  510.  
  511.  progr;
  512.  
  513. end;
  514.  
  515.  {$F-}
  516.  
  517. begin
  518.  
  519.  mul:=1;
  520.  
  521.  mul2:=1;
  522.  
  523. writeln(' SONIDO v1.00 ');
  524.  
  525. getintvec($9,@progr);
  526.  
  527. setintvec ($9,addr(rutina));
  528.  
  529. keep(0);
  530.  
  531. end.
  532.  
  533. Jorge Juan ArestΘ Espi
  534.  
  535. Muro (Alicante)
  536.  
  537.  
  538. RUTINAS PARA EL TECLADO
  539.  
  540. Las siguientes rutinas proporcionan un mayor control sobre el teclado.
  541. La primera de ellas, AceleraTeclado, sirve (como su propio nombre
  542. parece indicar) para acelerar considerablemente la respuesta del
  543. teclado. Su utilizaci≤n es bien sencilla, y puede ser de gran
  544. utilidad para determinados juegos que requieran una rßpida respuesta.
  545. Las otras dos, MaskOutKbd y UnMaskKbd tienen como funci≤n la de
  546. activar y desactivar el teclado.
  547.  
  548. Procedure AceleraTeclado;
  549.  
  550. assembler; asm
  551.  
  552.  mov ax,$305
  553.  
  554.  xor bx,bx
  555.  
  556.  int 16h
  557.  
  558. end;
  559.  
  560. Procedure MaskOutKbd; Assembler;
  561.  
  562. asm
  563.  
  564.  in al,21
  565.  
  566.  or al,00000010b
  567.  
  568.  out 21h,al
  569.  
  570. end;
  571.  
  572. Procedure UnMaskKbd; Assembler;
  573.  
  574. asm
  575.  
  576.  in al,21
  577.  
  578.  or al,11111101b
  579.  
  580.  out 21h,al
  581.  
  582. end;
  583.  
  584. La siguiente funci≤n lee una tecla del teclado o bien del buffer del
  585. teclado, y devuelve una variable numΘrica de formato Word, de modo que
  586. en el byte mßs alto obtenemos el c≤digo de rastreo y en el byte mßs
  587. bajo el c≤digo ASCII. Para obtener ambos valores podemos emplear las
  588. funciones Hi y Lo, para obtener los bytes mßs significativos y menos
  589. significativos respectivamente.
  590.  
  591. El uso de ambos valores combinados es interesante pues podemos
  592. distinguir la pulsaci≤n de las flechas del cursor, del teclado
  593. numΘrico, la pulsaci≤n de ½Alt╗ o ½Ctrl╗ con otra tecla, etc. TambiΘn
  594. es interesante el uso del byte de rastreo, pues este dato no
  595. diferencia, dada una tecla en particular, si se ha pulsado may·scula o
  596. min·scula o en combinaci≤n con ½Ctrl╗ o ½Alt╗. En resumen, cada tecla
  597. tiene un c≤digo de rastreo asignado. La lista de todos los c≤digos
  598. obtenidos al pulsar cada tecla es demasiado extensa para incluirla
  599. aquφ, pero todo es cuesti≤n de ir probando. Por ejemplo, el c≤digo de
  600. rastreo para la letra ½A╗ es el 30 (1E en Hexadecimal), tanto
  601. may·scula como min·scula, aunque su c≤digo ASCII es 65 para la
  602. may·scula y 97 si es min·scula. Si pulsamos ½Ctrl+A╗ obtenemos 3001,
  603. y si pulsamos ½Alt+A╗ obtenemos 3000.
  604.  
  605. Function LeeTecla : Word; Assembler;
  606.  
  607. Asm
  608.  
  609.  xor ax,ax
  610.  
  611.  int $16
  612.  
  613. End;
  614.  
  615. Definiendo al principio del programa las siguientes variables:
  616.  
  617. Var
  618.  
  619.  TeclaCabeza : Word Absolute 0:$41A;
  620.  
  621.  TeclaCola : Word Absolute 0:$41C;
  622.  
  623. De esta forma, TeclaCabeza contiene el c≤digo de la tecla que se
  624. encuentra al principio del buffer del teclado, mientras que en la
  625. variable TeclaCola se almacena el c≤digo de la tecla que se encuentra
  626. en la cola del buffer.
  627.  
  628. TambiΘn podemos utilizar el siguiente procedimiento, que se encarga de
  629. limpiar el buffer de teclado de una forma rßpida y efectiva.
  630.  
  631. Procedure LimpiaBuffer;
  632.  
  633. Begin
  634.  
  635.  TeclaCabeza:= TeclaCola;
  636.  
  637. End;
  638.  
  639. Podemos comparar TeclaCabeza con TeclaCola; en caso de obtener valores
  640. diferentes podemos afirmar que se ha pulsado una tecla. De esta forma
  641. obtenemos una nueva y sencilla forma para la funci≤n ½KeyPressed╗. Lo
  642. podemos hacer directamente comparando ambos valores mediante un If
  643. TeclaCabeza<>TeclaCola Then.... O podemos emplear la siguiente
  644. funci≤n en ensamblador que hace el mismo trabajo.
  645.  
  646. Function TeclaPulsada : Boolean; Assembler;
  647.  
  648. asm
  649.  
  650.  xor ax,ax
  651.  
  652.  mov es,ax
  653.  
  654.  mov ax,[es:TeclaCabeza]
  655.  
  656.  sub ax,[es:TeclaCola]
  657.  
  658.  jz @@1
  659.  
  660.  mov ax,1
  661.  
  662. @@1:
  663.  
  664.  sti
  665.  
  666. end;
  667.  
  668. Hemos de recordar que las funciones y procedimientos que hacen uso del
  669. ensamblador incorporado en Turbo Pascal, s≤lo podrßn ser compiladas en
  670. versiones posteriores a la 6.0, primera versi≤n en que se incorpor≤
  671. esta capacidad.
  672.  
  673. Santos Herranz Domingo
  674.  
  675. Madrid
  676.  
  677.  
  678.  
  679. ESPACIO EN EL DISCO
  680.  
  681. Cada vez que efectuamos un ½dir╗ de un directorio del disco se nos
  682. muestra la informaci≤n de los bytes ocupados y los que quedan libres.
  683. Aunque esta informaci≤n es mßs que suficiente, gracias a este programa
  684. podremos conseguir un resultado mßs vistoso de esta informaci≤n. La
  685. funci≤n de este programa es la de crear una barra de porcentaje con la
  686. cantidad del disco duro que tenemos ocupado.
  687.  
  688. Ademßs, no s≤lo nos muestra el tanto por ciento de disco ocupado, sino
  689. que para mayor informaci≤n el programa nos indica los bytes totales,
  690. los ocupados y los que nos quedan libres.
  691.  
  692. Program BarDisk;
  693.  
  694. Uses Crt, Dos;
  695.  
  696. Var total, Libre, Tanto: LongInt;
  697.  
  698.  Numero: String;
  699.  
  700.  i: Byte;
  701.  
  702. Function PuntoMil (n: LongInt): String;
  703.  
  704. Var f: Byte;
  705.  
  706.  s: String;
  707.  
  708. Begin
  709.  
  710.  Str(n,s);
  711.  
  712.  For f:=1 to 3 do
  713.  
  714.  If length (s) >= 4*f then
  715.  
  716.  Insert('.',s, Length(s) - f*4+2);
  717.  
  718.  PuntoMil:=s;
  719.  
  720. End;
  721.  
  722. Begin
  723.  
  724.  Total:=DiskSize(0) div 1024;
  725.  
  726.  Libre:=DiskFree(0) div 1024;
  727.  
  728.  Tanto:=((Total-Libre) *100) div Total;
  729.  
  730.  TextColor(3);
  731.  
  732.  GotoXY(24,WhereY);
  733.  
  734.  WriteLn(Tanto,'% de espacio en disco ocupado');
  735.  
  736.  {Dibuja barra y coloca porcentajes}
  737.  
  738.  For i:=3 To 78 do
  739.  
  740.  Begin
  741.  
  742.  GotoXY (i,WhereY);
  743.  
  744.  Write (#176);
  745.  
  746.  End;
  747.  
  748.  textColor(14);
  749.  
  750.  Tanto:= ((Total-Libre)*78) div Total;
  751.  
  752.  For i:=3 to Tanto do
  753.  
  754.  Begin
  755.  
  756.  GotoXY(i,WhereY);
  757.  
  758.  Write(#219);
  759.  
  760.  End;
  761.  
  762.  TextColor(3);
  763.  
  764.  WriteLn;
  765.  
  766.  GotoXY(3,WhereY); Write(#179,'0%');
  767.  
  768.  GotoXY(38,WhereY); Write(#179,'50%');
  769.  
  770.  GotoXY(74,WhereY); WritelN('100%',#179);
  771.  
  772.  WriteLn;
  773.  
  774.  { Coloca datos del disco }
  775.  
  776.  Numero := PuntoMil (DiskSize(0));
  777.  
  778.  WriteLn(#175#32, Numero, ' bytes totales ');
  779.  
  780.  Numero := PuntoMil (DiskSize(0)-DiskFree(0));
  781.  
  782.  WriteLn(#175#32, Numero, ' bytes ocupados');
  783.  
  784.  Numero := PuntoMil (DiskFree(0));
  785.  
  786.  WriteLn(#175#32, Numero, ' bytes libres');
  787.  
  788.  TextColor(7);
  789.  
  790.  WriteLn;
  791.  
  792. End.
  793.  
  794. Juan Antonio Fernßndez Moreno
  795.  
  796. Huelva
  797.  
  798.  
  799. ZOOM GRAFICO
  800.  
  801. Este programa incluye la rutina ½deforma╗, que permitirß efectuar
  802. ampliaciones y reducciones, y en general cualquier tipo de deformaci≤n
  803. de una zona de la pantalla.
  804.  
  805. Para su uso s≤lo hemos de llamar a ½deforma╗ con las coordenadas x, y
  806. de la esquina superior izquierda de la imagen a deformar; tras Θstas,
  807. las coordenadas x, y de la esquina inferior izquierda de la imagen a
  808. deformar. DespuΘs de teclear las cuatro coordenadas introducimos las
  809. mismas, pero esta vez dando las coordenadas donde queremos situar la
  810. imagen. Hay que notar que no tienen por quΘ tener el mismo tama±o, ya
  811. que el procedimiento se encarga de deformar la imagen para adecuarla a
  812. las coordenadas de destino.
  813.  
  814. En el programa de ejemplo podemos ver un ejemplo del uso de la rutina
  815. para efectuar un zoom hacia afuera.
  816.  
  817. program Uso_de_Deforma;
  818.  
  819. uses Crt;
  820.  
  821. type
  822.  
  823.  pantalla = array [0..199,0..319] of byte;
  824.  
  825. var
  826.  
  827.  pantallaPTR : ^pantalla;
  828.  
  829.  z : integer;
  830.  
  831. procedure deforma(x1,y1,x2,y2,x3,y3,x4,y4 : integer);
  832.  
  833. var
  834.  
  835.  x,y,dx1,dy1,dx3,dy3 : integer;
  836.  
  837. begin
  838.  
  839.  dx1:=x2-x1;
  840.  
  841.  dy1:=y2-y1;
  842.  
  843.  dx3:=x4-x3;
  844.  
  845.  dy3:=y4-y3;
  846.  
  847.  for y:=0 to dy3 do
  848.  
  849.  for x:=0 to dx3 do
  850.  
  851. pantallaPTR^[y+y3,x+x3]:=pantallaPTR^[((y*dy1)div dy3)+y1,((x*dx1)div
  852. dx3)+x1];
  853.  
  854.  end;
  855.  
  856. begin
  857.  
  858.  asm
  859.  
  860.  mov ax,13h
  861.  
  862.  int 10h
  863.  
  864.  end;
  865.  
  866.  pantallaPTR := ptr($a000,0); (*este puntero apunta a la pantalla*)
  867.  
  868.  for z:=0 to 100 do
  869.  
  870.  pantallaPTR^[random(29),random(29)]:=random(255);
  871.  
  872.  for z:=10 to 150 do
  873.  
  874.  begin
  875.  
  876.  deforma(0,0,29,29,100,40,100+z,40+z);
  877.  
  878.  delay(50);
  879.  
  880.  end;
  881.  
  882. end.
  883.  
  884. Antonio Ruiz
  885.  
  886. Mßlaga
  887.  
  888.  
  889.  
  890. INFORMACION SOBRE EL RATON
  891.  
  892. El siguiente programa, realizado en Turbo Pascal, efect·a un completo
  893. test del rat≤n mostrando la siguiente informaci≤n: n·mero de botones,
  894. IRQ utilizada, tama±o del buffer de estado, versi≤n del driver, idioma
  895. utilizado y tipo de rat≤n (serie, bus, etc.). Ademßs, activa el
  896. cursor para que lo podamos ver en pantalla.
  897.  
  898. Todas las llamadas a las distintas funciones del rat≤n se realizan a
  899. travΘs de la interrupci≤n 33h. Como se puede comprobar, esta
  900. interrupci≤n estß muy utilizada en este programa.
  901.  
  902. Program MTest (Mouse_Test);
  903.  
  904. Uses Crt, Dos;
  905.  
  906. Const aTipo: Array [1..5] Of string [8]=('Bus', 'Sere', 'InPort',
  907. 'PS/2', 'HP');
  908.  
  909.  aIdio: Array [0..8] Of string = ('InglΘs', 'FrancΘs', 'HolandΘs',
  910.  'Alemßn','Sueco','FinlandΘs', 'Espa±ol','PortuguΘs','Italiano');
  911.  
  912. Var regs:Registers;
  913.  
  914.  Botones: Byte;
  915.  
  916. Begin
  917.  
  918.  Regs.AX:=0;
  919.  
  920.  INTr($33,regs);
  921.  
  922.  WriteLn;
  923.  
  924.  If regs.AX=0 Then
  925.  
  926.  Begin
  927.  
  928.  WriteLn('No se encontr≤ el driver del rat≤n.');
  929.  
  930.  Halt;
  931.  
  932.  End
  933.  
  934.  Else
  935.  
  936.  Begin
  937.  
  938.  Botones:=regs.BX;
  939.  
  940.  {Dibuja Mouse}
  941.  
  942.  TextColor(15);
  943.  
  944.  WriteLn(#186:6);
  945.  
  946.  WriteLn(#219#177#219#177#219:8);
  947.  
  948.  WriteLn(#219#219#219#219#219:8);
  949.  
  950.  WriteLn('Driver del rat≤n en memoria.');
  951.  
  952.  WriteLn;
  953.  
  954.  {Coloca datos y activa rat≤n}
  955.  
  956.  regs.AX:=$24;
  957.  
  958.  INTr($33, regs);
  959.  
  960.  WriteLn('Versi≤n del driver: ', regs.BH, '.', regs.BL);
  961.  
  962.  WriteLn('Tipo del rat≤n....: ', (aTipo[regs.CH] ));
  963.  
  964.  WriteLn('N·mero de botones.: ', botones);
  965.  
  966.  WriteLn('Instalado en IRQ..: ', regs.CL);
  967.  
  968.  regs.AX:=$23;
  969.  
  970.  INTr($33,regs);
  971.  
  972.  WriteLn('Idioma............: ', (aIdio[regs.BX]));
  973.  
  974.  regs.AX:=$15;
  975.  
  976.  INTr($33,regs);
  977.  
  978.  WriteLn('Buffer de estado..: ', regs.BX, ' bytes');
  979.  
  980.  Regs.AX:=1;
  981.  
  982.  INTr($33,regs);
  983.  
  984.  Repeat Until KeyPressed;
  985.  
  986.  regs.AX:=2;
  987.  
  988.  INTr($33,regs);
  989.  
  990.  TextColor(7);
  991.  
  992.  WriteLn;
  993.  
  994.  End;
  995.  
  996. End.
  997.  
  998. Juan Antonio Fernßndez Moreno
  999.  
  1000. Huelva
  1001.  
  1002.  
  1003. VISUALIZADOR DE FICHEROS BMP
  1004.  
  1005. Este es un interesante programa que nos permite visualizar ficheros
  1006. BMP de 256 colores con codificaci≤n RGB. Aunque admite ficheros de
  1007. cualquier resoluci≤n, en las imßgenes mayores de 320 x 200 s≤lo se
  1008. visualizarßn las primeras 320 columnas y las primeras 200 filas; el
  1009. resto no se visualizarß.
  1010.  
  1011. Para su ejecuci≤n deberemos introducir ½VER_BMP nombre_fichero
  1012. [.BMP]╗. Esta rutina no comprueba la existencia de tarjeta grßfica
  1013. VGA, ni tampoco la existencia del fichero BMP introducido como
  1014. parßmetro; de manera que si se introduce un nombre no vßlido o no se
  1015. dispone de VGA se provocarß un error de ejecuci≤n.
  1016.  
  1017. Recordemos que s≤lo visualiza ficheros BMP con codificaci≤n RGB y con
  1018. 256 colores, de manera que si una imagen no puede visualizarse serß
  1019. por cualquiera de estos tres motivos: bmpfile.bfType distinto de
  1020. CABEZA_BMP (no es un fichero BMP); bmpinfo.biBitCount distinto de 8
  1021. (no es un fichero de 256 colores), o bmpinfo.biCompression distinto de
  1022. 0 (no tiene codificacion RGB).
  1023.  
  1024. Notas acerca de la rutina y los ficheros BMP
  1025.  
  1026. Dadas las diferentes caracterφsticas de VGA y BMP es necesario
  1027. reconvertir la paleta almacenada en un fichero BMP a un formato vßlido
  1028. para la VGA, ya que los valores que almacena el fichero BMP para cada
  1029. componente de color estan entre 0 y 255, mientras que la VGA s≤lo
  1030. maneja valores entre 0 y 63 para cada componente de color.
  1031.  
  1032. Por otra parte, la estructura de la paleta de un BMP asigna 4 bytes
  1033. para cada color, almacenando los colores en el siguiente orden: azul,
  1034. verde y rojo; mientras que la paleta que debe ser pasada a los
  1035. registros DAC de la VGA s≤lo tiene 3 bytes para cada color de la
  1036. paleta y los colores deben ir en el orden inverso, es decir, rojo,
  1037. verde y azul.
  1038.  
  1039. Por ·ltimo, la longitud de una lφnea de imagen almacenada en un
  1040. fichero BMP siempre es m·ltiplo de 4, por lo que una imagen con un
  1041. ancho que no sea m·ltiplo de dicha cantidad tendrß bytes basura, que
  1042. no deben ser visualizados (de hecho, tendrß tantos bytes basura como
  1043. los necesarios para igualar la longitud al m·ltiplo de 4 superior mßs
  1044. pr≤ximo).
  1045.  
  1046. Dado que la inicializaci≤n del modo de vφdeo se hace en ensamblador no
  1047. es necesario disponer del driver BGI correspondiente. Aunque, eso sφ,
  1048. para poder compilarlo necesitaremos al menos la versi≤n 6.0 de Turbo
  1049. Pascal.
  1050.  
  1051. Por otra parte, hay que se±alar que las lφneas:
  1052.  
  1053. cont := port[$3da]; port[$3c0] := $20;
  1054.  
  1055. cont := port[$3da]; port[$3c0] := $20;
  1056.  
  1057. posibilitan que s≤lo se muestre la imagen una vez que Θsta estΘ entera
  1058. en la pantalla. De ahφ que si queremos que la imagen vaya siendo
  1059. dibujada lφnea a lφnea, baste con eliminarlas.
  1060.  
  1061. Una ·ltima aclaraci≤n: las lφneas de imagen de un fichero BMP se almacenan
  1062. en orden inverso a como aparecerßn en la pantalla, esto es, la primera
  1063. lφnea de imagen en el fichero se corresponde con la ·ltima que aparece en
  1064. pantalla. Es por esto que el bucle en el que se transfiere la imagen del
  1065. archivo a la pantalla vaya de valores mayores a menores.
  1066.  
  1067. Program Ver_BMP;
  1068.  
  1069. Uses
  1070.  
  1071.  crt, dos;
  1072.  
  1073. Const
  1074.  
  1075.  CABEZA_BMP = $4D42;
  1076.  
  1077. Type
  1078.  
  1079.  BitmapFileHeader = Record
  1080.  
  1081.  bfType :word;
  1082.  
  1083.  bfSize :longint;
  1084.  
  1085.  bfReserved1,
  1086.  
  1087.  bfReserved2 :word;
  1088.  
  1089.  bfOffbits :longint;
  1090.  
  1091.  end;
  1092.  
  1093.  BitmapInfoHeader = record
  1094.  
  1095.  biSize, biWidth,
  1096.  
  1097.  biHeight :longint;
  1098.  
  1099.  biPlanes,
  1100.  
  1101.  biBitCount :word;
  1102.  
  1103.  biCompression,
  1104.  
  1105.  biSizeImage,
  1106.  
  1107.  biXpelsperMeter,
  1108.  
  1109.  biYpelsPerMeter,
  1110.  
  1111.  biClrUsed,
  1112.  
  1113.  biClrImportant :longint;
  1114.  
  1115.  end;
  1116.  
  1117.  RGBQuad = record
  1118.  
  1119.  rgbBlue, rgbGreen, rgbRed, rgbReserved :byte;
  1120.  
  1121.  end;
  1122.  
  1123.  rgbDAC = record
  1124.  
  1125.  rgbRed, rgbGreen, rgbBlue :byte;
  1126.  
  1127.  end;
  1128.  
  1129.  RGBQpaleta = array[0..255] of RGBquad;
  1130.  
  1131.  RGBpaleta = array[0..255] of rgbDAC;
  1132.  
  1133.  linea320 = array[0..319] of byte;
  1134.  
  1135. Var
  1136.  
  1137.  fichero :file;
  1138.  
  1139.  name :string;
  1140.  
  1141.  bmpFile :bitmapFileHeader;
  1142.  
  1143.  bmpInfo :bitmapInfoHeader;
  1144.  
  1145.  bmpPalet :RGBQpaleta;
  1146.  
  1147.  Paleta :rgbPaleta;
  1148.  
  1149.  linea :^linea320;
  1150.  
  1151.  suma :byte;
  1152.  
  1153.  scanline, mover, cont :word;
  1154.  
  1155.  regs :registers;
  1156.  
  1157.  buffergraf :array [0..64000] of byte absolute $a000:$00;
  1158.  
  1159. Begin
  1160.  
  1161.  name := paramstr(1);
  1162.  
  1163.  if pos('.',name) < 1 then
  1164.  
  1165.  name := name + '.bmp';
  1166.  
  1167.  assign(fichero, name);
  1168.  
  1169.  reset(fichero, 1);
  1170.  
  1171.  blockread(fichero, bmpfile, sizeof(bmpfile));
  1172.  
  1173.  blockread(fichero, bmpinfo, sizeof(bmpinfo));
  1174.  
  1175.  if (bmpfile.bfType <> CABEZA_BMP) or (bmpinfo.biBitCount <> 8) or
  1176.  
  1177.  (bmpinfo.biCompression <> 0) then
  1178.  
  1179.  writeln ('No se puede Visualizar el fichero')
  1180.  
  1181.  else begin
  1182.  
  1183.  blockread (fichero, bmpPalet[0], sizeof(bmpPalet));
  1184.  
  1185.  for cont := 0 to 255 do begin
  1186.  
  1187.  paleta[cont].rgbRed := bmpPalet[cont].rgbRed div 4;
  1188.  
  1189.  paleta[cont].rgbGreen := bmpPalet[cont].rgbGreen div 4;
  1190.  
  1191.  paleta[cont].rgbBlue := bmpPalet[cont].rgbBlue div 4;
  1192.  
  1193.  end;
  1194.  
  1195.  cont := bmpinfo.biWidth mod 4;
  1196.  
  1197.  case cont of
  1198.  
  1199.  1: suma := 3;
  1200.  
  1201.  2: suma := 2;
  1202.  
  1203.  3: suma := 1;
  1204.  
  1205.  else
  1206.  
  1207.  suma := 0;
  1208.  
  1209.  end;
  1210.  
  1211.  scanline := bmpinfo.biWidth + suma;
  1212.  
  1213.  if bmpinfo.biWidth > 320 then
  1214.  
  1215.  mover := 320
  1216.  
  1217.  else
  1218.  
  1219.  mover := bmpinfo.biWidth;
  1220.  
  1221.  asm
  1222.  
  1223.  mov ax, 0013h
  1224.  
  1225.  int 10h
  1226.  
  1227.  end;
  1228.  
  1229.  regs.ax := $1012;
  1230.  
  1231.  regs.bx := $00;
  1232.  
  1233.  regs.cx := $100;
  1234.  
  1235.  regs.es := seg(paleta[0]);
  1236.  
  1237.  regs.dx := ofs(paleta[0]);
  1238.  
  1239.  intr($10, regs);
  1240.  
  1241.  getmem(linea, scanline);
  1242.  
  1243.  cont := port[$3da];
  1244.  
  1245.  port[$3c0] := $00;
  1246.  
  1247.  if bmpinfo.biheight > 200 then begin
  1248.  
  1249.  seek(fichero, filepos(fichero)+ scanline * (bmpinfo.biheight-200));
  1250.  
  1251.  bmpinfo.biheight := 200
  1252.  
  1253.  end;
  1254.  
  1255.  for cont := (bmpinfo.biheight - 1) downto 0 do begin
  1256.  
  1257.  blockread(fichero, linea^[0], scanline);
  1258.  
  1259.  move (linea^[0], bufferGraf[cont*320], mover);
  1260.  
  1261.  end;
  1262.  
  1263.  cont := port[$3da];
  1264.  
  1265.  port[$3c0] := $20;
  1266.  
  1267.  close(fichero);
  1268.  
  1269.  freemem(linea, scanline);
  1270.  
  1271.  repeat until keypressed;
  1272.  
  1273.  asm
  1274.  
  1275.  mov ax, 0003h
  1276.  
  1277.  int 10h
  1278.  
  1279.  end;
  1280.  
  1281.  end;
  1282.  
  1283. end.
  1284.  
  1285. Carlos Soto Garcφa
  1286.  
  1287. Las Rozas (Madrid)
  1288.  
  1289.  
  1290. RUTINAS GRAFICAS
  1291.  
  1292. La introducci≤n a la programaci≤n del modo de vφdeo 13h de la VGA ha
  1293. tenido gran aceptaci≤n entre todos nuestros lectores. Buena prueba de
  1294. ello es que estamos recibiendo gran cantidad de rutinas para este modo
  1295. de vφdeo. Un buen ejemplo es la siguiente unidad para Turbo Pascal
  1296. 6.0 ≤ posterior, que contiene diversas rutinas (la mayorφa en
  1297. ensamblador) de gran interΘs para el mencionado modo de 320x200x256.
  1298.  
  1299. La unidad contiene los siguientes procedimientos:
  1300.  
  1301. LeePcx: Este procedimiento descomprime un fichero en formato
  1302. grßfico PCX de 320x200x256 (con la condici≤n de que el tama±o del
  1303. fichero no exceda de 64 Kbytes) y almacena el resultado en una zona de
  1304. memoria. TambiΘn devuelve la paleta del fichero.
  1305.  
  1306. MueveGraf: Se encarga de escribir en pantalla un grßfico
  1307. descomprimido con el procedimiento anterior. TambiΘn sirve para mover
  1308. grßficos que sean una imagen exacta de la memoria de pantalla. Es
  1309. equivalente a la instrucci≤n ½move╗ de Turbo Pascal.
  1310.  
  1311. LeeSprite: Captura una regi≤n de la pantalla y la almacena en
  1312. una regi≤n de memoria especificada. El formato del grßfico es el
  1313. siguiente: en la posici≤n 0 con un tama±o de una palabra se guarda el
  1314. ancho del dibujo; en la posici≤n 2 con un tama±o de una palabra se
  1315. guarda el alto del dibujo, y a partir de la posici≤n 4 con un tama±o
  1316. de (ancho x alto) bytes se guarda el dibujo grabado por filas.
  1317.  
  1318. PonSprite: Devuelve a la pantalla una regi≤n capturada con el
  1319. procedimiento ½LeeSprite╗. Ademßs, permite realizar operaciones
  1320. l≤gicas entre el dibujo y lo que hay en pantalla. Para seleccionar
  1321. quΘ operaci≤n l≤gica vamos a usar existen las constantes
  1322. mskNormal, mskXor, mskOr, mskAnd y
  1323. mskNot. Estas constantes vienen dadas en la siguiente tabla
  1324. donde se indican tambiΘn sus valores numΘricos, y las operaciones
  1325. l≤gicas que se realizan entre los puntos de la pantalla y del
  1326. Sprite.
  1327.  
  1328. MskNormal 0 MOV
  1329.  
  1330. MskXOR 1 XOR
  1331.  
  1332. MskOR 2 OR
  1333.  
  1334. MskAND 3 AND
  1335.  
  1336. MskNOT 4 NOT
  1337.  
  1338. Unit Graficos;
  1339.  
  1340. Interface
  1341.  
  1342. Const
  1343.  
  1344.  {-- Constantes del fundido --}
  1345.  
  1346.  funRojo = 0;
  1347.  
  1348.  funAzul = 1;
  1349.  
  1350.  funVerde = 2;
  1351.  
  1352.  {-- Operaciones l≤gicas del procedimiento PonSprite --}
  1353.  
  1354.  mskNormal = 0;
  1355.  
  1356.  mskXOR = 1;
  1357.  
  1358.  mskOR = 2;
  1359.  
  1360.  mskAND = 3;
  1361.  
  1362.  mskNOT = 4;
  1363.  
  1364. Type
  1365.  
  1366.  TPaleta = Array[0..767] of Byte;
  1367.  
  1368.  Procedure LeePcx(var Graf;Total:Word;var Pal:TPaleta;var Imagen);
  1369.  
  1370.  Procedure MueveGraf(var Graf);
  1371.  
  1372.  Procedure PonSprite(X,Y:Word;Mask:Byte;var Graf);
  1373.  
  1374.  Procedure LeeSprite(x1,y1,x2,y2:Word;var Graf);
  1375.  
  1376.  Procedure PonPunto(X,Y:Word;Color:Byte);
  1377.  
  1378.  Procedure Escribe(X,Y:Word;Texto:String;Color:Byte);
  1379.  
  1380. Implementation
  1381.  
  1382. Var
  1383.  
  1384.  Seg1F,
  1385.  
  1386.  Ofs1F : Word;
  1387.  
  1388. Procedure LeePcx; Assembler;
  1389.  
  1390. { Descomprime un fichero PCX en formato 320x200x256. Se asume que la
  1391.  
  1392.  informaci≤n que se pasa como grßfico es correcta. El fichero ha de tener
  1393.  
  1394.  menos de 64k. El dibujo resultante se almacena en la variable IMAGEN y la
  1395.  
  1396.  paleta correspondiente en PAL. }
  1397.  
  1398. Var
  1399.  
  1400.  Cont : Word;
  1401.  
  1402. Asm
  1403.  
  1404.  Push Ds
  1405.  
  1406.  { CONT indica d≤nde empieza la paleta }
  1407.  
  1408.  Mov Ax,Total
  1409.  
  1410.  Mov Cont,Ax
  1411.  
  1412.  Sub Cont,768
  1413.  
  1414.  { Cada valor de la paleta ha de ser dividido por 4 }
  1415.  
  1416.  Lds Si,Graf { Se cargan dos punteros a la variable GRAF }
  1417.  
  1418.  Les Di,Pal
  1419.  
  1420.  Add Si,Cont { Se colocan donde empieza la paleta }
  1421.  
  1422.  Cld
  1423.  
  1424.  Mov Cx,768 { Hay 256*3 elementos }
  1425.  
  1426.  Mov Bl,4
  1427.  
  1428.  Xor Dx,Dx { Para dividir no se usa DX ni AH }
  1429.  
  1430.  Xor Ah,Ah
  1431.  
  1432. @Divide:
  1433.  
  1434.  Lodsb
  1435.  
  1436.  Xor Ah,Ah
  1437.  
  1438.  Div Bl { Divide cada byte por 4 }
  1439.  
  1440.  Stosb
  1441.  
  1442.  Loop @Divide
  1443.  
  1444.  { Con Es:Di se direccionarß la memoria de vφdeo }
  1445.  
  1446.  Les Di,Imagen
  1447.  
  1448.  { Se salta la cabecera. Usa Ds:Di para leer de la variable }
  1449.  
  1450.  Lds Si,Graf
  1451.  
  1452.  Add Si,128
  1453.  
  1454.  Mov Dx,Cont
  1455.  
  1456.  { El byte alto del contador no se va a usar }
  1457.  
  1458.  Xor Ch,Ch
  1459.  
  1460. @Bucle:
  1461.  
  1462.  Lodsb { Carga el byte actual }
  1463.  
  1464.  Cmp Al,192 { Si es menor de 192 s≤lo se dibuja una vez }
  1465.  
  1466.  Jb @NoRepite
  1467.  
  1468.  Sub Al,192 { Calcula cuantas veces se ha de dibujar }
  1469.  
  1470.  Mov Cl,Al
  1471.  
  1472.  Lodsb { Lee el color que se habrß de escribir }
  1473.  
  1474.  Jmp @Escribe
  1475.  
  1476. @NoRepite:
  1477.  
  1478.  Mov Cx,1 { S≤lo hay que imprimir un pixel }
  1479.  
  1480. @Escribe:
  1481.  
  1482.  Stosb { Escribe el color }
  1483.  
  1484.  Loop @Escribe { tantas veces como haga falta }
  1485.  
  1486.  Cmp Si,Dx { Comprueba si hemos llegado al final }
  1487.  
  1488.  Jnz @Bucle
  1489.  
  1490.  Pop Ds { Se tiene que restaurar DS }
  1491.  
  1492. End; { PROCEDURE LeePcx }
  1493.  
  1494. Procedure MueveGraf;Assembler;
  1495.  
  1496. Asm
  1497.  
  1498.  Push Ds
  1499.  
  1500.  Lds Si,Graf
  1501.  
  1502.  Mov Ax,0A000h
  1503.  
  1504.  Mov Es,Ax
  1505.  
  1506.  Xor Di,Di
  1507.  
  1508.  Mov Cx,32000
  1509.  
  1510.  Rep Movsw
  1511.  
  1512.  Pop Ds
  1513.  
  1514. End; { PROCEDURE MueveGraf }
  1515.  
  1516. Procedure PonSprite;Assembler;
  1517.  
  1518. { Escribe en pantalla un sprite de los creados por el procedimient LeeSprite,
  1519.  
  1520.  haciendo una operaci≤n l≤gica al escribirlo. }
  1521.  
  1522. Var
  1523.  
  1524.  Ancho,Alto : Word;
  1525.  
  1526. Asm
  1527.  
  1528.  Push Ds
  1529.  
  1530.  Dec X
  1531.  
  1532.  Dec Y
  1533.  
  1534.  Les Di,Graf { Lee el alto y ancho del grßfico }
  1535.  
  1536.  Mov Ax,word ptr [Es:Di]
  1537.  
  1538.  Mov Ancho,Ax { que se encuentran en las dos primeras palabras }
  1539.  
  1540.  Mov Ax,Es:[Di+2]
  1541.  
  1542.  Mov Alto,Ax
  1543.  
  1544.  Lds Si,Graf { Carga la direcci≤n del grßfico }
  1545.  
  1546.  Add Si,4 { El grßfico en sφ comienza en [Graf+4] }
  1547.  
  1548.  Mov Ax,320
  1549.  
  1550.  Xor Dx,Dx
  1551.  
  1552.  Mul Y
  1553.  
  1554.  Add Ax,X
  1555.  
  1556.  Mov Di,Ax { Calcula la posici≤n de inicio }
  1557.  
  1558.  Mov Ax,0A000h
  1559.  
  1560.  Mov Es,Ax
  1561.  
  1562.  Mov Cx,Alto { El bucle se ejecutarß tantas veces como alto sea }
  1563.  
  1564.  Mov Dl,Mask
  1565.  
  1566. @Repite:
  1567.  
  1568.  Push Cx
  1569.  
  1570.  Mov Cx,Ancho
  1571.  
  1572. @Escribe:
  1573.  
  1574.  Lodsb
  1575.  
  1576. @Normal:
  1577.  
  1578.  Cmp Dl,0
  1579.  
  1580.  Jne @XOR
  1581.  
  1582.  Jmp @FinCase
  1583.  
  1584. @XOR:
  1585.  
  1586.  Cmp Dl,1
  1587.  
  1588.  Jne @OR
  1589.  
  1590.  Xor Al,byte ptr [Es:Di]
  1591.  
  1592.  Jmp @FinCase
  1593.  
  1594. @OR:
  1595.  
  1596.  Cmp Dl,2
  1597.  
  1598.  Jne @AND
  1599.  
  1600.  Or Al,byte ptr [Es:Di]
  1601.  
  1602.  Jmp @FinCase
  1603.  
  1604. @AND:
  1605.  
  1606.  Cmp Dl,3
  1607.  
  1608.  Jne @NOT
  1609.  
  1610.  And Al,byte ptr [Es:Di]
  1611.  
  1612.  Jmp @FinCase
  1613.  
  1614. @NOT:
  1615.  
  1616.  Not Al
  1617.  
  1618.  Jmp @FinCase
  1619.  
  1620. @FinCase:
  1621.  
  1622.  Stosb
  1623.  
  1624.  Loop @Escribe
  1625.  
  1626.  Pop Cx
  1627.  
  1628.  Mov Bx,320 { Salta a la siguiente lφnea }
  1629.  
  1630.  Sub Bx,Ancho
  1631.  
  1632.  Add Di,Bx
  1633.  
  1634.  Loop @Repite
  1635.  
  1636.  Pop Ds
  1637.  
  1638. End; { PROCEDURE PonSprite }
  1639.  
  1640.  
  1641. Procedure LeeSprite;Assembler;
  1642.  
  1643. { Lee una regi≤n de la pantalla y la almacena en un buffer }
  1644.  
  1645. Var
  1646.  
  1647.  Ancho,Alto : Word;
  1648.  
  1649. Asm
  1650.  
  1651.  Push Ds
  1652.  
  1653.  Les Di,Graf
  1654.  
  1655.  Xor Ah,Ah
  1656.  
  1657.  Mov Ax,x2
  1658.  
  1659.  Sub Ax,x1
  1660.  
  1661.  Inc Ax
  1662.  
  1663.  Mov word ptr [Es:Di],Ax
  1664.  
  1665.  Mov Ancho,Ax
  1666.  
  1667.  Mov Ax,y2
  1668.  
  1669.  Sub Ax,y1
  1670.  
  1671.  Inc Ax
  1672.  
  1673.  Mov word ptr [Es:Di+2],Ax
  1674.  
  1675.  Mov Alto,Ax
  1676.  
  1677.  Add Di,4
  1678.  
  1679.  Dec Y1
  1680.  
  1681.  Dec X1
  1682.  
  1683.  Mov Ax,320
  1684.  
  1685.  Xor Dx,Dx
  1686.  
  1687.  Mul Y1
  1688.  
  1689.  Add Ax,X1
  1690.  
  1691.  Mov Si,Ax { Calcula la posici≤n de origen }
  1692.  
  1693.  Mov Ax,0A000h
  1694.  
  1695.  Mov Ds,Ax
  1696.  
  1697.  Mov Cx,Alto
  1698.  
  1699. @Repite:
  1700.  
  1701.  Push Cx
  1702.  
  1703.  Mov Cx,Ancho { Almacena cada lφnea }
  1704.  
  1705.  Rep Movsb
  1706.  
  1707.  Pop Cx
  1708.  
  1709.  Mov Bx,320 { Salta a la siguiente lφnea }
  1710.  
  1711.  Sub Bx,Ancho
  1712.  
  1713.  Add Si,Bx
  1714.  
  1715.  Loop @Repite
  1716.  
  1717.  Pop Ds
  1718.  
  1719. End; { PROCEDURE LeeSprite }
  1720.  
  1721. Procedure PonPunto;Assembler;
  1722.  
  1723. { Escribe un punto de un color determinado }
  1724.  
  1725. Asm
  1726.  
  1727.  Dec X
  1728.  
  1729.  Dec Y
  1730.  
  1731.  Xor Dx,Dx
  1732.  
  1733.  Mov Ax,320
  1734.  
  1735.  Mul Y
  1736.  
  1737.  Add Ax,X
  1738.  
  1739.  Mov Di,Ax
  1740.  
  1741.  Mov Ax,0A000h
  1742.  
  1743.  Mov Es,Ax
  1744.  
  1745.  Mov Al,Color
  1746.  
  1747.  Mov Es:[Di],Al
  1748.  
  1749. End; { PROCEDURE PonPunto }
  1750.  
  1751. Procedure Escribe;
  1752.  
  1753. { Usando la tabla que hay en la posici≤n $F000:$FA6E y que contiene
  1754.  
  1755.  los caracteres CGA se escribe un texto. }
  1756.  
  1757. Var
  1758.  
  1759.  Linea : Byte;
  1760.  
  1761.  Byt,
  1762.  
  1763.  Bit,Codigo: Byte;
  1764.  
  1765.  Caracter : String[1];
  1766.  
  1767.  Car,Xx,Yy : Integer;
  1768.  
  1769.  Segm,Ofss : Word;
  1770.  
  1771. Begin
  1772.  
  1773.  Xx:=x;
  1774.  
  1775.  Yy:=y;
  1776.  
  1777.  For Car := 0 to Length(Texto)-1 do
  1778.  
  1779.  Begin
  1780.  
  1781.  Caracter:=Copy(Texto,Car+1,1);
  1782.  
  1783.  Codigo:=Ord(Caracter[1]);
  1784.  
  1785.  { Si el carßcter es mayor de 127 no aparece en la tabla estßndar. Aparece
  1786.  
  1787.  en una tabla en cuya direcci≤n se encuentra el vector de interrupci≤n
  1788.  
  1789.  1Fh. }
  1790.  
  1791.  If Codigo<128 then
  1792.  
  1793.  Begin
  1794.  
  1795.  Segm:=$F000;
  1796.  
  1797.  Ofss:=$FA6E+Codigo*8;
  1798.  
  1799.  End
  1800.  
  1801.  Else
  1802.  
  1803.  Begin
  1804.  
  1805.  Segm:=Seg1F;
  1806.  
  1807.  Ofss:=Ofs1F+Codigo*8;
  1808.  
  1809.  End;
  1810.  
  1811.  { Escribe el carßcter. Escribe las 8 lφneas de barrido. }
  1812.  
  1813.  For Byt:=0 to 7 do
  1814.  
  1815.  Begin
  1816.  
  1817.  Linea:=Byte(Ptr(Segm,Ofss+Byt)^);
  1818.  
  1819.  Xx:=x+Car*8;
  1820.  
  1821.  Yy:=Y+Byt;
  1822.  
  1823.  { Cada lφnea de barrido se compone de 8 pixels }
  1824.  
  1825.  For Bit:=0 to 7 do
  1826.  
  1827.  Begin
  1828.  
  1829.  { No hay que escribir }
  1830.  
  1831.  If Linea < $7F then
  1832.  
  1833.  Xx:=Xx+1
  1834.  
  1835.  Else
  1836.  
  1837.  Begin
  1838.  
  1839.  { Escribe el punto }
  1840.  
  1841.  PonPunto(Xx,Yy,Color);
  1842.  
  1843.  Xx:=Xx+1;
  1844.  
  1845.  Linea:=Linea-$80;
  1846.  
  1847.  End;
  1848.  
  1849.  Linea:=Linea Shl 1;
  1850.  
  1851.  End;
  1852.  
  1853.  End;
  1854.  
  1855.  Yy:=Yy-7;
  1856.  
  1857.  End;
  1858.  
  1859. End; { PROCEDURE Escribe }
  1860.  
  1861.  
  1862. Begin
  1863.  
  1864.  Asm
  1865.  
  1866.  Mov Ah,35h
  1867.  
  1868.  Mov Al,1Fh
  1869.  
  1870.  Int 21h { Calcula la direcci≤n de la tabla de caracteres ASCII }
  1871.  
  1872.  Mov Seg1F,Es
  1873.  
  1874.  Mov Ofs1F,Bx
  1875.  
  1876.  End;
  1877.  
  1878. End.
  1879.  
  1880. Miguel Hernßndez Martos
  1881.  
  1882. Las Gabias (Granada)
  1883.  
  1884.  
  1885. GRAFICOS FRACTALES
  1886.  
  1887. La funci≤n de este truco es generar grßficos fractales, mßs en
  1888. concreto de los conjuntos de Julia. Si deseßis tener mßs informaci≤n
  1889. sobre este tipo de conjuntos os recomendamos leer el mencionado ½PC
  1890. Prßctico╗.
  1891.  
  1892. El programa es realmente sencillo, por lo que resulta fßcil modificar
  1893. algunos parßmetros para conseguir otros efectos y asφ comprender un
  1894. poco mßs este tipo de grßficos. Es fßcil modificar los colores, el
  1895. tama±o del grßfico en pantalla y la regi≤n a visualizar.
  1896.  
  1897. Program Fractal;
  1898.  
  1899. Uses Graph, Crt;
  1900.  
  1901. Const
  1902.  
  1903.  PixelH=150;
  1904.  
  1905.  PixelV=100;
  1906.  
  1907.  { Tama±o en pixels del grßfico en pantalla }
  1908.  
  1909.  xsup=-1.8;
  1910.  
  1911.  ysup=1.8;
  1912.  
  1913.  xinf=-1.8;
  1914.  
  1915.  yinf=1.8;
  1916.  
  1917.  {regi≤n del fractal a mostrar }
  1918.  
  1919. Var
  1920.  
  1921.  a,b,DeltaX,DeltaY,NewY2,x,y,x1,x2,y1,y2,SumaCuadrados:Real;
  1922.  
  1923.  cont:Byte;
  1924.  
  1925.  i,j,gd,gm,color:Integer;
  1926.  
  1927. Begin
  1928.  
  1929.  ClrScr;
  1930.  
  1931.  WriteLn ('Es necesario introducir el valor de un n·mero imaginario con
  1932.  notaci≤n x+yi');
  1933.  
  1934.  Write('Introduzca el valor de x=> ');
  1935.  
  1936.  ReadLn(a);
  1937.  
  1938.  Write('Introduzca el valor de y=> ');
  1939.  
  1940.  ReadLn(b);
  1941.  
  1942.  gm:=Detect;
  1943.  
  1944.  gd:=0;
  1945.  
  1946.  InitGraph(gd,gm,'');
  1947.  
  1948.  x1:=xsup;
  1949.  
  1950.  y1:=ysup;
  1951.  
  1952.  x2:=xinf;
  1953.  
  1954.  y2:=yinf;
  1955.  
  1956.  DeltaX:=(y1-x1)/PixelH;
  1957.  
  1958.  DeltaY:=(y2-x2)/PixelV;
  1959.  
  1960.  For i:= 1 To PixelH do
  1961.  
  1962.  Begin
  1963.  
  1964.  x1:=x1+DeltaX;
  1965.  
  1966.  NewY2:=y2;
  1967.  
  1968.  For j:=1 To PixelV do
  1969.  
  1970.  Begin
  1971.  
  1972.  NewY2:=NewY2-DeltaY;
  1973.  
  1974.  y:=NewY2;
  1975.  
  1976.  x:=x1;
  1977.  
  1978.  cont:=0;
  1979.  
  1980.  SumaCuadrados:=sqr(x)+sqr(y);
  1981.  
  1982.  While (Cont<50) And (SumaCuadrados<100) Do
  1983.  
  1984.  Begin
  1985.  
  1986.  x:=Sqr(x)-Sqr(y)+a;
  1987.  
  1988.  y:=2*x*b+b;
  1989.  
  1990.  SumaCuadrados:=sqr(x)+sqr(y);
  1991.  
  1992.  inc(cont);
  1993.  
  1994.  End;
  1995.  
  1996. { En este bloque se asignan los colores a los puntos dependiendo de la
  1997. velocidad de escape del punto; se pueden modificar para jugar con el
  1998. grßfico }
  1999.  
  2000.  If SumaCuadrados>100 Then
  2001.  
  2002.  Begin
  2003.  
  2004.  If cont<3 Then color:=11
  2005.  
  2006.  Else If Cont<4 Then Color:=9
  2007.  
  2008.  Else If Cont<6 Then Color:=1
  2009.  
  2010.  Else If Cont<8 Then Color:=13
  2011.  
  2012.  Else If Cont<12 Then Color:=5
  2013.  
  2014.  Else If Cont<15 Then Color:=4
  2015.  
  2016.  Else If Cont<20 Then Color:=12
  2017.  
  2018.  Else If Cont<27 Then Color:=2
  2019.  
  2020.  Else If Cont<35 Then Color:=14
  2021.  
  2022.  Else If Cont<45 Then Color:=7
  2023.  
  2024.  Else Color:=8;
  2025.  
  2026.  PutPixel(i,j,color);
  2027.  
  2028.  End;
  2029.  
  2030.  End;
  2031.  
  2032.  End;
  2033.  
  2034.  ReadLn;
  2035.  
  2036.  CloseGraph;
  2037.  
  2038. End.
  2039.  
  2040. Para el correcto funcionamiento del programa deberemos poner el
  2041. driver BGI en el directorio en que se encuentre almacenado o
  2042. bien cambiar la lφnea:
  2043.  
  2044. InitGraph(gd,gm,'');
  2045.  
  2046. De forma que entre las comillas ponga el directorio donde se
  2047. encuentra el driver BGI que necesitamos usar.
  2048.  
  2049. Juan Carlos Romero
  2050.  
  2051. Trujillo (Cßceres)
  2052.  
  2053.  
  2054. SCROLL DE PELICULA
  2055.  
  2056. Seguro que mßs de una vez habΘis deseado a±adir en vuestros programas
  2057. alguna pantalla de presentaci≤n como las que aparecen en las pelφculas
  2058. de cine. Pues bien, ahora es posible gracias al siguiente programa,
  2059. con el que podemos conseguir un impresionante efecto de scroll en modo
  2060. texto con una gran suavidad.
  2061.  
  2062. Se pueden a±adir tantas lφneas de texto como se deseen, incluso hasta
  2063. llenar toda la pantalla: basta con poner tantos ½gotoxy (x,y); write
  2064. ('Texto');╗ como sean necesarios. Los ½delay╗ sirven para ajustar la
  2065. velocidad: si va demasiado lento basta con disminuir su valor,
  2066. mientras que si funciona muy rßpido habrß que incrementarlo.
  2067.  
  2068. USES crt;
  2069.  
  2070. VAR
  2071.  
  2072.  b:word;
  2073.  
  2074. BEGIN
  2075.  
  2076.  ClrScr;
  2077.  
  2078.  Gotoxy(34,13);write('*** PC Actual ***');
  2079.  
  2080.  Gotoxy(33,14);write('Scroll de pelφcula');
  2081.  
  2082.  Gotoxy(1,24);
  2083.  
  2084.  REPEAT
  2085.  
  2086.  WHILE (Port[$3DA] AND 8)=0 DO ;
  2087.  
  2088.  Portw[$3D4] := $008;
  2089.  
  2090.  Writeln;
  2091.  
  2092.  Delay(15);
  2093.  
  2094.  FOR b:=0 TO $E DO
  2095.  
  2096.  BEGIN
  2097.  
  2098.  WHILE (Port[$3DA] AND 8)=0 DO ;
  2099.  
  2100.  Portw[$3D4]:=$108+B*256;
  2101.  
  2102.  Delay(15);
  2103.  
  2104.  END;
  2105.  
  2106.  UNTIL KeyPressed;
  2107.  
  2108.  Portw[$3D4]:=$08;
  2109.  
  2110. END.
  2111.  
  2112. Santos Herranz Domingo
  2113.  
  2114. Madrid
  2115.  
  2116.  
  2117.  
  2118. VUELO ESPACIAL
  2119.  
  2120. Seguro que uno de los salvapantallas mßs utilizados por los usuarios
  2121. habituales de Windows es el ½Starfield simulation╗, ya que combina muy
  2122. acertadamente los ingredientes de sencillez y dinamismo. Pues bien,
  2123. con esta rutina tambiΘn los usuarios del DOS podrßn disfrutar de ese
  2124. conocido vuelo espacial.
  2125.  
  2126. Las aplicaciones de esta utilidad pueden ser diversas. Por ejemplo,
  2127. quienes comienzan a programar juegos de arcade la pueden encontrar
  2128. ·til como escenario en el que desarrollar la acci≤n. O quienes no
  2129. dispongan de un salvapantallas para DOS la pueden emplear como tal,
  2130. bien activßndola cuando se ausenten, bien modificßndola de modo que
  2131. quede residente (a tal fin, os recordamos que en nuestro n·mero de
  2132. enero del 93 premiamos un truco titulado ½Rutinas residentes╗, en el
  2133. que se indicaban los pasos a seguir).
  2134.  
  2135. La ½velocidad╗ de nuestro viaje dependerß de la potencia del ordenador
  2136. sobre el que lo ejecutemos, por lo que a los pasajeros que sufran del
  2137. denominado ½vΘrtigo espacial╗ les puede interesar incluir un Delay (n)
  2138. en cualquier punto del c≤digo, donde ½n╗ es un n·mero entero que
  2139. indica un retardo en milisegundos.
  2140.  
  2141. USES Graph, Crt;
  2142.  
  2143. TYPE
  2144.  
  2145.  Pointrec = RECORD
  2146.  
  2147.  sX, sY, ox, oy: LongInt;
  2148.  
  2149.  oapo, apo, c : Byte;
  2150.  
  2151.  END;
  2152.  
  2153. VAR
  2154.  
  2155.  Parr : Array[1..255] Of Pointrec;
  2156.  
  2157.  GD,GM,mx,my,I,cc,j,smx,smy : Integer;
  2158.  
  2159.  kl : LongInt;
  2160.  
  2161.  ch : Char;
  2162.  
  2163.  rx,ry,tx,ty : LongInt;
  2164.  
  2165.  starnum,decv : Byte;
  2166.  
  2167. BEGIN
  2168.  
  2169.  IF paramcount=0 THEN starnum:=120 ELSE val(paramstr(1),starnum,i);
  2170.  
  2171.  IF starnum<30 THEN starnum:=120;
  2172.  
  2173.  DetectGraph(GD,GM);
  2174.  
  2175. {la siguiente lφnea indica el path donde se sit·an los controladores
  2176. grßficos *.bgi dentro de nuestro disco duro}
  2177.  
  2178.  InitGraph(GD,GM,'d:\bp\bgi');
  2179.  
  2180.  mx:=getmaxx; my:=getmaxy; smx:=mx div 2; smy:=my div 2;
  2181.  
  2182.  decv:=starnum div 30;
  2183.  
  2184.  Randomize;
  2185.  
  2186.  FillChar(Parr,SizeOF(Parr),0);
  2187.  
  2188.  FOR i:=1 TO starnum DO WITH Parr[i] DO
  2189.  
  2190.  BEGIN
  2191.  
  2192.  sx:=(random(Succ(mx))-smx)*80; sy:=(random(Succ(my))-smy)*60;
  2193.  
  2194.  apo:=random(200)+decv;
  2195.  
  2196.  c:=Random(7)+1;
  2197.  
  2198.  ox:=sx; oy:=sy; oapo:=apo;
  2199.  
  2200.  END;
  2201.  
  2202.  REPEAT
  2203.  
  2204.  FOR i:=1 TO starnum DO WITH Parr[i] DO
  2205.  
  2206.  BEGIN
  2207.  
  2208.  oapo:=apo; ox:=sx; oy:=sy;
  2209.  
  2210.  dec(apo,decv);
  2211.  
  2212.  RX:=(sx div SUCC(apo))+smx;
  2213.  
  2214.  RY:=(sy div SUCC(apo))+smy;
  2215.  
  2216.  TX:=(ox div SUCC(oapo))+smx;
  2217.  
  2218.  TY:=(oy div SUCC(oapo))+smy;
  2219.  
  2220.  IF (RX>640) OR (RY>480) OR (RX<0) OR (RY<0) OR (APO<decv) THEN
  2221.  
  2222.  BEGIN
  2223.  
  2224.  sx:=(random(Succ(mx))-smx)*80; sy:=(random(Succ(my))-smy)*60;
  2225.  
  2226.  apo:=200+decv;
  2227.  
  2228.  RX:=(sx div SUCC(apo))+smx; RY:=(sy div SUCC(apo))+smy;
  2229.  
  2230.  END;
  2231.  
  2232.  IF apo>120 THEN cc:=C ELSE cc:=C+8;
  2233.  
  2234.  PutPixel(TX,TY,0); PutPixel(RX,RY,cc);
  2235.  
  2236.  IF OAPO<70 THEN PutPixel(TX+1,TY+1,0);
  2237.  
  2238.  IF APO<70 THEN PutPixel(RX+1,RY+1,cc);
  2239.  
  2240.  IF OAPO<60 THEN PutPixel(TX+1,TY,0);
  2241.  
  2242.  IF APO<60 THEN PutPixel(RX+1,RY,cc);
  2243.  
  2244.  IF OAPO<50 THEN PutPixel(TX,TY+1,0);
  2245.  
  2246.  IF APO<50 THEN PutPixel(RX,RY+1,cc);
  2247.  
  2248.  IF OAPO<40 THEN PutPixel(TX-1,TY-1,0);
  2249.  
  2250.  IF APO<40 THEN PutPixel(RX-1,RY-1,cc);
  2251.  
  2252.  IF OAPO<30 THEN PutPixel(TX+2,TY+2,0);
  2253.  
  2254.  IF APO<30 THEN PutPixel(RX+2,RY+2,cc);
  2255.  
  2256.  IF OAPO<20 THEN BEGIN
  2257.  
  2258.  PutPixel(TX+2,TY-1,0); PutPixel(TX-1,TY+2,0);
  2259.  
  2260.  END;
  2261.  
  2262.  IF APO<20 THEN BEGIN
  2263.  
  2264.  PutPixel(RX+2,RY-1,cc); PutPixel(RX-1,RY+2,cc);
  2265.  
  2266.  END;
  2267.  
  2268.  END;
  2269.  
  2270.  UNTIL KeyPressed;
  2271.  
  2272.  WHILE KeyPressed DO ch:= ReadKey;
  2273.  
  2274.  Closegraph;
  2275.  
  2276. END.
  2277.  
  2278. Antonio Delgado Garcφa
  2279.  
  2280. Madrid
  2281.  
  2282. Nota del Laboratorio: El programa funciona ejecutando ½stars╗ o
  2283. ½stars n╗, donde ½n╗ es un parßmetro que indica el n·mero de estrellas
  2284. que aparecerßn en pantalla. Si se introduce sin parßmetro s≤lo
  2285. aparecerßn 120 estrellas. Este programa detecta la tarjeta grßfica y
  2286. se adapta a su resoluci≤n.
  2287.  
  2288.  
  2289.  
  2290.  
  2291.  
  2292.