'=========================================================================== ' Subject: OPEN AVI VERSION 0.6 Date: 04-23-99 (18:32) ' Author: Yousuf Philips Code: QB, QBasic, PDS ' Origin: philipz@emirates.net.ae Packet: GRAPHICS.ABC '=========================================================================== '''''''''''''''''''''''''''''''''''''' ' Program : Plays AVI Files ' ' Name : OPENAVI Version 0.6 ' ' Programmer : Yousuf Philips ' ' Company : Y P I ' ' Updated On : 1st of March 1999 ' ' Email - [philipz85@hotmail.com] ' ' [http://members.xoom.com/Philipz/] ' '''''''''''''''''''''''''''''''''''''' '/* Do not edit this file if you distribute it. */' '/* (c) Copyrighted by YPI in 1998 | All Rights Reserved | Public Domain */' '/* This program has been created by YPI (Basic Programming Incorporation) */' '/* as a utility to play AVI files in QBASIC. */' '/* */' '/* What's New - */' '/* * Will play 8-bit uncompressed AVIs with sound */' '/* * 24-BIT uncompressed AVIs are played in color */' '/* */' '/* What's Great - */' '/* * Delay Function will work perfectly on any PC */' '/* * AVI displays very fast (even on a 486) */' '/* Special Thanks to Alexander Verhaeghe */' '/* An original program created by the professional programmers at YPI. */' '/* If you use any of this code in your program then you must credit YPI, */' '/* it would be appreciated if you sent us a copy of your program also. */' '/* Please send your comments and suggestions to */' DECLARE SUB GetSpeed () DECLARE SUB ShowAVI (FileName$) DECLARE SUB delay (MiliSeconds%) '/* 2 Added subs for the display of 24-bit AVIs taken from 24BITBMP.BAS */' DECLARE SUB ChangePalette (Alg%) DECLARE SUB BIT24AVI (ImageWidth%, ImageHeight%, Frames%) '/* 4 Added functions to use interrupt &H21 */' DECLARE SUB Close21 (Handle%) DECLARE SUB Seek21 (Handle%, offset!) DECLARE SUB Open21 (FileName$, Handle%) DECLARE SUB Get21 (Handle%, NoOfBytesToRead%, VariableSegment%, VariableOffset%) '/* 2 Added functions to call interrupts in QBASIC 1.0 */' DECLARE SUB NewInterrupt (intnum AS INTEGER, Regs AS ANY) DECLARE SUB InitInterrupt () '/* Functions to play sound AVIs taken from WAVEPLAY.BAS */' DECLARE FUNCTION GetBlasterAddr% () DECLARE FUNCTION SBreset% () DECLARE SUB WriteToDSP (v%) DECLARE SUB WavPlay (Bytes$, WavLen&, Sampling&, Bytes&, Channels%) DECLARE SUB PlayBack (Buffer$, size%, freq&, BytesPerSec&, chans%) TYPE RIFFHeaderType ValidID AS STRING * 4 '/* Must be - 'RIFF' SizeOfFile AS LONG '/* Size of AVI file in bytes RIFFFileType AS STRING * 4 '/* RIFF file type - Must be - 'AVI ' END TYPE TYPE AVIHeader ValidID AS STRING * 4 '/* Must be - 'avih' Reserved AS LONG '/* Not Important MicrosecPerFrame AS LONG '/* Number of Milliseconds between each Frame MaximumBytesPerSec AS LONG '/* Number of bytes the system must handle ' per second for the avi to run smoothly Reserved1 AS LONG '/* Reserved must be 0 BitFlags AS LONG '/* Bit Flags TotalFrames AS LONG '/* Total Number of Frames InitialFrame AS LONG '/* Not Understood NoOfStreams AS LONG '/* Number of Streams BufferSize AS LONG '/* Buffer size to read a frame Widthz AS LONG '/* Width of AVI Heightz AS LONG '/* Height of AVI Scale AS LONG '/* Not Understood Rate AS LONG '/* Not Understood Start AS LONG '/* Not Understood Length AS LONG '/* Not Understood END TYPE TYPE Listz ListID AS STRING * 4 BytesInList AS LONG ListType AS STRING * 4 END TYPE TYPE StreamHeader HeaderID AS STRING * 4 '/* Must be - 'strh' BytesIn AS LONG '/* Number of bytes in header Typez AS STRING * 4 '/* Type of stream - 'vids' for video stream 'auds' for audio stream Handle AS STRING * 4 '/* Compression Technology Used BitFlags AS LONG '/* Not Important Reserved1 AS LONG '/* Not Important InitialFrames AS LONG '/* Not Important Scale AS LONG '/* Not Important Rate AS LONG '/* Not Important Start AS LONG '/* Not Important Length AS LONG '/* Not Important BufferSize AS LONG '/* Not Important Quality AS LONG '/* Not Important SampleSize AS LONG '/* Not Important END TYPE TYPE StreamFormat StreamFormatID AS STRING * 4 '/* Must be - 'strf' BytesInFormat AS LONG '/* Not Important END TYPE TYPE BMPInfoHeader LengthOfHeader AS LONG '/* Must be - 40 ImageWidth AS LONG '/* AVI image width ImageHeight AS LONG '/* AVI image height Planes AS INTEGER '/* AVI image planes - Must be 1 BitsPerPixel AS INTEGER '/* AVI image bits per pixel - Must be 8 CompressMethod AS LONG '/* AVI image compression - Must be 0 ImageSizeInBytes AS LONG '/* Size of AVI image in bytes HorizontalRatio AS LONG '/* Not Important VerticalRatio AS LONG '/* Not Important ColorsUsed AS LONG '/* Number of colors used ImportantColors AS LONG '/* Number of important colors END TYPE TYPE WavHeader FormatTag AS INTEGER Channels AS INTEGER SampleRate AS LONG BytesPerSecond AS LONG BlockAlignment AS INTEGER BitsPerSample AS INTEGER END TYPE TYPE ImageData ChunkID AS STRING * 4 '/* Chunk type ID - 'db','dc','pc' or 'wb' NumberOfBytes AS LONG '/* Number of bytes in image data chunk END TYPE TYPE RegType '/* Registers for Interrupts ax AS INTEGER bx AS INTEGER cx AS INTEGER dx AS INTEGER bp AS INTEGER si AS INTEGER di AS INTEGER flags AS INTEGER ds AS INTEGER es AS INTEGER END TYPE COMMON SHARED Regs AS RegType, Speed& COMMON SHARED BlasterAddr%, dma%, num% DIM SHARED Intrpt(1 TO 50) AS INTEGER '/* Initializes Interrupt Functions (Very Important, don't touch) */' InitInterrupt CLS '/* Comment out GetSpeed if you don't want to have a delay between frames */' GetSpeed PRINT PRINT " 1st QBASIC AVI Player - OPENAVI ver 0.6" PRINT " (c) YPI (BASIC Programming Incorporation) 1999" PRINT " Press Any Key When You Want The AVI To Stop Playing (Don't press Ctrl-Break)" FILES "*.avi" INPUT " Enter File Name - ", FileName$ IF LEN(LTRIM$(FileName$)) = 0 THEN END ELSEIF INSTR(FileName$, ".") = 0 THEN FileName$ = FileName$ + ".avi" END IF CALL ShowAVI(FileName$) Wait$ = INPUT$(1) WHILE INKEY$ <> "": WEND '/* Some ending statements for those how didn't read the comments at the */' '/* beginning of the program. */' SCREEN 2: SCREEN 0 PRINT " 1st QBASIC AVI Player (ver 0.6) - By YPI (BASIC Programming Incorporation)" PRINT " Program is Public Domain, (c) Copyrighted by YPI, All Rights Reserved" PRINT " Programmed By Yousuf Philips in 1999" PRINT " Send suggestions and comments to philipz85@hotmail.com" PRINT " Visit the YPI Website at http://members.xoom.com/Philipz/" Wait$ = INPUT$(1) DEFINT A-Z SUB BIT24AVI (ImageWidth, ImageHeight, Frames) CALL ChangePalette(1) DIM ColorPalette(255, 3) DIM PixelArray(2000, 3) DIM ImageDataz AS ImageData ColorDif = 3 '/* Capture the current color palette into an array */' FOR Loops = 0 TO 255 OUT &H3C7, Loops ColorPalette(Loops, 1) = INP(&H3C9) ColorPalette(Loops, 2) = INP(&H3C9) ColorPalette(Loops, 3) = INP(&H3C9) NEXT Loops '/* Calculate the number of bytes per line for the current image */' LineExtract$ = SPACE$(ImageWidth * 3) IF (4 - ((ImageWidth * 3) MOD 4)) <> 4 THEN LineExtract$ = LineExtract$ + SPACE$(4 - ((ImageWidth * 3) MOD 4)) END IF LineExtract& = LEN(LineExtract$) '/* Resize image to fit the Screen */' ActualHeight! = 199 / (ImageHeight - 1) ActualWidth! = 319 / (ImageWidth - 1) IF ActualHeight! > 1 THEN ActualHeight! = 1 IF ActualWidth! > 1 THEN ActualWidth! = 1 ActualWidth1! = (ImageWidth - 1) / 319 ActualHeight1! = (ImageHeight - 1) / 199 IF ActualHeight1! < 1 THEN ActualHeight1! = 1 IF ActualWidth1! < 1 THEN ActualWidth1! = 1 WHILE INKEY$ <> "": WEND PlayStart& = LOC(255) + 1 Looping: FOR FrameNumber = 1 TO Frames GET #255, , ImageDataz IF RIGHT$(ImageDataz.ChunkID, 2) = "db" THEN StartingPos& = LOC(255) + 1 FOR YHeight = ImageHeight - 1 TO 0 STEP -ActualHeight1! GET #255, StartingPos& + (ImageHeight - 1 - YHeight) * LineExtract&, LineExtract$ FOR XWidth = 0 TO ImageWidth - 1 STEP ActualWidth1! XWidthPosition = XWidth * 3 '/* Extract the RGB of each pixel */' PixelBlue = ASC(MID$(LineExtract$, XWidthPosition + 1, 1)) \ 4 PixelGreen = ASC(MID$(LineExtract$, XWidthPosition + 2, 1)) \ 4 PixelRed = ASC(MID$(LineExtract$, XWidthPosition + 3, 1)) \ 4 PixelPut = 0: Movement = ColorDif + 1 '/* Check if the RGB or an RGB close to it are in the color array */' FOR PixelArraySearch = 1 TO ArrayNo IF PixelBlue >= PixelArray(PixelArraySearch, 1) - ColorDif AND PixelBlue <= PixelArray(PixelArraySearch, 1) + ColorDif THEN IF PixelGreen >= PixelArray(PixelArraySearch, 2) - ColorDif AND PixelGreen <= PixelArray(PixelArraySearch, 2) + ColorDif THEN IF PixelRed >= PixelArray(PixelArraySearch, 3) - ColorDif AND PixelRed <= PixelArray(PixelArraySearch, 3) + ColorDif THEN PSET (XWidth * ActualWidth!, YHeight * ActualHeight!), PixelArray(PixelArraySearch, 0) PixelPut = 1 EXIT FOR END IF END IF END IF NEXT PixelArraySearch IF PixelPut = 0 THEN '/* Algorithm to find the closest color in the color palette */' DO FOR Loops = 0 TO 255 IF PixelBlue >= (ColorPalette(Loops, 3) - Movement) AND PixelBlue <= (ColorPalette(Loops, 3) + Movement) THEN IF PixelGreen >= (ColorPalette(Loops, 2) - Movement) AND PixelGreen <= (ColorPalette(Loops, 2) + Movement) THEN IF PixelRed >= (ColorPalette(Loops, 1) - Movement) AND PixelRed <= (ColorPalette(Loops, 1) + Movement) THEN IF ColorPalette(Loops, 1) = ColorPalette(Loops, 2) AND ColorPalette(Loops, 2) = ColorPalette(Loops, 3) AND Movement > 3 THEN IF PixelBlue = PixelGreen AND PixelBlue = PixelRed THEN PSET (XWidth * ActualWidth!, YHeight * ActualHeight!), Loops IF ArrayNo < 2000 THEN ArrayNo = ArrayNo + 1 PixelArray(ArrayNo, 1) = PixelBlue PixelArray(ArrayNo, 2) = PixelGreen PixelArray(ArrayNo, 3) = PixelRed PixelArray(ArrayNo, 0) = Loops END IF EXIT DO END IF ELSE PSET (XWidth * ActualWidth!, YHeight * ActualHeight!), Loops IF ArrayNo < 2000 THEN ArrayNo = ArrayNo + 1 PixelArray(ArrayNo, 1) = PixelBlue PixelArray(ArrayNo, 2) = PixelGreen PixelArray(ArrayNo, 3) = PixelRed PixelArray(ArrayNo, 0) = Loops END IF EXIT DO END IF END IF END IF END IF NEXT Loops Movement = Movement + 1 LOOP END IF NEXT XWidth NEXT YHeight SEEK #255, StartingPos& + ImageDataz.NumberOfBytes ELSEIF RIGHT$(ImageDataz.ChunkID, 2) = "pc" THEN '/* Skipping the color changing */' 'GET #255, , ChangePalette SEEK #255, LOC(255) + 1 + ImageDataz.NumberOfBytes ELSEIF RIGHT$(ImageDataz.ChunkID, 2) = "wb" THEN '/* Skipping the sound part of the AVI if there is. */' SEEK #255, LOC(255) + 1 + ImageDataz.NumberOfBytes FrameNumber = FrameNumber - 1 ELSEIF RIGHT$(ImageDataz.ChunkID, 2) = "dc" THEN SCREEN 2: SCREEN 0 PRINT " ONLY UNCOMPRESSED AVI SEQUENCIES CAN BE SHOWN" END ELSE PRINT " An Error Occured" END END IF IF INKEY$ <> "" THEN EXIT SUB END IF NEXT FrameNumber SEEK #255, PlayStart& GOTO Looping END SUB '/* Sub to change the color palette */' SUB ChangePalette (Alg) IF Alg = 1 THEN '/* An excellent color palette from PALSTUFF.BAS [Graphics.abc|09/1995] */' '/* Created by Steve Demo */' Change$ = "#####M#M##MMM##M#MM8#MMM88888b8b88bbb88b8bbb8bbb+++" Change$ = Change$ + "...222555999===@@@DDDHHHKKKOOOSSSVVVZZZ^^^bbb3##8##" Change$ = Change$ + "=##?&&B**E--H11K55N88Q<#\B*]F2^K:_OA`TIaXQb]Y33#66#99#<<#" Change$ = Change$ + "??#BB#EE#HH#LL#OO#RR#UU#XX#[[#^^#bb##8%#:(#<,#?/#A3" Change$ = Change$ + "#C7#F:#H>#KB#ME#OI#RM#TP#WT#YX#\\YbYRbQJbJG^GDZDAWA" Change$ = Change$ + ">S>;O;8L85H52E2/A/,=,):)&6&$3#YbbQbbJbbE__A\\=ZZ:VV" Change$ = Change$ + "7RR5NN2JJ0FF-BB*>>(::%66#33Y^bQ[bJXbBUb:Rb3Ob+Mb#Jb" Change$ = Change$ + "#F\#BV#>P#:J#6D#3?#/9#,3YYbQRbJJbEE_@@\<'':%%6##3/@$2B#5D#8F#;H#>J#AL#DN#GP#JR#" Change$ = Change$ + "MT#PV#SX#VZ#Y\#]_#bYb`S`^N^\H\ZCZX=XV8VT3UP0QL.MH+I" Change$ = Change$ + "D(EA&A<%<7$73#3-+&1-'5/):2+;3+=4,?5-@6-B7.D8/E9/G:0" Change$ = Change$ + "I;1J<1L=2N>3O?3Q@4SA5UB6VD8WF;XH>YJAZMD[OG\QJ]SM^VP" Change$ = Change$ + "_XS`ZVb]ZZ##X)#W0#U6#T;#S@#RF#PJ#ON#CN#6M#*M##L(#K3" Change$ = Change$ + "#K?#KH#FL#>M#5M#-N6#Q>#QD#QL#QQ#NQ#FQ#@Q#9Q#1R#+R##" Change$ = Change$ + "bbb" FOR Loops = 0 TO 255 OUT &H3C8, Loops OUT &H3C9, ASC(MID$(Change$, Loops * 3 + 1, 1)) - 35 OUT &H3C9, ASC(MID$(Change$, Loops * 3 + 2, 1)) - 35 OUT &H3C9, ASC(MID$(Change$, Loops * 3 + 3, 1)) - 35 NEXT Loops Change$ = "" ELSE '/* Randomized color palette */' FOR Loops = 1 TO 255 Blue = INT(RND * 256) \ 4 Green = INT(RND * 256) \ 4 Red = INT(RND * 256) \ 4 OUT &H3C8, Loops OUT &H3C9, Red OUT &H3C9, Green OUT &H3C9, Blue NEXT Loops END IF END SUB SUB Close21 (Handle) '/* Don't edit this SUB if you don't have any knowledge of Interrupts */' Regs.ax = &H3E00 Regs.bx = Handle CALL NewInterrupt(&H21, Regs) END SUB DEFSNG A-Z SUB delay (MiliSeconds%) '/* This function slows down the program for the given amount of Miliseconds */' DelayTime = (Speed& * 5) * (MiliSeconds% / 1000) FOR Speed = 1 TO DelayTime NEXT Speed END SUB DEFINT A-Z SUB Get21 (Handle, NoOfBytesToRead, VariableSegment, VariableOffset) '/* Don't edit this SUB if you don't have any knowledge of Interrupts */' Regs.ax = &H3F00 Regs.bx = Handle Regs.cx = NoOfBytesToRead Regs.ds = VariableSegment Regs.dx = VariableOffset CALL NewInterrupt(&H21, Regs) END SUB FUNCTION GetBlasterAddr% tmp% = 0 Blast$ = UCASE$(ENVIRON$("BLASTER")) IF LEN(Blast$) THEN tmp% = INSTR(Blast$, "A") tmp1$ = MID$(Blast$, tmp% + 1, 3) tmp% = VAL("&H" + tmp1$) IF tmp% = 203 THEN tmp% = -1 IF tmp% > 0 THEN tmp2% = INSTR(Blast$, "D") dma% = VAL(MID$(Blast$, tmp2% + 1)) IF dma% < 0 OR dma% > 7 THEN tmp% = -2 END IF END IF GetBlasterAddr% = tmp% END FUNCTION DEFSNG A-Z SUB GetSpeed '/* This function finds out the proper delay period needed for the current PC*/' PRINT " Calculating delay for Delay Function according to your PC" Time& = TIMER: Time& = Time& + 1: Speed& = 0 DO LOOP UNTIL TIMER >= Time& DO Speed& = Speed& + 1 LOOP UNTIL TIMER >= Time& + 1 '/* Testing the calculated delay period with the Delay FUNCTION */' Time! = TIMER delay 1000 Time! = TIMER - Time! '/* If the Delay FUNCTION was not accurate then it is adjusted */' IF Time! < 1 THEN Speed& = INT(Speed& * (1 / Time!)) END IF END SUB DEFINT A-Z SUB InitInterrupt '/* Don't edit this SUB period. */' InterruptData$ = CHR$(85) + CHR$(139) + CHR$(236) + CHR$(86) + CHR$(87) + CHR$(30) + CHR$(139) + CHR$(118) + CHR$(6) + CHR$(139) + CHR$(4) + CHR$(139) + CHR$(92) + CHR$(2) InterruptData$ = InterruptData$ + CHR$(139) + CHR$(76) + CHR$(4) + CHR$(139) + CHR$(84) + CHR$(6) + CHR$(139) + CHR$(108) + CHR$(8) + CHR$(139) + CHR$(124) + CHR$(12) + CHR$(142) + CHR$(68) + CHR$(18) InterruptData$ = InterruptData$ + CHR$(255) + CHR$(116) + CHR$(10) + CHR$(131) + CHR$(124) + CHR$(18) + CHR$(255) + CHR$(117) + CHR$(2) + CHR$(30) + CHR$(7) + CHR$(131) + CHR$(124) + CHR$(16) + CHR$(255) InterruptData$ = InterruptData$ + CHR$(116) + CHR$(3) + CHR$(142) + CHR$(92) + CHR$(16) + CHR$(94) + CHR$(205) + CHR$(33) + CHR$(85) + CHR$(139) + CHR$(236) + CHR$(30) + CHR$(86) + CHR$(142) + CHR$(94) + CHR$(2) + CHR$(139) + CHR$(118) + CHR$(14) InterruptData$ = InterruptData$ + CHR$(137) + CHR$(4) + CHR$(137) + CHR$(92) + CHR$(2) + CHR$(137) + CHR$(76) + CHR$(4) + CHR$(137) + CHR$(84) + CHR$(6) + CHR$(143) + CHR$(68) + CHR$(10) + CHR$(143) + CHR$(68) + CHR$(16) InterruptData$ = InterruptData$ + CHR$(143) + CHR$(68) + CHR$(8) + CHR$(137) + CHR$(124) + CHR$(12) + CHR$(140) + CHR$(68) + CHR$(18) + CHR$(156) + CHR$(143) + CHR$(68) + CHR$(14) InterruptData$ = InterruptData$ + CHR$(95) + CHR$(95) + CHR$(94) + CHR$(93) + CHR$(202) + CHR$(2) + CHR$(0) DEF SEG = VARSEG(Intrpt(1)) address = VARPTR(Intrpt(1)) FOR I = 0 TO 99 POKE address + I, ASC(MID$(InterruptData$, I + 1, 1)) NEXT DEF SEG END SUB SUB NewInterrupt (intnum AS INTEGER, Regs AS RegType) '/* Don't edit this SUB period. */' DEF SEG = VARSEG(Intrpt(1)) address = VARPTR(Intrpt(1)) POKE address + 51, intnum CALL ABSOLUTE(Regs, address) DEF SEG END SUB SUB Open21 (FileName$, Handle) '/* Don't edit this SUB if you don't have any knowledge of Interrupts */' FileName$ = FileName$ + CHR$(0) Regs.ax = &H3D00 Regs.ds = VARSEG(FileName$) Regs.dx = SADD(FileName$) CALL NewInterrupt(&H21, Regs) FileName$ = LEFT$(FileName$, LEN(FileName$) - 1) Handle = Regs.ax END SUB SUB PlayBack (Buffer$, size%, freq&, BytesPerSec&, chans%) size% = size% - 1 segment& = VARSEG(Buffer$) offset& = SADD(Buffer$) IF segment& < 0 THEN segment& = segment& + 65536 IF offset& < 0 THEN offset& = offset& + 65536 baseaddr& = segment& * 16 + offset& look1% = VARPTR(baseaddr&) look2% = VARPTR(size%) SELECT CASE dma% CASE 0 dmapage% = &H87 '135 decimal dmaaddr% = 0 dmalen% = 1 CASE 1 dmapage% = &H83 '131 decimal dmaaddr% = 2 dmalen% = 3 CASE 2 dmapage% = &H81 dmaaddr% = 4 dmalen% = 5 CASE 3 dmapage% = &H82 dmaaddr% = 6 dmalen% = 7 CASE 4 dmapage% = &H8F dmaaddr% = &HC0 dmalen% = &HC2 CASE 5 dmapage% = &H8B dmaaddr% = &HC4 dmalen% = &HC6 CASE 6 dmapage% = &H89 dmaaddr% = &HC8 dmalen% = &HCA CASE 7 dmapage% = &H8A dmaaddr% = &HCC dmalen% = &HCE END SELECT SELECT CASE dma% CASE 0 TO 3 dmamask% = &HA dmamode% = &HB dmaclear% = &HC dmastatus% = &H8 CASE 4 TO 7 dmamask% = &HD4 dmamode% = &HD6 dmaclear% = &HD8 dmastatus% = &HD0 END SELECT SELECT CASE dma% CASE 0, 4 dmaterminal% = 1 'bit 0 of status register (&H08 or &HD0) CASE 1, 5 dmaterminal% = 2 'bit 1 CASE 2, 6 dmaterminal% = 4 'bit 2 CASE 3, 7 dmaterminal% = 8 'bit 3 END SELECT OUT dmamask%, dma% + 4 'mask the dma channel OUT dmaclear%, &H0 '(clear the internal DMA flip/flop) OUT dmamode%, 72 + dma% ' 72=010010XX where XX=dmachannel% OUT dmaaddr%, PEEK(look1%) 'bits 0-7 of the 20bit address OUT dmaaddr%, PEEK(look1% + 1) 'bits 8-15 of the 20bit address OUT dmapage%, PEEK(look1% + 2) 'bits 16-19 of the 20 bit address OUT dmalen%, PEEK(look2%) 'bits 0-7 of size% OUT dmalen%, PEEK(look2% + 1) 'bits 8-15 of size% OUT dmamask%, dma% 'enable channel IF num% = 1 THEN 'only need to Write out time constant once timeconst% = 256 - 1000000 / (freq& * chans%) CALL WriteToDSP(&H40) CALL WriteToDSP(timeconst%) 'Reset Mixer DSPmixeraddress = Blasteraddr% + &H4 OUT BlasterAddr% + &H4, &H0 OUT BlasterAddr% + &H4 + 1, 0 'Set Volume to Maximum...255 OUT BlasterAddr% + &H4, &H22 OUT BlasterAddr% + &H4 + 1, 50'255 IF chans% = 2 THEN 'Set mixer to Stereo Output OUT BlasterAddr% + &H4, &HE OUT BlasterAddr% + &H4 + 1, 34 '34=2^5+2^1 END IF END IF IF BytesPerSec& > 22000 THEN CALL WriteToDSP(&H48) 'Set Block Size ELSE CALL WriteToDSP(&H14) 'DMA Mode 8-bit DAC END IF CALL WriteToDSP(PEEK(look2%)) 'Lo byte of address CALL WriteToDSP(PEEK(look2% + 1)) 'High byte of address IF BytesPerSec& > 22000 THEN CALL WriteToDSP(&H91) 'High Speed DMA mode 8-bit dummy% = INP(dmastatus%) 'Read status byte once to make sure DMA is going. WAIT dmastatus%, dmaterminal% 'Loop until terminal count bit set in DMA status register 'DMA Transfer is Now Complete 'Acknowledge the DSP interrupt by reading the DATA AVAILABLE port once dummy% = INP(BlasterAddr% + &HE) 'DSP Available address END SUB FUNCTION SBreset% OUT BlasterAddr% + &H6, 1 'Reset address delay .1 OUT BlasterAddr% + &H6, 0 time1! = TIMER: noreset% = 0 DO IF TIMER - time1! > 1! THEN noreset% = -1 LOOP UNTIL ((INP(BlasterAddr% + &HE) AND 128) = 128) OR noreset% IF NOT noreset% THEN IF INP(BlasterAddr% + &HA) = &HAA THEN SBreset% = -1 ELSE SBreset% = 0 END IF ELSE SBreset% = 0 END IF END FUNCTION SUB Seek21 (Handle, offset!) '/* Don't edit this SUB if you don't have any knowledge of Interrupts */' Regs.ax = &H4200 Regs.bx = Handle Regs.cx = offset! \ 65536 Regs.dx = (offset! AND 32767) - (offset! AND 32768) CALL NewInterrupt(&H21, Regs) END SUB SUB ShowAVI (FileName$) OPEN FileName$ FOR BINARY AS #255 IF LOF(255) = 0 THEN PRINT " FILE IS EMPTY" CLOSE #255 KILL FileName$ EXIT SUB END IF DIM RIFFHeaderType AS RIFFHeaderType DIM AVIHead AS AVIHeader DIM Listz AS Listz DIM StreamHead AS StreamHeader DIM StreamForm AS StreamFormat DIM BMPInfoHead AS BMPInfoHeader DIM ImageDataz AS ImageData DIM WavHeader AS WavHeader Speedo& = Speed& GET #255, , RIFFHeaderType IF RIFFHeaderType.RIFFFileType <> "AVI " THEN PRINT " INVALID AVI FILE" EXIT SUB END IF GET #255, 25, AVIHead AVIHead.MicrosecPerFrame = (AVIHead.MicrosecPerFrame / 1000) '* (1 / 2) FramesPerSecond = CINT(1000 / AVIHead.MicrosecPerFrame) IF AVIHead.ValidID <> "avih" THEN PRINT " Invalid AVI File Header" EXIT SUB END IF SEEK #255, 25 + AVIHead.Reserved + 8 FOR NumberOfStreams = 1 TO AVIHead.NoOfStreams GET #255, , Listz IF Listz.ListType = "strl" THEN Position& = LOC(255) + 1 GET #255, , StreamHead '/* Checks if the stream is a video stream indicated by the characters*/' '/* 'vids', audio stream is indicated by the characters 'auds' */' IF LCASE$(StreamHead.Typez) = "vids" THEN SEEK #255, Position& + StreamHead.BytesIn + 8 GET #255, , StreamForm Position& = LOC(255) + 1 GET #255, , BMPInfoHead IF BMPInfoHead.BitsPerPixel <> 8 AND BMPInfoHead.BitsPerPixel <> 24 THEN PRINT " Can't Play AVI File" EXIT SUB ELSEIF BMPInfoHead.CompressMethod <> 0 THEN PRINT " Only Uncompressed AVIs Can Be Played" EXIT SUB END IF '/* Changes graphix screen to SCREEN 13 and changes the color palettes */' SCREEN 13 IF BMPInfoHead.BitsPerPixel = 8 THEN Palette$ = SPACE$(1024) GET #255, , Palette$ FOR Loops = 0 TO 255 OUT &H3C8, Loops OUT &H3C9, ASC(MID$(Palette$, (Loops * 4) + 3, 1)) \ 4 OUT &H3C9, ASC(MID$(Palette$, (Loops * 4) + 2, 1)) \ 4 OUT &H3C9, ASC(MID$(Palette$, (Loops * 4) + 1, 1)) \ 4 NEXT Loops END IF Palette$ = "" SEEK #255, Position& + StreamForm.BytesInFormat'Listz.BytesInList - 4 ELSEIF LCASE$(StreamHead.Typez) = "auds" THEN BlasterAddr% = GetBlasterAddr% IF BlasterAddr% <> -2 AND BlasterAddr% <> -1 AND BlasterAddr% <> 0 THEN Blasting = 1 END IF IF NOT SBreset% THEN SoundBlast = -1 END IF SEEK #255, Position& + StreamHead.BytesIn + 8 GET #255, , StreamForm GET #255, , WavHeader IF WavHeader.BitsPerSample <> 8 OR WavHeader.BytesPerSecond > 22050 THEN PRINT " Sound Can't Be Played" SoundBlast = -1: SLEEP 1 END IF IF Blasting = 1 AND SoundBlast = 0 THEN CALL WriteToDSP(&HD1) 'Speaker ON END IF WaveBytesPerFrame = INT(WavHeader.BytesPerSecond / FramesPerSecond) SEEK #255, Position& + Listz.BytesInList - 4 END IF ELSE PRINT " UNABLE TO USE AVI FILE" EXIT SUB END IF NEXT NumberOfStreams DO GET #255, , Listz IF LCASE$(Listz.ListID) = "junk" OR LCASE$(Listz.ListID) = "vedt" THEN SEEK #255, LOC(255) + 1 + Listz.BytesInList - 4 ELSE '/* List [4] Movi is extracted 'SEEK #255, LOC(255) + 1 - 12 EXIT DO END IF LOOP IF BMPInfoHead.BitsPerPixel = 24 THEN CALL BIT24AVI(INT(BMPInfoHead.ImageWidth), INT(BMPInfoHead.ImageHeight), INT(AVIHead.TotalFrames)) CLOSE EXIT SUB ELSEIF AVIHead.Widthz > 320 OR AVIHead.Heightz > 200 THEN PRINT " AVI Image Is To Large" EXIT SUB END IF '/* Calculate the number of bytes to extract for each image line */' IF 4 - (BMPInfoHead.ImageWidth MOD 4) = 4 THEN BytesToExtract = BMPInfoHead.ImageWidth ELSE BytesToExtract = BMPInfoHead.ImageWidth + (4 - (BMPInfoHead.ImageWidth MOD 4)) END IF RealCurrentLocation! = LOC(255) HeightAdjust = (200 - BMPInfoHead.ImageHeight) \ 2 WidthAdjust = (320 - BMPInfoHead.ImageWidth) \ 2 IF HeightAdjust < 0 THEN HeightAdjust = 0 IF WidthAdjust < 0 THEN WidthAdjust = 0 CLOSE '/* Reopen the AVI file */' CALL Open21(FileName$, AVIHandle) repeat: CurrentLocation! = RealCurrentLocation! CALL Seek21(AVIHandle, CurrentLocation!) FOR FrameNumber = 1 TO AVIHead.TotalFrames CALL Get21(AVIHandle, LEN(ImageDataz), VARSEG(ImageDataz), VARPTR(ImageDataz)) IF ImageDataz.ChunkID = "LIST" THEN CurrentLocation! = CurrentLocation! + 12 CALL Seek21(AVIHandle, CurrentLocation!) CALL Get21(AVIHandle, LEN(ImageDataz), VARSEG(ImageDataz), VARPTR(ImageDataz)) '/* Just incase something does go wrong */' ELSEIF RIGHT$(ImageDataz.ChunkID, 3) = "00d" THEN CALL Seek21(AVIHandle, CurrentLocation! + 1) CALL Get21(AVIHandle, LEN(ImageDataz), VARSEG(ImageDataz), VARPTR(ImageDataz)) ELSEIF RIGHT$(ImageDataz.ChunkID, 2) = "00" THEN CALL Seek21(AVIHandle, CurrentLocation! + 2) CALL Get21(AVIHandle, LEN(ImageDataz), VARSEG(ImageDataz), VARPTR(ImageDataz)) END IF IF RIGHT$(ImageDataz.ChunkID, 2) = "db" THEN FOR YHeight = BMPInfoHead.ImageHeight - 1 TO 0 STEP -1 IF YHeight + HeightAdjust < 100 THEN CALL Get21(AVIHandle, BytesToExtract, &HA000, (YHeight + HeightAdjust) * 320 + WidthAdjust) ELSE CALL Get21(AVIHandle, BytesToExtract, &HA7D0, (YHeight + HeightAdjust - 100) * 320 + WidthAdjust) END IF NEXT YHeight IF PlayWave = 1 AND WaveBuffer$ <> "" THEN Speed& = INT(Speedo& * (1 / 128)) ExtractBytes$ = LEFT$(WaveBuffer$, WaveBytesPerFrame) IF (LEN(WaveBuffer$) - LEN(ExtractBytes$)) < 100 THEN ExtractBytes$ = WaveBuffer$ WaveBuffer$ = "" END IF ExtractBytes = LEN(ExtractBytes$) CALL WavPlay(ExtractBytes$, LEN(ExtractBytes$), WavHeader.SampleRate, WavHeader.BytesPerSecond, WavHeader.Channels) IF WaveBuffer$ <> "" THEN WaveBuffer$ = RIGHT$(WaveBuffer$, LEN(WaveBuffer$) - ExtractBytes) END IF ELSE Speed& = Speedo& END IF ELSEIF RIGHT$(ImageDataz.ChunkID, 2) = "pc" THEN '/* Skipping the color changing */' ELSEIF RIGHT$(ImageDataz.ChunkID, 2) = "wb" THEN IF Blasting = 1 AND SoundBlast = 0 THEN WaveBuffer$ = SPACE$(ImageDataz.NumberOfBytes) CALL Get21(AVIHandle, LEN(WaveBuffer$), VARSEG(WaveBuffer$), SADD(WaveBuffer$)) PlayWave = 1 Speed& = 0 END IF FrameNumber = FrameNumber - 1 ELSEIF RIGHT$(ImageDataz.ChunkID, 2) = "dc" THEN '/* Ending program because compressed data was encountered */' CALL Close21(AVIHandle) IF Blasting = 1 AND SoundBlast = 0 THEN OUT &H20, &H20 'Reset Normal Interrupt Service CALL WriteToDSP(&HD3) 'Speaker OFF END IF SCREEN 2: SCREEN 0 PRINT " Only Uncompressed AVIs Can Be Played" EXIT SUB ELSE CALL Close21(AVIHandle) IF Blasting = 1 AND SoundBlast = 0 THEN OUT &H20, &H20 'Reset Normal Interrupt Service CALL WriteToDSP(&HD3) 'Speaker OFF END IF SCREEN 2: SCREEN 0 PRINT " Something Went Wrong"; ImageDataz.ChunkID, ImageDataz.NumberOfBytes PRINT " Please Send This AVI To " EXIT SUB END IF '/* Delay FUNCTION - slows down display according to speed given from*/' '/* AVI file */' delay (AVIHead.MicrosecPerFrame) '/* Checks if the user presses a key */' IF INKEY$ <> "" THEN CALL Close21(AVIHandle) IF Blasting = 1 AND SoundBlast = 0 THEN OUT &H20, &H20 'Reset Normal Interrupt Service CALL WriteToDSP(&HD3) 'Speaker OFF END IF EXIT SUB END IF CurrentLocation! = CurrentLocation! + ImageDataz.NumberOfBytes + 8 CALL Seek21(AVIHandle, CurrentLocation!) CALL Get21(AVIHandle, LEN(Listz), VARSEG(Listz), VARPTR(Listz)) IF LCASE$(Listz.ListID) = "junk" OR LCASE$(Listz.ListID) = "vedt" THEN CurrentLocation! = CurrentLocation! + 8 + Listz.BytesInList CALL Seek21(AVIHandle, CurrentLocation!) ELSE CALL Seek21(AVIHandle, CurrentLocation!) END IF NEXT FrameNumber GOTO repeat END SUB SUB WavPlay (Bytes$, WavLen&, Sampling&, Bytes&, Channels) MaxBuffer% = 7053 Remaining& = WavLen& DO num% = num% + 1 IF Remaining& >= MaxBuffer% THEN BufferLen% = MaxBuffer% Buffer$ = LEFT$(Bytes$, BufferLen%) Bytes$ = RIGHT$(Bytes$, LEN(Bytes$) - BufferLen%) ELSE BufferLen% = Remaining& Buffer$ = LEFT$(Bytes$, BufferLen%) Bytes$ = RIGHT$(Bytes$, LEN(Bytes$) - BufferLen%) END IF Remaining& = Remaining& - BufferLen% CALL PlayBack(Buffer$, BufferLen%, Sampling&, Bytes&, Channels) LOOP WHILE Remaining& > 0 END SUB SUB WriteToDSP (v%) DO LOOP UNTIL (INP(BlasterAddr% + &HC) AND 128) = 0 OUT BlasterAddr% + &HC, v% END SUB