home *** CD-ROM | disk | FTP | other *** search
/ The Party 1994: Try This At Home / disk_image.bin / source / astrasrc / astral.asm next >
Assembly Source File  |  1994-08-13  |  20KB  |  624 lines

  1.  
  2.  comment /*******************************************************************
  3.  
  4.      Astral Plane BBS advertisement intro
  5.  
  6.      Original file size 1285B, now cut down to 1263B (wow, 22 bytes saved..)
  7.      Code commented, a bit fixed & released on August 13th, 1994
  8.      Written by Johannes H. Heinonen (aka Wihannes of Nordic Vision)
  9.  
  10.      This code was first written sometime in year 1993 and it was
  11.      my second true asm-program, the first one was that usual
  12.      "Hello Mom'n'Dad'n'AllTheOtherWorld!" stuff.. That's why you can
  13.      optimize this code like hell and even get it under 1kB if
  14.      you really want it.. One point to start is to use two virtual
  15.      pages and combine the transformation routine & the vram output
  16.      code -- just go for it!
  17.  
  18.      Oh, by the way: special greetings to everyone who admired this
  19.      little addy at Assembly'94 gathering! Next year we'll come back
  20.      with another amazing addy! ;-)
  21.  
  22.  ***************************************************************************/
  23.  
  24. code    SEGMENT para public 'CODE'
  25.         ASSUME  cs:code
  26.         LOCALS
  27.         .286                    ; generate 80286+ compatible code
  28.  
  29. ORG     100h                    ; make .COM file
  30.  
  31. start:  mov     di, OFFSET frame
  32.         mov     cx, 56*80
  33.         mov     ax, 00FEh       ; initialize the fire table
  34.         rep     stosw
  35.         mov     di, OFFSET fmask
  36.         mov     cx, 2384        ; 4000b for fmask, rest for palette
  37.         xor     ax, ax          ; fmask includes the texts..
  38.         rep     stosw
  39.  
  40.         ; create palette table
  41.  
  42.         mov     si, OFFSET paldata
  43.         mov     cx, 0007
  44. doLi_s: push    cx
  45.         mov     bx, ds:[si]
  46.         mov     cx, ds:[si+2]
  47.         mov     ax, ds:[si+4]
  48.         mov     dx, ds:[si+6]
  49.         call    doLiuku
  50.         pop     cx
  51.         add     si, 0008
  52.         loop    doLi_s          ; hum..hum.. it's not the clearest
  53.         mov     cx, 0002        ; one but it costs less than that
  54. vaFi_s: push    cx              ; 768 bytes table..
  55.         mov     bx, ds:[si]
  56.         mov     cx, ds:[si+2]
  57.         mov     ax, ds:[si+4]
  58.         call    vakioFi
  59.         pop     cx
  60.         add     si, 0006
  61.         loop    vaFi_s
  62.  
  63.         mov     dx, 0a000h
  64.         mov     es, dx          ; es=vram
  65.  
  66. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ check VGA  ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  67.  
  68.     mov     ax, 1a00h       ; this vgacheck ripped sumwhere
  69.     int     10h
  70.     cmp     al, 01ah
  71.     jne     endjmp          ; not vga
  72.     cmp     bl, 07
  73.     jb      endjmp          ; not vga
  74.  
  75. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ check 80286+ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  76.  
  77. tst286: pushf                    ; this 286check ripped sumwhere
  78.         xor     ax, ax
  79.         push    ax
  80.         popf
  81.         pushf
  82.         pop     ax
  83.         and     ax, 0f000h
  84.         cmp     ax, 0f000h
  85.         jne     tst186
  86.         jmp     endjmp           ; 8088/8086
  87. tst186: push    sp
  88.         pop     bx
  89.         cmp     bx, sp
  90.         jne     endjmp           ; 80186
  91.  
  92.         jmp     setfne           ; 80286-> .. run the intro
  93. endjmp: jmp     endtxt           ; <-80186 .. quit the proggy
  94.                    
  95. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ copy font from RAM ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  96.  
  97. setfne: mov     ax, 0013h       ; well, hope this mess works :)
  98.         int     10h             ; whee.. it has worked almost a year already!
  99.  
  100.         mov     ax, 1124h       ; select 8x16 font
  101.         mov     bl, 00          ; user defined lines
  102.         mov     dl, 12          ; 12 x 16 <= 200
  103.         int     10h
  104.  
  105.         mov     cx, 'z'-' '+1   ;  !"#$%&'()*+,-./0123456789:;<=>?@ ..
  106.         mov     bx, 16          ; .. ABCDEF..XYZ[\]^_`abcdef..xyz
  107.         mov     al, ' '
  108. onechr: mov     ah, 0eh         ; teletype output
  109.         int     10h
  110.         inc     al
  111.         loop    onechr          ; a char by char output
  112.  
  113.         mov     di, OFFSET font ; now copy it from vram to ds:[di]
  114.         xor     si, si          ; read from es:[si]
  115.         mov     cx, 'z'-' '+1   ; nmbr of characters..
  116.         shl     cx, 3           ; nbmr of columns (pixels)
  117. horz_l: push    cx
  118.         push    si
  119.         mov     cx, 16          ; vertical size
  120. vert_l: mov     al, es:[si]     ; read byte -> write byte
  121.         cmp     al, 16          ; 16 (black) -> 255
  122.         jne     zero_j
  123.         mov     al, 255         ; now it works better later
  124. zero_j: mov     ds:[di], al     ; write
  125.         inc     di              
  126.         add     si, 320         ; next line
  127.         loop    vert_l          ; jmp for next point in column
  128. horz_c: pop     si
  129.         pop     cx              ; now prepare for next column
  130.         inc     si              ; next column
  131.         cmp     si, 320         ; next row?
  132.         jne     not_nr
  133.         mov     si, 00 + 16*320 ; one 16x8 row downwards
  134. not_nr: cmp     si, 320+ 16*320 ; next row?
  135.         jne     not_nr2
  136.         mov     si, 00 + 32*320 ; one 16x8 row downwards
  137. not_nr2:loop    horz_l
  138.  
  139. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ set modex  ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  140.  
  141. setmde: mov     ax, 0013h       ; normal mode 13h
  142.         int     10h
  143.  
  144.         mov     dx, 3c4h
  145.         mov     ax, 604h        ; unchain VGA
  146.         out     dx, ax
  147.         mov     ax, 0f02h       ; all planes 
  148.         out     dx, ax
  149.  
  150.         mov     dx, 3d4h
  151.         mov     ax, 14h         ; disable dword 
  152.         out     dx, ax
  153.         mov     ax, 0e317h      ; enable byte 
  154.         out     dx, ax
  155.  
  156.         mov     al, 09
  157.         out     dx, al
  158.         inc     dx              ; y-zoom 8 times
  159.         in      al, dx
  160.         and     al, 0e0h        ; now one byte write to vram equals
  161.         add     al, 07          ; to a 4x4 pixel square..
  162.         out     dx, al
  163.  
  164. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ set palette ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  165.  
  166.         mov     si, OFFSET palette
  167.         mov     cx, 765
  168.         mov     dx, 03c8h
  169.         xor     al, al
  170.         out     dx, al
  171.         inc     dx
  172. set_it: mov     al, ds:[si]
  173.         out     dx, al          ; outta 'em
  174.         inc     si
  175.         loop    set_it
  176.  
  177.         ; color 255:            ; textcolor
  178.  
  179.         xor     al, al          ; zero for red
  180.         out     dx, al
  181.         mov     al, cs:infoclr[0]
  182.         out     dx, al
  183.         mov     al, cs:infoclr[1]
  184.         out     dx, al
  185.  
  186.   ;═════════ initialize new keyboard routine ══════════
  187.         mov     ds:Q_flag, 00
  188.         call    initint
  189.         mov     word ptr ds:counter, 0000       ; you got this?
  190.         mov     byte ptr ds:texto, 01           ; which text to show?
  191.         mov     byte ptr ds:cflag, 00           ; uu.. sumthing ;-)
  192.         call    text1                           ; copy 1st text to fmask
  193.         jmp     ROUTE                           ; main loop
  194.  
  195. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ fmask text routines ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  196.  
  197. text1:  mov     si, OFFSET texts
  198.         mov     ax, 0016
  199.         mov     bx, 0017
  200.         mov     cx, 0006
  201.         call    dotext
  202.         mov     ax, 0020        ; YES, why I didn't wrote these to
  203.         mov     bx, 0031        ; a table.. Okey, it's your business to do
  204.         mov     cx, 0005        ; it when you are about to release another
  205.         call    dotext          ; BBS addy using this source code :)
  206.         ret
  207.  
  208. text2:  lea     si, texts [11]
  209.         mov     ax, 0020
  210.         mov     bx, 0017
  211.         mov     cx, 0005
  212.         call    dotext
  213.         mov     ax, 0016
  214.         mov     bx, 0031
  215.         mov     cx, 0006
  216.         call    dotext
  217.         ret
  218.  
  219. text3:  lea     si, texts [22]
  220.         mov     ax, 0004
  221.         mov     bx, 0017
  222.         mov     cx, 0006
  223.         call    dotext
  224.         mov     ax, 0028
  225.         mov     bx, 0031
  226.         mov     cx, 0006
  227.         call    dotext
  228.         ret
  229.  
  230. text4:  lea     si, texts [34]
  231.         mov     ax, 0028
  232.         mov     bx, 0017
  233.         mov     cx, 0003
  234.         call    dotext
  235.         mov     ax, 0020
  236.         mov     bx, 0031
  237.         mov     cx, 0005
  238.         call    dotext
  239.         ret
  240.  
  241. text5:  lea     si, texts [42]
  242.         mov     ax, 0004
  243.         mov     bx, 0024
  244.         mov     cx, 0009
  245.         call    dotext
  246.         ret
  247.  
  248. text6:  lea     si, texts [51]
  249.         mov     ax, 0020
  250.         mov     bx, 0017
  251.         mov     cx, 0005
  252.         call    dotext
  253.         mov     ax, 0020
  254.         mov     bx, 0031
  255.         mov     cx, 0005
  256.         call    dotext
  257.         ret
  258.  
  259. text7:  lea     si, texts [61]
  260.         mov     ax, 0008
  261.         mov     bx, 0024
  262.         mov     cx, 0008
  263.         call    dotext
  264.         ret
  265.  
  266. dotext: xor     dh, dh
  267. @tl1:   mov     dl, ds:[si]
  268.         sub     dl, ' '
  269.         call    makechr
  270.         inc     si
  271.         add     ax, 0008
  272.         dec     cx
  273.         jnz     @tl1
  274.         ret
  275.  
  276. clrmsk: mov     si, OFFSET fmask
  277.         add     si, 17*80 
  278.         mov     di, OFFSET frame
  279.         add     di, 17*80*2
  280.         mov     cx, 30*80
  281.         mov     ax, 00FEh
  282.         mov     bx, 00FFh       ; you can figure most of these by reading
  283. clr_lp: cmp     ds:[si], bl     ; the variable names..
  284.         jne     NoNeed
  285.         mov     ds:[di], ax
  286.         mov     ds:[si], bh
  287. NoNeed: inc     si
  288.         add     di, 2
  289.         dec     cx
  290.         jnz     clr_lp
  291.         ret
  292.  
  293. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ the loop. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ 
  294.  
  295. ROUTE:  mov     dx, 3dah
  296.     wa: in      al, dx
  297.         test    al, 8           ; vertical retrace
  298.         jnz     wa
  299.     re: in      al, dx
  300.         test    al, 8
  301.         jz      re
  302.  
  303.   ;═══════════════════ copy to vram ═══════════════════
  304.         mov     si, OFFSET frame
  305.         xor     di, di
  306.         mov     bx, OFFSET fmask
  307.  
  308.         mov     cx, 50*40       ; only 50 lines are visible (50*4 = 200)
  309. write:  mov     dl, ds:[si]
  310.         mov     dh, ds:[si+2]
  311.         or      dx, ds:[bx]
  312.         mov     es:[di], dx     ; word output costs less
  313.         add     si, 4
  314.         add     di, 2
  315.         add     bx, 2
  316.         dec     cx
  317.         jnz     write
  318.  
  319.         mov     cx, 4400        ; transform the buffer (expect the last line)
  320.         mov     di, OFFSET frame
  321.         xor     ax, ax
  322.  
  323. build1: mov     al, ds:[di+158] ; simple logic..  . n . . . (n=new pixel)
  324.         add     ax, ds:[di+160] ;               . c c c .   (c=count these)
  325.         add     ax, ds:[di+162] ;             . . . c .     (.=other pixels)
  326.         add     ax, ds:[di+320]
  327.         shr     ax, 2           ; divide by four
  328.         sub     al, 4           ; subtract some colors..
  329.         jnc     build2
  330.         xor     al, al
  331.  
  332. build2: mov     ds:[di], al     ; save it..
  333. next:   add     di, 2
  334.         dec     cx
  335.         jnz     build1
  336.  
  337.   ;══════════ random new values for line 56. ══════════
  338.         mov     cx, 80
  339.         lea     di, frame[4400*2]
  340.   ;───────────────── random routine ───────────────────
  341. randor: push    cx
  342.         mov     ax, ds:[seed1]
  343.         mov     bx, ds:seed2
  344.         mov     cx, ds:[seed3]  ; it works.. after all :)
  345.         mov     dx, ds:seed4
  346.         add     ax, bx
  347.         add     ax, cx
  348.         add     ax, dx
  349.         mov     ds:seed1, bx
  350.         mov     ds:seed2, dx
  351.         mov     ds:seed3, cx
  352.         mov     ds:seed4, ax
  353.         pop     cx
  354.   ;───────────────── end-of-randor. ───────────────────
  355.         cmp     ax, dx
  356.         jl      takelo
  357.         mov     al, ah
  358. takelo: shr     al, 6           ; now al is either 00 or 01
  359.         cmp     al, 01
  360.         jl      fine
  361.         mov     al, 254
  362. fine:   mov     ds:[di], al
  363.         mov     ds:[di-160], al
  364. nochng: add     di, 2
  365.         dec     cx
  366.         jnz     randor
  367.  
  368.   ;═════════ time to check keyb flag & counter ════════
  369. keybbi: inc     word ptr ds:counter
  370.         cmp     word ptr ds:counter, 0045
  371.         jne     chk_key
  372.         mov     word ptr ds:counter, 0000
  373.         inc     byte ptr ds:cflag
  374.         cmp     byte ptr ds:cflag, 03
  375.         jne     tst04
  376.         call    clrmsk
  377.         jmp     chk_key
  378. tst04:  cmp     byte ptr ds:cflag, 04
  379.         jne     chk_key
  380.         mov     byte ptr ds:cflag, 00
  381.         inc     byte ptr ds:texto
  382.         mov     al, ds:texto
  383. tst1:   cmp     al, 01
  384.         jne     tst2
  385.         call    text1
  386.         jmp     chk_key
  387. tst2:   cmp     al, 02
  388.         jne     tst3
  389.         call    text2
  390.         jmp     chk_key         ; uh.. this is it. the "where no man
  391. tst3:   cmp     al, 03          ; has gone before" zone... you might
  392.         jne     tst4            ; understand these, i don't have time
  393.         call    text3           ; to describe each of them.
  394.         jmp     chk_key         ; basically these "tstx" lines check
  395. tst4:   cmp     al, 04          ; whether or not to write a new text..
  396.         jne     tst5
  397.         call    text4           ; tables rules, it'd save some bytes..
  398.         jmp     chk_key
  399. tst5:   cmp     al, 05
  400.         jne     tst6
  401.         call    text5
  402.         jmp     chk_key
  403. tst6:   cmp     al, 06
  404.         jne     tst7
  405.         call    text6
  406.         jmp     chk_key
  407. tst7:   cmp     al, 07
  408.         jne     tstrest
  409.         call    text7
  410.         jmp     chk_key
  411. tstrest:cmp     al, 08
  412.         jne     chk_key
  413.         mov     byte ptr ds:texto, 00
  414.  
  415. chk_key:cmp     ds:Q_flag, 01   ; esc pressed?
  416.         je      quitto
  417.         jmp     ROUTE
  418.  
  419. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ back to dos ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  420.  
  421. quitto: call    deinitint       ; return the original irq handler
  422.  
  423. endtxt: mov     ax, 0003h       ; text mode
  424.         int     10h
  425.                                 
  426.         push    0b800h          ; write some last notes, color code support
  427.         pop     es
  428.         xor     di, di
  429.         mov     ax, di          ; al = character, ah = attribute
  430.         mov     si, OFFSET tsau
  431. lst_lp: lodsb
  432.         cmp     al, 31
  433.         jae     tst_nd          ; this writer mainly derived from starport
  434.         mov     ah, al          ; intro (1993b) by Psi
  435.         jmp     lst_lp
  436. tst_nd: jz      termin          
  437.         stosw
  438.         jmp     lst_lp
  439.  
  440. termin: mov     ax, 4c00h       ; terminate 
  441.         int     21h
  442.  
  443.  
  444. initint PROC NEAR
  445.         push    es
  446.         xor     ax, ax
  447.         mov     es, ax
  448.     mov    ax, es:[9*4]
  449.         mov     bx, es:[9*4+2]  ; no 386+ code, no 32-bit registers!
  450.     mov    ds:old9_1, ax
  451.         mov     ds:old9_2, bx
  452.         mov     ax, OFFSET intti9
  453.         mov     bx, cs
  454.         jmp     set
  455. deinitint:                      ; combined init and uninit
  456.         push    es
  457.         xor     ax, ax
  458.         mov     es, ax
  459.         mov     ax, ds:old9_1
  460.         mov     bx, ds:old9_2
  461. set:    cli
  462.         mov     es:[9*4], ax
  463.         mov     es:[9*4+2], bx
  464.         sti
  465.         pop     es
  466.         ret
  467. initint ENDP
  468.  
  469.  
  470. intti9    PROC FAR                ; keyboard interrupt
  471.     push    ax
  472.     in      al, 60h
  473.         cmp     al, 01h         ; esc pressed?
  474.         jne     notESc
  475.         mov     ds:Q_flag, 01
  476. notESc: in      al, 61h
  477.         mov     ah, al
  478.         or      al, 80h
  479.         out     61h, al
  480.         xchg    ah, al
  481.         out     61h, al
  482.         mov    al, 20h
  483.     out    20h, al         ; clear call
  484.         pop    ax
  485.     iret                    
  486. intti9    ENDP                    
  487.                                 
  488.                                 
  489. makechr PROC NEAR               ; build a character
  490.         push    ax
  491.         push    bx
  492.         push    cx
  493.         push    dx
  494.         push    si
  495.         mov     si, OFFSET font
  496.         shl     dx, 7           ; * 128
  497.         add     si, dx          ; ds:[si], offset to chr data
  498.         mov     di, OFFSET fmask
  499.         mov     cx, bx
  500.         shl     cx, 6           ; * 64 +
  501.         shl     bx, 4           ; * 16 = * 80
  502.         add     di, cx
  503.         add     di, bx
  504.         add     di, ax          ; ds:[di], offset to frame
  505.         mov     cx, 8
  506. copyl:  push    cx
  507.         push    di
  508.         mov     cx, 8
  509. copyl1: mov     ax, ds:[si]
  510.         mov     ds:[di], al
  511.         mov     ds:[di+80], ah 
  512.         add     di, 160
  513.         add     si, 2
  514.         loop    copyl1
  515.         pop     di
  516.         inc     di
  517.         pop     cx
  518.         loop    copyl
  519.         pop     si
  520.         pop     dx
  521.         pop     cx
  522.         pop     bx
  523.         pop     ax
  524.         ret
  525. makechr ENDP                    
  526.                                 
  527.                                 ; es = ds !
  528. vakioFi PROC NEAR               ; strt = bx  count = cx  arvo = al
  529.         lea     di, cs:palette[bx]
  530. fillit: stosb
  531.         add     di, 2           ; jmp the other two values (rgb)
  532.         loop    fillit
  533.         ret                     
  534. vakioFi ENDP                    
  535.                                 ; es = ds !
  536.                                 ; strt = bx  count = cx  arvo = ax
  537. doLiuku PROC NEAR               ; ince = dx
  538.         lea     di, cs:palette[bx]            
  539. doit:   push    ax
  540.         shr     ax, 6
  541.         stosb
  542.         add     di, 2
  543.         pop     ax              ; these are derived from my previous
  544.         add     ax, dx          ; pascal routines, that's why all those
  545.         loop    doit            ; variable alike names (count,arvo..)
  546.         ret
  547. doLiuku ENDP
  548.  
  549. ;█████████████████████ data site ██████████████████████
  550.  
  551. seed1   dw      036c2h
  552. seed2   dw      0a43dh
  553. seed3   dw      0f21ch          ; random number seeds
  554. seed4   dw      01c34h
  555.  
  556.         ; Black     │ 0 ║ DarkGray     │  8
  557.         ; Blue      │ 1 ║ LightBlue    │  9
  558.         ; Green     │ 2 ║ LightGreen   │ 10  <- table from Turbo Pascal's
  559.         ; Cyan      │ 3 ║ LightCyan    │ 11     on-line help
  560.         ; Red       │ 4 ║ LightRed     │ 12
  561.         ; Magenta   │ 5 ║ LightMagenta │ 13
  562.         ; Brown     │ 6 ║ Yellow       │ 14  <- color codes
  563.         ; LightGray │ 7 ║ White        │ 15
  564.  
  565. tsau    LABEL BYTE
  566.         db      15, 'Astral Plane'
  567.         db      08, ' ─── '
  568.         db      11, '(973) 733148'      ; 31=end, <31=attribute, >31=text
  569.         db      08, ' ─── '
  570.         db      11, '24h  v.32bis'
  571.         db      08, ' ─── '
  572.         db      09, 'SPO WHQ'
  573.         db      31
  574.  
  575.         ; currently supported letters:
  576.         ;  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEF..XYZ[\]^_`abcdef..xyz
  577.  
  578.         ; the "v" marks are hardcoded to the code..
  579.  
  580.         ;        v     v    v    v     v     v     v  v    v
  581. texts   db      'AstralPlane(973)733148-> SPOBBS <-24H14.4kPrgrmming'
  582.         ;        v    v    v
  583.         db      'DemosGamesAnd more'
  584.  
  585. infoclr db      25, 62          ; text color, bright blue
  586.  
  587.         ; hack these out :) (not a hard task..)
  588.         ; (strt mod 3) = {0..2} = {R,G,B}
  589. paldata dw      0021, 0017, 0000, 0128, 0072, 0032, 2048, 0059
  590.         dw      0115, 0101, 0000, 0032, 0418, 0053, 3328, 0013
  591.         dw      0005, 0007, 0384, 0042, 0026, 0016, 0640, 0ffd6h
  592.         dw      0563, 0069, 0000, 0059
  593.         dw      0168, 0199, 0063, 0577, 0063, 0063
  594.  
  595. counter dw      0000
  596. cflag   db      00
  597. texto   db      00                      ; run postproc and get rid of
  598. frame   dw      4480    dup (0000)      ; these unused zeros..
  599. fmask   db      4000    dup (00)
  600. palette db      768     dup (00)
  601. font    db      91*8*16 dup (00)
  602. old9_1    dw    0000
  603. old9_2  dw      0000
  604. Q_flag  db      00
  605.  
  606. code    ENDS
  607.         END start
  608.  
  609.  comment /*******************************************************************
  610.  
  611.      Contact us!
  612.  
  613.      By mail  :  Johannes H. Heinonen
  614.                  Touvitie 1
  615.                  FIN-80160 Joensuu
  616.  
  617.      E-mail   :  wihannes@pcb.mpoli.fi  ( at least until summer/autumn -95 )
  618.  
  619.      By modem :  Astral Plane BBS
  620.                  +358-(9)73-733148      
  621.                  1200-14400bps, 24H
  622.  
  623.  ***************************************************************************/
  624.