'===========================================================================
' Subject: PB FORMAT FLOPPY DISKS             Date: 05-12-97 (17:05)       
'  Author: Dave Navarro, Jr.                  Code: PB                     
'  Origin: dave@powerbasic.com              Packet: DISK.ABC
'===========================================================================
'==============================================================================
'
'  PowerBASIC 3.2 source code for formatting floppy disks
'  Original by Thaddy De Konig
'  Additions and modifications by Dave Navarro, Jr. (dave@powerbasic.com)
'
'==============================================================================

$DIM ALL

DECLARE FUNCTION PBFORMAT(BYVAL drive AS INTEGER, BYVAL media AS INTEGER) AS INTEGER

DECLARE FUNCTION ValidateDisk(BYVAL drive AS INTEGER, BYVAL media AS INTEGER) AS INTEGER
DECLARE FUNCTION FormatDisk(BYVAL drive AS INTEGER) AS INTEGER
DECLARE FUNCTION WriteBoot(BYVAL drive AS INTEGER) AS INTEGER
DECLARE FUNCTION WriteFAT(BYVAL drive AS INTEGER) AS INTEGER
DECLARE FUNCTION WriteDir(BYVAL drive AS INTEGER) AS INTEGER
DECLARE SUB InitFormatParms(BYVAL media AS INTEGER)
DECLARE SUB ResetFDC(BYVAL drive AS INTEGER)
DECLARE FUNCTION FormatTrack(BYVAL drive AS INTEGER, BYVAL track AS INTEGER, BYVAL head AS INTEGER) AS INTEGER
DECLARE FUNCTION WriteBootSector(BYVAL drive AS INTEGER) AS INTEGER
DECLARE SUB ComputeCHS( LogSec AS INTEGER, cyl AS INTEGER, hd AS INTEGER, sec AS INTEGER)
DECLARE FUNCTION WriteSector( BYVAL drive AS INTEGER, BYVAL cylinder AS INTEGER, BYVAL head AS INTEGER, BYVAL sector AS INTEGER, BYVAL Buffer AS DWORD) AS INTEGER

%FLAGS = 0
%AX    = 1
%BX    = 2
%CX    = 3
%DX    = 4
%SI    = 5
%DI    = 6
%BP    = 7
%DS    = 8
%ES    = 9

%F360  = &HFD
%F1200 = &HF9
%F720  = - &HF9 ' media byte is NEGATIVE to differ from %F1200
%F1440 = &HF0
%F2880 = - &HF0 ' media byte is negative to differ from %F1440

%RETRIES = 5 '%RETRIES on BIOS error

TYPE ADDRFIELDtype
  track   AS STRING * 1
  head    AS STRING * 1
  sector  AS STRING * 1
  bytesec AS STRING * 1
END TYPE '4

TYPE INFOtype
  OEM AS STRING * 8 'system name
  BS  AS WORD 'bytes/sector
  SC  AS BYTE 'STRING * 1 'sectors/cluster
  RS  AS WORD 'reserved sectors
  NF  AS BYTE 'STRING * 1 'FATs
  DE  AS WORD 'root directory entries
  TS  AS WORD 'total sectors on volume
  MB  AS STRING * 1 'media byte
  SF  AS WORD 'sectors/FAT
  ST  AS WORD 'sectors/track
  NH  AS WORD 'heads
  HS  AS WORD 'hidden sectors
END TYPE '27

TYPE BOOTRECtype
  jmp   AS STRING * 3
  parms AS INFOtype
  code  AS STRING * 482
END TYPE '512

'INT 1Eh disk parameter table vectors
DIM OldDPTseg AS SHARED WORD
DIM OldDPToff AS SHARED WORD
DIM NewDPTseg AS SHARED WORD
DIM NewDPToff AS SHARED WORD

'Number of tracks on media
DIM NoTracks AS SHARED INTEGER

'format info for media
DIM Info AS SHARED INFOtype

'interface with INTERUPTX routine
'boot record buffer
DIM BootRec AS SHARED BOOTRECtype

'sector buffer to write FAT & root directory sectors
DIM SectorBuff AS SHARED STRING * 512

DIM Drive AS SHARED INTEGER
DIM Media AS SHARED INTEGER
DIM verifydisk AS SHARED INTEGER

$STATIC

'Allocate address field data to max possible sectors per track
DIM AddrField( 1 TO 36 ) AS SHARED ADDRFIELDtype
'============================================================================


DIM xerr AS INTEGER
DIM errl AS INTEGER
DIM errc AS INTEGER

'The following code is a sample run to format a disk
'All other code can be compiled and put in a library
'format test drive A:
drive = 0
media = %F1440

PRINT "Insert 1.44 disk to format in drive A: and"
PRINT "Press a key to start PBFORMAT";

SLEEP

PRINT
PRINT

xerr = PBFORMAT( drive, media )
IF xerr THEN
  errl = xerr \ 256
  errc = xerr AND 255
  PRINT "*** Error level:"; errl; " code:"; errc
ELSE
  PRINT "done."
END IF
END

'level error codes
'0:no error
'1:validate error
'2:format error
'3:boot record write error
'4:FAT write error
'5:directory write error

'floppy disk error codes (xerr,in decimal):
'0:no error
'1:invalid function request
'2:address mark not found
'3:write protected
'4:sector not found
'6:diskette changed
'8:DMA overrun
'9:DMA boundary error
'12:media type not available
'16:bad CRC
'32:diskette controller failed
'64:seek failed
'128:time-out/drive not ready
'
FUNCTION PBFORMAT(BYVAL drive AS INTEGER, _
                  BYVAL media AS INTEGER) PUBLIC AS INTEGER

  DIM xerr  AS INTEGER
  DIM level AS INTEGER

  xerr = ValidateDisk( drive, media )
  IF xerr = 0 THEN
    xerr = FormatDisk( drive )
  ELSE
    level = 1
  END iF
  IF xerr = 0 THEN
    PRINT "Writing boot sector..."
    xerr = WriteBoot( drive )
  ELSEIF level = 0 THEN
    level = 2
  END IF
  IF xerr = 0 THEN
    PRINT "Creating FAT tables..."
    xerr = WriteFAT( drive )
  ELSEIF level = 0 THEN
    level = 3
  END IF
  IF xerr = 0 THEN
    xerr = WriteDir( drive )
  ELSEIF level = 0 THEN
    level = 4
  END IF
  IF xerr THEN
    IF level = 0 THEN
      level = 5
    END IF
  END IF
'reset INT 1Eh vector to original,check both for <>0
  IF OldDPTseg < > 0 OR OldDPToff < > 0 THEN
    REG %ax, &H251E
    REG %ds, OldDPTseg
    REG %dx, OldDPToff
    CALL INTERRUPT &H21
  END IF
  FUNCTION = ( level * 256 ) + xerr
END FUNCTION

'check if media supported by program, by drive, and if drive is ready
FUNCTION ValidateDisk(BYVAL drive AS INTEGER, _
                      BYVAL media AS INTEGER) PRIVATE AS INTEGER

  DIM CMOS AS INTEGER
  DIM checks AS INTEGER
  DIM zerr AS INTEGER

  InitFormatParms media
  IF Info.ST THEN
  'check to see if there is CMOS RAM (means we have an AT BIOS)
    OUT &H70, &H10
    CMOS = ( INP( &H71 ) < > &HFF )
    ResetFDC drive
    IF CMOS THEN
    'get original INT 1Eh vector to disk parameter table
      REG %ax, &H351E
      CALL INTERRUPT &H21
      OldDPTseg = REG( %es )
      OldDPToff = REG( %bx )
    'set media type for format on AT BIOS/multi-media drive
    'let BIOS determine if drive can format media with a DPT in BIOS ROM
      FOR checks = 1 TO %RETRIES 'zerr=0 no error
        REG %ax, &H1800
        REG %cx,(( NoTracks - 1 ) * 256 ) + Info.ST
        REG %dx, drive
        CALL INTERRUPT &H13
        zerr = REG( %ax ) \ 256 'zerr=&H0C unknown media/maybe invalid CMOS
        IF zerr THEN ResetFDC drive ELSE EXIT FOR
      NEXT
    'set INT 1Eh vector to this media's disk parameter table in BIOS ROM
      IF zerr = 0 THEN
        NewDPTseg = REG( %es )
        NewDPToff = REG( %di )
        REG %ax, &H251E
        REG %ds, NewDPTseg
        REG %dx, NewDPToff
        CALL INTERRUPT &H21
      ELSE
        OldDPTseg = 0
        OldDPToff = 0
      END IF
    END IF
  ELSE
    zerr = &HC 'media not supported by program
  END IF
'physical check for disk in the drive
  IF zerr = 0 THEN
    REG %ax, &H401 'verify 1 sector from drive
    REG %cx, &H1 'track=0 sector=1
    REG %dx, drive 'head=0 drive=drive
    FOR checks = 1 TO %RETRIES
      CALL INTERRUPT &H13
      IF REG(( %flags ) AND 1 ) THEN 'bad read
        zerr = REG( %ax )
      'need to detect an unformatted disk
        SHIFT RIGHT zerr, 8 '= e \ 256
        ResetFDC drive
      ELSE
        zerr = 0 'good read,already formatted disk in drive
        EXIT FOR
      END IF
    NEXT
  'zerr may be any of the BIOS diskette error codes if non-zero here
  'address mark not found(2)=unformatted disk in drive
  'sector not found(4)=wacko disk but okay to proceed
    IF zerr = 2 OR zerr = 4 THEN zerr = 0
  END IF
  ValidateDisk = zerr
END FUNCTION


'format a track at a time a side at a time
'any error aborts format, diskette presumed unreliable
'retry format 1 or 2 more times before trashing the diskette
FUNCTION FormatDisk(BYVAL drive AS INTEGER) AS INTEGER

  DIM y AS INTEGER
  DIM x AS INTEGER
  DIM track AS INTEGER
  DIM head AS INTEGER
  DIM xerr AS INTEGER
  DIM i AS INTEGER

  y = POS( 0 )
  x = CSRLIN
  LOCATE ,,1
  FOR track = 0 TO( NoTracks - 1 )
    LOCATE x, y: PRINT "Formatting track:"; track;
  'This is where you insert any printed info.
  'If you don't want it, remove it......
    FOR head = 0 TO( Info.NH - 1 )
      FOR i = 1 TO %RETRIES
        xerr = FormatTrack( drive, track, head )
        IF xerr = 0 THEN
          EXIT FOR
        END IF
      NEXT
      IF xerr THEN
        PRINT
        FUNCTION = xerr
        EXIT FUNCTION
      END IF
    NEXT
  NEXT
  PRINT
  FUNCTION = 0
END FUNCTION

FUNCTION WriteBoot(BYVAL drive AS INTEGER) AS INTEGER

  DIM offset AS WORD
  DIM i AS INTEGER
  DIM Byte AS INTEGER
  DIM xerr AS INTEGER

  RESTORE BootSector

'read default boot record data
  DEF SEG = VARSEG( BootRec ): offset = VARPTR( BootRec )
  FOR i = 0 TO 511
    READ Byte
    POKE offset + i, Byte
  NEXT
  DEF SEG

'update OEM name and BIOS parameter block
  BootRec.parms = Info

'write the boot record
  FOR i = 1 TO %RETRIES
    xerr = WriteBootSector( drive )
    IF xerr = 0 THEN EXIT FOR
  NEXT

  FUNCTION = xerr

END FUNCTION

FUNCTION WriteFAT(BYVAL drive AS INTEGER) AS INTEGER

  DIM FAT1 AS STRING
  DIM FAT2 AS STRING
  DIM i AS INTEGER
  DIM LogSec AS INTEGER
  DIM j AS INTEGER
  DIM k AS INTEGER
  DIM xerr AS INTEGER
  DIM cyl AS INTEGER
  DIM hd AS INTEGER
  DIM sec AS INTEGER

  FAT1 = Info.MB + CHR$( 255 ) + CHR$( 255 )
  FAT2 = CHR$( 0 ) + CHR$( 0 ) + CHR$( 0 )
  FOR i = 1 TO 512: MID$( SectorBuff, i, 1 ) = CHR$( 0 ): NEXT
  LogSec = Info.RS + Info.HS 'first logical FAT sector
  FOR i = 1 TO Info.NF
    FOR j = 1 TO Info.SF
      IF j = 1 THEN
        MID$( SectorBuff, 1 ) = FAT1
      ELSE
        MID$( SectorBuff, 1 ) = FAT2
      END IF
      ComputeCHS LogSec, cyl, hd, sec
      FOR k = 1 TO %RETRIES
        xerr = WriteSector( drive, cyl, hd, sec, VARPTR32(SectorBuff) )
        IF xerr = 0 THEN EXIT FOR
      NEXT
      IF xerr THEN
        FUNCTION = xerr
        EXIT FUNCTION
      END IF
      LogSec = LogSec + 1
    NEXT
  NEXT
  FUNCTION = 0
END FUNCTION

FUNCTION WriteDir(BYVAL drive AS INTEGER) AS INTEGER

  DIM i AS INTEGER
  DIM LogSec AS INTEGER
  DIM k AS INTEGER
  DIM xerr AS INTEGER
  DIM cyl AS INTEGER
  DIM hd AS INTEGER
  DIM sec AS INTEGER

  MID$( SectorBuff, 1, 1 ) = CHR$( 0 )
  FOR i = 2 TO 512
    IF ( i - 1 ) MOD 32 = 0 THEN
      MID$( SectorBuff, i, 1 ) = CHR$( 0 )
    ELSE
      MID$( SectorBuff, i, 1 ) = CHR$( &HF6 )
    END IF
  NEXT
  LogSec = Info.RS + Info.HS + ( Info.SF * Info.NF ) 'first logical dir sector
  FOR i = 1 TO( Info.DE \ 16 ) 'sectors needed for root directory
    ComputeCHS LogSec, cyl, hd, sec
    FOR k = 1 TO %RETRIES
      xerr = WriteSector( drive, cyl, hd, sec, VARPTR32(SectorBuff) )
      IF xerr = 0 THEN EXIT FOR
    NEXT
    IF xerr THEN WriteDir = xerr: EXIT FUNCTION
    LogSec = LogSec + 1
  NEXT
  WriteDir = 0
END FUNCTION

'set up media's format data
SUB InitFormatParms(BYVAL media AS INTEGER)
  Info.OEM = "IBM  PB3" 'avoid changing 'IBM'
  Info.BS = 512
  Info.RS = 1
  Info.NF = 2
  Info.NH = 2
  Info.HS = 0
  SELECT CASE media
    CASE %F360
      Info.SC = 2
      Info.DE = 112
      Info.TS = 720
      Info.MB = CHR$( %F360 )
      Info.SF = 2
      Info.ST = 9
    CASE %F1200
      Info.SC = 1
      Info.DE = 224
      Info.TS = 2400
      Info.MB = CHR$( %F1200 )
      Info.SF = 7
      Info.ST = 15
    CASE %F720
      Info.SC = 2
      Info.DE = 112
      Info.TS = 1440
      Info.MB = CHR$( ABS( %F720 ))
      Info.SF = 3
      Info.ST = 9
    CASE %F1440
      Info.SC = 1
      Info.DE = 224
      Info.TS = 2880
      Info.MB = CHR$( %F1440 )
      Info.SF = 9
      Info.ST = 18
    CASE %F2880
      Info.SC = 2
      Info.DE = 240
      Info.TS = 5760
      Info.MB = CHR$( ABS( %F2880 ))
      Info.SF = 9
      Info.ST = 36
    CASE ELSE
      Info.OEM = ""
      Info.BS = 0
      Info.RS = 0
      Info.NF = 0
      Info.NH = 0
      Info.HS = 0
      Info.SC = 0
      Info.DE = 0
      Info.TS = 0
      Info.MB = CHR$( 0 )
      Info.SF = 0
      Info.ST = 0
  END SELECT
  NoTracks = Info.TS \ Info.NH \ Info.ST
  NewDPTseg = 0    'INT 1Eh vector
  NewDPToff = 0    'new -> disk parameter table for formatted media
  OldDPTseg = 0    'original-
  OldDPToff = 0    '-vector
END SUB

'reset the controller after any BIOS FDC error
SUB ResetFDC(BYVAL drive AS INTEGER)
  ! push DS

  ! mov AX, 0
  ! mov DX, drive
  ! int &H13

  ! pop DS
END SUB

FUNCTION FormatTrack(BYVAL drive AS INTEGER, _
                     BYVAL track AS INTEGER, _
                     BYVAL head AS INTEGER) AS INTEGER

  DIM sec AS INTEGER
  DIM cf AS INTEGER
  DIM e AS WORD

'Initialize address field for each sector on this track
  FOR sec = 1 TO Info.ST
    AddrField( sec ).track   = CHR$( track )
    AddrField( sec ).head    = CHR$( head )
    AddrField( sec ).sector  = CHR$( sec )
    AddrField( sec ).bytesec = CHR$( 2 ) 'bytecode 2 = 512-byte sector
  NEXT

  REG %ax, &H500 + Info.ST         'format track with sectors/track
  REG %cx,( track * 256 ) + 1      'track to format,start with sector 1
  REG %dx,( head * 256 ) + drive   'head,drive
  REG %es, VARSEG( AddrField( 1 )) 'point to address field data
  REG %bx, VARPTR( AddrField( 1 ))
  CALL INTERRUPT &H13

  cf = REG( %flags ) AND 1         'cf=1 if disk error
  IF cf THEN
    E = REG( %ax )
    SHIFT RIGHT e, 8             'return with status byte
    FUNCTION = e
    ResetFDC drive
  ELSE
    IF verifydisk THEN
      REG %ax, &H400 + Info.ST       'ok, verify track integrity-
      CALL INTERRUPT &H13            '-optional but recommended on format
      cf = REG( %flags ) AND 1       'cf=1 if disk error
      IF cf THEN
        e = REG( %ax )
        SHIFT RIGHT e, 8           'return with status byte
        FUNCTION = e
        ResetFDC drive
      END IF
    END IF
  END IF

  FUNCTION = 0                     'format ok

END FUNCTION

'convert a DOS logical sector to BIOS form
SUB ComputeCHS( LogSec AS INTEGER, cyl AS INTEGER, hd AS INTEGER, sec AS INTEGER)

  DIM CylSec AS INTEGER
  DIM rm AS INTEGER

  CylSec = Info.ST * Info.NH
  cyl    = LogSec \ CylSec
  rm     = LogSec - ( cyl * CylSec )
  hd     = rm \ Info.ST
  sec    = rm - ( hd * Info.ST ) + 1

END SUB


FUNCTION WriteBootSector(BYVAL drive AS INTEGER) AS INTEGER

  DIM cf AS INTEGER
  DIM e AS WORD

  ! push DS              ; save DS for PowerBASIC

  ! mov  AX, &H301       ; write 1 sector
  ! mov  CX, 1           ; track 0,sector 1
  ! mov  DX, drive       ; head 0, drive
  ! push SS
  ! pop  ES              ; ES:BX points to BootRec
  ! lea  BX, BootRec
  ! int  &H13            ; call BIOS
  ! pop  DS
  ! jnc  WriteBootDone
  ! mov  FUNCTION[0], AH ; AH holds error code

  ResetFDC Drive         ' reset floppy controller

WriteBootDone:

END FUNCTION

'BIOS write a FAT or directory sector
FUNCTION WriteSector( BYVAL drive AS INTEGER, _
                      BYVAL cylinder AS INTEGER, _
                      BYVAL head AS INTEGER, _
                      BYVAL sector AS INTEGER, _
                      BYVAL Buffer AS DWORD ) AS INTEGER

  ! push DS

  ! mov AX, &H301
  ! mov CL, Byte Ptr sector
  ! mov CH, Byte Ptr cylinder
  ! mov DL, Byte Ptr drive
  ! mov DH, Byte Ptr head
  ! les BX, Buffer
  ! int &H13
  ! jnc WriteSectorDone
  ! xchg AL, AH
  ! xor AH, AH
  ! mov FUNCTION[0], AX
  ! push drive
  ! call WriteSector
WriteSectorDone:

  ! pop DS

END FUNCTION

BootSector:
DATA &HEB, &H3E, &H90, &H20, &H20, &H20, &H20, &H20, &H20, &H20, &H20, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &HA, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H2B, &HC0, &H8E, &HD0, &HBC, &H0, &H7C, &HB8, &HC0, &H7, &H8E, &HD8, &H8E, &HC0, &HBE, &H3
DATA &H0, &HBF, &HAF, &H0, &HB9, &H4, &H0, &HF3, &HA5, &HBE, &HAF, &H0, &HB4, &HE, &H8A, &H4
DATA &HA, &HC0, &H74, &H7, &H56, &HCD, &H10, &H5E, &H46, &HEB, &HF1, &HFC, &HBE, &H7A, &H0, &HBF
DATA &H0, &H2, &HB9, &H0, &H2, &HF3, &HA4, &HE9, &H86, &H1, &HB8, &H1, &H2, &H2B, &HDB, &HB9
DATA &H1, &H0, &HBA, &H50, &H0, &HCD, &H13, &H72, &HC, &HBB, &HFE, &H1, &H81, &H3F, &H55, &HAA
DATA &H75, &H3, &HE9, &HE5, &HFD, &HBE, &H58, &H2, &HB4, &HE, &H8A, &H4, &HA, &HC0, &H74, &H7
DATA &H56, &HCD, &H10, &H5E, &H46, &HEB, &HF1, &H2B, &HC0, &HCD, &H16, &HCD, &H19, &HCD, &H18, &H20
DATA &H20, &H20, &H20, &H20, &H20, &H20, &H20, &H20, &H6E, &H6F, &H6E, &H2D, &H62, &H6F, &H6F, &H74
DATA &H61, &H62, &H6C, &H65, &H20, &H64, &H69, &H73, &H6B, &H20, &H69, &H6E, &H20, &H41, &H3A, &HD
DATA &HA, &H0, &H4E, &H6F, &H20, &H62, &H6F, &H6F, &H74, &H20, &H64, &H69, &H73, &H6B, &H20, &H66
DATA &H6F, &H75, &H6E, &H64, &H2C, &H20, &H72, &H65, &H70, &H6C, &H61, &H63, &H65, &H20, &H61, &H6E
DATA &H64, &H20, &H70, &H72, &H65, &H73, &H73, &H20, &H61, &H20, &H6B, &H65, &H79, &H20, &HD, &HA
DATA &HD, &HA, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0
DATA &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H55, &HAA
