diff --git a/internal/help/$SCREENHIDE.txt b/internal/help/$SCREENHIDE.txt index bc78a2577..ccae45a05 100644 --- a/internal/help/$SCREENHIDE.txt +++ b/internal/help/$SCREENHIDE.txt @@ -24,7 +24,7 @@ The [[$SCREENHIDE]] [[Metacommand|metacommand]] can be used to hide the main pro {{Cl|DIM}} s1 {{Cl|AS}} {{Cl|STRING}} s0 = "Text" + {{Cl|CHR$}}(0) s1 = "Caption" + {{Cl|CHR$}}(0) -ExitProcess MessageBoxA(0, {{Cl|_OFFSET (function)|_OFFSET}}(s0), {{Cl|_OFFSET(function)|_OFFSET}}(s1), 0) +ExitProcess MessageBoxA(0, {{Cl|_OFFSET (function)|_OFFSET}}(s0), {{Cl|_OFFSET (function)|_OFFSET}}(s1), 0) {{CodeEnd}}{{small|Code by Michael Calkins}} diff --git a/internal/help/ALIAS.txt b/internal/help/ALIAS.txt index 25594ab10..90b18f00b 100644 --- a/internal/help/ALIAS.txt +++ b/internal/help/ALIAS.txt @@ -19,10 +19,6 @@ The [[ALIAS]] clause in a [[DECLARE LIBRARY]] statement block tells the program * QB64 does not support optional parameters. -==QBasic/QuickBASIC== -* In Qbasic ALIAS was originally only used in a [[DECLARE (non-BASIC statement)]] library declarations. - - {{PageExamples}} ''Example:'' Instead of creating a SUB with the Library statement inside of it, just rename it: {{CodeStart}} '' '' @@ -43,7 +39,6 @@ MouseMove 1, 1 * [[SUB]], [[FUNCTION]] * [[DECLARE LIBRARY]], [[BYVAL]] * [[DECLARE DYNAMIC LIBRARY]] -* [[DECLARE (non-BASIC statement)]] {{PageNavigation}} diff --git a/internal/help/AS.txt b/internal/help/AS.txt index 9610aeae6..e75c33aeb 100644 --- a/internal/help/AS.txt +++ b/internal/help/AS.txt @@ -1,9 +1,9 @@ -The [[AS]] keyword defines a variable data [[type]]. +The [[AS]] keyword defines a variable data [[Variable Types|type]]. {{PageDescription}} * AS defines the variable or array type AS [[_BIT]], [[_BYTE]], [[INTEGER]], [[LONG]], [[_INTEGER64]], [[SINGLE]], [[DOUBLE]], [[_FLOAT]] or [[STRING]]. -* Specifies a variable's [[type]] in a declarative statement or parameter list using: +* Specifies a variable's [[Variable Types|type]] in a declarative statement or parameter list using: ** [[DIM]] or [[REDIM]] ** [[DECLARE LIBRARY]] ** [[SUB]] @@ -15,7 +15,7 @@ The [[AS]] keyword defines a variable data [[type]]. ===Details=== -* Specifies a '''[[parameter]]''' variable's type in a [[SUB]] or [[FUNCTION]] procedure. '''Cannot be used to define a function's [[type]]''' +* Specifies a '''[[parameter]]''' variable's type in a [[SUB]] or [[FUNCTION]] procedure. '''Cannot be used to define a function's [[Variable Types|type]]''' * Specifies an element's type in a user-defined data [[TYPE]]. * Assigns a file number to a file or device in an [[OPEN]] statement. * Specifies a field name in a random-access record (see [[FIELD]]) diff --git a/internal/help/CALL.txt b/internal/help/CALL.txt index 479aa420f..55c859ff6 100644 --- a/internal/help/CALL.txt +++ b/internal/help/CALL.txt @@ -14,12 +14,6 @@ * To pass parameters by value, instead of by reference, enclose passed variables in parenthesis. -==QBasic/QuickBASIC== -* PDS or Quickbasic 7 up could use [[BYVAL]] to pass variables by values instead of reference. -* QuickBASIC 4.5 could use [[BYVAL]] only for procedures created in Assembly or another language. -* QBasic required [[CALL ABSOLUTE]] only. It did not have to be DECLAREd. - - {{PageExamples}} ''Example:'' How parameters are passed in two [[SUB]] calls, one with CALL using brackets and one without CALL or brackets: {{CodeStart}} '' '' @@ -58,7 +52,6 @@ Hello World! {{PageSeeAlso}} * [[SUB]], [[FUNCTION]] -* DECLARE, [[DECLARE (non-BASIC statement)]] {{PageNavigation}} diff --git a/internal/help/CALL_ABSOLUTE.txt b/internal/help/CALL_ABSOLUTE.txt index ecb2016bb..b4bcbb596 100644 --- a/internal/help/CALL_ABSOLUTE.txt +++ b/internal/help/CALL_ABSOLUTE.txt @@ -13,13 +13,12 @@ * [[CALL]] and parameter brackets are required in the statement. * {{Parameter|argumentList}} contains the list of arguments passed to the procedure. * {{Parameter|integerOffset}} contains the offset from the current code segment, set by [[DEF SEG]] and [[SADD]], to the starting location of the called procedure. -* QBasic and '''QB64''' have the ABSOLUTE statement built in and require no library, like QuickBASIC did. +* '''QB64''' has the ABSOLUTE statement built in and requires no external library, like QuickBASIC did. * '''NOTE: QB64 does not support INT 33h mouse functions above 3 or [[BYVAL]] in an ABSOLUTE statement. Registers are emulated.''' {{PageSeeAlso}} * [[SADD]], [[INTERRUPT]] -* [[DECLARE (non-BASIC statement)]] * [[_MOUSEINPUT]] diff --git a/internal/help/CHAIN.txt b/internal/help/CHAIN.txt index bd69fea8a..a2b93ce2c 100644 --- a/internal/help/CHAIN.txt +++ b/internal/help/CHAIN.txt @@ -17,16 +17,12 @@ * In Windows, '''QB64''' will automatically compile a CHAIN referenced BAS file if there is no EXE file found. * CHAIN looks for a file extension that is the same as the invoking module's extension. * The module's filename extension is not required. To save editing at compile time just omit the extensions in the calls. -* To pass data from one module to the other use [[COMMON SHARED]]. The COMMON list should match [[type]]s and names. +* To pass data from one module to the other use [[COMMON SHARED]]. The COMMON list should match [[Variable Types|type]]s and names. * '''QB64 does not retain the [[SCREEN]] mode like QBasic did.''' * Variable data can be passed in files instead of using [[COMMON SHARED]] values. '''QB64''' uses files to pass [[COMMON]] lists. * [[Keywords_currently_not_supported_by_QB64#Keywords_Not_Supported_in_Linux_or_MAC_OSX_versions|Not available in Linux or macOS]]'''. -''QBasic/QuickBASIC:'' -* Compiled EXE files had to include BRUN45.EXE in QuickBASIC 4.5 when CHAIN was used with [[COMMON SHARED]]. - - {{PageExamples}} ''Example:'' CHAIN looks for same file type extension as program module (BAS or EXE). {{CodeStart}} '' '' @@ -40,7 +36,6 @@ * [[RUN]] * [[COMMON]], [[COMMON SHARED]] * [[SHARED]] -* [[LINKed or Merged Modules]] {{PageNavigation}} diff --git a/internal/help/Cavemen.txt b/internal/help/Cavemen.txt new file mode 100644 index 000000000..2bb901d03 --- /dev/null +++ b/internal/help/Cavemen.txt @@ -0,0 +1,15 @@ +'''Cavemen''' lived thousands of years ago in caves or primitive shelters. + + +* Using simple technology, such as clubs, they acquired food and women. +* They often used short utterances called grunts and snarls. +* In 7,000 BC they came up with the word [[LET]]. Linguists believe that this word was used in sentences such as "Let GRRRR!" or "Let MEEE!". Since then, the word LET has featured prominently in the design of the BASIC programming language. +* Why are you here? Did you look up '''LET'''? Too bad! Tell your teacher to actually teach you something! + + +''See also:'' +* [[LET]] there be light! +* [[LET|Allow me to go back]] + + +{{PageNavigation}} diff --git a/internal/help/Converting_Bytes_to_Bits.txt b/internal/help/Converting_Bytes_to_Bits.txt new file mode 100644 index 000000000..d8f815b69 --- /dev/null +++ b/internal/help/Converting_Bytes_to_Bits.txt @@ -0,0 +1,68 @@ +Although QB64 has [[_BYTE]] and [[_BIT]] variable types, there may be times that you just want to know which bits are on of off in the byte value or convert the value to a [[Binary]] number. + + +Bits are numbered from 0 to 7 and normally are read from the most significant bit(MSB = 7) to the least significant bit(LSB = 0). + + +: The following example shows how to convert an [[_UNSIGNED]] [[_BYTE]] or [[INTEGER]] value(0 to 255) to a [[Binary]] [[STRING]] number in Qbasic. +{{CodeStart}} '' '' +{{Cl|DIM}} byte as {{Cl|_UNSIGNED}} {{Cl|_BYTE}} + +byte = 222 + +{{Cl|FOR...NEXT|FOR}} bit = 7 to 0 {{Cl|STEP}} -1 + {{Cl|IF...THEN|IF}} byte {{Cl|AND (boolean)|AND}} 2 ^ bit {{Cl|THEN}} {{Cl|PRINT}} "1"; {{Cl|ELSE}} {{Cl|PRINT}} "0"; +{{Cl|NEXT}} '' '' +{{CodeEnd}} +: ''Notes:'' The above code can be adapted to place a value into a bit [[Arrays|Array]] for up to 8 flag values in a single Byte. + + +: How upper and lower [[_BYTE|byte]] bits are read from an [[INTEGER]] value using whole decimal or [[HEX$|hexadecimal]] values. +{{CodeStart}} '' '' +{{Cl|SCREEN}} 12 + +{{Cl|COLOR}} 11: {{Cl|LOCATE}} 10, 2: {{Cl|PRINT}} " AH (High Register Byte Bits) AL (Low Register Byte Bits)" +{{Cl|COLOR}} 14: {{Cl|LOCATE}} 11, 2: {{Cl|PRINT}} " 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0" +{{Cl|COLOR}} 13: {{Cl|LOCATE}} 14, 2: {{Cl|PRINT}} " {{Cl|&H}}8000 4000 2000 1000 800 400 200 100 80 40 20 10 8 4 2 {{Cl|&H}}1" +{{Cl|COLOR}} 11: {{Cl|LOCATE}} 15, 2: {{Cl|PRINT}} "-32768 16384 8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1" +{{Cl|FOR...NEXT|FOR}} i = 1 {{Cl|TO}} 16 + {{Cl|CIRCLE}} (640 - (37 * i), 189), 8, 9 'place bit circles +{{Cl|NEXT}} +{{Cl|LINE}} (324, 160)-(326, 207), 11, BF 'line splits bytes +DO + {{Cl|IF...THEN|IF}} Num {{Cl|THEN}} + {{Cl|FOR...NEXT|FOR}} i = 15 {{Cl|TO}} 0 {{Cl|STEP}} -1 + {{Cl|IF...THEN|IF}} (Num {{Cl|AND (boolean)|AND}} 2 ^ i) {{Cl|THEN}} + {{Cl|PAINT}} (640 - (37 * (i + 1)), 189), 12, 9 + Bin$ = Bin$ + "1" + {{Cl|ELSE}}: {{Cl|PAINT}} (640 - (37 * (i + 1)), 189), 0, 9 + Bin$ = Bin$ + "0" + {{Cl|END IF}} + {{Cl|NEXT}} + {{Cl|COLOR}} 10: {{Cl|LOCATE}} 16, 50: {{Cl|PRINT}} "Binary ="; {{Cl|VAL}}(Bin$) + {{Cl|COLOR}} 9: {{Cl|LOCATE}} 16, 10: {{Cl|PRINT}} "Decimal ="; Num;: {{Cl|COLOR}} 13: {{Cl|PRINT}} " Hex = "; Hexa$ + Hexa$ = "": Bin$ = "" + {{Cl|END IF}} + {{Cl|COLOR}} 14: {{Cl|LOCATE}} 17, 15: {{Cl|INPUT}} "Enter a decimal or HEX({{Cl|&H}}) value (0 Quits): ", frst$ + first = {{Cl|VAL}}(frst$) + {{Cl|LOCATE}} 17, 15: {{Cl|PRINT}} {{Cl|SPACE$}}(55) + {{Cl|IF...THEN|IF}} first {{Cl|THEN}} + {{Cl|COLOR}} 13: {{Cl|LOCATE}} 17, 15: {{Cl|INPUT}} "Enter a second value: ", secnd$ + second = {{Cl|VAL}}(secnd$) + {{Cl|LOCATE}} 16, 10: {{Cl|PRINT}} {{Cl|SPACE$}}(69) + {{Cl|END IF}} + Num = first + second + Hexa$ = "{{Cl|&H}}" + {{Cl|HEX$}}(Num) +{{Cl|LOOP}} {{Cl|UNTIL}} first = 0 {{Cl|OR (boolean)|OR}} Num > 32767 {{Cl|OR (boolean)|OR}} Num < -32768 {{Cl|OR (boolean)|OR}} (Num < -1 {{Cl|AND (boolean)|AND}} Num > -32768 '' '' +{{Cl|END}} +{{CodeEnd}}{{small|Code by Ted Weissgerber}} + + +''See also:'' +* [[Binary]] +* [[_SHL]], [[_SHR]] +* [[_BIT]], [[&B]] +* [[_BYTE]] + + +{{PageNavigation}} diff --git a/internal/help/Creating_Icon_Bitmaps.txt b/internal/help/Creating_Icon_Bitmaps.txt new file mode 100644 index 000000000..bf3556826 --- /dev/null +++ b/internal/help/Creating_Icon_Bitmaps.txt @@ -0,0 +1,475 @@ +==Icon Viewer and Bitmap Creator== +The following program can be used to view Icon or Cursor images and save them as Bitmaps. When you answer Y the bitmap is saved with a black background so that it can be PUT using [[XOR]] on to the [[AND]] image. The AND image will be black and white if the image is irregularly shaped(not a full box image). It is placed first using [[PUT (graphics statement)|PUT]] with the AND action or can be placed using [[_PUTIMAGE]] with the color white [[_ALPHA]] being set to 0. In that case, try just placing the XOR image with the color black 0 [[_ALPHA|alpha]] with [[_SETALPHA]]. + +{{small|Code by Ted Weissgerber}} +{{TextStart}} +'' '' +'********************************* IconType.BI INCLUDE FILE ******************************** + +{{Cb|TYPE}} IconType 'Icon or cursor file header + Reserved {{Cb|AS}} {{Cb|INTEGER}} 'Reserved (always 0) + ID {{Cb|AS}} {{Cb|INTEGER}} 'Resource ID (Icon = 1, Cursor = 2) + Count {{Cb|AS}} {{Cb|INTEGER}} 'Number of icon bitmaps in Directory of icon entries array +{{Cb|END}} {{Cb|TYPE}} '6 bytes + +{{Cb|TYPE}} ICONENTRY 'or unanimated Cursor entry (see ANI for animated cursors) + PWidth {{Cb|AS}} {{Cb|_BYTE}} 'Width of icon in pixels (USE THIS) + PDepth {{Cb|AS}} {{Cb|_BYTE}} 'Height of icon in pixels (USE THIS) + NumColors {{Cb|AS}} {{Cb|_BYTE}} 'Maximum number of colors: (2 or 16 colors. 256 or 24/32 bit = 0} + RES2 {{Cb|AS}} {{Cb|_BYTE}} 'Reserved. Not used (always 0) + HotSpotX {{Cb|AS}} {{Cb|INTEGER}} 'Icon: NumberPlanes(normally 0), Cursor: hotspot pixels from left + HotSpotY {{Cb|AS}} {{Cb|INTEGER}} 'Icon: BitsPerPixel(normally 0), Cursor: hotspot pixels from top + DataSize {{Cb|AS}} {{Cb|LONG}} 'Length of icon bitmap in bytes (USE THIS) + DataOffset {{Cb|AS}} {{Cb|LONG}} 'Offset byte position of icon bitmap data header in file(add 1) +{{Cb|END}} {{Cb|TYPE}} '16 bytes + +{{Cb|TYPE}} ICONHEADER 'Bitmap type header found using entry DataOffset + 1 + IconHSize {{Cb|AS}} {{Cb|LONG}} 'size of ICON header (always 40 bytes) + ICONWidth {{Cb|AS}} {{Cb|LONG}} 'bitmap width in pixels. (width and double height may be missing) + ICONDepth {{Cb|AS}} {{Cb|LONG}} 'Total map height in pixels (TWO TIMES the image height). + NumPlanes {{Cb|AS}} {{Cb|INTEGER}} 'number of color planes. Must be set to 1. + BPP {{Cb|AS}} {{Cb|INTEGER}} 'bits per pixel 1, 4, 8, 16, 24 or 32.(USE THIS for BPP) + Compress {{Cb|AS}} {{Cb|LONG}} 'compression method should always be 0. + RAWSize {{Cb|AS}} {{Cb|LONG}} 'size of the raw ICON image data(may only be {{Cb|XOR}} mask size). + Hres {{Cb|AS}} {{Cb|LONG}} 'horizontal resolution of the image(not normally used) + Vres {{Cb|AS}} {{Cb|LONG}} 'vertical resolution of the image(not normally used) + NumColors {{Cb|AS}} {{Cb|LONG}} 'number of colors in the color palette(not normally used) + SigColors {{Cb|AS}} {{Cb|LONG}} 'number of important colors used(not normally used) +{{Cb|END}} {{Cb|TYPE}} '40 byte +'' '' +{{TextEnd}} +{{CodeStart}} +'' '' +{{Cl|REM}} {{Cl|$INCLUDE}}: 'IconType.BI' +{{Cl|DEFINT}} A-Z +{{Cl|DIM}} Icon {{Cl|AS}} IconType +{{Cl|DIM}} {{Cl|SHARED}} Item, BPP +{{Cl|DIM}} {{Cl|SHARED}} wide&, deep&, bmp&, bmpStretch& +{{Cl|DIM}} Image(26000) +dst& = {{Cl|_NEWIMAGE}}(800, 600, 32) +{{Cl|SCREEN (statement)|SCREEN}} dst& + +hdr$ = " & File ID = # ## Image(s) in file #######, bytes " +ico$ = " Size = ## X ## Colors = ## Planes = # BPP = ## " +cur$ = " Size = ## X ## Colors = ## HotSpot X = ## Y = ## " +dat$ = " DATA Size = #####, bytes {{Cl|DATA}} Offset = ######, " +bm1$ = " HeaderSize = ## MaskArea = ## X ## Planes = # BPP = ## " +bm2$ = " Compression = # RAW Data Size = ######, bytes " + +{{Cl|LOCATE}} 20, 20: {{Cl|LINE INPUT}} "Enter an ICOn or CURsor file name: ", IconName$ +L = {{Cl|LEN}}(IconName$) +{{Cl|IF}} L = 0 {{Cl|THEN}} {{Cl|SOUND}} 400, 4: {{Cl|SYSTEM}} +dot = {{Cl|INSTR}}(IconName$, ".") +{{Cl|IF}} dot = 0 {{Cl|THEN}} + Save$ = IconName$: IconName$ = IconName$ + ".ICO" +{{Cl|ELSE}} Save$ = {{Cl|LEFT$}}(IconName$, dot - 1) +{{Cl|END IF}} +{{Cl|OPEN}} IconName$ {{Cl|FOR (file statement)|FOR}} {{Cl|BINARY}} {{Cl|AS}} #1 +length& = {{Cl|LOF}}(1) +{{Cl|PRINT}} +{{Cl|IF}} length& {{Cl|THEN}} + {{Cl|GET}} #1, 1, Icon + {{Cl|SELECT CASE}} Icon.ID + {{Cl|CASE}} 1: IC$ = "Icon": ent$ = ico$ + {{Cl|CASE}} 2: IC$ = "Cursor": ent$ = cur$ + {{Cl|CASE ELSE}}: IC$ = "Bitmap?" + {{Cl|END SELECT}} + {{Cl|LOCATE}} 22, 20: {{Cl|PRINT USING}} hdr$; IC$; Icon.ID; Icon.Count; length& + {{Cl|IF}} Icon.Count {{Cl|THEN}} + count = Icon.Count + {{Cl|DIM}} {{Cl|SHARED}} Entry(count) {{Cl|AS}} ICONENTRY + {{Cl|DIM}} {{Cl|SHARED}} Header(count) {{Cl|AS}} ICONHEADER + {{Cl|FOR...NEXT|FOR}} Item = 1 {{Cl|TO}} count '16 bytes each entry + {{Cl|GET}} #1, , Entry(Item) + {{Cl|NEXT}} + {{Cl|VIEW PRINT}} 24 {{Cl|TO}} 32 + {{Cl|FOR...NEXT|FOR}} Item = 1 {{Cl|TO}} count + {{Cl|GET}} #1, Entry(Item).DataOffset + 1, Header(Item) 'ADD 1 to offsets! + {{Cl|COLOR}} {{Cl|_RGB}}(255, 255, 0): {{Cl|LOCATE}} 24, 30 + {{Cl|IF}} count > 1 {{Cl|THEN}} {{Cl|PRINT}} " IMAGE ENTRY #"; Item {{Cl|ELSE}} {{Cl|PRINT}} " IMAGE ENTRY" + {{Cl|COLOR}} {{Cl|_RGB}}(50, 200, 255) + {{Cl|PRINT USING}} ent$; Entry(Item).PWidth; Entry(Item).PDepth; Entry(Item).NumColors; Entry(Item).HotSpotX; Entry(Item).HotSpotY + {{Cl|PRINT USING}} dat$; Entry(Item).DataSize; Entry(Item).DataOffset + {{Cl|PRINT USING}} bm1$; Header(Item).IconHSize; Header(Item).ICONWidth; Header(Item).ICONDepth, Header(Item).NumPlanes; Header(Item).BPP + {{Cl|PRINT USING}} bm2$; Header(Item).Compress; Header(Item).RAWSize + {{Cl|PRINT}} + k$ = {{Cl|INPUT$}}(1) 'Palette(4 or 8BPP) and/or {{Cl|XOR (boolean)|XOR}} mask starts immediately after an ICONHEADER + wide& = Entry(Item).PWidth: deep& = Entry(Item).PDepth: BPP = Header(Item).BPP + {{Cl|IF}} BPP > 8 {{Cl|THEN}} BitColor = 32 {{Cl|ELSE}} BitColor = 256 'assign for proper colors + bmpStretch& = {{Cl|_NEWIMAGE}}(4 * wide&, 4 * deep&, BitColor) 'set either 256 or 32 + bmp& = {{Cl|_NEWIMAGE}}(wide&, deep&, BitColor) 'don't bother with {{Cl|_FREEIMAGE}}, reuse them! + {{Cl|SELECT CASE}} BPP + {{Cl|CASE}} 1: OneBit + {{Cl|CASE}} 4: FourBIT + {{Cl|CASE}} 8: EightBIT + {{Cl|CASE}} {{Cl|IS}} > 8: True{{Cl|COLOR}} + {{Cl|END SELECT}} + {{Cl|IF}} BPP < 24 {{Cl|THEN}} {{Cl|_COPYPALETTE}} bmp&, bmpStretch& + {{Cl|_PUTIMAGE}} , bmp&, bmpStretch& + {{Cl|_DEST}} 0: {{Cl|_PUTIMAGE}} (100, 0), bmpStretch& + {{Cl|SOUND}} 600, 3 + {{Cl|COLOR}} {{Cl|_RGB}}(255, 0, 255): {{Cl|LOCATE}} {{Cl|CSRLIN}}, 30: {{Cl|PRINT}} "Save as Bitmap? (Y/N)"; + k$ = {{Cl|INPUT$}}(1) + k$ = {{Cl|UCASE$}}(k$) + {{Cl|PRINT}} k$ + {{Cl|SPACE$}}(1); + {{Cl|IF}} k$ = "Y" {{Cl|THEN}} + SaveFile$ = Save$ + {{Cl|LTRIM$}}({{Cl|STR$}}(Item)) + ".BMP" + ThirtyTwoBit 0, 0, wide& - 1, deep& - 1, bmp&, SaveFile$ + {{Cl|END IF}} + {{Cl|IF}} k$ = "Y" {{Cl|THEN}} {{Cl|PRINT}} "Saved!" {{Cl|ELSE}} {{Cl|PRINT}} "Not saved" + {{Cl|AND (boolean)|AND}}Mask + {{Cl|IF}} BPP < 24 {{Cl|THEN}} {{Cl|_COPYPALETTE}} bmp&, bmpStretch& + {{Cl|_PUTIMAGE}} , bmp&, bmpStretch& + {{Cl|_DEST}} 0: {{Cl|_PUTIMAGE}} (400, 0), bmpStretch& + {{Cl|IF}} k$ = "Y" {{Cl|THEN}} + ANDFile$ = Save$ + {{Cl|LTRIM$}}({{Cl|STR$}}(Item)) + "BG.BMP" + ThirtyTwoBit 0, 0, wide& - 1, deep& - 1, bmp&, ANDFile$ + {{Cl|END IF}} + k$ = {{Cl|INPUT$}}(1) + {{Cl|CLS}} + {{Cl|NEXT}} + {{Cl|VIEW PRINT}} + {{Cl|ELSE}} {{Cl|SOUND}} 400, 4: {{Cl|CLOSE}} #1: {{Cl|PRINT}} "No images entries found!": {{Cl|END}} + {{Cl|END IF}} +{{Cl|ELSE}}: {{Cl|CLOSE}} #1: {{Cl|SOUND}} 400, 4: {{Cl|KILL}} IconName$: {{Cl|END}} +{{Cl|END IF}} +{{Cl|CLOSE}} #1 +{{Cl|END}} + +{{Cl|SUB}} OneBit 'adapted from TheBob's Winbit 'B & W monochrome images ONLY (NO {{Cl|PALETTE}} data) +BitsOver = wide& {{Cl|MOD}} 32 +{{Cl|IF}} BitsOver {{Cl|THEN}} ZeroPAD$ = {{Cl|SPACE$}}((32 - BitsOver) \ 8) +{{Cl|_DEST}} bmp& +y = deep& - 1: p$ = " " +{{Cl|DO}} + x = 0 + {{Cl|DO}} + {{Cl|GET}} #1, , p$ + Byte{{Cl|VAL}} = {{Cl|ASC}}(p$) + {{Cl|FOR...NEXT|FOR}} Bit% = 7 {{Cl|TO}} 0 {{Cl|STEP}} -1 'read bits left to right + {{Cl|IF}} Byte{{Cl|VAL}} {{Cl|AND}} 2 ^ Bit% {{Cl|THEN}} {{Cl|PSET}} (x, y), 15 {{Cl|ELSE}} {{Cl|PSET}} (x, y), 0 + x = x + 1 + {{Cl|NEXT}} Bit% + {{Cl|LOOP}} {{Cl|WHILE}} x < wide& + {{Cl|GET}} #1, , ZeroPAD$ ' 'prevents odd width image skewing + y = y - 1 ' +{{Cl|LOOP}} {{Cl|UNTIL}} y = -1 +{{Cl|END SUB}} + +{{Cl|SUB}} EightBIT 'adapted from TheBob's Winbit '256 palette data Colors (8 BPP) +{{Cl|IF}} wide& {{Cl|MOD}} 4 {{Cl|THEN}} ZeroPAD$ = {{Cl|SPACE$}}(4 - (wide& {{Cl|MOD}} 4)) +{{Cl|_DEST}} bmp& +a$ = " ": u$ = " " +{{Cl|OUT}} {{Cl|&H}}3C8, 0 +{{Cl|FOR...NEXT|FOR}} Colr = 0 {{Cl|TO}} 255 + {{Cl|GET}} #1, , a$: Blu = {{Cl|ASC}}(a$) \ 4 + {{Cl|GET}} #1, , a$: Grn = {{Cl|ASC}}(a$) \ 4 + {{Cl|GET}} #1, , a$: Red = {{Cl|ASC}}(a$) \ 4 + {{Cl|OUT}} {{Cl|&H}}3C9, Red + {{Cl|OUT}} {{Cl|&H}}3C9, Grn + {{Cl|OUT}} {{Cl|&H}}3C9, Blu + {{Cl|GET}} #1, , u$ '--- unused byte +{{Cl|NEXT}} Colr +y = deep& - 1: p$ = " " +{{Cl|DO}}: x = 0 + {{Cl|DO}} + {{Cl|GET}} #1, , p$ + {{Cl|PSET}} (x, y), {{Cl|ASC}}(p$) + x = x + 1 + {{Cl|LOOP}} {{Cl|WHILE}} x < wide& + {{Cl|GET}} #1, , ZeroPAD$ ' 'prevents odd width image skewing + y = y - 1 +{{Cl|LOOP}} {{Cl|UNTIL}} y = -1 +{{Cl|END SUB}} + +{{Cl|SUB}} FourBIT 'adapted from TheBob's Winbit '16 palette data colors (4 BPP = 8 or 16 color) +{{Cl|_DEST}} bmp& +{{Cl|IF}} wide& {{Cl|MOD}} 8 {{Cl|THEN}} ZeroPAD$ = {{Cl|SPACE$}}((8 - wide& {{Cl|MOD}} 8) \ 2) 'prevents odd width image skewing +a$ = " ": u$ = " " +{{Cl|FOR...NEXT|FOR}} Colr = 0 {{Cl|TO}} 15 + {{Cl|OUT}} {{Cl|&H}}3C8, Colr + {{Cl|GET}} #1, , a$: Blu = {{Cl|ASC}}(a$) \ 4 + {{Cl|GET}} #1, , a$: Grn = {{Cl|ASC}}(a$) \ 4 + {{Cl|GET}} #1, , a$: Red = {{Cl|ASC}}(a$) \ 4 + {{Cl|OUT}} {{Cl|&H}}3C9, Red + {{Cl|OUT}} {{Cl|&H}}3C9, Grn + {{Cl|OUT}} {{Cl|&H}}3C9, Blu + {{Cl|GET}} #1, , u$ '--- unused byte +{{Cl|NEXT}} Colr +y = deep& - 1: p$ = " " +{{Cl|DO}} + x = 0 + {{Cl|DO}} + {{Cl|GET}} #1, , p$ + HiNIBBLE = {{Cl|ASC}}(p$) \ {{Cl|&H}}10 + LoNIBBLE = {{Cl|ASC}}(p$) {{Cl|AND (boolean)|AND}} {{Cl|&H}}F + {{Cl|PSET}} (x, y), HiNIBBLE + x = x + 1 + {{Cl|PSET}} (x, y), LoNIBBLE + x = x + 1 + {{Cl|LOOP}} {{Cl|WHILE}} x < wide& + {{Cl|GET}} #1, , ZeroPAD$ ' 'prevents odd width image skewing + y = y - 1 +{{Cl|LOOP}} {{Cl|UNTIL}} y = -1 +{{Cl|END SUB}} + +{{Cl|SUB}} ANDMask ' '{{Cl|AND (boolean)|AND}} MASK is B & W. Black area holds {{Cl|XOR (boolean)|XOR}} colors, white displays background +BitsOver = wide& {{Cl|MOD}} 32 +{{Cl|IF}} BitsOver {{Cl|THEN}} ZeroPAD$ = {{Cl|SPACE$}}((32 - BitsOver) \ 8) 'look for sizes not multiples of 32 bits +{{Cl|_DEST}} bmp& +{{Cl|IF}} BPP < 24 {{Cl|THEN}} {{Cl|PALETTE}} ' 'remove for a PUT using previous {{Cl|XOR (boolean)|XOR}} mask palette data +y = deep& - 1: a$ = " ": p$ = " " +{{Cl|DO}} + x = 0 + {{Cl|DO}} + {{Cl|GET}} #1, , a$ + Byte{{Cl|VAL}} = {{Cl|ASC}}(a$) 'MSBit is left when calculating 16 X 16 cursor map 2 byte integer + {{Cl|FOR...NEXT|FOR}} Bit% = 7 {{Cl|TO}} 0 {{Cl|STEP}} -1 'values despite M$ documentation that says otherwise! + {{Cl|IF}} Byte{{Cl|VAL}} {{Cl|AND}} 2 ^ Bit% {{Cl|THEN}} '{{Cl|LONG}} values cannot be used in a cursor file! + {{Cl|IF}} BPP > 8 {{Cl|THEN}} {{Cl|PSET}} (x, y), {{Cl|_RGB32}}(255, 255, 255) {{Cl|ELSE}} {{Cl|PSET}} (x, y), 15 + {{Cl|ELSE}}: {{Cl|IF}} BPP > 8 {{Cl|THEN}} {{Cl|PSET}} (x, y), {{Cl|_RGB32}}(0, 0, 0) {{Cl|ELSE}} {{Cl|PSET}} (x, y), 0 + {{Cl|END IF}} + x = x + 1 '16 X 16 = 32 bytes, 32 X 32 = 128 bytes {{Cl|AND (boolean)|AND}} MASK SIZES + {{Cl|NEXT}} Bit% '48 X 48 = 288 bytes, 64 X 64 = 512 bytes, 128 X 128 = 2048 bytes + {{Cl|LOOP}} {{Cl|WHILE}} x < wide& + {{Cl|GET}} #1, , ZeroPAD$ '16 X 16 and 48 X 48 = 2 byte end padder per row in the {{Cl|AND (boolean)|AND}} MASK + y = y - 1 'adds 32 and 96 bytes respectively to the raw data size! +{{Cl|LOOP}} {{Cl|UNTIL}} y = -1 +{{Cl|END SUB}} + +{{Cl|SUB}} True{{Cl|COLOR}} ' ' 16 Million colors. NO {{Cl|PALETTE}}! Colored by pixels (24 or 32 BPP) +{{Cl|_DEST}} bmp& +{{Cl|IF}} ((BMP.PWidth * 3) {{Cl|MOD}} 4) <> 0 {{Cl|THEN}} '3 byte pixels +ZeroPAD$ = {{Cl|SPACE$}}((4 - ((BMP.PWidth * 3) {{Cl|MOD}} 4))) +{{Cl|END IF}} +R$ = " ": G$ = " ": B$ = " " +y = deep& - 1 +{{Cl|DO}} + x = 0 + {{Cl|DO}} + {{Cl|GET}} #1, , B$ '3 bytes set RGB color intensities + {{Cl|GET}} #1, , G$ + {{Cl|GET}} #1, , R$ + red& = {{Cl|ASC}}(R$) + green& = {{Cl|ASC}}(G$) + blue& = {{Cl|ASC}}(B$) + {{Cl|PSET}} (x, y), {{Cl|_RGB}}(red&, green&, blue&) 'returns closest attribute in 4 or 8 bit + x = x + 1 + {{Cl|LOOP}} {{Cl|WHILE}} x < wide& + {{Cl|GET}} #1, , ZeroPAD$ ' 'prevents odd width image skewing + y = y - 1 +{{Cl|LOOP}} {{Cl|UNTIL}} y = -1 +{{Cl|END SUB}} '' '' + +{{Cl|REM}} {{Cl|$INCLUDE}}: '32BitSUB.BM' + +{{CodeEnd}} +{{TextStart}} + +'*********************************** 32BitSUB.BM INCLUDE FILE ******************************* + +{{Cb|SUB}} ThirtyTwoBit (x1%, y1%, x2%, y2%, image&, Filename$) + {{Cb|DIM}} Colors8%(255) + {{Cb|IF}} x1% > x2% {{Cb|THEN}} {{Cb|SWAP}} x1%, x2% + {{Cb|IF}} y1% > y2% {{Cb|THEN}} {{Cb|SWAP}} y1%, y2% + + {{Cb|_SOURCE}} image& + pixelbytes& = {{Cb|_PIXELSIZE}}(image&) + {{Cb|IF}} pixelbytes& = 0 {{Cb|THEN}} {{Cb|BEEP}}: {{Cb|EXIT SUB}} 'no text screens + + FileType$ = "BM" + QB64$ = "QB64" 'free advertiising in reserved bytes + {{Cb|IF}} pixelbytes& = 1 {{Cb|THEN}} OffsetBITS& = 1078 {{Cb|ELSE}} OffsetBITS& = 54 'no palette in 24/32 bit + InfoHEADER& = 40 + PictureWidth& = (x2% - x1%) + 1 ' don't exceed maximum screen resolutions! + PictureDepth& = (y2% - y1%) + 1 + NumPLANES% = 1 + {{Cb|IF}} pixelbytes& = 1 {{Cb|THEN}} BPP% = 8 {{Cb|ELSE}} BPP% = 24 + Compression& = 0 + WidthPELS& = 3780 + DepthPELS& = 3780 + {{Cb|IF}} pixelbytes& = 1 {{Cb|THEN}} NumColors& = 256 '24/32 bit say none + + {{Cb|IF}} (PictureWidth& {{Cb|AND (boolean)|AND}} 3) {{Cb|THEN}} ZeroPAD$ = {{Cb|SPACE$}}(4 - (PictureWidth& {{Cb|AND (boolean)|AND}} 3)) + + ImageSize& = (PictureWidth& + {{Cb|LEN}}(ZeroPAD$)) * PictureDepth& + FileSize& = ImageSIZE& + OffsetBITS& + f = {{Cb|FREEFILE}} + {{Cb|OPEN}} Filename$ {{Cb|FOR (file statement)|FOR}} {{Cb|BINARY}} {{Cb|AS}} #f + + {{Cb|PUT}} #f, , FileType$ + {{Cb|PUT}} #f, , FileSize& + {{Cb|PUT}} #f, , QB64$ + {{Cb|PUT}} #f, , OffsetBITS& + {{Cb|PUT}} #f, , InfoHEADER& + {{Cb|PUT}} #f, , PictureWidth& + {{Cb|PUT}} #f, , PictureDepth& + {{Cb|PUT}} #f, , NumPLANES% + {{Cb|PUT}} #f, , BPP% + {{Cb|PUT}} #f, , Compression& + {{Cb|PUT}} #f, , ImageSize& + {{Cb|PUT}} #f, , WidthPELS& + {{Cb|PUT}} #f, , DepthPELS& + {{Cb|PUT}} #f, , NumColors& + {{Cb|PUT}} #f, , SigColors& '51 offset + + {{Cb|IF}} pixelbytes& = 1 {{Cb|THEN}} '4 or 8 BPP Palettes set for 256 colors + u$ = {{Cb|CHR$}}(0) + {{Cb|FOR...NEXT|FOR}} c& = 0 {{Cb|TO}} 255 'PUT as BGR order colors + cv& = {{Cb|_PALETTECOLOR (function)|_PALLETTECOLOR}}(c&, image&) + Colr$ = {{Cb|CHR$}}({{Cb|_BLUE32}}(cv&)) + {{Cb|PUT}} #f, , Colr$ + Colr$ = {{Cb|CHR$}}({{Cb|_GREEN32}}(cv&)) + {{Cb|PUT}} #f, , Colr$ + Colr$ = {{Cb|CHR$}}({{Cb|_RED32}}(cv&)) + {{Cb|PUT}} #f, , Colr$ + {{Cb|PUT}} #f, , u$ 'Unused byte + {{Cb|NEXT}} + {{Cb|END IF}} + + {{Cb|FOR...NEXT|FOR}} y% = y2% {{Cb|TO}} y1% {{Cb|STEP}} -1 'place bottom up + {{Cb|FOR...NEXT|FOR}} x% = x1% {{Cb|TO}} x2% + c& = {{Cb|POINT}}(x%, y%) + {{Cb|IF}} pixelbytes& = 1 {{Cb|THEN}} + a$ = {{Cb|CHR$}}(c&) + Colors8%({{Cb|ASC}}(a$)) = 1 + {{Cb|ELSE}} : a$ = {{Cb|LEFT$}}({{Cb|MKL$}}(c&), 3) + {{Cb|END IF}} + {{Cb|PUT}} #f, , a$ + {{Cb|NEXT}} + {{Cb|PUT}} #f, , ZeroPAD$ + {{Cb|NEXT}} + + {{Cb|FOR...NEXT|FOR}} n = 0 {{Cb|TO}} 255 + {{Cb|IF}} Colors8%(n) = 1 {{Cb|THEN}} SigColors& = SigColors& + 1 + {{Cb|NEXT}} n + {{Cb|PUT}} #f, 51, SigColors& + {{Cb|CLOSE}} #f +{{Cb|END SUB}} '' '' +'' '' +{{TextEnd}} +{{small|Adapted from code by Bob Seguin}} +<center>'''If full code is not displayed, refresh browser!'''</center> + + +<center>'''NOTE: Black areas of an image may become "see through" unless another color attribute is used and set to black!'''</center> + +: This can be done by changing another color attribute's RGB settings to 0 or almost 0 and creating a mask after using it in solid black areas of a 4 or 8 BPP palette image. This can also be done using [[_PUTIMAGE]] with 32 bit [[_CLEARCOLOR]] settings. + +<center>''See the following page:'' [[Creating Sprite Masks]]</center> + +==Icon to Bitmap Conversion Function== + +The following program uses a conversion function with the [[TYPE]] definitions inside of the function to eliminate an [[$INCLUDE]] library file. +{{CodeStart}} +{{Cl|SCREEN}} {{Cl|_NEWIMAGE}}(640, 480, 256) +{{Cl|_TITLE}} "Icon Converter" +icon$ = "daphne.ico" '<<<<<<<<< change icon file name +bitmap$ = "tempfile.bmp" +indx% = 5 '1 minimum <<<<<<< higher values than count get highest entry image in icon file + +{{Cl|IF...THEN|IF}} Icon2BMP(icon$, bitmap$, indx%) {{Cl|THEN}} + img& = {{Cl|_LOADIMAGE}}(bitmap$) + {{Cl|PRINT}} img& + {{Cl|IF...THEN|IF}} img& < -1 {{Cl|THEN}} ' check that handle value is good before loading + {{Cl|_ICON}} img& ' place image in header + {{Cl|_PUTIMAGE}} (300, 250), img& 'place image on screen + {{Cl|_FREEIMAGE}} img& ' always free unused handles to save memory + '{{Cl|KILL}} bitmap$ ' comment out and/or rename to save the bitmaps + {{Cl|END IF}} +{{Cl|ELSE}} {{Cl|PRINT}} "Could not create bitmap!" +{{Cl|END IF}} +{{Cl|END}} +' ---------------------------------------------------- + +{{Cl|FUNCTION}} Icon2BMP% (filein {{Cl|AS}} {{Cl|STRING}}, fileout {{Cl|AS}} {{Cl|STRING}}, index {{Cl|AS}} {{Cl|INTEGER}}) +{{Cl|TYPE}} ICONTYPE ' Icon or cursor file header + Reserved {{Cl|AS}} {{Cl|INTEGER}} ' Reserved (always 0) + ID {{Cl|AS}} {{Cl|INTEGER}} ' Resource ID (Icon = 1, Cursor = 2) + Count {{Cl|AS}} {{Cl|INTEGER}} ' Number of icon bitmaps in Directory of icon entries array +{{Cl|END}} {{Cl|TYPE}} '6 bytes +{{Cl|TYPE}} ENTRYTYPE ' or unanimated Cursor entry (ANI are animated cursors) + Wide {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_BYTE}} ' Width of icon in pixels (USE THIS) Use {{Cl|_UNSIGNED}} over 127 + High {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_BYTE}} ' Height of icon in pixels (USE THIS) Use {{Cl|_UNSIGNED}} over 127 + NumColors {{Cl|AS}} {{Cl|_BYTE}} ' Maximum number of colors. (2, 8 or 16 colors. 256 or 24/32 bit = 0) + RES2 {{Cl|AS}} {{Cl|_BYTE}} ' Reserved. Not used (always 0) + HotSpotX {{Cl|AS}} {{Cl|INTEGER}} ' Icon: NumberPlanes(normally 0), Cursor: hotspot pixels from left + HotSpotY {{Cl|AS}} {{Cl|INTEGER}} ' Icon: BitsPerPixel(normally 0), Cursor: hotspot pixels from top + DataSize {{Cl|AS}} {{Cl|LONG}} ' Length of image data in bytes minus Icon and Entry headers (USE THIS) + Offset {{Cl|AS}} {{Cl|LONG}} ' Start Offset byte position of icon bitmap header(add 1 if {{Cl|TYPE}} GET) +{{Cl|END}} {{Cl|TYPE}} '16 bytes +{{Cl|TYPE}} PREHEADER ' Bitmap information not in icon BM header + BM {{Cl|AS}} {{Cl|INTEGER}} ' Integer value changed to "BM" by PUT + Size {{Cl|AS}} {{Cl|LONG}} ' Size of the data file({{Cl|LOF}}) + Reser {{Cl|AS}} {{Cl|LONG}}' 2 reserved integers are zero automatically + BOffset {{Cl|AS}} {{Cl|LONG}} ' Start offset of pixel data(next byte) +{{Cl|END}} {{Cl|TYPE}} '14 bytes +{{Cl|TYPE}} BMPHEADER ' Bitmap type header found using entry DataOffset + 1 + IconHSize {{Cl|AS}} {{Cl|LONG}} ' size of ICON header (always 40 bytes) + PWidth {{Cl|AS}} {{Cl|LONG}} ' bitmap width in pixels (signed integer). + PDepth {{Cl|AS}} {{Cl|LONG}} ' Total map height in pixels (signed integer is 2 times image height) + NumPlanes {{Cl|AS}} {{Cl|INTEGER}} ' number of color planes. Must be set to 1. + BPP {{Cl|AS}} {{Cl|INTEGER}} ' bits per pixel 1, 4, 8, 16, 24 or 32.(USE THIS) + Compress {{Cl|AS}} {{Cl|LONG}} ' compression method should always be 0. + RAWSize {{Cl|AS}} {{Cl|LONG}} ' size of the raw ICON image data(may only be {{Cl|XOR (boolean)|XOR}} mask size). + Hres {{Cl|AS}} {{Cl|LONG}} ' horizontal resolution of the image(not normally used) + Vres {{Cl|AS}} {{Cl|LONG}} ' vertical resolution of the image(not normally used) + NumColors {{Cl|AS}} {{Cl|LONG}} ' number of colors in the color palette(not normally used) + SigColors {{Cl|AS}} {{Cl|LONG}} ' number of important colors used(not normally used) +{{Cl|END}} {{Cl|TYPE}} '40 bytes palette and image data immediately follow this header! + +{{Cl|DIM}} ICON {{Cl|AS}} ICONTYPE, ENT {{Cl|AS}} ENTRYTYPE, PRE {{Cl|AS}} PREHEADER, BMP {{Cl|AS}} BMPHEADER + +rf = {{Cl|FREEFILE}} +{{Cl|IF...THEN|IF}} {{Cl|LCASE$}}({{Cl|RIGHT$}}(filein, 4)) = ".ico" {{Cl|THEN}} 'check file extension is ICO only + {{Cl|OPEN}} filein {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|ACCESS}} {{Cl|READ}} {{Cl|AS}} rf +{{Cl|ELSE}} {{Cl|EXIT FUNCTION}} +{{Cl|END IF}} +{{Cl|GET}} rf, , ICON 'GET 6 byte icon header +{{Cl|IF...THEN|IF}} ICON.ID <> 1 {{Cl|OR (boolean)|OR}} ICON.Count = 0 {{Cl|THEN}} {{Cl|CLOSE}} rf: {{Cl|EXIT FUNCTION}} +{{Cl|IF...THEN|IF}} index > 0 {{Cl|AND (boolean)|AND}} index <= ICON.Count {{Cl|THEN}} entry = 16 * (index - 1) {{Cl|ELSE}} entry = 16 * (ICON.Count - 1) +{{Cl|PRINT}} ICON.Count, entry +{{Cl|SEEK}} rf, 1 + 6 + entry 'start of indexed Entry header selected +{{Cl|GET}} rf, , ENT 'GET 16 byte Entry Header set by index request or highest available + +{{Cl|SEEK}} rf, 1 + ENT.Offset 'go to BMP header offset given in Entry header +{{Cl|GET}} rf, , BMP 'GET 40 byte icon bitmap header information +{{Cl|IF...THEN|IF}} BMP.BPP <= 24 {{Cl|THEN}} pixelbytes = BMP.BPP / 8 {{Cl|ELSE}} pixelbytes = 3 +{{Cl|IF...THEN|IF}} BMP.BPP > 1 {{Cl|AND (boolean)|AND}} BMP.BPP <= 8 {{Cl|THEN}} palettebytes = 4 * (2 ^ BMP.BPP) {{Cl|ELSE}} palettebytes = 0 +datasize& = (ENT.Wide * ENT.High * pixelbytes) + palettebytes 'no padder should be necessary +filesize& = datasize& + 14 + 40 ' data and palette + header +bmpoffset& = palettebytes + 54 ' data offset from start of bitmap +BMP.PWidth = ENT.Wide +BMP.PDepth = ENT.High +BMP.RAWSize = datasize& - palettebytes + +PRE.BM = {{Cl|CVI}}("BM") 'integer value changes to "BM" in file +PRE.Size = filesize& +PRE.BOffset = bmpoffset& 'start of data after header and palette if used + +wf = {{Cl|FREEFILE}} +{{Cl|OPEN}} fileout {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|AS}} wf +{{Cl|PUT}} wf, , PRE 'PUT 14 byte bitmap information +{{Cl|PUT}} wf, , BMP 'PUT 40 byte bitmap header information +{{Cl|SEEK}} rf, 1 + ENT.Offset + 40 +dat$ = {{Cl|STRING$}}(datasize&, 0) 'create string variable the length of remaining image data +{{Cl|GET}} rf, , dat$ 'GET remaining palette and only the XOR image data after the indexed header +{{Cl|PUT}} wf, , dat$ 'PUT remaining data into new bitmap file +{{Cl|CLOSE}} rf, wf +Icon2BMP = ICON.Count 'function returns number of images available in icon file +{{Cl|END FUNCTION}} '' '' +{{CodeEnd}} +{{small|Code by Ted Weissgerber}} +: ''Note:'' The index selected or the highest numbered icon image less than the index value is the image displayed. + +==References== + +''See also:'' +* [[Creating Icons from Bitmaps]] +* [[Bitmaps]], [[Icons and Cursors]] +* [[_CLEARCOLOR]] +* [[_ALPHA]], [[_ICON]] +* [[SaveIcon32]] {{text|(create icons from any image)}} + + +{{PageNavigation}} diff --git a/internal/help/DATE$.txt b/internal/help/DATE$.txt index 3a09420d8..64201fe8a 100644 --- a/internal/help/DATE$.txt +++ b/internal/help/DATE$.txt @@ -62,7 +62,7 @@ Today is Wednesday, June 2, 2010 {{PageSeeAlso}} -* [[DATE$ (statement)]], [[TIME$]], [[TIME$ (statement)]] +* [[TIME$]] * [[VAL]], [[STR$]], [[MID$]], [[LEFT$]], [[IF...THEN]] diff --git a/internal/help/DECLARE_DYNAMIC_LIBRARY.txt b/internal/help/DECLARE_DYNAMIC_LIBRARY.txt index bdb2cbfa3..168b5a363 100644 --- a/internal/help/DECLARE_DYNAMIC_LIBRARY.txt +++ b/internal/help/DECLARE_DYNAMIC_LIBRARY.txt @@ -97,7 +97,7 @@ QuickUTF16toUTF32$ = b$ * [[SUB]], [[FUNCTION]] * [[BYVAL]], [[ALIAS]] * [[_OFFSET (function)]], [[_OFFSET]] {{text|(variable type)}} -* [[C Libraries]], [[SDL Libraries]], [[DLL Libraries]], [[Windows Libraries]] +* [[C Libraries]], [[DLL Libraries]], [[Windows Libraries]] * [[Port Access Libraries]] diff --git a/internal/help/DEFDBL.txt b/internal/help/DEFDBL.txt index 8a9808da9..c0cf2143d 100644 --- a/internal/help/DEFDBL.txt +++ b/internal/help/DEFDBL.txt @@ -14,7 +14,7 @@ The [[DEFDBL]] statement defines all variables with names starting with the spec * {{Parameter|letter}} (or {{Parameter|range}}) can be from A-Z or any other range, like '''G-M'''. * You can also use commas for specific undefined variable first letters. * Variables [[DIM]]ensioned as another variable type or that use type suffixes are not affected by [[DEFDBL]]. -* [[DEFDBL]] sets the [[type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). +* [[DEFDBL]] sets the [[Variable Types|type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). * '''Warning: QBasic keyword names cannot be used as numerical variable names with or without the type suffix.''' diff --git a/internal/help/DEFINT.txt b/internal/help/DEFINT.txt index 45b7c6045..3a5ed61d8 100644 --- a/internal/help/DEFINT.txt +++ b/internal/help/DEFINT.txt @@ -14,7 +14,7 @@ The [[DEFINT]] statement defines all variables with names starting with the spec * {{Parameter|letter}} (or {{Parameter|range}}) can be from A-Z or any other range, like '''G-M'''. * You can also use commas for specific undefined variable first letters. * Variables [[DIM]]ensioned as another variable type or that use type suffixes are not affected by [[DEFINT]]. -* [[DEFINT]] sets the [[type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). +* [[DEFINT]] sets the [[Variable Types|type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). * For [[_UNSIGNED]] [[INTEGER]], use [[_DEFINE]] * '''Warning: QBasic keyword names cannot be used as numerical variable names with or without the type suffix.''' diff --git a/internal/help/DEFLNG.txt b/internal/help/DEFLNG.txt index b3bd40ee3..59178d239 100644 --- a/internal/help/DEFLNG.txt +++ b/internal/help/DEFLNG.txt @@ -14,7 +14,7 @@ The [[DEFLNG]] statement defines all variables with names starting with the spec * {{Parameter|letter}} (or {{Parameter|range}}) can be from A-Z or any other range, like '''G-M'''. * You can also use commas for specific undefined variable first letters. * Variables [[DIM]]ensioned as another variable type or that use type suffixes are not affected by [[DEFLNG]]. -* [[DEFLNG]] sets the [[type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). +* [[DEFLNG]] sets the [[Variable Types|type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). * For [[_UNSIGNED]] [[LONG]], use [[_DEFINE]] * '''Warning: QBasic keyword names cannot be used as numerical variable names with or without the type suffix.''' diff --git a/internal/help/DEFSNG.txt b/internal/help/DEFSNG.txt index 75cc91ac1..6a7a51248 100644 --- a/internal/help/DEFSNG.txt +++ b/internal/help/DEFSNG.txt @@ -15,7 +15,7 @@ The [[DEFSNG]] statement defines all variables with names starting with the spec * {{Parameter|letter}} (or {{Parameter|range}}) can be from A-Z or any other range, like '''G-M'''. * You can also use commas for specific undefined variable first letters. * Variables [[DIM]]ensioned as another variable type or that use type suffixes are not affected by [[DEFSNG]]. -* [[DEFSNG]] sets the [[type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). +* [[DEFSNG]] sets the [[Variable Types|type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). * '''Warning: QBasic keyword names cannot be used as numerical variable names with or without the type suffix.''' diff --git a/internal/help/DEFSTR.txt b/internal/help/DEFSTR.txt index 24cbc17fb..03f157aed 100644 --- a/internal/help/DEFSTR.txt +++ b/internal/help/DEFSTR.txt @@ -14,7 +14,7 @@ The [[DEFSTR]] statement defines all variables with names starting with the spec * {{Parameter|letter}} (or {{Parameter|range}}) can be from A-Z or any other range, like '''G-M'''. * You can also use commas for specific undefined variable first letters. * Variables [[DIM]]ensioned as another variable type or that use type suffixes are not affected by [[DEFSTR]]. -* [[DEFSTR]] sets the [[type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). +* [[DEFSTR]] sets the [[Variable Types|type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). * '''Warning: QBasic keyword names can only be used as string variable names when they are followed by the string type suffix ($).''' diff --git a/internal/help/Data_types.txt b/internal/help/Data_types.txt new file mode 100644 index 000000000..3e5721885 --- /dev/null +++ b/internal/help/Data_types.txt @@ -0,0 +1,105 @@ +Any [[Expression|expression]], including [[CONST|constants]] and [[Variable|variables]] all have an associated type to describe their value. QB64 has various built-in data types used to represent number and text values. [[#Numeric types|Numeric types]] represent number values, while [[#String types|string types]] represent text values. + +==Numeric types== +QB64 supports several numeric types, capable of representing a wide range of numbers. There are two kinds of numeric data type: ''integer types'' and ''floating-point types''. + +===Integer types=== +Integer types represent integer (whole number) values, such as 1 and 100. They are divided into two flavors: ''signed'' and ''unsigned''. + +====Signed Integer types==== +Signed integers can represent positive and negative integer (whole number) values, such as 3, 10 and -16. These values are stored as a series of bits in [http://en.wikipedia.org/wiki/Two%27s_complement two's complement form], a common representation that makes them both straightforward and efficient to perform calculations with. + +Signed integers are typically used in simple mathematical equations. + +The range of values that these types can represent is based on their size, in bits; the greater number of bits, the larger positive and lesser negative value the types can represent. + +The signed integer types are: [[_BYTE]], [[INTEGER]], [[LONG]], [[_INTEGER64]] and [[_OFFSET]] + +{{CodeStart}}DIM n AS INTEGER +n = -1 +PRINT n +{{CodeEnd}} +{{OutputStart}}-1 +{{OutputEnd}} + +====Unsigned Integer types==== +Unsigned integers can represent positive integer values only, such as 3, 10 and 16. These values are also stored as a series of bits, but unlike signed integers, all of the bits contribute to their value. Thus, these types can represent larger positive integer values than their signed counterparts. + +Unsigned integers are typically used to represent a simple quantity, like a ''count'' or a ''length''. They are also often used as ''bit masks'', where certain bits that make up the value represent separate information (such as the state of one or more ''flags''). + +Types: [[_UNSIGNED]] [[_BYTE]], [[_UNSIGNED]] [[INTEGER]], [[_UNSIGNED]] [[LONG]], [[_UNSIGNED]] [[_INTEGER64]], [[_UNSIGNED]] [[_OFFSET]] + + +{{CodeStart}}' display the largest value representable by an _UNSIGNED INTEGER: +DIM n AS _UNSIGNED INTEGER +n = -1 +PRINT n +{{CodeEnd}} +{{OutputStart}}65535 +{{OutputEnd}} + + +====_OFFSET Integer types==== + +Offset Integer types can be any byte size integer value that can be used to designate pointer offset positions in memory. DO NOT TRANSFER offset values to other Integer types! + + +===Floating-point types=== +Floating-point types can represent both positive and negative number values, as well as fractional number values, such as 1.2 and -34.56. + +Floating-point types are used in mathematical equations where fractional precision is important, such as trigonometry. + +The floating-point types are: [[SINGLE]], [[DOUBLE]] and [[_FLOAT]]. + + +{{CodeStart}}f! = 76.0 +c! = (5.0 / 9.0) * (f! - 32.0) + +PRINT f! ; "degrees Fahrenheit is" ; c! ; "degrees Celcius." +{{CodeEnd}} +{{OutputStart}} 76 degrees Fahrenheit is 24.44444 degrees Celcius. +{{OutputEnd}} + +==String types== +QB64 has built-in support for strings, which are contiguous sequences of characters represented as <tt>[[_UNSIGNED]] [[_BYTE]]</tt> values. Strings are usually used to store and manipulate text, but can also be used as a general storage area for arbitrary data (like a binary file). + +Strings have a property called ''length'', which is the number of characters currently stored in the string, and QB64 supports two kinds of string types based on this property: ''variable-length strings'' and ''fixed-length strings''. + +===Variable-length strings=== + +Variable length strings are undefined length string variables. Fixed length strings MUST be defined in a program before they are used. Undefined strings can be up to 32767 characters in Qbasic. + + +{{CodeStart}} + message$ = "Hello" + message$ = message$ + " world!" 'add to string variables using string concatenation only! + PRINT message$ +{{CodeEnd}} +{{OutputStart}} + Hello world! +{{OutputEnd}} + +===Fixed-length strings=== + +Fixed length strings must be defined in a {{KW|DIM}} statement, {{KW|SUB}} or {{KW|FUNCTION}} parameter or {{KW|TYPE}} definition. The designated multiple is the maximum number of {{KW|STRING}} character bytes that the variable or {{KW|Arrays|array}} can hold. Excess bytes will not be included. No error is created. + + +{{CodeStart}} + DIM message AS STRING * 5 + message$ = "Hello" + message$ = message$ + " world!" + PRINT message$ +{{CodeEnd}} +{{OutputStart}} + Hello +{{OutputEnd}} + +==Data type limits== +The following table lists the numerical and string data types, their type suffix symbol, and the range of the values they can represent: +{{DataTypeTable}} + + +==References== + + +{{PageNavigation}} diff --git a/internal/help/ERL.txt b/internal/help/ERL.txt index 53b86b290..67d93cdf0 100644 --- a/internal/help/ERL.txt +++ b/internal/help/ERL.txt @@ -36,7 +36,7 @@ errorfix: * [[ERR]] * [[ERROR]] * [[ON ERROR]] -* [[_ERRORLINE]], [[_INCLERRORLINE]], [[_INCLERRORFILE$]] +* [[_ERRORLINE]], [[_INCLERRORLINE]], [[_INCLERRORFILE$]], [[_ERRORMESSAGE$]] * [[ERROR Codes]] diff --git a/internal/help/ERR.txt b/internal/help/ERR.txt index ff49706ba..382510cea 100644 --- a/internal/help/ERR.txt +++ b/internal/help/ERR.txt @@ -36,7 +36,7 @@ handler: {{PageSeeAlso}} * [[ON ERROR]], [[RESUME]] * [[ERL]] -* [[_ERRORLINE]], [[_INCLERRORLINE]], [[_INCLERRORFILE$]] +* [[_ERRORLINE]], [[_INCLERRORLINE]], [[_INCLERRORFILE$]], [[_ERRORMESSAGE$]] * [[ERROR]] * [[ERROR Codes]] diff --git a/internal/help/ERROR.txt b/internal/help/ERROR.txt index 6a9f74728..6747c621b 100644 --- a/internal/help/ERROR.txt +++ b/internal/help/ERROR.txt @@ -34,7 +34,8 @@ handler: {{PageSeeAlso}} *[[ON ERROR]] *[[ERR]], [[ERL]] -*[[_ERRORLINE]] +*[[_ERRORLINE]], [[_ERRORMESSAGE$]] +*[[_INCLERRORLINE]], [[_INCLERRORFILE$]] *[[ERROR Codes]] (list) diff --git a/internal/help/ERROR_Codes.txt b/internal/help/ERROR_Codes.txt index 40ca1e07a..04571cda9 100644 --- a/internal/help/ERROR_Codes.txt +++ b/internal/help/ERROR_Codes.txt @@ -151,6 +151,7 @@ The following table describes the error codes that are reported by the '''QB64'' *[[ERROR]] (simulates error), [[ERR]] ('''QB''' error code number), [[ERL]] (closest line number when line numbers are used) *[[ON ERROR]] (calls error handing routine using [[GOTO]] only), [[_ERRORLINE]] (actual '''QB64''' text code line) +*[[_INCLERRORLINE]], [[_INCLERRORFILE$]], [[_ERRORMESSAGE$]] {{PageNavigation}} diff --git a/internal/help/INPUT_(file_statement).txt b/internal/help/INPUT_(file_statement).txt index eec499846..e85fda66a 100644 --- a/internal/help/INPUT_(file_statement).txt +++ b/internal/help/INPUT_(file_statement).txt @@ -7,13 +7,13 @@ The [[INPUT #]] file or port statement reads sequential data using one variable {{Parameters}} * {{Parameter|fileNumber&}} is a positive [[LONG]] integer value used to [[OPEN]] the file FOR [[INPUT (file mode)|INPUT]] mode. -* The [[type]] of the ''variable'' used defines the value or list of values to be returned from the file. Numeric types must match the values returned. +* The [[Variable Types|type]] of the ''variable'' used defines the value or list of values to be returned from the file. Numeric types must match the values returned. * As reflected in the syntax you can list a number of variables with different types seperated by a comma and they will hold the values in the file (keep in mind that the information in the file should match the variable types used). {{PageDescription}} * The file number can be determined by the programmer or be an unused number returned by the [[FREEFILE]] function. -* Variable types must match the numerical [[type]]s being read. [[STRING]] variables can return unquoted numeric values. +* Variable types must match the numerical [[Variable Types|type]]s being read. [[STRING]] variables can return unquoted numeric values. * Leading or trailing spaces of [[STRING]] values must be inside of quotes. [[WRITE (file statement)|WRITE #]] writes strings inside of quotes automatically. [[PRINT (file statement)|PRINT #]] removes quotes. * [[INPUT #]] will read each value until it encounters a comma for the next value in a list. * Use the [[EOF]] function to avoid reading past the end of a file. diff --git a/internal/help/Icons_and_Cursors.txt b/internal/help/Icons_and_Cursors.txt new file mode 100644 index 000000000..2155b0da0 --- /dev/null +++ b/internal/help/Icons_and_Cursors.txt @@ -0,0 +1,267 @@ +<center>'''Icons''' and '''Cursors''' are image files with ICO or CUR filename extensions.</center> +{| align="right" + | __TOC__ + |} + + +* Both can use 1 BPP(B & W), 4 BPP(16), 8 BPP(256) or 24/32 BPP(16 million) colors. +* They are formatted similar to bitmaps, but each file can hold more than one image. +* Images can be different sizes and use different color palettes. The image width and depth are usually the same and multiples of 16 up to 128. Use [[_UNSIGNED]] [[_BYTE]] values in the Entry header. +* Normal Icon and Cursor sizes are multiples of 16 such as 16 X 16, 32 X 32, 48 X 48 and 64 X 64. +* Each image has an XOR and an AND image mask to allow background transparency in the white pixel areas. Change background areas to white in the [[AND]] mask for irregular shapes. +* The [[XOR]] mask is normally different colors while the [[AND]] mask is 1 BPP where black is translucent(solid) and white transparent. +* The AND image mask is placed on a background using a process like [[PUT (graphics statement)|PUT]] with the AND action by the Operating System. +* Then the [[XOR]] mask is placed on top of the blackened areas to display the image colors. +* The resulting image can allow any background to be seen through the [[AND]] mask parts of the image that are white. + + +==Icon Headers== + +{{TextStart}} +' ******************* ICONCUR.BI +' INCLUDE this BI file at the start of a program +' +{{Cb|TYPE}} ICONTYPE 'Icon or cursor file header + Reserved {{Cb|AS}} {{Cb|INTEGER}} 'Reserved (always 0) + ID {{Cb|AS}} {{Cb|INTEGER}} 'Resource ID (Icon = 1, Cursor = 2) + Count {{Cb|AS}} {{Cb|INTEGER}} 'Number of icon bitmaps in Directory of icon entries array +{{Cb|END}} {{Cb|TYPE}} '6 bytes + +{{Cb|TYPE}} ICONENTRY 'or unanimated Cursor entry (ANI are animated cursors) + PWidth {{Cb|AS}} {{Cb|_UNSIGNED}} {{Cb|_BYTE}} 'Width of icon in pixels (USE THIS) + PDepth {{Cb|AS}} {{Cb|_UNSIGNED}} {{Cb|_BYTE}} 'Height of icon in pixels (USE THIS) + NumColors {{Cb|AS}} {{Cb|_BYTE}} 'Maximum number of colors. (2, 8 or 16 colors. 256 or 24/32 bit = 0) + RES2 {{Cb|AS}} {{Cb|_BYTE}} 'Reserved. Not used (always 0) + HotSpotX {{Cb|AS}} {{Cb|INTEGER}} 'Icon: NumberPlanes(normally 0), Cursor: hotspot pixels from left + HotSpotY {{Cb|AS}} {{Cb|INTEGER}} 'Icon: BitsPerPixel(normally 0), Cursor: hotspot pixels from top + DataSize {{Cb|AS}} {{Cb|LONG}} 'Length of image data in bytes minus Icon and Entry headers (USE THIS) + DataOffset {{Cb|AS}} {{Cb|LONG}} 'Start Offset byte position of icon bitmap header(add 1 if [[TYPE]] GET) +{{Cb|END}} {{Cb|TYPE}} '16 bytes ''' 'BMP header and image data follow ALL entry data(after 22, 38, 54, etc.)''' + +{{Cb|TYPE}} BMPHEADER 'Bitmap type header found using entry DataOffset + 1 + IconHSize {{Cb|AS}} {{Cb|LONG}} 'size of ICON header (always 40 bytes) + ICONWidth {{Cb|AS}} {{Cb|LONG}} 'bitmap width in pixels (signed integer). + ICONDepth {{Cb|AS}} {{Cb|LONG}} 'Total map height in pixels (signed integer is 2 times image height) + NumPlanes {{Cb|AS}} {{Cb|INTEGER}} 'number of color planes. Must be set to 1. + BPP {{Cb|AS}} {{Cb|INTEGER}} 'bits per pixel 1, 4, 8, 16, 24 or 32.(USE THIS) + Compress {{Cb|AS}} {{Cb|LONG}} 'compression method should always be 0. + RAWSize {{Cb|AS}} {{Cb|LONG}} 'size of the raw ICON image data(may only be {{Cb|XOR}} mask size). + Hres {{Cb|AS}} {{Cb|LONG}} 'horizontal resolution of the image(not normally used) + Vres {{Cb|AS}} {{Cb|LONG}} 'vertical resolution of the image(not normally used) + NumColors {{Cb|AS}} {{Cb|LONG}} 'number of colors in the color palette(not normally used) + SigColors {{Cb|AS}} {{Cb|LONG}} 'number of important colors used(not normally used) +{{Cb|END}} {{Cb|TYPE}} '40 bytes ''' 'palette and/or image data immediately follow this header! ''' +{{TextEnd}} +{{CodeStart}} '' '' +{{Cl|DIM}} ICO {{Cl|AS}} ICONTYPE +items% = ICO.Count +{{Cl|DIM}} {{Cl|SHARED}} Entry(items%) {{Cl|AS}} ICONENTRY +{{Cl|DIM}} {{Cl|SHARED}} BMP(items%) {{Cl|AS}} BMPHEADER '' '' +{{CodeEnd}} + + +<center>'''ICON File Header Information'''</center> + +::* The Icon header is only six bytes. The first [[INTEGER]] value is reserved and is always 0. +::* The second [[INTEGER]] indicates the type of file: + +:::* 1 indicates that the file is an ICO Icon file which may hold more than one image. +:::* 2 indicates that the file is a CUR Cursor file which may hold more than one image. + +::* The third [[INTEGER]] value indicates the number of images contained in the file. This will also tell you the number of Icon Entry information headers follow. A [[TYPE]] array can be used to reference the entry and BMP header information later when there is more than one image. The start of all bitmap header and image data information is after 6 + (count * 16) bytes. + +<center>'''ICON Entry Information'''</center> +: The Entry header information for all icon images contained in the icon file follow the icon header. No image data will be found until after all of the Entry information. Each entry contains the dimensions, size of data and the location of the start of image data. + +::* The image width and height are [[_BYTE]] numerical values or [[ASC]] [[ASCII]] code [[STRING]] values. +::* The number of colors is a [[_BYTE]] value which may be zero. Use the Bitmap header's BPP value instead. +::* The reserved [[_BYTE]] value is always zero. +::* The 2 Hotspot [[INTEGER]] values are always 0 unless the file is a CUR cursor file. Cursor files position the click spot. +::* The [[LONG]] Data Size value should indicate the size of the image data including bitmap header, palette and pixel data. +::* The [[LONG]] Data Offset value will indicate the byte position of the image bitmap header. Add one byte in QB and QB64. + +<center>'''Bitmap Header Information'''</center> +: The Bitmap header information is located one byte after the Data Offset position because Qbasic sets the first byte of a file as 1 instead of zero. This bitmap image information is identical to a bitmap image header's last 40 bytes, but the height is doubled. + +::* The [[LONG]] header size is always 40 bytes. This can be used to verify the start position of the header. +::* The [[LONG]] image width should be the same as the Entry header width. +::* The [[LONG]] image height should be '''2 times''' the actual image height as read in the Entry header. +::* The number of planes [[INTEGER]] value should always be 1. +::* The BPP [[INTEGER]] value is always used to find the number of colors, palette size(if any) and pixel byte size. +:::* 1 indicates a black and white(2 ^ 1) color, one bit(on or off) per pixel image with no palette. Each bit on is white. +:::* 4 indicates a 16(2 ^ 4) color, 4 bits(attributes 0 to 15) per pixel image with a 64 byte palette. +:::* 8 indicates a 256(2 ^ 8) color, one byte(attributes 0 to 255) per pixel image with a 1024 byte palette. +:::* 24 or 32 indicates a 16 million(2 ^ 24) color, 3 bytes(BGR intensities 0 to 255) per pixel image with no palette. +::* The [[LONG]] compression value should always be zero. +::* The [[LONG]] Raw data size should indicate the image data size, but it is unreliable. Calculate it when necessary. +::* The four remaining [[LONG]] bitmap header values can be ignored as they will normally be zero. + + + +<p style="text-align: center">([[#toc|Return to Table of Contents]])</p> + +==XOR Image Data== +{{WhiteStart}} + '''Single Image Icon or Cursor''' + + ┌──────┐ ┌─────┐ ┌──────┐ ┌───────┐ ┌───────┐ ┌───────┐ + │ ICON │ │Entry│ │BMP[1]│ │PALETTE│ │ XOR │ │ AND │ + │Header├─6─┤ [1] ├─22─┤Header├─62─┤ 4 BPP ├─126─┤ 4 BPP ├─638─┤ 1 BPP │ + │ 6B │ │16 B │ │ 40 B │ │½ byte │ │32*32*½│ │32*32\8│ + └──────┘ └─────┘ └──────┘ │ 64 B │ │ 512 B │ │ 128 B │ + └───────┘ └───────┘ └───────┘ + + '''Multiple Image (3)''' + + ┌──────┐ ┌───────┐ ┌───────┐ ┌───────┐ + │ ICON │ │ Entry │ │ Entry │ │ Entry │ + │Header├─6─┤ [1] ├─22─┤ [2] ├─38─┤ [3] ├─54─┐ Entry precedes all data + │ 6B │ │ 16 B │ │ 16 B │ │ 16 B │ │ + └──────┘ └───────┘ └───────┘ └───────┘ │ + ┌───◄ GET Offset + 1 = 55◄─────────┘ + ┌───┴───┐ ┌───────┐ ┌───────┐ + │ BMP[1]│ │ BMP[2]│ │ BMP[3]│ + │Header │ ┌─┤Header │ ┌─┤Header │ Image settings + │ 40 B │ │ │ 40 B │ │ │ 40 B │ + └───┬───┘ │ └───┬───┘ │ └───┬───┘ + ┌───┴───┐ ▲ ┌───┴───┐ ▲ │ + │PALETTE│ O │PALETTE│ O │ + │ 4 BPP │ f │ 8 BPP │ f 24 BPP RGB color intensities + │½ byte │ f │1 byte │ f 3 byte + │ 64 B │ s │1024 B │ s │ + └───┬───┘ e └───┬───┘ e │ + ┌───┴───┐ t ┌───┴───┐ t ┌───┴───┐ + │ XOR │ + │ XOR │ + │ XOR │ + │16*16*½│ 1 │32*32*1│ 1 │48*48*3│ Image color data + │ 128 B │ ▲ │1024 B │ ▲ │6912 B │ + └───┬───┘ │ └───┬───┘ │ └───┬───┘ + ┌────┴───┐ │ ┌───┴───┐ │ ┌───┴────┐ + │ AND │ │ │ AND │ │ │ AND │ + │ 1 BPP ├──┘ │ 1 BPP ├──┘ │ 1 BPP │ B & W mask + │16*(2+2)│ │32*32\8│ │48*(6+2)│ + │ 64 B │ │ 128 B │ │ 384 B │ + └────────┘ └───────┘ └────────┘ + + Add one to Offset position when using one TYPE definition GET for the BMP Header data! + BPP = bits per pixel B = bytes +2 = padder bytes +{{WhiteEnd}} + + +<center>'''Palette Data'''</center> + +:The Palette is only used in '''4 BPP''' and '''8 BPP''' Icons or Cursors. It is exactly the same format as a bitmap. The number of available colors determines the size of palette data. The data is read as blue, green, red [[_BYTE|byte]]s with a zero([[CHR$]](0)) spacer so the palette size is 4 times the number of available colors: 4 BPP = 4 * (2 ^ 4) = 64 bytes and 8 BPP = 4 * (2 ^ 8) = 1024 bytes. +: The palette sets the Blue, Green and Red color intensities before each color attribute value is read in the image's pixel data. + + +<center>'''XOR Mask Image Data'''</center> + +:The [[XOR]] mask is found after the Palette in 4 BPP or 8 BPP or immediately after the icon BMP Header if 1 BPP or 24 BPP colors. The XOR data is also read the same as a bitmap. The BPP determines the size of the data as bits per pixel: +:::* 1 BPP is one bit per pixel (on white or off black) or bytes = (width * height) / 8 bits +:::* 4 BPP is four bits per pixel attribute or bytes = (4 * width * height) / 8 bits +:::* 8 BPP is one byte per pixel attribute or bytes = (8 * width * height) /8 bits +:::* 24 BPP is 3 bytes per pixel (blue, green, red) or bytes = (24 * width * height) / 8 bits +: All color settings use 4 byte padding to prevent image skewing although most icons use multiples of 8 pixels and won't need it. +: The color intensity of each 24 bit pixel is read as blue, green and red bytes. See the [[Bitmaps]] page for more information. + + +<p style="text-align: center">([[#toc|Return to Table of Contents]])</p> + +==AND Mask Data== + +:The AND mask is read as a '''one BPP''' black and white image with each [[_BIT]] being on(white) or off(black). It is white where the background may show and black where the colors (including black) from the XOR mask will show. It is placed using the AND action by Windows first. Then the XOR mask is placed on top using an XOR action. The following SUB procedure can adapt to 24 bit colors so that colors will not be affected. Make sure that the BPP value is [[SHARED]] or pass it using a parameter! + +: A [[CHR$|zero]] byte or [[SPACE$|space]] padder is used in the AND mask for image widths that are not multiples of 4 bytes(32 pixels). + +{{CodeStart}} '' '' +{{Cl|SUB}} ANDMask 'MASK is B & W. Black area holds {{Cl|XOR}} colors, white displays background +BitsOver = Entry(i).PWidth& {{Cl|MOD}} 32 +{{Cl|IF}} BitsOver {{Cl|THEN}} ZeroPAD$ = {{Cl|SPACE$}}((32 - BitsOver) \ 8) 'look for sizes not multiples of 32 bits +{{Cl|_DEST}} bmp& 'destination handle if used +y = Entry(i).PDepth - 1: a$ = " ": p$ = " " +{{Cl|DO}} + x = 0 + {{Cl|DO}} + {{Cl|GET}} #1, , a$ 'position is immediately AFTER XOR mask data + ByteVAL = {{Cl|ASC}}(a$) 'MSBit is left when calculating 16 X 16 cursor map 2 byte integer + {{Cl|FOR...NEXT|FOR}} Bit% = 7 {{Cl|TO}} 0 {{Cl|STEP}} -1 'values despite M$ documentation that says otherwise! + {{Cl|IF}} ByteVAL {{Cl|AND}} 2 ^ Bit% {{Cl|THEN}} + {{Cl|PSET}} (x, y), {{Cl|_RGB}}(255, 255, 255) '_RGB can be used in 1, 4, 8 or 24/32 BPP + {{Cl|ELSE}}: {{Cl|PSET}} (x, y), {{Cl|_RGB}}(0, 0, 0) + {{Cl|END IF}} + x = x + 1 '16 X 16 = 32 bytes, 32 X 32 = 128 bytes AND MASK SIZES + {{Cl|NEXT}} Bit% '48 X 48 = 288 bytes, 64 X 64 = 512 bytes, 128 X 128 = 2048 bytes + {{Cl|LOOP}} {{Cl|WHILE}} x < Entry(i).PWidth + {{Cl|GET}} #1, , ZeroPAD$ '16 X 16 and 48 X 48 = 2 byte end padder per row in the AND MASK + y = y - 1 'adds 32 and 96 bytes respectively to the raw data size! +{{Cl|LOOP}} {{Cl|UNTIL}} y = -1 +{{Cl|END}} {{Cl|SUB}} '' '' +{{CodeEnd}} +: ''Note:'' Icon widths that are not multiples of 32, such as 16 or 48, are padded 2 extra zero bytes to bring them to specifications. + +<p style="text-align: center">([[#toc|Return to Table of Contents]])</p> + +==Calculating Data Size== + +: The size of the data is based on the pixel size of the image, any bit padding and the BPP palette intensity data required. + +{{CodeStart}} '' '' +Entry(item%).DataSize = DataSize&(item%) 'example function call + +{{Cl|FUNCTION}} DataSize&(i AS INTEGER) +PixelBytes! = BMP(i)BPP / 8 '1 BPP = 1/8; 4 BPP = 1/2; 8 BPP = 1; 24 BPP = 3 + +{{Cl|SELECT CASE}} BPP + {{Cl|CASE}} 1: PaletteBytes% = 0 + {{Cl|IF}} Entry(i).PWidth {{Cl|MOD}} 32 {{Cl|THEN}} Pad% = (32 - (Entry(i).PWidth {{Cl|MOD}} 32)) \ 8 {{Cl|ELSE}} Pad% = 0 + {{Cl|CASE}} 4: PaletteBytes% = 64 + {{Cl|IF}} Entry(i).PWidth {{Cl|MOD}} 8 {{Cl|THEN}} Pad% = (8 - (Entry(i).PWidth {{Cl|MOD}} 8)) \ 2 {{Cl|ELSE}} Pad% = 0 + {{Cl|CASE}} 8: PaletteBytes% = 1024 + {{Cl|IF}} Entry(i).PWidth {{Cl|MOD}} 4 {{Cl|THEN}} Pad% = 4 - (Entry(i).PWidth {{Cl|MOD}} 4) {{Cl|ELSE}} Pad% = 0 + {{Cl|CASE}} {{Cl|IS}} > 8: PaletteBytes% = 0 + {{Cl|IF}} ((Picture{{Cl|Entry(i).PWidth * 3) {{Cl|MOD}} 4) {{Cl|THEN}} + Pad% = ((4 - ((Entry(i).PWidth * 3) {{Cl|MOD}} 4))) + {{Cl|ELSE}}: Pad% = 0 + {{Cl|END IF}} +{{Cl|END SELECT}} + +XORsize& = ((Entry(i).PWidth + Pad%) * Entry(i).PDepth) * PixelBytes! +{{Cl|IF}} Entry(i).PWidth {{Cl|MOD}} 32 {{Cl|THEN}} ANDpad% = (32 - (Entry(i).PWidth {{Cl|MOD}} 32)) {{Cl|ELSE}} ANDpad% = 0 +ANDsize& = ((Entry(i).PWidth + ANDpad%) * Entry(i).PDepth) \ 8 + +DataSize& = XORsize& + ANDsize& + PaletteBytes% + 40 'header is always 40 bytes +{{Cl|END FUNCTION}} '' '' +{{CodeEnd}} +: ''NOTE:'' A 2 byte padder adds 32 bytes to 16 X 16 and 96 bytes to 48 X 48 AND mask data. 32 and 64 wide have no padders. + + +''Snippet:'' Shows how bit padder is calculated and used to calculate the AND mask data size: +{{TextStart}} '' '' +{{Cb|INPUT}} "Enter an icon width(multiples of 8 or 16 only): ", width + +{{Cb|IF...THEN|IF}} (width {{Cb|MOD}} 32) {{Cb|THEN}} bitpad = (32 - (width {{Cb|MOD}} 32)) +bytes = (width + bitpad) * width \ 8 'dividing by 8 returns the byte size + +{{Cb|PRINT}} "AND mask size:"; bytes; "bytes with a"; bitpad; "bit padder." '' '' +{{TextEnd}} +{{OutputStart}}Enter an icon width(multiples of 8 or 16 only): 16 +AND mask size: 64 bytes with a 16 bit padder. +{{OutputEnd}} + +<p style="text-align: center">([[#toc|Return to Table of Contents]])</p> + +==References== +''Member Examples:'' +* [[Creating Icon Bitmaps]] +* [[Creating Icons from Bitmaps]] +* [[SaveIcon32]] {{text|(create icons from any image)}} + + +''See Also:'' +* [[$EXEICON]] +* [[_ICON]] +* [[Creating Sprite Masks]] +* [[Bitmaps]], [[GIF Images]] +* [[Resource_Table_extraction#Extract_Icon|Icon Extraction]] + + +{{PageNavigation}} diff --git a/internal/help/Keyword_Reference_-_Alphabetical.txt b/internal/help/Keyword_Reference_-_Alphabetical.txt index 77dd2c75b..5f7c22434 100644 --- a/internal/help/Keyword_Reference_-_Alphabetical.txt +++ b/internal/help/Keyword_Reference_-_Alphabetical.txt @@ -143,6 +143,7 @@ __NOTOC__ * [[$ELSEIF]] (Pre-Compiler [[Metacommand]]) {{text|used in conjunction with $IF for the precompiler.}} * [[$END IF]] (Pre-Compiler [[Metacommand]]) {{text|used in conjunction with $IF for the precompiler.}} * [[_ERRORLINE]] (function) {{text|returns the source code line number that caused the most recent runtime error.}} +* [[_ERRORMESSAGE$]] (function) {{text|returns a human-readable message describing the most recent runtime error.}} * [[$EXEICON]] (Pre-Compiler [[Metacommand]]) {{text|used with a .ICO icon file name to embed the image into the QB64 executable.}} * [[_EXIT (function)]] {{text|prevents a user exit and indicates if a user has clicked the close X window button or CTRL + BREAK.}} @@ -251,7 +252,6 @@ __NOTOC__ * [[_MOUSEMOVE]] (statement) {{text|moves the mouse pointer to a designated position on the program [[SCREEN]].}} * [[_MOUSEMOVEMENTX]] (function) {{text|returns the relative horizontal position of the mouse cursor compared to the previous position.}} * [[_MOUSEMOVEMENTY]] (function) {{text|returns the relative vertical position of the mouse cursor compared to the previous position.}} -* [[_MOUSEPIPEOPEN]] (function) {{text|creates a pipe handle value for a mouse when using a virtual keyboard.}} * [[_MOUSESHOW]] (statement) {{text|displays the mouse cursor after it has been hidden or can change the cursor shape.}} * [[_MOUSEWHEEL]] (function) {{text|returns the number of mouse scroll wheel "clicks" since last read.}} * [[_MOUSEX]] (function) {{text|returns the current horizontal position of the mouse cursor.}} @@ -462,12 +462,9 @@ __NOTOC__ <div id = "C">C</div> * [[CALL]] (statement) {{text|optional statement that sends the program to a [[SUB]] procedure. Requires parameters be enclosed in brackets(parenthesis).}} * [[CALL ABSOLUTE]] (statement) {{text|is used to access computer interrupt registers.}} -* [[CALLS]] (non-BASIC call statement) * [[CASE]] ([[SELECT CASE]] condition) {{text|designates specific conditions in a [[SELECT CASE]] statement block.}} * [[CASE ELSE]] ([[SELECT CASE]] condition) {{text|designates an alternative condition to be evaluated in a [[SELECT CASE]] statement block.}} * [[CASE IS]] ([[SELECT CASE]] condition) {{text|designates specific conditions in a [[SELECT CASE]] statement block.}} -* [[CDBL]] (function) {{text|returns the closest [[DOUBLE]] value of a number.}} -* [[CDECL]] ([[DECLARE (non-BASIC statement)]]) * [[CHAIN]] (statement) {{text|sends a program to another specified program module or compiled program.}} * [[CHDIR]] (statement) {{text|changes the current program path for file access.}} * [[CHR$]] (function) {{text|returns a text [[STRING|string]] character by the specified [[ASCII]] code number.}} @@ -499,9 +496,6 @@ __NOTOC__ <div id = "D">D</div> * [[DATA]] (statement) {{text|creates a line of fixed program information separated by commas.}} * [[DATE$]] (function) {{text|returns the present Operating System date [[STRING|string]] formatted as mm-dd-yyyy.}} -* [[DATE$ (statement)]] {{text|sets the date of the Operating System using a mm-dd-yyyy [[STRING|string]] format.}} -* DECLARE (BASIC statement) {{text|declares a [[SUB]] or [[FUNCTION]] procedure at the start of a program. Not required in QB64.}} -* [[DECLARE (non-BASIC statement)]] {{text|declares non-basic [[SUB]] or [[FUNCTION]] procedures. Not implemented in QB64.}} * [[DECLARE LIBRARY|DECLARE LIBRARY (QB64 statement block)]] {{text|declares a C++, SDL or Operating System [[SUB]] or [[FUNCTION]] to be used.}} * [[DECLARE DYNAMIC LIBRARY|DECLARE DYNAMIC LIBRARY (QB64 statement)]] {{text|declares DYNAMIC, CUSTOMTYPE or STATIC library(DLL) [[SUB]] or [[FUNCTION]].}} * [[DEF SEG]] (statement) {{text|defines a segment in memory to be accessed by a memory procedure.}} @@ -531,8 +525,6 @@ __NOTOC__ * [[EOF]] (file function) {{text|returns -1 when a file [[INPUT (file statement)|INPUT]] or [[GET]] has reached the end of a file.}} * [[EQV]] (logic operator) {{text|is used to compare two numerical values bitwise.}} * [[ERASE]] (statement) {{text|clears the values from [[$STATIC]] arrays and completely removes [[$DYNAMIC]] arrays.}} -* [[ERDEV]] (function) {{text|returns an error code from the last device to create an error.}} -* [[ERDEV$]] (function) {{text|returns the 8 character name of the last device to declare an error as a [[STRING|string]].}} * [[ERL]] (error function) {{text|returns the closest line number before an error occurred if line numbers are used.}} * [[ERR]] (function) {{text|returns the [[ERROR Codes|ERROR code]] when a program error occurs.}} * [[ERROR]] (statement) {{text|sets a specific [[ERROR Codes|ERROR code]] to be simulated.}} @@ -546,12 +538,10 @@ __NOTOC__ <div id = "F">F</div> * [[FIELD]] (statement) {{text|defines the variable sizes to be written or read from a file.}} -* [[FILEATTR]] (function) {{text|returns the current file access mode.}} * [[FILES]] (statement) {{text|returns a list of files in the current directory path to the [[SCREEN]].}} * [[FIX]] (function) {{text|returns the rounded [[INTEGER]] value of a numerical value.}} * [[FOR...NEXT]] (statement) {{text|creates a recursive loop procedure that loop a specified number of times.}} * [[FOR (file statement)]] {{text|used in an [[OPEN]] file or device statement to indicate the access mode.}} -* [[FRE]] (function) {{text|returns the number of bytes of Memory available to running programs.}} * [[TIMER (statement)|FREE (QB64 TIMER statement)]] {{text|frees a numbered TIMER event in QB64.}} * [[FREEFILE]] (file function) {{text|returns a file number that is currently not in use by the Operating System.}} * [[FUNCTION]] (procedure block) {{text|sub-procedure that can calculate and return one value to a program in its name.}} @@ -594,8 +584,6 @@ __NOTOC__ * [[INTEGER]] (% numerical type) {{text|2 byte whole values from -32768 to 32767.}} * [[INTERRUPT]] (statement) {{text|is used to access computer interrupt registers.}} * [[INTERRUPTX]] (statement) {{text|is used to access computer interrupt registers.}} -* [[IOCTL]] (statement) -* [[IOCTL$]] (function) <p style="text-align: center">([[#toc|Return to Table of Contents]])</p> @@ -671,14 +659,10 @@ __NOTOC__ <div id = "O">O</div> * [[OCT$]] (function) {{text|returns the octal (base 8) [[STRING]] representation of a decimal [[INTEGER]] value.}} * [[OFF]] (event statement) {{text|turns off all [[ON]] event checking.}} -* [[ON COM(n)]] (statement) {{text|sets up a COM port event procedure call.}} * [[ON ERROR]] (statement) {{text|sets up and activates an error event checking procedure call. Use to avoid program errors.}} * [[ON KEY(n)]] (statement) {{text|sets up a keyboard key entry event procedure.}} -* [[ON PEN]] (statement) {{text|sets up a pen event procedure call.}} -* [[ON PLAY(n)]] (statement) {{text|sets up a [[PLAY]] event procedure call.}} * [[ON STRIG(n)]] (statement) {{text|sets up a joystick button event procedure call.}} * [[ON TIMER(n)]] (statement) {{text|sets up a timed event procedure call.}} -* [[ON UEVENT]] (statement) '''{{text|Not implemented in QB64.}}''' * [[ON...GOSUB]] (statement) {{text|sets up a numerical event procedure call.}} * [[ON...GOTO]] (statement) {{text|sets up a numerical event procedure call.}} * [[OPEN]] (file statement) {{text|opens a file name for an access mode with a specific file number.}} @@ -700,9 +684,6 @@ __NOTOC__ * [[PALETTE USING]] (statement) {{text|sets the color intensity settings using a designated [[arrays|array]].}} * [[PCOPY]] (statement) {{text|swaps two designated memory page images when page swapping is enabled in the [[SCREEN]] statement.}} * [[PEEK]] (function) {{text|returns a numerical value from a specified segment address in memory.}} -* [[PEN]] (function) {{text|returns requested information about the lightpen device used.}} -* [[PEN (statement)]] {{text|enables/disables or suspends event trapping of a lightpen device.}} -* [[PLAY(n)]] (function) {{text|returns the number of notes currently in the background music queue.}} * [[PLAY]] (statement) {{text|uses a special [[STRING|string]] format that can produce musical tones and effects.}} * [[PMAP]] (function) {{text|returns the physical or WINDOW view graphic coordinates.}} * [[POINT]] (function) {{text|returns the color attribute number or 32 bit [[_RGB32]] value.}} @@ -753,12 +734,10 @@ __NOTOC__ * [[SEEK]] (function) {{text|returns the present byte position in an [[OPEN|opened]] file.}} * [[SEEK (statement)]] {{text|moves to a specified position in an [[OPEN|opened]] file.}} * [[SELECT CASE]] (statement) {{text|a program flow block that can handle numerous conditional evaluations.}} -* [[SETMEM]] (function) {{text|sets the memory to use.}} * [[SGN]] (function) {{text|returns -1 for negative, 0 for zero, and 1 for positive numerical values.}} * [[SHARED]] (statement) {{text|designates that a variable can be used by other procedures or the main procedure when in a sub-procedure.}} * [[SHELL]] (statement) {{text|sends [[STRING]] commands to the command line. SHELL calls will not affect the current path.}} * [[SHELL (function)|SHELL (QB64 function)]] {{text|executes an external command or calls another program. Returns codes sent by [[END]] or [[SYSTEM]].}} -* [[SIGNAL]] (OS 2 event) * [[SIN]] (function) {{text|returns the sine of a radian angle.}} * [[SINGLE]] (! numerical type) {{text|4 byte floating decimal point values up to 7 decimal places.}} * [[SLEEP]] (statement) {{text|pauses the program for a designated number of seconds or until a key is pressed.}} @@ -802,7 +781,6 @@ __NOTOC__ <div id = "U">U</div> * [[UBOUND]] (function) {{text|returns the upper-most index number of a designated [[arrays|array]].}} * [[UCASE$]] (function) {{text|returns an uppercase representation of a specified [[STRING]].}} -* [[UEVENT]] (statement) '''{{text|Not implemented in QB64.}}''' * [[UNLOCK]] (statement) {{text|unlocks a designated file or portions of it.}} * [[UNTIL]] (condition) {{text|evaluates a [[DO...LOOP]] condition until it is True.}} diff --git a/internal/help/Keyword_Reference_-_By_usage.txt b/internal/help/Keyword_Reference_-_By_usage.txt index 377edd49b..c2a3e859b 100644 --- a/internal/help/Keyword_Reference_-_By_usage.txt +++ b/internal/help/Keyword_Reference_-_By_usage.txt @@ -332,6 +332,9 @@ The following table describes the error codes that are reported by the '''QB64'' * [[_ASSERT]] (statement) {{text|Performs debug tests.}} * [[$ASSERTS]] (metacommand) {{text|Enables the [[_ASSERT]] macro}}* [[$CHECKING]] ([[Metacommand]]) {{text|turns off or on error event checking and strips error code from compiled programs.}} * [[_ERRORLINE]] (function) {{text|returns the actual text code line where a program error occurred.}} +* [[_INCLERRORFILE$]] {function) {{text|returns the name of the original source code $INCLUDE module that caused the most recent error.}} +* [[_INCLERRORLINE]] (function) {{text|returns the line number in an included file that caused the most recent error.}} +* [[_ERRORMESSAGE$]] (function) {{text|returns a human-readable message describing the most recent runtime error.}} * [[ERR]] (function) {{text|returns the error code number of the last error to occur.}} * [[ERROR]] (statement) {{text|simulates a program error based on the error code number used.}} * [[ERL]] (function) {{text|returns the closest line number before an error occurred if the program uses them.}} @@ -382,7 +385,6 @@ The following table describes the error codes that are reported by the '''QB64'' * [[CLOSE]] (statement) {{text|closes a specified file or all open files.}} * [[EOF]] (file function) {{text|returns -1 when the end of a file has been read.}} * [[FIELD]] (statement) {{text|creates a [[STRING]] type definition for a random-access file buffer.}} -* [[FILEATTR]] (function) {{text|can return a file's current file mode or DOS handle number.}} * [[FILES]] (statement) {{text|displays a specified list of files.}} * [[FREEFILE]] (file function) {{text|returns a file access number that is currently not in use.}} * [[GET]] (file I/O statement) {{text|reads file data by byte or record positions.}} @@ -524,7 +526,7 @@ The following table describes the error codes that are reported by the '''QB64'' * [[_CONTROLCHR (function)]] {{text| returns the current state of _CONTROLCHR as 1 when OFF and 0 when ON.}} * [[_EXIT (function)]] {{text|prevents a program user exit and indicates if a user has clicked the close X window button or CTRL + BREAK.}} * [[_KEYDOWN]] (function) {{text|returns whether modifying keys like CTRL, ALT, SHIFT, and any other keys are pressed.}} -* [[_KEYHIT]] (function) {{text|returns ASCII one and two byte, SDL Virtual Key and Unicode keyboard key press codes.}} +* [[_KEYHIT]] (function) {{text|returns ASCII one and two byte, Virtual Key and Unicode keyboard key press codes.}} * [[_SCREENPRINT]] (statement) {{text|simulates typing text into another OS program using the keyboard.}} @@ -553,7 +555,7 @@ The following table describes the error codes that are reported by the '''QB64'' * [[ALIAS]] (statement) {{text|tells the program that you will use a different name than the name used in the Library file.}} * [[BYVAL]] (statement) {{text|used to pass a parameter's value with sub-procedures from a Library.}} -* [[DECLARE LIBRARY]] {{text|allows the use of OS specific, SDL or C++ external library [[SUB]] and [[FUNCTION]] procedures}} +* [[DECLARE LIBRARY]] {{text|allows the use of OS specific or C++ external library [[SUB]] and [[FUNCTION]] procedures}} * [[DECLARE DYNAMIC LIBRARY]] {{text|declares DYNAMIC, CUSTOMTYPE or STATIC library(DLL) [[SUB]]s or [[FUNCTION]]s.}} * [[DECLARE LIBRARY| END DECLARE]] {{text|required at the END of the block of Library declarations in QB64.}} @@ -740,14 +742,11 @@ The following table describes the error codes that are reported by the '''QB64'' == Port Input and Output (COM and LPT) == -* [[COM(n)]] (statement) {{text|used in an OPEN COM statement to open "COM1" or "COM2".}} - * [[GET]] (file I/O statement) {{text|reads port data data by byte or record positions.}} * [[LOC]] (function) {{text|finds the current file location or size of a [[COM]] port receive buffer.}} -* [[ON COM(n)]] (event statement) {{text|branches to a line number or label when there is a value in the serial port specified.}} * [[OPEN COM]] (statement) {{text|opens a computer serial COMmunications port.}} * [[OUT]] (statement) {{text|sends values to register or port hardware addresses (emulated - limited access).}} @@ -993,7 +992,7 @@ The following table describes the error codes that are reported by the '''QB64'' * [[_DISPLAY]] (statement) {{text|turns off automatic display while only displaying the screen changes when called.}} *[[_FREETIMER]] (function) {{text|returns a free TIMER number for multiple [[ON TIMER(n)]] events.}} * [[_KEYDOWN]] (function) {{text|returns whether modifying keys like CTRL, ALT, SHIFT, and any other keys are pressed.}} -* [[_KEYHIT]] (function) {{text|returns ASCII one and two byte, SDL Virtual Key and Unicode keyboard key press codes.}} +* [[_KEYHIT]] (function) {{text|returns ASCII one and two byte, Virtual Key and Unicode keyboard key press codes.}} * [[_LIMIT]] (statement) {{text|sets the loop repeat rate of a program to so many per second, relinquishing spare cpu cycles.}} @@ -1046,7 +1045,7 @@ The following table describes the error codes that are reported by the '''QB64'' * [[SCREEN]] {{text|sets the screen mode of a program. No statement defaults the program to SCREEN 0 text mode.}} -<center>''See also:'' [[C_Libraries#Console_Window|Console Window]], [[SDL_Libraries#Window|SDL Frameless Window Library]], [[Windows_Libraries#Hot_Keys_.28maximize.29|Windows Hot Keys]] or [[Windows_Libraries#Focus|Focus on Program]].</center> +<center>''See also:'' [[C_Libraries#Console_Window|Console Window]], [[Windows_Libraries#Hot_Keys_.28maximize.29|Windows Hot Keys]] or [[Windows_Libraries#Focus|Focus on Program]].</center> <p style="text-align: center">([[#toc|Return to Table of Contents]])</p> diff --git a/internal/help/Keywords_currently_not_supported_by_QB64.txt b/internal/help/Keywords_currently_not_supported_by_QB64.txt index baf196efa..a934d9b23 100644 --- a/internal/help/Keywords_currently_not_supported_by_QB64.txt +++ b/internal/help/Keywords_currently_not_supported_by_QB64.txt @@ -6,7 +6,7 @@ The keywords listed here are not supported in QB64. QB64 is meant to be compatib |} * [[ALIAS]] (supported in [[DECLARE LIBRARY]] only) -* [[ANY]] +* ANY * [[BYVAL]] (supported in [[DECLARE LIBRARY]] only) * CALLS * CDECL diff --git a/internal/help/LINE_INPUT.txt b/internal/help/LINE_INPUT.txt index c7e8a4aff..bca1fdc60 100644 --- a/internal/help/LINE_INPUT.txt +++ b/internal/help/LINE_INPUT.txt @@ -13,7 +13,7 @@ The [[LINE INPUT]] statement requests a [[STRING]] keyboard entry from a program {{PageDescription}} -* Cannot use numerical [[type]] variables or [[comma]] separated variable lists for multiple entries. +* Cannot use numerical [[Variable Types|type]] variables or [[comma]] separated variable lists for multiple entries. * Allows [[comma]]s and [[quotation mark]]s in the user input, unlike [[INPUT]] where commas denote extra input values and quotes delimit strings. * The statement halts the program until an entry is made. Pressing Enter ends the entry and code execution resumes. * LINE INPUT does not trim off leading or trailing spaces in the string entry like [[INPUT]] string returns. diff --git a/internal/help/LPRINT_USING.txt b/internal/help/LPRINT_USING.txt index 3b8685392..02f684de6 100644 --- a/internal/help/LPRINT_USING.txt +++ b/internal/help/LPRINT_USING.txt @@ -8,7 +8,7 @@ The [[LPRINT USING]] statement sends formatted data to LPT1, the parallel port p {{Parameters}} * Literal or variable [[STRING]] ''text$'' can be placed between [[LPRINT]] and USING or it can be included in the {{Parameter|template$}}. * A [[semicolon]] or [[comma]] may follow the {{Parameter|text$}} to stop or tab the print cursor before the {{Parameter|template$}} [[LPRINT]]. -* The literal or variable [[STRING]] {{Parameter|template$}} should use the template symbols to display each variable [[type]] in the list following it. +* The literal or variable [[STRING]] {{Parameter|template$}} should use the template symbols to display each variable [[Variable Types|type]] in the list following it. * The list of data ''variables'' used in the {{Parameter|template$}} are '''separated by semicolons''' after the template string value. * A [[semicolon]] or [[comma]] may follow the variable list to stop or tab the print cursor for pending prints. diff --git a/internal/help/Mathematical_Operations.txt b/internal/help/Mathematical_Operations.txt index 4cbdddf0f..33ad0a49d 100644 --- a/internal/help/Mathematical_Operations.txt +++ b/internal/help/Mathematical_Operations.txt @@ -293,7 +293,7 @@ END FUNCTION '' '' {{WhiteEnd}} -<center>[http://support.microsoft.com/kb/28249 Microsoft's Derived BASIC Functions (KB 28249)]</center> +<center>[https://web.archive.org/web/20140417011701/http://support.microsoft.com/kb/28249 Microsoft's Derived BASIC Functions (KB 28249)]</center> <center>[[#toc|Return to Top]]</center> diff --git a/internal/help/OFF.txt b/internal/help/OFF.txt index 7836216dc..97747d644 100644 --- a/internal/help/OFF.txt +++ b/internal/help/OFF.txt @@ -1,9 +1,9 @@ -[[OFF]] is a flag that disables event-trappping for [[KEY(n)]], [[ON COM (n)|COM(n)]], [[PEN]], [[PLAY]], [[STRIG(n)]], [[TIMER]], [[UEVENT]]. +[[OFF]] is a flag that disables event-trappping for [[KEY(n)]], [[STRIG(n)]], [[TIMER]]. {{PageDescription}} * [[OFF]] can be used to turn off the display of soft-key assignments at the bottom of the screen using [[KEY]]. -* [[OFF]] can also be used to disable an event-trapping in the following statements: [[KEY(n)]], [[ON COM (n)|COM(n)]], [[PEN]], [[PLAY]], [[STRIG(n)]], [[TIMER]], [[UEVENT]]. The trap can be turned back [[ON]], but all events triggered since [[OFF]] was used are lost. +* [[OFF]] can also be used to disable an event-trapping in the following statements: [[KEY(n)]], [[STRIG(n)]], [[TIMER]]. The trap can be turned back [[ON]], but all events triggered since [[OFF]] was used are lost. * [[$CHECKING]]:'''OFF''' is used to disable C++ error trapping (used for verified sections of code that require speed). diff --git a/internal/help/ON.txt b/internal/help/ON.txt index 7d3fdb0bc..1ff32cb00 100644 --- a/internal/help/ON.txt +++ b/internal/help/ON.txt @@ -1,9 +1,9 @@ ON creates event procedure calls or enables event trapping. -* Set the sub-procedure call for [[KEY(n)]], [[ON COM (n)|COM(n)]], [[PEN]], [[PLAY]], [[STRIG(n)]], [[TIMER]], [[UEVENT]] +* Set the sub-procedure call for [[KEY(n)]], [[STRIG(n)]], [[TIMER]] -* To turn on event trapping for [[ON COM (n)]], [[ON KEY (n)]], [[ON PEN]], [[ON PLAY (n)]], [[ON STRIG (n)]], [[ON TIMER (n)]] and [[ON UEVENT]]. +* To turn on event trapping for [[ON KEY (n)]], [[ON STRIG (n)]] and [[ON TIMER (n)]]. * In the case of [[ON ERROR]] the trap is also enabled until a subsequent ON ERROR statement. * ON procedures should be used only in the main program module and not inside of SUB procedures! diff --git a/internal/help/ON_ERROR.txt b/internal/help/ON_ERROR.txt index 328f6549e..aac767601 100644 --- a/internal/help/ON_ERROR.txt +++ b/internal/help/ON_ERROR.txt @@ -62,7 +62,7 @@ hand: {{PageSeeAlso}} * [[ERR]], [[ERL]], [[RESUME]] * [[ON...GOTO]] -* [[_ERRORLINE]], [[_INCLERRORLINE]], [[_INCLERRORFILE$]] +* [[_ERRORLINE]], [[_INCLERRORLINE]], [[_INCLERRORFILE$]], [[_ERRORMESSAGE$]] * [[ERROR]] {{text|(simulates an error)}} * [[ERROR Codes]] diff --git a/internal/help/OPEN.txt b/internal/help/OPEN.txt index be9393c99..06f71a7ae 100644 --- a/internal/help/OPEN.txt +++ b/internal/help/OPEN.txt @@ -47,7 +47,7 @@ The [[OPEN]] statement is used to open a file or [[OPEN_COM|COM]] serial communi ===File Access Modes=== * FOR mode can be: -** '''OUTPUT''': Sequential mode creates a new file or erases an existing file for new program output. Use [[WRITE (file statement)|WRITE #]] to write numerical or text data or [[PRINT (file statement)|PRINT #]] for text. '''OUTPUT clears files of all data''' and clears the receive buffer on other devices such as [[ON COM(n)|COM]]. +** '''OUTPUT''': Sequential mode creates a new file or erases an existing file for new program output. Use [[WRITE (file statement)|WRITE #]] to write numerical or text data or [[PRINT (file statement)|PRINT #]] for text. '''OUTPUT clears files of all data''' and clears the receive buffer on other devices such as COM ports. ** '''APPEND''': Sequential mode creates a new file if it doesn't exist or appends program output to the end of an existing file. Use [[WRITE (file statement)|WRITE #]] for numerical or text data or [[PRINT (file statement)|PRINT #]] for text as in the OUTPUT mode. '''APPEND does not remove previous data.''' ** '''INPUT''' : Sequential mode '''only reads input''' from an existing file. '''[[ERROR Codes|File error]] if file does not exist.''' Use [[INPUT (file statement)|INPUT #]] for comma separated numerical or text data and [[LINE INPUT (file statement)|LINE INPUT #]] or [[INPUT$]] to only read text data. '''Use [[_FILEEXISTS]] or [[_DIREXISTS]] to avoid errors.''' ** '''BINARY''': Creates a new file when it doesn't exist or reads and writes to an existing binary file. Use [[GET|GET #]] to read or [[PUT|PUT #]] to write byte positions simultaneously. [[LEN]] = statements are ignored in this mode. diff --git a/internal/help/PRINT_USING.txt b/internal/help/PRINT_USING.txt index 07b0b1499..c321eaac5 100644 --- a/internal/help/PRINT_USING.txt +++ b/internal/help/PRINT_USING.txt @@ -8,7 +8,7 @@ The '''PRINT USING''' statement is used to [[PRINT]] formatted data to the Scree {{Parameters}} * Literal or variable [[STRING]] ''text$'' can be placed between PRINT and USING or it can be included in the ''template''. * A [[semicolon]] or [[comma]] may follow the ''text'' to stop or tab the print cursor before the ''template'' [[PRINT]]. -* The literal or variable [[STRING]] ''template'' should use the template symbols to display each variable [[type]] in the list following it. +* The literal or variable [[STRING]] ''template'' should use the template symbols to display each variable [[Variable Types|type]] in the list following it. * The list of data ''variables'' used in the ''template'' are '''separated by semicolons''' after the template string value. * In '''QB64''' ONE [[semicolon]] or [[comma]] may follow the variable list to stop the print cursor for pending prints. QB only allowed a semicolon. diff --git a/internal/help/PRINT_USING_(file_statement).txt b/internal/help/PRINT_USING_(file_statement).txt index 69320c8b0..1469777c1 100644 --- a/internal/help/PRINT_USING_(file_statement).txt +++ b/internal/help/PRINT_USING_(file_statement).txt @@ -10,7 +10,7 @@ The '''PRINT #, USING''' statement is used to [[PRINT]] formatted text data to a * [[INTEGER]] ''filenumber'' refers to the file number [[OPEN]]ed previously followed by a [[comma]]. * Literal or variable [[STRING]] ''text$'' can be placed between PRINT and USING or it can be included in the ''template''. * A [[semicolon]] or [[comma]] may follow the ''text'' to stop or tab the print cursor before the ''template'' [[PRINT]]. -* The literal or variable [[STRING]] ''template'' should use the template symbols to display each variable [[type]] in the list following it. +* The literal or variable [[STRING]] ''template'' should use the template symbols to display each variable [[Variable Types|type]] in the list following it. * The list of data ''variables'' used in the ''template'' are '''separated by semicolons''' after the template string value. * In '''QB64''' ONE [[semicolon]] or [[comma]] may follow the variable list to stop the print cursor for pending prints. QB only allowed a semicolon. diff --git a/internal/help/Resource_Table_extraction.txt b/internal/help/Resource_Table_extraction.txt new file mode 100644 index 000000000..f688d6b2c --- /dev/null +++ b/internal/help/Resource_Table_extraction.txt @@ -0,0 +1,1878 @@ +The following information was supplied by Michael Calkins in a member's request to find a way to extract icons from EXE files. There is no warranty implied and users should use the information and code at their own risk! We are not responsible for any damages! + +==COFF Specifications== +There are 3 layers to the resource tables, Type, Name, and Language, The Microsoft PE and COFF specifications can be found here: + +<center>http://msdn.microsoft.com/en-us/windows/hardware/gg463119</center> + + +<center>'''Image Extraction Procedure'''</center> +{{CodeStart}} '' '' +{{Cl|DIM}} nam {{Cl|AS}} {{Cl|STRING}} * 8 +{{Cl|DIM}} fil {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} k {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ul {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} coff {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} SectionTable {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ImageBase {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} rsrc {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} pe32plus {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} SizeOfOptionalHeader {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} {{Cl|SHARED}} NumberOfSections {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} NumberOfRvaAndSizes {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} + +{{Cl|CLS}} +{{Cl|LINE INPUT}} "Name of the PE image to open? "; fil +{{Cl|IF...THEN|IF}} {{Cl|_FILEEXISTS}}(fil) = 0 {{Cl|THEN}} {{Cl|PRINT}} "File not found.": {{Cl|END}} +{{Cl|OPEN}} fil {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|ACCESS}} {{Cl|READ}} {{Cl|AS}} 1 +{{Cl|GET}} 1, 1 + 0, w +{{Cl|IF...THEN|IF}} w <> {{Cl|&H}}5A4D {{Cl|THEN}} {{Cl|PRINT}} "No MZ signature.": {{Cl|END}} +{{Cl|GET}} 1, 1 + {{Cl|&H}}3C, dw +coff = dw + 4 +{{Cl|GET}} 1, dw + 1, dw +{{Cl|IF...THEN|IF}} dw <> {{Cl|&H}}4550& {{Cl|THEN}} {{Cl|PRINT}} "No PE signature.": {{Cl|END}} +{{Cl|GET}} 1, 1 + coff + 2, NumberOfSections +{{Cl|IF...THEN|IF}} NumberOfSections = 0 {{Cl|THEN}} {{Cl|PRINT}} "No sections.": {{Cl|END}} +{{Cl|PRINT}} "NumberOfSections:"; NumberOfSections +{{Cl|DIM}} {{Cl|SHARED}} secsva(0 {{Cl|TO}} NumberOfSections - 1) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} {{Cl|SHARED}} secsfp(0 {{Cl|TO}} NumberOfSections - 1) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|GET}} 1, 1 + coff + 16, SizeOfOptionalHeader +{{Cl|IF...THEN|IF}} SizeOfOptionalHeader = 0 {{Cl|THEN}} {{Cl|PRINT}} "No optional header.": {{Cl|END}} +{{Cl|PRINT}} "SizeOfOptionalHeader:", {{Cl|SPACE$}}(4); word$(SizeOfOptionalHeader) +{{Cl|GET}} 1, 1 + coff + 20, w +{{Cl|SELECT CASE}} w + {{Cl|CASE}} {{Cl|&H}}10B: pe32plus = 0: {{Cl|PRINT}} "PE32" + {{Cl|CASE}} {{Cl|&H}}20B: pe32plus = -1: {{Cl|PRINT}} "PE32+" + {{Cl|CASE ELSE}}: {{Cl|PRINT}} "Unknown Magic.": {{Cl|END}} +{{Cl|END SELECT}} +{{Cl|GET}} 1, 1 + coff + 20 + 28 + (-4 {{Cl|AND}} pe32plus), ImageBase +{{Cl|PRINT}} "ImageBase:", "", dword$(ImageBase) +{{Cl|GET}} 1, 1 + coff + 20 + 92 + (16 {{Cl|AND}} pe32plus), NumberOfRvaAndSizes +{{Cl|IF...THEN|IF}} NumberOfRvaAndSizes < 3 {{Cl|THEN}} {{Cl|PRINT}} "No resource table.": {{Cl|END}} +{{Cl|PRINT}} "NumberOfRvaAndSizes:"; NumberOfRvaAndSizes +{{Cl|GET}} 1, 1 + coff + 20 + 112 + (16 {{Cl|AND}} pe32plus), rsrc +{{Cl|PRINT}} "Rva of resource table:", dword$(rsrc) +{{Cl|GET}} 1, 1 + coff + 20 + 4 + 112 + (16 {{Cl|AND}} pe32plus), dw +{{Cl|PRINT}} "Size of resource table:", dword$(dw) +{{Cl|IF...THEN|IF}} (rsrc = 0) {{Cl|OR (boolean)|OR}} (dw = 0) {{Cl|THEN}} {{Cl|PRINT}} "No resource table.": {{Cl|END}} +SectionTable = coff + 20 + SizeOfOptionalHeader +{{Cl|PRINT}} "section", "va", "file ptr" +{{Cl|FOR...NEXT|FOR}} w = 0 {{Cl|TO}} NumberOfSections - 1 + {{Cl|GET}} 1, 1 + SectionTable + (40 * w), nam + {{Cl|GET}} 1, 1 + SectionTable + 12 + (40 * w), ul + {{Cl|GET}} 1, 1 + SectionTable + 20 + (40 * w), dw + {{Cl|PRINT}} nam, dword$(ul), dword$(dw) + secsva(w) = ul + secsfp(w) = dw +{{Cl|NEXT}} +{{Cl|PRINT}} +{{Cl|PRINT}} "Proceed? "; +DO + k = {{Cl|LCASE$}}({{Cl|INKEY$}}) + {{Cl|IF...THEN|IF}} k = "n" {{Cl|THEN}} {{Cl|PRINT}} k: {{Cl|END}} +{{Cl|LOOP}} {{Cl|UNTIL}} k = "y" +{{Cl|PRINT}} k +processtable rva2fp(rsrc), rva2fp(rsrc), 0 +{{Cl|SYSTEM}} + +{{Cl|SUB}} processtable (bs {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}, addr {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}, level {{Cl|AS}} {{Cl|INTEGER}}) +{{Cl|DIM}} k {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} numnamest8 {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} dat {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} siz {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} so {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} sc {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} numnames {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} numids {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} ln {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} x {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} y {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} b {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_BYTE}} + +{{Cl|GET}} 1, 1 + addr + 12, numnames +{{Cl|GET}} 1, 1 + addr + 14, numids +{{Cl|DIM}} nams(0 {{Cl|TO}} numnames + (numnames > 0)) {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} namsrva(0 {{Cl|TO}} numnames + (numnames > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ids(0 {{Cl|TO}} numids + (numids > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} idsrva(0 {{Cl|TO}} numids + (numids > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} + +'get named entries +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} numnames - 1 + {{Cl|GET}} 1, 1 + addr + 16 + (x * 8), dw + dw = rva2fp(dw) + {{Cl|GET}} 1, 1 + dw, ln + {{Cl|FOR...NEXT|FOR}} y = 0 {{Cl|TO}} ln - 1 + {{Cl|GET}} 1, , w + {{Cl|SELECT CASE}} w + {{Cl|CASE}} {{Cl|&H}}20 {{Cl|TO}} {{Cl|&H}}7E: nams(x) = nams(x) + {{Cl|CHR$}}(w) + {{Cl|CASE ELSE}}: nams(x) = nams(x) + {{Cl|CHR$}}({{Cl|&H}}1A) + {{Cl|END SELECT}} + {{Cl|IF...THEN|IF}} y = 68 {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|NEXT}} + {{Cl|GET}} 1, 1 + addr + 16 + 4 + (x * 8), namsrva(x) +{{Cl|NEXT}} + +'get numbered entries: +numnamest8 = numnames * 8 +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} numids - 1 + {{Cl|GET}} 1, 1 + addr + 16 + numnamest8 + (x * 8), ids(x) + {{Cl|GET}} 1, 1 + addr + 16 + 4 + numnamest8 + (x * 8), idsrva(x) +{{Cl|NEXT}} + +'display: +{{Cl|VIEW PRINT}} +DO + {{Cl|CLS}} 0 'qb64 bug? not locating to 1,1? + {{Cl|LOCATE}} 1, 1 + {{Cl|SELECT CASE}} level + {{Cl|CASE}} 0: {{Cl|PRINT}} "1st level - Type"; + {{Cl|CASE}} 1: {{Cl|PRINT}} "2nd level - Name"; + {{Cl|CASE}} 2: {{Cl|PRINT}} "3rd level - Language"; + {{Cl|CASE ELSE}}: {{Cl|PRINT}} {{Cl|LTRIM$}}({{Cl|STR$}}(level)) + "th level"; + {{Cl|END SELECT}} + {{Cl|PRINT}} "", "file ptr: "; dword$(addr); ". Press 'D' to dump." + {{Cl|PRINT}} numnames; "names in this level, in this branch." + {{Cl|PRINT}} numids; "IDs in this level, in this branch." + {{Cl|IF...THEN|IF}} (numnames {{Cl|OR (boolean)|OR}} numids) = 0 {{Cl|THEN}} + {{Cl|IF...THEN|IF}} level {{Cl|THEN}} + {{Cl|PRINT}} "Press any key to go up one level." + {{Cl|SLEEP}}: {{Cl|DO...LOOP|DO}}: {{Cl|LOOP}} {{Cl|WHILE}} {{Cl|LEN}}({{Cl|INKEY$}}) + {{Cl|EXIT SUB}} + {{Cl|ELSE}} + {{Cl|END}} + {{Cl|END IF}} + {{Cl|END IF}} + {{Cl|PRINT}} "names are unicode. For simplicity, non ASCII chars will be shown as " + {{Cl|CHR$}}({{Cl|&H}}1A) + "." + {{Cl|IF...THEN|IF}} level {{Cl|THEN}} + {{Cl|PRINT}} "BKSP or ESC to go up one level." + {{Cl|ELSE}} + {{Cl|PRINT}} "BKSP or ESC to exit." + {{Cl|END IF}} + {{Cl|PRINT}} "UP, DOWN, PGUP, PGDN, HOME, {{Cl|END}} to navigate list." + {{Cl|PRINT}} "ENTER to select." + {{Cl|PRINT}} {{Cl|STRING$}}(80, {{Cl|&H}}C4); + {{Cl|LOCATE}} 22, 1 + {{Cl|PRINT}} {{Cl|STRING$}}(80, {{Cl|&H}}C4); + sc = 0 + so = 0 + DO + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 8, 1: {{Cl|PRINT}} dword$(sc) + {{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} 11 + {{Cl|LOCATE}} 10 + x, 1 + {{Cl|IF...THEN|IF}} x + so = sc {{Cl|THEN}} {{Cl|COLOR}} 15, 1 {{Cl|ELSE}} {{Cl|COLOR}} 7, 0 + {{Cl|IF...THEN|IF}} (x + so) < numnames {{Cl|THEN}} + {{Cl|PRINT}} nams(x + so); {{Cl|SPACE$}}(70 - {{Cl|LEN}}(nams(x + so))); + {{Cl|PRINT}} dword$(bs + (namsrva(x + so) {{Cl|AND}} {{Cl|&H}}7FFFFFFF&)); + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 7, 18 + {{Cl|IF...THEN|IF}} namsrva(x + so) {{Cl|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + {{Cl|PRINT}} "(descend)"; + {{Cl|ELSE}} + {{Cl|PRINT}} "(extract)"; + {{Cl|END IF}} + {{Cl|ELSEIF}} (x + so) < (numnames + numids) {{Cl|THEN}} + {{Cl|PRINT}} "ID: " + dword$(ids(x + so - numnames)); {{Cl|SPACE$}}(56); + {{Cl|PRINT}} dword$(bs + (idsrva(x + so - numnames))); + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 7, 18 + {{Cl|IF...THEN|IF}} idsrva(x + (so - numnames)) {{Cl|AND (boolean)|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + {{Cl|PRINT}} "(descend)"; + {{Cl|ELSE}} + {{Cl|PRINT}} "(extract)"; + {{Cl|END IF}} + {{Cl|ELSE}} + {{Cl|PRINT}} {{Cl|SPACE$}}(80); + {{Cl|END IF}} + {{Cl|NEXT}} + DO + k = {{Cl|INKEY$}} + {{Cl|LOOP}} {{Cl|UNTIL}} {{Cl|LEN}}(k) + {{Cl|SELECT CASE}} k + {{Cl|CASE}} "d", "D" + dump addr + {{Cl|EXIT DO}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4800) 'up + {{Cl|IF...THEN|IF}} sc > 0 {{Cl|THEN}} + sc = sc - 1 + {{Cl|IF...THEN|IF}} sc < so {{Cl|THEN}} so = sc + {{Cl|END IF}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}5000) 'down + {{Cl|IF...THEN|IF}} sc < (numnames + numids - 1) {{Cl|THEN}} + sc = sc + 1 + {{Cl|IF...THEN|IF}} sc > (so + 11) {{Cl|THEN}} + so = sc - 11 + {{Cl|IF...THEN|IF}} so > sc {{Cl|THEN}} so = 0 'unsigned + {{Cl|END IF}} + {{Cl|END IF}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4700) 'home + sc = 0 + so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4F00) 'end + sc = numnames + numids - 1 + so = sc - 11 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4900) 'pgup + sc = sc - 12 + so = so - 12 + {{Cl|IF...THEN|IF}} sc < 0 {{Cl|THEN}} sc = 0 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}5100) 'pgdn + sc = sc + 12 + {{Cl|IF...THEN|IF}} sc > (numnames + numids - 1) {{Cl|THEN}} sc = numnames + numids - 1 + so = sc - 11 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|CHR$}}({{Cl|&H}}8), {{Cl|CHR$}}({{Cl|&H}}1B) 'bksp, esc + {{Cl|EXIT SUB}} + {{Cl|CASE}} {{Cl|CHR$}}({{Cl|&H}}D) 'enter + {{Cl|IF...THEN|IF}} sc < numnames {{Cl|THEN}} + dw = namsrva(sc) + {{Cl|ELSE}} + dw = idsrva(sc - numnames) + {{Cl|END IF}} + {{Cl|IF...THEN|IF}} dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + 'the spec says its an rfa, but it seems to be an offset in the section/table + processtable bs, bs + (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}7FFFFFFF&), level + 1 + {{Cl|EXIT DO}} + {{Cl|ELSE}} + 'the spec says its an rfa, but it seems to be an offset in the section/table + dw = bs + dw + {{Cl|GET}} 1, 1 + dw, dat + {{Cl|GET}} 1, 1 + 4 + dw, siz + {{Cl|LOCATE}} 24, 1 + {{Cl|PRINT}} dword$(siz) + " bytes."; + {{Cl|LOCATE}} 23, 1 + {{Cl|LINE INPUT}} "(leave blank to cancel) Output file? "; k + {{Cl|IF...THEN|IF}} {{Cl|LEN}}(k) {{Cl|THEN}} + {{Cl|IF...THEN|IF}} {{Cl|_FILEEXISTS}}(k) {{Cl|THEN}} + {{Cl|PRINT}} + {{Cl|PRINT}} "File already exists."; + {{Cl|ELSE}} + {{Cl|OPEN}} k {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|AS}} 2 + {{Cl|SEEK}} 1, 1 + rva2fp(dat) + {{Cl|FOR...NEXT|FOR}} dw = 1 {{Cl|TO}} siz + {{Cl|GET}} 1, , b + {{Cl|PUT}} 2, , b + {{Cl|NEXT}} + {{Cl|CLOSE}} 2 + {{Cl|PRINT}} + {{Cl|PRINT}} "Done."; + {{Cl|END IF}} + {{Cl|SLEEP}}: {{Cl|DO...LOOP|DO}}: {{Cl|LOOP}} {{Cl|WHILE}} {{Cl|LEN}}({{Cl|INKEY$}}) + {{Cl|END IF}} + {{Cl|EXIT DO}} + {{Cl|END IF}} + {{Cl|END SELECT}} + {{Cl|LOOP}} +{{Cl|LOOP}} +{{Cl|END SUB}} + +{{Cl|FUNCTION}} word$ (w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +t = {{Cl|LCASE$}}({{Cl|HEX$}}(w)) +word = "0x" + {{Cl|STRING$}}(4 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t +{{Cl|END FUNCTION}} + +{{Cl|FUNCTION}} dword$ (dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +t = {{Cl|LCASE$}}({{Cl|HEX$}}(dw)) +dword = "0x" + {{Cl|STRING$}}(8 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t +{{Cl|END FUNCTION}} + +{{Cl|FUNCTION}} rva2fp~& (rva {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|FOR...NEXT|FOR}} w = 0 {{Cl|TO}} NumberOfSections - 1 + {{Cl|IF...THEN|IF}} rva < secsva(w) {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} +{{Cl|NEXT}} +w = w - 1 +{{Cl|IF...THEN|IF}} w > NumberOfSections - 1 {{Cl|THEN}} {{Cl|PRINT}} dword$(rva), w: {{Cl|SLEEP}} +rva2fp = rva + (secsfp(w) - secsva(w)) +{{Cl|END FUNCTION}} + +{{Cl|SUB}} dump (addr {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ul {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} b {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_BYTE}} + +{{Cl|VIEW PRINT}} +ul = addr +DO + {{Cl|COLOR}} 7, 0 + {{Cl|CLS}} 0 + {{Cl|SEEK}} 1, 1 + ul + {{Cl|FOR...NEXT|FOR}} dw = ul {{Cl|TO}} (ul {{Cl|AND}} {{Cl|&H}}FFFFFFF0) + {{Cl|&H}}15F + {{Cl|IF...THEN|IF}} (1 + ul) > {{Cl|LOF}}(1) {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|GET}} 1, , b + {{Cl|IF...THEN|IF}} (dw {{Cl|AND}} {{Cl|&H}}F) = 0 {{Cl|THEN}} + t = {{Cl|LCASE$}}({{Cl|HEX$}}(dw)) + {{Cl|COLOR}} 7 + {{Cl|PRINT}} {{Cl|STRING$}}(8 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t; {{Cl|SPACE$}}(2); + {{Cl|END IF}} + {{Cl|IF...THEN|IF}} (dw {{Cl|AND}} {{Cl|&H}}4) {{Cl|THEN}} {{Cl|COLOR}} 3 {{Cl|ELSE}} {{Cl|COLOR}} 2 + {{Cl|LOCATE}} , 14 + ((dw {{Cl|AND}} {{Cl|&H}}F) * 3) + t = {{Cl|LCASE$}}({{Cl|HEX$}}(b)) + {{Cl|IF...THEN|IF}} b < {{Cl|&H}}10 {{Cl|THEN}} {{Cl|PRINT}} "0" + t; {{Cl|ELSE}} {{Cl|PRINT}} t; + {{Cl|LOCATE}} , 65 + (dw {{Cl|AND}} {{Cl|&H}}F) + {{Cl|SELECT CASE}} b + {{Cl|CASE}} 7, 9 {{Cl|TO}} {{Cl|&H}}D, {{Cl|&H}}1F: {{Cl|PRINT}} "."; + {{Cl|CASE ELSE}}: {{Cl|PRINT}} {{Cl|CHR$}}(b); + {{Cl|END SELECT}} + {{Cl|NEXT}} + {{Cl|PRINT}} + {{Cl|COLOR}} 7 + {{Cl|LINE INPUT}} "(leave blank to cancel) Address: 0x"; t + {{Cl|IF...THEN|IF}} {{Cl|LTRIM$}}(t) = "" {{Cl|THEN}} {{Cl|EXIT DO}} + ul = {{Cl|VAL}}("&h" + t + "&") {{Cl|AND}} {{Cl|&H}}7FFFFFFF +{{Cl|LOOP}} +{{Cl|END SUB}} '' '' +{{CodeEnd}} +{{small|Public domain October 2011 by Michael Calkins based on the Microsoft PE and COFF spec, Revision 8.2 - September 21, 2010}} + + +:If you open ''c:\windows\system32\shell32.dll'', and save the first item (descend the first entry, then the first entry of the next level, etc), it's an .AVI file of a flashlight searching a folder. If you go down the first entry of the first level, but the last entry of the second level, it's an .AVI of a globe throwing a page at a folder. Save both files as AVI to view the video. + +:I wouldn't consider the program finished. There's some double checking, tweaking, and optimizing that could be done. For example, the dump sub could probably use an extra variable, and could probably use some increased functionality. I wrote it to help me debug the part that reads the resource tables. As I say in the comments, the part that gives the address of either the "leaf" or the next table lower seems to be relative to the start of the main table or section, not an actual RVA. + +:With things like: + +{{WhiteStart}} GET 1, 1 + coff + 20 + 28 + (-4 AND pe32plus), ImageBase {{WhiteEnd}} + +:That could obviously be optimized by combining the 1 + 20 + 28. By leaving it uncombined, though, it documents itself better in terms of helping the human reader match it up with the specification. 1 because QBASIC's GET/PUT/SEEK idiotically starts at 1 instead of 0. Coff because we want an offset from the start of the coff header, 20 to skip the 20 byte coff main header, 28 because that's the offset of ImageBase in the optional header, and (-4 AND pe32plus) because the offset is 24 if the Magic is PE32+. Either QB64 or GCC will probably optimize it anyway, I would think. + +:In the Section table, the name of the field is VirtualAddress, but the description seems to say that it is an RVA. My program assumes that it is an RVA. The rva2fp function finds which section a given RVA is in, and then uses the difference between the RVA and the file pointer for that section to turn the given RVA into a file pointer. + +:Regards, Michael Calkins + + +<p style="text-align: center">([[#toc|Return to Table of Contents]])</p> + +==Revision 2== +: I've made a few minor changes to the program. It will show you the first 400 bytes when you choose to export the data. Also, by moving the initialization of sc and so outside the loop, you will now come back to the correct entry upon ascending a level. I experimented with code to PSET the data, but it is commented out. +{{CodeStart}} '' '' +'october 2011, michael calkins +'my code is public domain, but it's based on Microsoft's spec, so I'm not sure +'what kind of patents or copyrights apply. +'based on the Microsoft PE and COFF spec, Revision 8.2 - September 21, 2010 +'http://msdn.microsoft.com/en-us/windows/hardware/gg463119.aspx + +{{Cl|DIM}} nam {{Cl|AS}} {{Cl|STRING}} * 8 +{{Cl|DIM}} fil {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} k {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ul {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} coff {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} SectionTable {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ImageBase {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} rsrc {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} pe32plus {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} SizeOfOptionalHeader {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} {{Cl|SHARED}} NumberOfSections {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} NumberOfRvaAndSizes {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} + +{{Cl|CLS}} +{{Cl|LINE INPUT}} "Name of the PE image to open? "; fil +{{Cl|IF...THEN|IF}} {{Cl|_FILEEXISTS}}(fil) = 0 {{Cl|THEN}} {{Cl|PRINT}} "File not found.": {{Cl|END}} +{{Cl|OPEN}} fil {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|ACCESS}} {{Cl|READ}} {{Cl|AS}} 1 +{{Cl|GET}} 1, 1 + 0, w +{{Cl|IF...THEN|IF}} w <> {{Cl|&H}}5A4D {{Cl|THEN}} {{Cl|PRINT}} "No MZ signature.": {{Cl|END}} +{{Cl|GET}} 1, 1 + {{Cl|&H}}3C, dw +coff = dw + 4 +{{Cl|GET}} 1, dw + 1, dw +{{Cl|IF...THEN|IF}} dw <> {{Cl|&H}}4550& {{Cl|THEN}} {{Cl|PRINT}} "No PE signature.": {{Cl|END}} +{{Cl|GET}} 1, 1 + coff + 2, NumberOfSections +{{Cl|IF...THEN|IF}} NumberOfSections = 0 {{Cl|THEN}} {{Cl|PRINT}} "No sections.": {{Cl|END}} +{{Cl|PRINT}} "NumberOfSections:"; NumberOfSections +{{Cl|DIM}} {{Cl|SHARED}} secsva(0 {{Cl|TO}} NumberOfSections - 1) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} {{Cl|SHARED}} secsfp(0 {{Cl|TO}} NumberOfSections - 1) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|GET}} 1, 1 + coff + 16, SizeOfOptionalHeader +{{Cl|IF...THEN|IF}} SizeOfOptionalHeader = 0 {{Cl|THEN}} {{Cl|PRINT}} "No optional header.": {{Cl|END}} +{{Cl|PRINT}} "SizeOfOptionalHeader:", {{Cl|SPACE$}}(4); word$(SizeOfOptionalHeader) +{{Cl|GET}} 1, 1 + coff + 20, w +{{Cl|SELECT CASE}} w + {{Cl|CASE}} {{Cl|&H}}10B: pe32plus = 0: {{Cl|PRINT}} "PE32" + {{Cl|CASE}} {{Cl|&H}}20B: pe32plus = -1: {{Cl|PRINT}} "PE32+" + {{Cl|CASE ELSE}}: {{Cl|PRINT}} "Unknown Magic.": {{Cl|END}} +{{Cl|END SELECT}} +{{Cl|GET}} 1, 1 + coff + 20 + 28 + (-4 {{Cl|AND}} pe32plus), ImageBase +{{Cl|PRINT}} "ImageBase:", "", dword$(ImageBase) +{{Cl|GET}} 1, 1 + coff + 20 + 92 + (16 {{Cl|AND}} pe32plus), NumberOfRvaAndSizes +{{Cl|IF...THEN|IF}} NumberOfRvaAndSizes < 3 {{Cl|THEN}} {{Cl|PRINT}} "No resource table.": {{Cl|END}} +{{Cl|PRINT}} "NumberOfRvaAndSizes:"; NumberOfRvaAndSizes +{{Cl|GET}} 1, 1 + coff + 20 + 112 + (16 {{Cl|AND}} pe32plus), rsrc +{{Cl|PRINT}} "Rva of resource table:", dword$(rsrc) +{{Cl|GET}} 1, 1 + coff + 20 + 4 + 112 + (16 {{Cl|AND}} pe32plus), dw +{{Cl|PRINT}} "Size of resource table:", dword$(dw) +{{Cl|IF...THEN|IF}} (rsrc = 0) {{Cl|OR}} (dw = 0) {{Cl|THEN}} {{Cl|PRINT}} "No resource table.": {{Cl|END}} +SectionTable = coff + 20 + SizeOfOptionalHeader +{{Cl|PRINT}} "section", "va", "file ptr" +{{Cl|FOR...NEXT|FOR}} w = 0 {{Cl|TO}} NumberOfSections - 1 + {{Cl|GET}} 1, 1 + SectionTable + (40 * w), nam + {{Cl|GET}} 1, 1 + SectionTable + 12 + (40 * w), ul + {{Cl|GET}} 1, 1 + SectionTable + 20 + (40 * w), dw + {{Cl|PRINT}} nam, dword$(ul), dword$(dw) + secsva(w) = ul + secsfp(w) = dw +{{Cl|NEXT}} +{{Cl|PRINT}} +{{Cl|PRINT}} "Proceed? "; +DO + k = {{Cl|LCASE$}}({{Cl|INKEY$}}) + {{Cl|IF...THEN|IF}} k = "n" {{Cl|THEN}} {{Cl|PRINT}} k: {{Cl|END}} +{{Cl|LOOP}} {{Cl|UNTIL}} k = "y" +{{Cl|PRINT}} k +processtable rva2fp(rsrc), rva2fp(rsrc), 0 +{{Cl|SYSTEM}} + +{{Cl|SUB}} processtable (bs {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}, addr {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}, level {{Cl|AS}} {{Cl|INTEGER}}) +{{Cl|DIM}} k {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} numnamest8 {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} dat {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} siz {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} so {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} sc {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} numnames {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} numids {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} ln {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} x {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} y {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} b {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_BYTE}} + +{{Cl|GET}} 1, 1 + addr + 12, numnames +{{Cl|GET}} 1, 1 + addr + 14, numids +{{Cl|DIM}} nams(0 {{Cl|TO}} numnames + (numnames > 0)) {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} namsrva(0 {{Cl|TO}} numnames + (numnames > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ids(0 {{Cl|TO}} numids + (numids > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} idsrva(0 {{Cl|TO}} numids + (numids > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} + +'get named entries +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} numnames - 1 + {{Cl|GET}} 1, 1 + addr + 16 + (x * 8), dw + dw = rva2fp(dw) + {{Cl|GET}} 1, 1 + dw, ln + {{Cl|FOR...NEXT|FOR}} y = 0 {{Cl|TO}} ln - 1 + {{Cl|GET}} 1, , w + {{Cl|SELECT CASE}} w + {{Cl|CASE}} {{Cl|&H}}20 {{Cl|TO}} {{Cl|&H}}7E: nams(x) = nams(x) + {{Cl|CHR$}}(w) + {{Cl|CASE ELSE}}: nams(x) = nams(x) + {{Cl|CHR$}}({{Cl|&H}}1A) + {{Cl|END SELECT}} + {{Cl|IF...THEN|IF}} y = 68 {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|NEXT}} + {{Cl|GET}} 1, 1 + addr + 16 + 4 + (x * 8), namsrva(x) +{{Cl|NEXT}} + +'get numbered entries: +numnamest8 = numnames * 8 +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} numids - 1 + {{Cl|GET}} 1, 1 + addr + 16 + numnamest8 + (x * 8), ids(x) + {{Cl|GET}} 1, 1 + addr + 16 + 4 + numnamest8 + (x * 8), idsrva(x) +{{Cl|NEXT}} + +'display: +{{Cl|VIEW PRINT}} +sc = 0 +so = 0 +DO + {{Cl|CLS}} 0 'qb64 bug? not locating to 1,1? + {{Cl|LOCATE}} 1, 1 + {{Cl|SELECT CASE}} level + {{Cl|CASE}} 0: {{Cl|PRINT}} "1st level - Type"; + {{Cl|CASE}} 1: {{Cl|PRINT}} "2nd level - Name"; + {{Cl|CASE}} 2: {{Cl|PRINT}} "3rd level - Language"; + {{Cl|CASE ELSE}}: {{Cl|PRINT}} {{Cl|LTRIM$}}({{Cl|STR$}}(level)) + "th level"; + {{Cl|END SELECT}} + {{Cl|PRINT}} "", "file ptr: "; dword$(addr); ". Press 'D' to dump." + {{Cl|PRINT}} numnames; "names in this level, in this branch." + {{Cl|PRINT}} numids; "IDs in this level, in this branch." + {{Cl|IF...THEN|IF}} (numnames {{Cl|OR (boolean)|OR}} numids) = 0 {{Cl|THEN}} + {{Cl|IF...THEN|IF}} level {{Cl|THEN}} + {{Cl|PRINT}} "Press any key to go up one level." + {{Cl|SLEEP}}: {{Cl|DO...LOOP|DO}}: {{Cl|LOOP}} {{Cl|WHILE}} {{Cl|LEN}}({{Cl|INKEY$}}) + {{Cl|EXIT SUB}} + {{Cl|ELSE}} + {{Cl|END}} + {{Cl|END IF}} + {{Cl|END IF}} + {{Cl|PRINT}} "names are unicode. For simplicity, non ASCII chars will be shown as " + {{Cl|CHR$}}({{Cl|&H}}1A) + "." + {{Cl|IF...THEN|IF}} level {{Cl|THEN}} + {{Cl|PRINT}} "BKSP or ESC to go up one level." + {{Cl|ELSE}} + {{Cl|PRINT}} "BKSP or ESC to exit." + {{Cl|END IF}} + {{Cl|PRINT}} "UP, DOWN, PGUP, PGDN, HOME, {{Cl|END}} to navigate list." + {{Cl|PRINT}} "ENTER to select." + {{Cl|PRINT}} {{Cl|STRING$}}(80, {{Cl|&H}}C4); + {{Cl|LOCATE}} 22, 1 + {{Cl|PRINT}} {{Cl|STRING$}}(80, {{Cl|&H}}C4); + DO + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 8, 1: {{Cl|PRINT}} dword$(sc) + {{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} 11 + {{Cl|LOCATE}} 10 + x, 1 + {{Cl|IF...THEN|IF}} x + so = sc {{Cl|THEN}} {{Cl|COLOR}} 15, 1 {{Cl|ELSE}} {{Cl|COLOR}} 7, 0 + {{Cl|IF...THEN|IF}} (x + so) < numnames {{Cl|THEN}} + {{Cl|PRINT}} nams(x + so); {{Cl|SPACE$}}(70 - {{Cl|LEN}}(nams(x + so))); + {{Cl|PRINT}} dword$(bs + (namsrva(x + so) {{Cl|AND}} {{Cl|&H}}7FFFFFFF&)); + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 7, 18 + {{Cl|IF...THEN|IF}} namsrva(x + so) {{Cl|AND (boolean)|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + {{Cl|PRINT}} "(descend)"; + {{Cl|ELSE}} + {{Cl|PRINT}} "(extract)"; + {{Cl|END IF}} + {{Cl|ELSEIF}} (x + so) < (numnames + numids) {{Cl|THEN}} + {{Cl|PRINT}} "ID: " + dword$(ids(x + so - numnames)); {{Cl|SPACE$}}(56); + {{Cl|PRINT}} dword$(bs + (idsrva(x + so - numnames))); + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 7, 18 + {{Cl|IF...THEN|IF}} idsrva(x + (so - numnames)) {{Cl|AND (boolean)|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + {{Cl|PRINT}} "(descend)"; + {{Cl|ELSE}} + {{Cl|PRINT}} "(extract)"; + {{Cl|END IF}} + {{Cl|ELSE}} + {{Cl|PRINT}} {{Cl|SPACE$}}(80); + {{Cl|END IF}} + {{Cl|NEXT}} + DO + k = {{Cl|INKEY$}} + {{Cl|LOOP}} {{Cl|UNTIL}} {{Cl|LEN}}(k) + {{Cl|SELECT CASE}} k + {{Cl|CASE}} "d", "D" + dump addr + {{Cl|EXIT DO}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4800) 'up + {{Cl|IF...THEN|IF}} sc > 0 {{Cl|THEN}} + sc = sc - 1 + {{Cl|IF...THEN|IF}} sc < so {{Cl|THEN}} so = sc + {{Cl|END IF}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}5000) 'down + {{Cl|IF...THEN|IF}} sc < (numnames + numids - 1) {{Cl|THEN}} + sc = sc + 1 + {{Cl|IF...THEN|IF}} sc > (so + 11) {{Cl|THEN}} + so = sc - 11 + {{Cl|IF...THEN|IF}} so > sc {{Cl|THEN}} so = 0 'unsigned + {{Cl|END IF}} + {{Cl|END IF}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4700) 'home + sc = 0 + so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4F00) 'end + sc = numnames + numids - 1 + so = sc - 11 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4900) 'pgup + sc = sc - 12 + so = so - 12 + {{Cl|IF...THEN|IF}} sc < 0 {{Cl|THEN}} sc = 0 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}5100) 'pgdn + sc = sc + 12 + {{Cl|IF...THEN|IF}} sc > (numnames + numids - 1) {{Cl|THEN}} sc = numnames + numids - 1 + so = sc - 11 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|CHR$}}({{Cl|&H}}8), {{Cl|CHR$}}({{Cl|&H}}1B) 'bksp, esc + {{Cl|EXIT SUB}} + {{Cl|CASE}} {{Cl|CHR$}}({{Cl|&H}}D) 'enter + {{Cl|IF...THEN|IF}} sc < numnames {{Cl|THEN}} + dw = namsrva(sc) + {{Cl|ELSE}} + dw = idsrva(sc - numnames) + {{Cl|END IF}} + {{Cl|IF...THEN|IF}} dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + 'the spec says its an rva, but it seems to be an offset in the section/table + processtable bs, bs + (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}7FFFFFFF&), level + 1 + {{Cl|EXIT DO}} + {{Cl|ELSE}} + 'the spec says its an rva, but it seems to be an offset in the section/table + dw = bs + dw + {{Cl|GET}} 1, 1 + dw, dat + {{Cl|GET}} 1, 1 + 4 + dw, siz + {{Cl|CLS}} + {{Cl|LOCATE}} 1, 1 'qb64 seems to default to line 2 + {{Cl|SEEK}} 1, 1 + rva2fp(dat) + {{Cl|FOR...NEXT|FOR}} dw = 1 {{Cl|TO}} siz + {{Cl|IF...THEN|IF}} dw > 400 {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|GET}} 1, , b + {{Cl|SELECT CASE}} b + {{Cl|CASE}} 7, 9 {{Cl|TO}} {{Cl|&H}}D, {{Cl|&H}}1F: {{Cl|PRINT}} "."; + {{Cl|CASE ELSE}}: {{Cl|PRINT}} {{Cl|CHR$}}(b); + {{Cl|END SELECT}} + {{Cl|NEXT}} + {{Cl|LOCATE}} 24, 1 + {{Cl|PRINT}} dword$(siz) + " bytes."; + {{Cl|LOCATE}} 23, 1 + {{Cl|LINE INPUT}} "(leave blank to cancel) Output file? "; k + + ' {{Cl|IF...THEN|IF}} k = "v" {{Cl|THEN}} + ' {{Cl|INPUT}} "width in pixels"; w + ' {{Cl|SCREEN}} 13 + ' {{Cl|SEEK}} 1, 1 + rva2fp(dat) + ' {{Cl|FOR...NEXT|FOR}} dw = 1 {{Cl|TO}} siz + ' {{Cl|IF...THEN|IF}} dw \ w >= 200 {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + ' {{Cl|GET}} 1, , b + ' {{Cl|PSET}} (dw {{Cl|MOD}} w, dw \ w), b + ' {{Cl|NEXT}} + ' {{Cl|SLEEP}}: {{Cl|DO...LOOP|DO}}: {{Cl|LOOP}} {{Cl|WHILE}} {{Cl|LEN}}({{Cl|INKEY$}}) + ' {{Cl|SCREEN}} 0 + ' {{Cl|WIDTH}} 80, 25 + ' {{Cl|VIEW PRINT}} + ' {{Cl|CLS}} + ' {{Cl|END IF}} + + {{Cl|IF...THEN|IF}} {{Cl|LEN}}(k) {{Cl|THEN}} + {{Cl|IF...THEN|IF}} {{Cl|_FILEEXISTS}}(k) {{Cl|THEN}} + {{Cl|PRINT}} + {{Cl|PRINT}} "File already exists."; + {{Cl|ELSE}} + {{Cl|OPEN}} k {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|AS}} 2 + {{Cl|SEEK}} 1, 1 + rva2fp(dat) + {{Cl|FOR...NEXT|FOR}} dw = 1 {{Cl|TO}} siz + {{Cl|GET}} 1, , b + {{Cl|PUT}} 2, , b + {{Cl|NEXT}} + {{Cl|CLOSE}} 2 + {{Cl|PRINT}} + {{Cl|PRINT}} "Done."; + {{Cl|END IF}} + {{Cl|SLEEP}}: {{Cl|DO...LOOP|DO}}: {{Cl|LOOP}} {{Cl|WHILE}} {{Cl|LEN}}({{Cl|INKEY$}}) + {{Cl|END IF}} + {{Cl|EXIT DO}} + {{Cl|END IF}} + {{Cl|END SELECT}} + {{Cl|LOOP}} +{{Cl|LOOP}} +{{Cl|END SUB}} + +{{Cl|FUNCTION}} word$ (w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +t = {{Cl|LCASE$}}({{Cl|HEX$}}(w)) +word = "0x" + {{Cl|STRING$}}(4 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t +{{Cl|END FUNCTION}} + +{{Cl|FUNCTION}} dword$ (dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +t = {{Cl|LCASE$}}({{Cl|HEX$}}(dw)) +dword = "0x" + {{Cl|STRING$}}(8 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t +{{Cl|END FUNCTION}} + +{{Cl|FUNCTION}} rva2fp~& (rva {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|FOR...NEXT|FOR}} w = 0 {{Cl|TO}} NumberOfSections - 1 + {{Cl|IF...THEN|IF}} rva < secsva(w) {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} +{{Cl|NEXT}} +w = w - 1 +{{Cl|IF...THEN|IF}} w > NumberOfSections - 1 {{Cl|THEN}} {{Cl|PRINT}} dword$(rva), w: {{Cl|SLEEP}} +rva2fp = rva + (secsfp(w) - secsva(w)) +{{Cl|END FUNCTION}} + +{{Cl|SUB}} dump (addr {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ul {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} b {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_BYTE}} + +{{Cl|VIEW PRINT}} +ul = addr +DO + {{Cl|COLOR}} 7, 0 + {{Cl|CLS}} 0 + {{Cl|SEEK}} 1, 1 + ul + {{Cl|FOR...NEXT|FOR}} dw = ul {{Cl|TO}} (ul {{Cl|AND}} {{Cl|&H}}FFFFFFF0) + {{Cl|&H}}15F + {{Cl|IF...THEN|IF}} (1 + ul) > {{Cl|LOF}}(1) {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|GET}} 1, , b + {{Cl|IF...THEN|IF}} (dw {{Cl|AND}} {{Cl|&H}}F) = 0 {{Cl|THEN}} + t = {{Cl|LCASE$}}({{Cl|HEX$}}(dw)) + {{Cl|COLOR}} 7 + {{Cl|PRINT}} {{Cl|STRING$}}(8 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t; {{Cl|SPACE$}}(2); + {{Cl|END IF}} + {{Cl|IF...THEN|IF}} (dw {{Cl|AND}} {{Cl|&H}}4) {{Cl|THEN}} {{Cl|COLOR}} 3 {{Cl|ELSE}} {{Cl|COLOR}} 2 + {{Cl|LOCATE}} , 14 + ((dw {{Cl|AND}} {{Cl|&H}}F) * 3) + t = {{Cl|LCASE$}}({{Cl|HEX$}}(b)) + {{Cl|IF...THEN|IF}} b < {{Cl|&H}}10 {{Cl|THEN}} {{Cl|PRINT}} "0" + t; {{Cl|ELSE}} {{Cl|PRINT}} t; + {{Cl|LOCATE}} , 65 + (dw {{Cl|AND}} {{Cl|&H}}F) + {{Cl|SELECT CASE}} b + {{Cl|CASE}} 7, 9 {{Cl|TO}} {{Cl|&H}}D, {{Cl|&H}}1F: {{Cl|PRINT}} "."; + {{Cl|CASE ELSE}}: {{Cl|PRINT}} {{Cl|CHR$}}(b); + {{Cl|END SELECT}} + {{Cl|NEXT}} + {{Cl|PRINT}} + {{Cl|COLOR}} 7 + {{Cl|LINE INPUT}} "(leave blank to cancel) Address: 0x"; t + {{Cl|IF...THEN|IF}} {{Cl|LTRIM$}}(t) = "" {{Cl|THEN}} {{Cl|EXIT DO}} + ul = {{Cl|VAL}}("&h" + t + "&") {{Cl|AND}} {{Cl|&H}}7FFFFFFF +{{Cl|LOOP}} +{{Cl|END SUB}} +{{CodeEnd}} + +: The .ICO format: + +<center>http://en.wikipedia.org/wiki/ICO_%28file_format%29 + +http://www.iconolog.org/info/icoFormat.html + +http://en.wikipedia.org/wiki/BMP_file_format </center> + + +:Note that the BMP file header is excluded, but the DIB information header is included. My observations from using Resource Hacker on ''c:\windows\notepad.exe'': + +:I've downloaded Resource Hacker. Note that if you export the first icon of \windows\notepad.exe as a binary file, it is identical to the file exported from my program (verifiable with fc /b). However, if you export it as an icon file, Resource Hacker adds 22 bytes to the beginning of it, a 6 byte ICONDIR structure, and a 16 byte ICONDIRENTRY structure. Resource Hacker is getting this information from the Icon Group resource. + +:If you export the Icon Group resource as a binary file, you will see that it starts with an ICONDIR structure specifying 9 images. It is followed by an array of 9 structures, 14 bytes each. The first 12 bytes are the same as an ICONDIRENTRY structure. (with a 2x Height difference). The last element, which would be a dword offset in a ICONDIRENTRY structure is instead a word index identifying the particular icon. + +:You can see what I mean: Use Resource Hacker to export the Icon Group as a binary file, named rhig.bin: + +{{WhiteStart}} edit /78 rhig.bin {{WhiteEnd}} + +: Delete the first 6 bytes, and save it as rhigmod.bin. + +{{WhiteStart}} edit /14 rhigmod.bin {{WhiteEnd}} + +: and you can clearly see the array. + +: Note that, according to: + +<center>http://www.iconolog.org/info/icoFormat.html</center> + +: There is supposed to be a 2x Height difference between the ICONDIRENTRY structure in the icon file, and the DIB header within the icon file, with the DIB header having 2x the Height. However, when Resource Hacker exported the Icon file, it put 2x the Height in the ICONDIRENTRY structure also, doubling it from the Icon Group data. Icons seem to be Type ID 0x3, and Icon Groups seem to be Type ID 0xe. This seems consistent with: + +<center>http://msdn.microsoft.com/en-us/library/ms648009(v=VS.85).aspx</center> + +: I'll probably write some code in the next day or two to automate the process of extracting icons from a PE. My observations would need to be double checked before being relied upon. (as always) + +:Regards, Michael Calkins + + +<p style="text-align: center">([[#toc|Return to Table of Contents]])</p> + +==Revision 3== +: The addresses of the strings were also offsets from the start of the main table. So now, it should correctly display the names of named entries. It now displays the names of known Type IDs. It can now accept the PE file name as a command line parameter, so that you can press up, enter, from the cmd prompt to restart it without having to type the name again. + +:I've moved the first horizontal line down 1 line. There is a minor optimization in that there is one less call to rva2fp. +{{CodeStart}} '' '' +'revision 20120316, michael calkins +'october 2011, michael calkins +'my code is public domain, but it's based on Microsoft's spec, so I'm not sure +'what kind of patents or copyrights apply. +'based on the Microsoft PE and COFF spec, Revision 8.2 - September 21, 2010 +'http://msdn.microsoft.com/en-us/windows/hardware/gg463119.aspx + +'bug fixes on 2012 03 16: +' changed NumberOfRvaAndSizes to an _unsigned long +' added {{Cl|_CONTROLCHR}} OFF to the dump sub, and replaced the select case + +{{Cl|DIM}} nam {{Cl|AS}} {{Cl|STRING}} * 8 +{{Cl|DIM}} fil {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} k {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ul {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} coff {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} SectionTable {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ImageBase {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} rsrc {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} pe32plus {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} SizeOfOptionalHeader {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} {{Cl|SHARED}} NumberOfSections {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} NumberOfRvaAndSizes {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} + +{{Cl|CLS}} +fil = {{Cl|COMMAND$}} +{{Cl|IF...THEN|IF}} {{Cl|LEN}}(fil) = 0 {{Cl|THEN}} {{Cl|LINE INPUT}} "Name of the PE image to open? "; fil +{{Cl|IF...THEN|IF}} {{Cl|_FILEEXISTS}}(fil) = 0 {{Cl|THEN}} {{Cl|PRINT}} "File not found.": {{Cl|END}} +{{Cl|OPEN}} fil {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|ACCESS}} {{Cl|READ}} {{Cl|AS}} 1 +{{Cl|GET}} 1, 1 + 0, w +{{Cl|IF...THEN|IF}} w <> {{Cl|&H}}5A4D {{Cl|THEN}} {{Cl|PRINT}} "No MZ signature.": {{Cl|END}} +{{Cl|GET}} 1, 1 + {{Cl|&H}}3C, dw +coff = dw + 4 +{{Cl|GET}} 1, dw + 1, dw +{{Cl|IF...THEN|IF}} dw <> {{Cl|&H}}4550& {{Cl|THEN}} {{Cl|PRINT}} "No PE signature.": {{Cl|END}} +{{Cl|GET}} 1, 1 + coff + 2, NumberOfSections +{{Cl|IF...THEN|IF}} NumberOfSections = 0 {{Cl|THEN}} {{Cl|PRINT}} "No sections.": {{Cl|END}} +{{Cl|PRINT}} "NumberOfSections:"; NumberOfSections +{{Cl|DIM}} {{Cl|SHARED}} secsva(0 {{Cl|TO}} NumberOfSections - 1) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} {{Cl|SHARED}} secsfp(0 {{Cl|TO}} NumberOfSections - 1) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|GET}} 1, 1 + coff + 16, SizeOfOptionalHeader +{{Cl|IF...THEN|IF}} SizeOfOptionalHeader = 0 {{Cl|THEN}} {{Cl|PRINT}} "No optional header.": {{Cl|END}} +{{Cl|PRINT}} "SizeOfOptionalHeader:", {{Cl|SPACE$}}(4); word$(SizeOfOptionalHeader) +{{Cl|GET}} 1, 1 + coff + 20, w +{{Cl|SELECT CASE}} w + {{Cl|CASE}} {{Cl|&H}}10B: pe32plus = 0: {{Cl|PRINT}} "PE32" + {{Cl|CASE}} {{Cl|&H}}20B: pe32plus = -1: {{Cl|PRINT}} "PE32+" + {{Cl|CASE ELSE}}: {{Cl|PRINT}} "Unknown Magic.": {{Cl|END}} +{{Cl|END SELECT}} +{{Cl|GET}} 1, 1 + coff + 20 + 28 + (-4 {{Cl|AND (boolean)|AND}} pe32plus), ImageBase +{{Cl|PRINT}} "ImageBase:", "", dword$(ImageBase) +{{Cl|GET}} 1, 1 + coff + 20 + 92 + (16 {{Cl|AND (boolean)|AND}} pe32plus), NumberOfRvaAndSizes +{{Cl|IF...THEN|IF}} NumberOfRvaAndSizes < 3 {{Cl|THEN}} {{Cl|PRINT}} "No resource table.": {{Cl|END}} +{{Cl|PRINT}} "NumberOfRvaAndSizes:"; NumberOfRvaAndSizes +{{Cl|GET}} 1, 1 + coff + 20 + 112 + (16 {{Cl|AND (boolean)|AND}} pe32plus), rsrc +{{Cl|PRINT}} "Rva of resource table:", dword$(rsrc) +{{Cl|GET}} 1, 1 + coff + 20 + 4 + 112 + (16 {{Cl|AND (boolean)|AND}} pe32plus), dw +{{Cl|PRINT}} "Size of resource table:", dword$(dw) +{{Cl|IF...THEN|IF}} (rsrc = 0) {{Cl|OR (boolean)|OR}} (dw = 0) {{Cl|THEN}} {{Cl|PRINT}} "No resource table.": {{Cl|END}} +SectionTable = coff + 20 + SizeOfOptionalHeader +{{Cl|PRINT}} "section", "va", "file ptr" +{{Cl|FOR...NEXT|FOR}} w = 0 {{Cl|TO}} NumberOfSections - 1 + {{Cl|GET}} 1, 1 + SectionTable + (40 * w), nam + {{Cl|GET}} 1, 1 + SectionTable + 12 + (40 * w), ul + {{Cl|GET}} 1, 1 + SectionTable + 20 + (40 * w), dw + {{Cl|PRINT}} nam, dword$(ul), dword$(dw) + secsva(w) = ul + secsfp(w) = dw +{{Cl|NEXT}} +{{Cl|PRINT}} +{{Cl|PRINT}} "Proceed? "; +DO + k = {{Cl|LCASE$}}({{Cl|INKEY$}}) + {{Cl|IF...THEN|IF}} k = "n" {{Cl|THEN}} {{Cl|PRINT}} k: {{Cl|END}} +{{Cl|LOOP}} {{Cl|UNTIL}} k = "y" +{{Cl|PRINT}} k +dw = rva2fp(rsrc) +processtable dw, dw, 0 +{{Cl|SYSTEM}} + +{{Cl|SUB}} processtable (bs {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}, addr {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}, level {{Cl|AS}} {{Cl|INTEGER}}) +{{Cl|DIM}} k {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} numnamest8 {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} dat {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} siz {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} so {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} sc {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} numnames {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} numids {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} ln {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} x {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} y {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} b {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_BYTE}} + +{{Cl|GET}} 1, 1 + addr + 12, numnames +{{Cl|GET}} 1, 1 + addr + 14, numids +{{Cl|DIM}} nams(0 {{Cl|TO}} numnames + (numnames > 0)) {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} namsrva(0 {{Cl|TO}} numnames + (numnames > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ids(0 {{Cl|TO}} numids + (numids > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} idsrva(0 {{Cl|TO}} numids + (numids > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} + +'get named entries +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} numnames - 1 + {{Cl|GET}} 1, 1 + addr + 16 + (x * 8), dw + 'the spec says its an rva, but it seems to be an offset in the section/table + 'low 31 bits are an offset from bs + {{Cl|GET}} 1, 1 + bs + (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}7FFFFFFF), ln + {{Cl|FOR...NEXT|FOR}} y = 0 {{Cl|TO}} ln - 1 + {{Cl|GET}} 1, , w + {{Cl|SELECT CASE}} w + {{Cl|CASE}} {{Cl|&H}}20 {{Cl|TO}} {{Cl|&H}}7E: nams(x) = nams(x) + {{Cl|CHR$}}(w) + {{Cl|CASE ELSE}}: nams(x) = nams(x) + {{Cl|CHR$}}({{Cl|&H}}1A) + {{Cl|END SELECT}} + {{Cl|IF...THEN|IF}} y = 68 {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|NEXT}} + {{Cl|GET}} 1, 1 + addr + 16 + 4 + (x * 8), namsrva(x) +{{Cl|NEXT}} + +'get numbered entries: +numnamest8 = numnames * 8 +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} numids - 1 + {{Cl|GET}} 1, 1 + addr + 16 + numnamest8 + (x * 8), ids(x) + {{Cl|GET}} 1, 1 + addr + 16 + 4 + numnamest8 + (x * 8), idsrva(x) +{{Cl|NEXT}} + +'display: +{{Cl|VIEW PRINT}} +sc = 0 +so = 0 +DO + {{Cl|CLS}} 0 'qb64 bug? not locating to 1,1? + {{Cl|LOCATE}} 1, 1 + {{Cl|SELECT CASE}} level + {{Cl|CASE}} 0: {{Cl|PRINT}} "1st level - Type"; + {{Cl|CASE}} 1: {{Cl|PRINT}} "2nd level - Name"; + {{Cl|CASE}} 2: {{Cl|PRINT}} "3rd level - Language"; + {{Cl|CASE ELSE}}: {{Cl|PRINT}} {{Cl|LTRIM$}}({{Cl|STR$}}(level)) + "th level"; + {{Cl|END SELECT}} + {{Cl|PRINT}} "", "file ptr: "; dword$(addr); ". Press 'D' to dump." + {{Cl|PRINT}} numnames; "names in this level, in this branch." + {{Cl|PRINT}} numids; "IDs in this level, in this branch." + {{Cl|IF...THEN|IF}} (numnames {{Cl|OR (boolean)|OR}} numids) = 0 {{Cl|THEN}} + {{Cl|IF...THEN|IF}} level {{Cl|THEN}} + {{Cl|PRINT}} "Press any key to go up one level." + {{Cl|SLEEP}}: {{Cl|DO...LOOP|DO}}: {{Cl|LOOP}} {{Cl|WHILE}} {{Cl|LEN}}({{Cl|INKEY$}}) + {{Cl|EXIT SUB}} + {{Cl|ELSE}} + {{Cl|END}} + {{Cl|END IF}} + {{Cl|END IF}} + {{Cl|PRINT}} "names are unicode. For simplicity, non ASCII chars will be shown as " + {{Cl|CHR$}}({{Cl|&H}}1A) + "." + {{Cl|IF...THEN|IF}} level {{Cl|THEN}} + {{Cl|PRINT}} "BKSP or ESC to go up one level." + {{Cl|ELSE}} + {{Cl|PRINT}} "BKSP or ESC to exit." + {{Cl|END IF}} + {{Cl|PRINT}} "UP, DOWN, PGUP, PGDN, HOME, {{Cl|END}} to navigate list." + {{Cl|PRINT}} "ENTER to select." + {{Cl|LOCATE}} 9, 1 + {{Cl|PRINT}} {{Cl|STRING$}}(80, {{Cl|&H}}C4); + {{Cl|LOCATE}} 22, 1 + {{Cl|PRINT}} {{Cl|STRING$}}(80, {{Cl|&H}}C4); + DO + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 8, 1: {{Cl|PRINT}} dword$(sc) + {{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} 11 + {{Cl|LOCATE}} 10 + x, 1 + {{Cl|IF...THEN|IF}} x + so = sc {{Cl|THEN}} {{Cl|COLOR}} 15, 1 {{Cl|ELSE}} {{Cl|COLOR}} 7, 0 + {{Cl|IF...THEN|IF}} (x + so) < numnames {{Cl|THEN}} + {{Cl|PRINT}} nams(x + so); {{Cl|SPACE$}}(70 - {{Cl|LEN}}(nams(x + so))); + {{Cl|PRINT}} dword$(bs + (namsrva(x + so) {{Cl|AND (boolean)|AND}} {{Cl|&H}}7FFFFFFF&)); + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 7, 18 + {{Cl|IF...THEN|IF}} namsrva(x + so) {{Cl|AND (boolean)|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + {{Cl|PRINT}} "(descend)"; + {{Cl|ELSE}} + {{Cl|PRINT}} "(extract)"; + {{Cl|END IF}} + {{Cl|ELSEIF}} (x + so) < (numnames + numids) {{Cl|THEN}} + {{Cl|PRINT}} "ID: " + dword$(ids(x + so - numnames)); + {{Cl|IF...THEN|IF}} level = 0 {{Cl|THEN}} + {{Cl|PRINT}} " (RT_"; + 'derived from: + ' http://msdn.microsoft.com/en-us/library/ms648009(v=VS.85).aspx + {{Cl|SELECT CASE}} ids(x + so - numnames) + {{Cl|CASE}} 9: {{Cl|PRINT}} "ACCELERATOR"; + {{Cl|CASE}} 21: {{Cl|PRINT}} "ANICURSOR"; + {{Cl|CASE}} 22: {{Cl|PRINT}} "ANIICON"; + {{Cl|CASE}} 2: {{Cl|PRINT}} "BITMAP"; + {{Cl|CASE}} 1: {{Cl|PRINT}} "CURSOR"; + {{Cl|CASE}} 5: {{Cl|PRINT}} "DIALOG"; + {{Cl|CASE}} 17: {{Cl|PRINT}} "DLGINCLUDE"; + {{Cl|CASE}} 8: {{Cl|PRINT}} "FONT"; + {{Cl|CASE}} 7: {{Cl|PRINT}} "FONTDIR"; + {{Cl|CASE}} 12: {{Cl|PRINT}} "GROUP_CURSOR"; + {{Cl|CASE}} 14: {{Cl|PRINT}} "GROUP_ICON"; + {{Cl|CASE}} 23: {{Cl|PRINT}} "HTML"; + {{Cl|CASE}} 3: {{Cl|PRINT}} "ICON"; + {{Cl|CASE}} 24: {{Cl|PRINT}} "MANIFEST"; + {{Cl|CASE}} 4: {{Cl|PRINT}} "MENU"; + {{Cl|CASE}} 11: {{Cl|PRINT}} "MESSAGETABLE"; + {{Cl|CASE}} 19: {{Cl|PRINT}} "PLUGPLAY"; + {{Cl|CASE}} 10: {{Cl|PRINT}} "RCDATA"; + {{Cl|CASE}} 6: {{Cl|PRINT}} "{{Cl|STRING}}"; + {{Cl|CASE}} 16: {{Cl|PRINT}} "VERSION"; + {{Cl|CASE}} 20: {{Cl|PRINT}} "VXD"; + {{Cl|END SELECT}} + {{Cl|PRINT}} ")"; + {{Cl|END IF}} + {{Cl|PRINT}} {{Cl|SPACE$}}(71 - {{Cl|POS}}(0)); + {{Cl|PRINT}} dword$(bs + (idsrva(x + so - numnames))); + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 7, 18 + {{Cl|IF...THEN|IF}} idsrva(x + (so - numnames)) {{Cl|AND (boolean)|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + {{Cl|PRINT}} "(descend)"; + {{Cl|ELSE}} + {{Cl|PRINT}} "(extract)"; + {{Cl|END IF}} + {{Cl|ELSE}} + {{Cl|PRINT}} {{Cl|SPACE$}}(80); + {{Cl|END IF}} + {{Cl|NEXT}} + DO + k = {{Cl|INKEY$}} + {{Cl|LOOP}} {{Cl|UNTIL}} {{Cl|LEN}}(k) + {{Cl|SELECT CASE}} k + {{Cl|CASE}} "d", "D" + dump addr + {{Cl|EXIT DO}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4800) 'up + {{Cl|IF...THEN|IF}} sc > 0 {{Cl|THEN}} + sc = sc - 1 + {{Cl|IF...THEN|IF}} sc < so {{Cl|THEN}} so = sc + {{Cl|END IF}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}5000) 'down + {{Cl|IF...THEN|IF}} sc < (numnames + numids - 1) {{Cl|THEN}} + sc = sc + 1 + {{Cl|IF...THEN|IF}} sc > (so + 11) {{Cl|THEN}} + so = sc - 11 + {{Cl|IF...THEN|IF}} so > sc {{Cl|THEN}} so = 0 'unsigned + {{Cl|END IF}} + {{Cl|END IF}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4700) 'home + sc = 0 + so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4F00) 'end + sc = numnames + numids - 1 + so = sc - 11 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4900) 'pgup + sc = sc - 12 + so = so - 12 + {{Cl|IF...THEN|IF}} sc < 0 {{Cl|THEN}} sc = 0 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}5100) 'pgdn + sc = sc + 12 + {{Cl|IF...THEN|IF}} sc > (numnames + numids - 1) {{Cl|THEN}} sc = numnames + numids - 1 + so = sc - 11 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|CHR$}}({{Cl|&H}}8), {{Cl|CHR$}}({{Cl|&H}}1B) 'bksp, esc + {{Cl|EXIT SUB}} + {{Cl|CASE}} {{Cl|CHR$}}({{Cl|&H}}D) 'enter + {{Cl|IF...THEN|IF}} sc < numnames {{Cl|THEN}} + dw = namsrva(sc) + {{Cl|ELSE}} + dw = idsrva(sc - numnames) + {{Cl|END IF}} + {{Cl|IF...THEN|IF}} dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + 'the spec says its an rva, but it seems to be an offset in the section/table + processtable bs, bs + (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}7FFFFFFF&), level + 1 + {{Cl|EXIT DO}} + {{Cl|ELSE}} + 'the spec says its an rva, but it seems to be an offset in the section/table + dw = bs + dw + {{Cl|GET}} 1, 1 + dw, dat + {{Cl|GET}} 1, 1 + 4 + dw, siz + {{Cl|CLS}} + {{Cl|LOCATE}} 1, 1 'qb64 seems to default to line 2 + {{Cl|SEEK}} 1, 1 + rva2fp(dat) + {{Cl|FOR...NEXT|FOR}} dw = 1 {{Cl|TO}} siz + {{Cl|IF...THEN|IF}} dw > 400 {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|GET}} 1, , b + {{Cl|SELECT CASE}} b + {{Cl|CASE}} 7, 9 {{Cl|TO}} {{Cl|&H}}D, {{Cl|&H}}1F: {{Cl|PRINT}} "."; + {{Cl|CASE ELSE}}: {{Cl|PRINT}} {{Cl|CHR$}}(b); + {{Cl|END SELECT}} + {{Cl|NEXT}} + {{Cl|LOCATE}} 24, 1 + {{Cl|PRINT}} dword$(siz) + " bytes."; + {{Cl|LOCATE}} 23, 1 + {{Cl|LINE INPUT}} "(leave blank to cancel) Output file? "; k + {{Cl|IF...THEN|IF}} {{Cl|LEN}}(k) {{Cl|THEN}} + {{Cl|IF...THEN|IF}} {{Cl|_FILEEXISTS}}(k) {{Cl|THEN}} + {{Cl|PRINT}} + {{Cl|PRINT}} "File already exists."; + {{Cl|ELSE}} + {{Cl|OPEN}} k {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|AS}} 2 + {{Cl|SEEK}} 1, 1 + rva2fp(dat) + {{Cl|FOR...NEXT|FOR}} dw = 1 {{Cl|TO}} siz + {{Cl|GET}} 1, , b + {{Cl|PUT}} 2, , b + {{Cl|NEXT}} + {{Cl|CLOSE}} 2 + {{Cl|PRINT}} + {{Cl|PRINT}} "Done."; + {{Cl|END IF}} + {{Cl|SLEEP}}: {{Cl|DO...LOOP|DO}}: {{Cl|LOOP}} {{Cl|WHILE}} {{Cl|LEN}}({{Cl|INKEY$}}) + {{Cl|END IF}} + {{Cl|EXIT DO}} + {{Cl|END IF}} + {{Cl|END SELECT}} + {{Cl|LOOP}} +{{Cl|LOOP}} +{{Cl|END SUB}} + +{{Cl|FUNCTION}} word$ (w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +t = {{Cl|LCASE$}}({{Cl|HEX$}}(w)) +word = "0x" + {{Cl|STRING$}}(4 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t +{{Cl|END FUNCTION}} + +{{Cl|FUNCTION}} dword$ (dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +t = {{Cl|LCASE$}}({{Cl|HEX$}}(dw)) +dword = "0x" + {{Cl|STRING$}}(8 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t +{{Cl|END FUNCTION}} + +{{Cl|FUNCTION}} rva2fp~& (rva {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|FOR...NEXT|FOR}} w = 0 {{Cl|TO}} NumberOfSections - 1 + {{Cl|IF...THEN|IF}} rva < secsva(w) {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} +{{Cl|NEXT}} +w = w - 1 +{{Cl|IF...THEN|IF}} w > NumberOfSections - 1 {{Cl|THEN}} {{Cl|PRINT}} dword$(rva), w: {{Cl|SLEEP}} +rva2fp = rva + (secsfp(w) - secsva(w)) +{{Cl|END FUNCTION}} + +{{Cl|SUB}} dump (addr {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ul {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} b {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_BYTE}} + +{{Cl|_CONTROLCHR}} OFF +{{Cl|VIEW PRINT}} +ul = addr +DO + {{Cl|COLOR}} 7, 0 + {{Cl|CLS}} 0 + {{Cl|SEEK}} 1, 1 + ul + {{Cl|FOR...NEXT|FOR}} dw = ul {{Cl|TO}} (ul {{Cl|AND (boolean)|AND}} {{Cl|&H}}FFFFFFF0) + {{Cl|&H}}15F + {{Cl|IF...THEN|IF}} (1 + ul) > {{Cl|LOF}}(1) {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|GET}} 1, , b + {{Cl|IF...THEN|IF}} (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}F) = 0 {{Cl|THEN}} + t = {{Cl|LCASE$}}({{Cl|HEX$}}(dw)) + {{Cl|COLOR}} 7 + {{Cl|PRINT}} {{Cl|STRING$}}(8 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t; {{Cl|SPACE$}}(2); + {{Cl|END IF}} + {{Cl|IF...THEN|IF}} (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}4) {{Cl|THEN}} {{Cl|COLOR}} 3 {{Cl|ELSE}} {{Cl|COLOR}} 2 + {{Cl|LOCATE}} , 14 + ((dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}F) * 3) + t = {{Cl|LCASE$}}({{Cl|HEX$}}(b)) + {{Cl|IF...THEN|IF}} b < {{Cl|&H}}10 {{Cl|THEN}} {{Cl|PRINT}} "0" + t; {{Cl|ELSE}} {{Cl|PRINT}} t; + {{Cl|LOCATE}} , 65 + (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}F) + {{Cl|PRINT}} {{Cl|CHR$}}(b); + {{Cl|NEXT}} + {{Cl|PRINT}} + {{Cl|COLOR}} 7 + {{Cl|LINE INPUT}} "(leave blank to cancel) Address: 0x"; t + {{Cl|IF...THEN|IF}} {{Cl|LTRIM$}}(t) = "" {{Cl|THEN}} {{Cl|EXIT DO}} + ul = {{Cl|VAL}}("&h" + t + "&") {{Cl|AND (boolean)|AND}} {{Cl|&H}}7FFFFFFF +{{Cl|LOOP}} +{{Cl|END SUB}} '' '' +{{CodeEnd}} + + +<p style="text-align: center">([[#toc|Return to Table of Contents]])</p> + +==Extract Icon== +: Here is a program to extract an icon from a PE file. You specify the PE file, the index of the icon group (the first is 0), the maximum width and colors, and the output file. It will try to find the best matching icon, and extract the icon from the first language. I had earlier said that Resource Hacker gets the information for the ICO header from the icon group data. It could, but it could also get the data from the DIB header. Resource Hacker seems to use several fields that are reserved according to: + +<center>http://www.iconolog.org/info/icoFormat.html</center> + +:I use some of those fields in the icon group data to select the best icon from the group. + +: ''Notepad.exe'' has 1 group of 9 icons: 48, 32, and 16 pixels; 32, 8, and 4 bpp each. The 4 bpp icons are the old fashioned ones. :-) I like both the old and new. ''C:\Windows\System32\shell32.dll'' and ''pifmgr.dll'' have numerous icons. +{{CodeStart}} '' '' +'revision date, last person to revise +'revision 20111101, michael calkins +'(derivitives may list sources of derivision) + +'october 2011, michael calkins +'my code is public domain, but it's based on Microsoft's spec, so I'm not sure +'what kind of patents or copyrights apply. +'based on the Microsoft PE and COFF spec, Revision 8.2 - September 21, 2010 +'{{Cl|http://msdn.microsoft.com/en-us/windows/hardware/gg463119.aspx}} + + +{{Cl|DIM}} fil {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} n {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} gi {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} wi {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} bpp {{Cl|AS}} {{Cl|LONG}} + +fil = "\windows\notepad.exe" + +{{Cl|IF...THEN|IF}} {{Cl|LEN}}(fil) = 0 {{Cl|THEN}} {{Cl|LINE INPUT}} fil +gi = 0 'first icon group is normally 0 in most EXE or DLL files +wi = 32 '16 to 256 max width '<<<<<<<<<<< change settings for other sizes +bpp = 8 '4 to 32 bit max color '<<<<<<<<<<< 4 bit may use older style images +mode = 0 ' 0 = icon, 1 = bitmap +del$ = "delme.ico" 'change file extension to .BMP with mode 1 for bitmaps + +{{Cl|IF...THEN|IF}} {{Cl|_FILEEXISTS}}(del$) {{Cl|THEN}} {{Cl|KILL}} del$ 'this file will be erased. +n = geticon(fil, del$, gi, wi, bpp, mode) +{{Cl|IF...THEN|IF}} n {{Cl|THEN}} + {{Cl|PRINT}} "error:"; n, geticonerror(n) + {{Cl|END}} +{{Cl|ELSE}} + {{Cl|SHELL}} {{Cl|_DONTWAIT}} "mspaint " + del$ +{{Cl|END IF}} +{{Cl|SYSTEM}} +' --------------------------------------------------- + +{{Cl|FUNCTION}} geticon& (fin {{Cl|AS}} {{Cl|STRING}}, fout {{Cl|AS}} {{Cl|STRING}}, gi {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}, wi {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}, co {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}, m {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +'function extracts the best matching icon from a specified icon group from +'a specified PE image, and saves it to a specified file in a specified format. +'extracts the first language. + +'fil = input file name +'fout = output file name +'gi = the number of the Icon Group (0 is first) +'wi = the preferred width (width is given priority over color) +'co = the preferred bits per pixel +'m = mode (0 for .ico, nonzero for .bmp) + +'returns 0 for success, nonzero for error. + +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} coff {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} SectionTable {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} pe32plus {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} bs {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} addr {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} nfin {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} nfout {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} numnamest8 {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} dat {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} siz {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} rva {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} fp {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} bc {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} bw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} SizeOfOptionalHeader {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} NumberOfSections {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} NumberOfRvaAndSizes {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} numnames {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} numids {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} x {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} y {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} z {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} b {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_BYTE}} + +{{Cl|IF...THEN|IF}} {{Cl|_FILEEXISTS}}(fin) = 0 {{Cl|THEN}} geticon = 1: {{Cl|EXIT FUNCTION}} +nfin = {{Cl|FREEFILE}} +{{Cl|OPEN}} fin {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|ACCESS}} {{Cl|READ}} {{Cl|AS}} nfin +{{Cl|GET}} nfin, 1 + 0, w +{{Cl|IF...THEN|IF}} w <> {{Cl|&H}}5A4D {{Cl|THEN}} geticon = 2: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|GET}} nfin, 1 + {{Cl|&H}}3C, dw +coff = dw + 4 +{{Cl|GET}} nfin, dw + 1, dw +{{Cl|IF...THEN|IF}} dw <> {{Cl|&H}}4550& {{Cl|THEN}} geticon = 3: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|GET}} nfin, 1 + coff + 2, NumberOfSections +{{Cl|IF...THEN|IF}} NumberOfSections = 0 {{Cl|THEN}} geticon = 4: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|DIM}} secsva(0 {{Cl|TO}} NumberOfSections - 1) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} secsfp(0 {{Cl|TO}} NumberOfSections - 1) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|GET}} nfin, 1 + coff + 16, SizeOfOptionalHeader +{{Cl|IF...THEN|IF}} SizeOfOptionalHeader = 0 {{Cl|THEN}} geticon = 5: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|GET}} nfin, 1 + coff + 20, w +{{Cl|SELECT CASE}} w + {{Cl|CASE}} {{Cl|&H}}10B: pe32plus = 0 + {{Cl|CASE}} {{Cl|&H}}20B: pe32plus = -1 + {{Cl|CASE ELSE}}: geticon = 6: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|END SELECT}} +{{Cl|GET}} nfin, 1 + coff + 20 + 92 + (16 {{Cl|AND}} pe32plus), NumberOfRvaAndSizes +{{Cl|IF...THEN|IF}} NumberOfRvaAndSizes < 3 {{Cl|THEN}} geticon = 7: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|GET}} nfin, 1 + coff + 20 + 112 + (16 {{Cl|AND}} pe32plus), bs +{{Cl|GET}} nfin, 1 + coff + 20 + 4 + 112 + (16 {{Cl|AND}} pe32plus), dw +{{Cl|IF...THEN|IF}} (bs = 0) {{Cl|OR}} (dw = 0) {{Cl|THEN}} geticon = 8: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +SectionTable = coff + 20 + SizeOfOptionalHeader +{{Cl|FOR...NEXT|FOR}} w = 0 {{Cl|TO}} NumberOfSections - 1 + {{Cl|GET}} nfin, 1 + SectionTable + 12 + (40 * w), secsva(w) + {{Cl|GET}} nfin, 1 + SectionTable + 20 + (40 * w), secsfp(w) +{{Cl|NEXT}} + +rva = bs +{{Cl|GOSUB}} rva2fp +bs = fp + +addr = bs +'group icon, first level +{{Cl|GET}} nfin, 1 + addr + 12, numnames +{{Cl|GET}} nfin, 1 + addr + 14, numids +numnamest8 = numnames * 8 +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} numids - 1 + {{Cl|GET}} nfin, 1 + addr + 16 + numnamest8 + (x * 8), dw + {{Cl|IF...THEN|IF}} dw = {{Cl|&H}}E {{Cl|THEN}} + {{Cl|GET}} nfin, 1 + addr + 16 + 4 + numnamest8 + (x * 8), dw: {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|END IF}} +{{Cl|NEXT}} +{{Cl|IF...THEN|IF}} x = numids {{Cl|THEN}} geticon = 9: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|IF...THEN|IF}} dw {{Cl|AND}} {{Cl|&H}}80000000~& = 0 {{Cl|THEN}} geticon = 10: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} + +addr = bs + (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}7FFFFFFF&) +'group icon, second level +{{Cl|GET}} nfin, 1 + addr + 12, numnames +{{Cl|GET}} nfin, 1 + addr + 14, numids +{{Cl|IF...THEN|IF}} gi >= numnames + numids {{Cl|THEN}} geticon = 11: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|GET}} nfin, 1 + addr + 16 + 4 + (gi * 8), dw +{{Cl|IF...THEN|IF}} dw {{Cl|AND}} {{Cl|&H}}80000000~& = 0 {{Cl|THEN}} geticon = 12: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} + +addr = bs + (dw {{Cl|AND}} {{Cl|&H}}7FFFFFFF&) +'group icon, third level +{{Cl|GET}} nfin, 1 + addr + 12, numnames +{{Cl|GET}} nfin, 1 + addr + 14, numids +{{Cl|IF...THEN|IF}} 0 = (numnames + numids) {{Cl|THEN}} geticon = 13: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|GET}} nfin, 1 + addr + 16 + 4, dw +{{Cl|IF...THEN|IF}} dw {{Cl|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} geticon = 14: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} + +'search for best icon within icon group +dw = bs + dw +{{Cl|GET}} nfin, 1 + dw, rva +{{Cl|GET}} nfin, 1 + 4 + dw, siz +{{Cl|GOSUB}} rva2fp +dat = fp +{{Cl|SEEK}} nfin, 1 + dat +{{Cl|IF...THEN|IF}} siz < 6 {{Cl|THEN}} geticon = 15: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|GET}} nfin, 1 + dat, dw +{{Cl|IF...THEN|IF}} dw <> {{Cl|&H}}10000 {{Cl|THEN}} geticon = 16: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|GET}} nfin, 1 + dat + 4, y +{{Cl|IF...THEN|IF}} y = 0 {{Cl|THEN}} geticon = 17: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|IF...THEN|IF}} siz < (6 + (y * 14)) {{Cl|THEN}} geticon = 18: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +bc = 0 +bw = 0 +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} y - 1 + {{Cl|GET}} nfin, 1 + dat + 6 + (x * 14), b + {{Cl|IF...THEN|IF}} b = 0 {{Cl|THEN}} b = 255 + 'best width, then best color + {{Cl|IF...THEN|IF}} (b >= bw) {{Cl|AND}} (b <= wi) {{Cl|THEN}} + {{Cl|GET}} nfin, 1 + dat + 6 + (x * 14) + 6, w + {{Cl|IF...THEN|IF}} ((w > bc) {{Cl|OR}} (b > bw)) {{Cl|AND (boolean)|AND}} (w <= co) {{Cl|THEN}} + bc = w + bw = b + {{Cl|GET}} nfin, 1 + dat + 6 + (x * 14) + 12, z + {{Cl|END IF}} + {{Cl|END IF}} +{{Cl|NEXT}} +{{Cl|IF...THEN|IF}} bc = 0 {{Cl|THEN}} geticon = 19: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} + +addr = bs +'icon, first level +{{Cl|GET}} nfin, 1 + addr + 12, numnames +{{Cl|GET}} nfin, 1 + addr + 14, numids +numnamest8 = numnames * 8 +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} numids - 1 + {{Cl|GET}} nfin, 1 + addr + 16 + numnamest8 + (x * 8), dw + {{Cl|IF...THEN|IF}} dw = {{Cl|&H}}3 {{Cl|THEN}} + {{Cl|GET}} nfin, 1 + addr + 16 + 4 + numnamest8 + (x * 8), dw: {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|END IF}} +{{Cl|NEXT}} +{{Cl|IF...THEN|IF}} x = numids {{Cl|THEN}} geticon = 20: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|IF...THEN|IF}} dw {{Cl|AND}} {{Cl|&H}}80000000~& = 0 {{Cl|THEN}} geticon = 21: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} + +addr = bs + (dw {{Cl|AND}} {{Cl|&H}}7FFFFFFF&) +'icon, second level +{{Cl|GET}} nfin, 1 + addr + 12, numnames +{{Cl|GET}} nfin, 1 + addr + 14, numids +numnamest8 = numnames * 8 +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} numids - 1 + {{Cl|GET}} nfin, 1 + addr + 16 + numnamest8 + (x * 8), dw + {{Cl|IF...THEN|IF}} dw = z {{Cl|THEN}} + {{Cl|GET}} nfin, 1 + addr + 16 + 4 + numnamest8 + (x * 8), dw: {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|END IF}} +{{Cl|NEXT}} +{{Cl|IF...THEN|IF}} x = numids {{Cl|THEN}} geticon = 22: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|IF...THEN|IF}} dw {{Cl|AND}} {{Cl|&H}}80000000~& = 0 {{Cl|THEN}} geticon = 23: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} + +addr = bs + (dw {{Cl|AND}} {{Cl|&H}}7FFFFFFF&) +'icon, third level +{{Cl|GET}} nfin, 1 + addr + 12, numnames +{{Cl|GET}} nfin, 1 + addr + 14, numids +{{Cl|IF...THEN|IF}} 0 = (numnames + numids) {{Cl|THEN}} geticon = 24: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +{{Cl|GET}} nfin, 1 + addr + 16 + 4, dw +{{Cl|IF...THEN|IF}} dw {{Cl|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} geticon = 25: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} + +'extract icon +dw = bs + dw +{{Cl|GET}} nfin, 1 + dw, rva +{{Cl|GET}} nfin, 1 + 4 + dw, siz +{{Cl|GOSUB}} rva2fp +dat = fp +{{Cl|IF...THEN|IF}} {{Cl|_FILEEXISTS}}(fout) {{Cl|THEN}} geticon = 26: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +nfout = {{Cl|FREEFILE}} +{{Cl|OPEN}} fout {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|AS}} nfout +{{Cl|GET}} nfin, 1 + dat + 4, dw 'width, start 4 bytes into BMP header + {{Cl|IF...THEN|IF}} dw < {{Cl|&H}}100 {{Cl|THEN}} wide = dw {{Cl|ELSE}} wide = wi +{{Cl|GET}} nfin, , dw 'double height + {{Cl|IF...THEN|IF}} dw < {{Cl|&H}}1FF {{Cl|THEN}} high = dw \ 2 {{Cl|ELSE}} high = wi +{{Cl|GET}} nfin, 1 + dat + 14, w 'bpp + {{Cl|IF...THEN|IF}} w <= {{Cl|&H}}20 {{Cl|THEN}} bpp = w {{Cl|ELSE}} bpp = co + +{{Cl|IF...THEN|IF}} m {{Cl|THEN}} + 'Create bitmap format pre-header info of 14 bytes + w = {{Cl|CVI}}("BM") + {{Cl|PUT}} nfout, 1, w 'magic + {{Cl|IF...THEN|IF}} bpp <= 8 {{Cl|THEN}} pal = (2 ^ bpp) * 4: pb = bpp / 8 {{Cl|ELSE}} pal = 0: pb = 3 + dw = 54 + (wide * high * pb) + pal 'file size + {{Cl|PUT}} nfout, , dw 'file size + dw = 0 + {{Cl|PUT}} nfout, , dw '2 reserved + dw = 54 + pal 'bitmap header offset + palette if used + {{Cl|PUT}} nfout, , dw 'data offset +{{Cl|ELSE}} + 'Create icon format Icon header and Entry header + w = 0 + {{Cl|PUT}} nfout, 1, w 'reserved + w = 1 '1 = icon, 2 = cursor(this could be set by mode value) + {{Cl|PUT}} nfout, , w 'resource id + {{Cl|PUT}} nfout, , w 'icon count is always one in this procedure + b = wide + {{Cl|PUT}} nfout, , b 'width in Entry header + b = high + {{Cl|PUT}} nfout, , b 'height + {{Cl|IF...THEN|IF}} bpp < 8 {{Cl|THEN}} b = 2 ^ bpp {{Cl|ELSE}} b = 0 + {{Cl|PUT}} nfout, , b 'num of colors + b = 0: w = 0 + {{Cl|PUT}} nfout, , b 'reserved + {{Cl|PUT}} nfout, , w 'column hot spot for cursor + {{Cl|PUT}} nfout, , w 'row hot spot for cursor + {{Cl|PUT}} nfout, , siz 'size of data + dw = 22 'offset of bmp header is 6 + 16 bytes + {{Cl|PUT}} nfout, , dw +{{Cl|END IF}} +{{Cl|SEEK}} nfin, 1 + dat 'seek start of bmp 40 byte header +{{Cl|IF...THEN|IF}} m {{Cl|THEN}} + {{Cl|GET}} nfin, , dw + {{Cl|PUT}} nfout, , dw 'header size + {{Cl|GET}} nfin, , dw + dw = wide + {{Cl|PUT}} nfout, , dw 'width + dw = high + {{Cl|PUT}} nfout, , dw 'height + {{Cl|GET}} nfin, , dw 'ignore double height + siz = (wide * high * pb) + 28 + pal 'stop at {{Cl|AND}} mask +{{Cl|END IF}} +{{Cl|FOR...NEXT|FOR}} dw = 1 {{Cl|TO}} siz 'GET remaining image data including + {{Cl|GET}} nfin, , b ' 'BMP header, palette and mask(s) + {{Cl|PUT}} nfout, , b +{{Cl|NEXT}} dw +{{Cl|CLOSE}} nfout +{{Cl|CLOSE}} nfin + +geticon = 0 +{{Cl|EXIT FUNCTION}} + +rva2fp: 'call with rva returns fp modifies w + +{{Cl|FOR...NEXT|FOR}} w = 0 {{Cl|TO}} NumberOfSections - 1 + {{Cl|IF...THEN|IF}} rva < secsva(w) {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} +{{Cl|NEXT}} +w = w - 1 +{{Cl|IF...THEN|IF}} w > NumberOfSections - 1 {{Cl|THEN}} geticon = 27: {{Cl|CLOSE}} nfin: {{Cl|EXIT FUNCTION}} +fp = rva + (secsfp(w) - secsva(w)) +{{Cl|RETURN}} + +{{Cl|END FUNCTION}} + +{{Cl|FUNCTION}} geticonerror$ (n {{Cl|AS}} {{Cl|LONG}}) +'revision date, last person to revise revision 20111031, michael calkins +'(derivitives may list sources of derivision) october 2011, public domain, michael calkins +{{Cl|SELECT CASE}} n + {{Cl|CASE}} 0: geticonerror = "success" + {{Cl|CASE}} 1: geticonerror = "input file not found" + {{Cl|CASE}} 2: geticonerror = "MZ signature not found" + {{Cl|CASE}} 3: geticonerror = "PE signature not found" + {{Cl|CASE}} 4: geticonerror = "no sections found" + {{Cl|CASE}} 5: geticonerror = "optional header not found" + {{Cl|CASE}} 6: geticonerror = "unknown PE optional header" + {{Cl|CASE}} 7: geticonerror = "no resource table" + {{Cl|CASE}} 8: geticonerror = "no resource table" + {{Cl|CASE}} 9: geticonerror = "icon groups not found" + {{Cl|CASE}} 10: geticonerror = "icon group: 1st level entry is a leaf" + {{Cl|CASE}} 11: geticonerror = "specified icon group not found" + {{Cl|CASE}} 12: geticonerror = "icon group: 2nd level entry is a leaf" + {{Cl|CASE}} 13: geticonerror = "no language for specified icon group" + {{Cl|CASE}} 14: geticonerror = "icon group: 3rd level entry is not a leaf" + {{Cl|CASE}} 15: geticonerror = "icon group data is too small" + {{Cl|CASE}} 16: geticonerror = "icon group data is not as expected" + {{Cl|CASE}} 17: geticonerror = "no icons in group" + {{Cl|CASE}} 18: geticonerror = "icon array is too small" + {{Cl|CASE}} 19: geticonerror = "could not find an icon matching the specifications" + {{Cl|CASE}} 20: geticonerror = "icons not found" + {{Cl|CASE}} 21: geticonerror = "icon: 1st level entry is a leaf" + {{Cl|CASE}} 22: geticonerror = "target icon not found" + {{Cl|CASE}} 23: geticonerror = "icon: 2nd level entry is a leaf" + {{Cl|CASE}} 24: geticonerror = "no language for target icon" + {{Cl|CASE}} 25: geticonerror = "icon: 3rd level is not a leaf" + {{Cl|CASE}} 26: geticonerror = "output file already exists" + {{Cl|CASE}} 27: geticonerror = "could not convert rva to fp" + {{Cl|CASE ELSE}}: geticonerror = "unknown error" +{{Cl|END SELECT}} +{{Cl|END FUNCTION}} '' '' +{{CodeEnd}} +: ''Note:'' Change the file name to .BMP and mode to 1 to extract the icon as a bitmap for QB64 to use. QB64 cannot load icons! + +: Have fun, and don't forget to double check it before relying on it. I appreciate bug reports, but I'm not responsible for errors. + +: Regards, Michael Calkins + + +<p style="text-align: center">([[#toc|Return to Table of Contents]])</p> + +==Extract Resources== + +{{CodeStart}} '' '' +'revision 20120316, michael calkins +'october 2011, michael calkins +'my code is public domain, but it's based on Microsoft's spec, so I'm not sure +'what kind of patents or copyrights apply. +'based on the Microsoft PE and COFF spec, Revision 8.2 - September 21, 2010 +'http://msdn.microsoft.com/en-us/windows/hardware/gg463119.aspx + +'bug fixes on 2012 03 16: +' changed NumberOfRvaAndSizes to an _unsigned long +' added {{Cl|_CONTROLCHR}} OFF to the dump sub, and replaced the select case + +{{Cl|DIM}} nam {{Cl|AS}} {{Cl|STRING}} * 8 +{{Cl|DIM}} fil {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} k {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ul {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} coff {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} SectionTable {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ImageBase {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} rsrc {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} pe32plus {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} SizeOfOptionalHeader {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} {{Cl|SHARED}} NumberOfSections {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} NumberOfRvaAndSizes {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} + +{{Cl|CLS}} +fil = {{Cl|COMMAND$}} +{{Cl|IF...THEN|IF}} {{Cl|LEN}}(fil) = 0 {{Cl|THEN}} {{Cl|LINE INPUT}} "Name of the PE image to open? "; fil +{{Cl|IF...THEN|IF}} {{Cl|_FILEEXISTS}}(fil) = 0 {{Cl|THEN}} {{Cl|PRINT}} "File not found.": {{Cl|END}} +{{Cl|OPEN}} fil {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|ACCESS}} {{Cl|READ}} {{Cl|AS}} 1 +{{Cl|GET}} 1, 1 + 0, w +{{Cl|IF...THEN|IF}} w <> {{Cl|&H}}5A4D {{Cl|THEN}} {{Cl|PRINT}} "No MZ signature.": {{Cl|END}} +{{Cl|GET}} 1, 1 + {{Cl|&H}}3C, dw +coff = dw + 4 +{{Cl|GET}} 1, dw + 1, dw +{{Cl|IF...THEN|IF}} dw <> {{Cl|&H}}4550& {{Cl|THEN}} {{Cl|PRINT}} "No PE signature.": {{Cl|END}} +{{Cl|GET}} 1, 1 + coff + 2, NumberOfSections +{{Cl|IF...THEN|IF}} NumberOfSections = 0 {{Cl|THEN}} {{Cl|PRINT}} "No sections.": {{Cl|END}} +{{Cl|PRINT}} "NumberOfSections:"; NumberOfSections +{{Cl|DIM}} {{Cl|SHARED}} secsva(0 {{Cl|TO}} NumberOfSections - 1) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} {{Cl|SHARED}} secsfp(0 {{Cl|TO}} NumberOfSections - 1) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|GET}} 1, 1 + coff + 16, SizeOfOptionalHeader +{{Cl|IF...THEN|IF}} SizeOfOptionalHeader = 0 {{Cl|THEN}} {{Cl|PRINT}} "No optional header.": {{Cl|END}} +{{Cl|PRINT}} "SizeOfOptionalHeader:", {{Cl|SPACE$}}(4); word$(SizeOfOptionalHeader) +{{Cl|GET}} 1, 1 + coff + 20, w +{{Cl|SELECT CASE}} w + {{Cl|CASE}} {{Cl|&H}}10B: pe32plus = 0: {{Cl|PRINT}} "PE32" + {{Cl|CASE}} {{Cl|&H}}20B: pe32plus = -1: {{Cl|PRINT}} "PE32+" + {{Cl|CASE ELSE}}: {{Cl|PRINT}} "Unknown Magic.": {{Cl|END}} +{{Cl|END SELECT}} +{{Cl|GET}} 1, 1 + coff + 20 + 28 + (-4 {{Cl|AND (boolean)|AND}} pe32plus), ImageBase +{{Cl|PRINT}} "ImageBase:", "", dword$(ImageBase) +{{Cl|GET}} 1, 1 + coff + 20 + 92 + (16 {{Cl|AND (boolean)|AND}} pe32plus), NumberOfRvaAndSizes +{{Cl|IF...THEN|IF}} NumberOfRvaAndSizes < 3 {{Cl|THEN}} {{Cl|PRINT}} "No resource table.": {{Cl|END}} +{{Cl|PRINT}} "NumberOfRvaAndSizes:"; NumberOfRvaAndSizes +{{Cl|GET}} 1, 1 + coff + 20 + 112 + (16 {{Cl|AND (boolean)|AND}} pe32plus), rsrc +{{Cl|PRINT}} "Rva of resource table:", dword$(rsrc) +{{Cl|GET}} 1, 1 + coff + 20 + 4 + 112 + (16 {{Cl|AND (boolean)|AND}} pe32plus), dw +{{Cl|PRINT}} "Size of resource table:", dword$(dw) +{{Cl|IF...THEN|IF}} (rsrc = 0) {{Cl|OR (boolean)|OR}} (dw = 0) {{Cl|THEN}} {{Cl|PRINT}} "No resource table.": {{Cl|END}} +SectionTable = coff + 20 + SizeOfOptionalHeader +{{Cl|PRINT}} "section", "va", "file ptr" +{{Cl|FOR...NEXT|FOR}} w = 0 {{Cl|TO}} NumberOfSections - 1 + {{Cl|GET}} 1, 1 + SectionTable + (40 * w), nam + {{Cl|GET}} 1, 1 + SectionTable + 12 + (40 * w), ul + {{Cl|GET}} 1, 1 + SectionTable + 20 + (40 * w), dw + {{Cl|PRINT}} nam, dword$(ul), dword$(dw) + secsva(w) = ul + secsfp(w) = dw +{{Cl|NEXT}} +{{Cl|PRINT}} +{{Cl|PRINT}} "Proceed? "; +DO + k = {{Cl|LCASE$}}({{Cl|INKEY$}}) + {{Cl|IF...THEN|IF}} k = "n" {{Cl|THEN}} {{Cl|PRINT}} k: {{Cl|END}} +{{Cl|LOOP}} {{Cl|UNTIL}} k = "y" +{{Cl|PRINT}} k +dw = rva2fp(rsrc) +processtable dw, dw, 0 +{{Cl|SYSTEM}} + +{{Cl|SUB}} processtable (bs {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}, addr {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}, level {{Cl|AS}} {{Cl|INTEGER}}) +{{Cl|DIM}} k {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} numnamest8 {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} dat {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} siz {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} so {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} sc {{Cl|AS}} {{Cl|LONG}} +{{Cl|DIM}} numnames {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} numids {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} ln {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} x {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} y {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|DIM}} b {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_BYTE}} + +{{Cl|GET}} 1, 1 + addr + 12, numnames +{{Cl|GET}} 1, 1 + addr + 14, numids +{{Cl|DIM}} nams(0 {{Cl|TO}} numnames + (numnames > 0)) {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} namsrva(0 {{Cl|TO}} numnames + (numnames > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ids(0 {{Cl|TO}} numids + (numids > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} idsrva(0 {{Cl|TO}} numids + (numids > 0)) {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} + +'get named entries +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} numnames - 1 + {{Cl|GET}} 1, 1 + addr + 16 + (x * 8), dw + 'the spec says its an rva, but it seems to be an offset in the section/table + 'low 31 bits are an offset from bs + {{Cl|GET}} 1, 1 + bs + (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}7FFFFFFF), ln + {{Cl|FOR...NEXT|FOR}} y = 0 {{Cl|TO}} ln - 1 + {{Cl|GET}} 1, , w + {{Cl|SELECT CASE}} w + {{Cl|CASE}} {{Cl|&H}}20 {{Cl|TO}} {{Cl|&H}}7E: nams(x) = nams(x) + {{Cl|CHR$}}(w) + {{Cl|CASE ELSE}}: nams(x) = nams(x) + {{Cl|CHR$}}({{Cl|&H}}1A) + {{Cl|END SELECT}} + {{Cl|IF...THEN|IF}} y = 68 {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|NEXT}} + {{Cl|GET}} 1, 1 + addr + 16 + 4 + (x * 8), namsrva(x) +{{Cl|NEXT}} + +'get numbered entries: +numnamest8 = numnames * 8 +{{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} numids - 1 + {{Cl|GET}} 1, 1 + addr + 16 + numnamest8 + (x * 8), ids(x) + {{Cl|GET}} 1, 1 + addr + 16 + 4 + numnamest8 + (x * 8), idsrva(x) +{{Cl|NEXT}} + +'display: +{{Cl|VIEW PRINT}} +sc = 0 +so = 0 +DO + {{Cl|CLS}} 0 'qb64 bug? not locating to 1,1? + {{Cl|LOCATE}} 1, 1 + {{Cl|SELECT CASE}} level + {{Cl|CASE}} 0: {{Cl|PRINT}} "1st level - Type"; + {{Cl|CASE}} 1: {{Cl|PRINT}} "2nd level - Name"; + {{Cl|CASE}} 2: {{Cl|PRINT}} "3rd level - Language"; + {{Cl|CASE ELSE}}: {{Cl|PRINT}} {{Cl|LTRIM$}}({{Cl|STR$}}(level)) + "th level"; + {{Cl|END SELECT}} + {{Cl|PRINT}} "", "file ptr: "; dword$(addr); ". Press 'D' to dump." + {{Cl|PRINT}} numnames; "names in this level, in this branch." + {{Cl|PRINT}} numids; "IDs in this level, in this branch." + {{Cl|IF...THEN|IF}} (numnames {{Cl|OR (boolean)|OR}} numids) = 0 {{Cl|THEN}} + {{Cl|IF...THEN|IF}} level {{Cl|THEN}} + {{Cl|PRINT}} "Press any key to go up one level." + {{Cl|SLEEP}}: {{Cl|DO...LOOP|DO}}: {{Cl|LOOP}} {{Cl|WHILE}} {{Cl|LEN}}({{Cl|INKEY$}}) + {{Cl|EXIT SUB}} + {{Cl|ELSE}} + {{Cl|END}} + {{Cl|END IF}} + {{Cl|END IF}} + {{Cl|PRINT}} "names are unicode. For simplicity, non ASCII chars will be shown as " + {{Cl|CHR$}}({{Cl|&H}}1A) + "." + {{Cl|IF...THEN|IF}} level {{Cl|THEN}} + {{Cl|PRINT}} "BKSP or ESC to go up one level." + {{Cl|ELSE}} + {{Cl|PRINT}} "BKSP or ESC to exit." + {{Cl|END IF}} + {{Cl|PRINT}} "UP, DOWN, PGUP, PGDN, HOME, {{Cl|END}} to navigate list." + {{Cl|PRINT}} "ENTER to select." + {{Cl|LOCATE}} 9, 1 + {{Cl|PRINT}} {{Cl|STRING$}}(80, {{Cl|&H}}C4); + {{Cl|LOCATE}} 22, 1 + {{Cl|PRINT}} {{Cl|STRING$}}(80, {{Cl|&H}}C4); + DO + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 8, 1: {{Cl|PRINT}} dword$(sc) + {{Cl|FOR...NEXT|FOR}} x = 0 {{Cl|TO}} 11 + {{Cl|LOCATE}} 10 + x, 1 + {{Cl|IF...THEN|IF}} x + so = sc {{Cl|THEN}} {{Cl|COLOR}} 15, 1 {{Cl|ELSE}} {{Cl|COLOR}} 7, 0 + {{Cl|IF...THEN|IF}} (x + so) < numnames {{Cl|THEN}} + {{Cl|PRINT}} nams(x + so); {{Cl|SPACE$}}(70 - {{Cl|LEN}}(nams(x + so))); + {{Cl|PRINT}} dword$(bs + (namsrva(x + so) {{Cl|AND (boolean)|AND}} {{Cl|&H}}7FFFFFFF&)); + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 7, 18 + {{Cl|IF...THEN|IF}} namsrva(x + so) {{Cl|AND (boolean)|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + {{Cl|PRINT}} "(descend)"; + {{Cl|ELSE}} + {{Cl|PRINT}} "(extract)"; + {{Cl|END IF}} + {{Cl|ELSEIF}} (x + so) < (numnames + numids) {{Cl|THEN}} + {{Cl|PRINT}} "ID: " + dword$(ids(x + so - numnames)); + {{Cl|IF...THEN|IF}} level = 0 {{Cl|THEN}} + {{Cl|PRINT}} " (RT_"; + 'derived from: + ' http://msdn.microsoft.com/en-us/library/ms648009(v=VS.85).aspx + {{Cl|SELECT CASE}} ids(x + so - numnames) + {{Cl|CASE}} 9: {{Cl|PRINT}} "ACCELERATOR"; + {{Cl|CASE}} 21: {{Cl|PRINT}} "ANICURSOR"; + {{Cl|CASE}} 22: {{Cl|PRINT}} "ANIICON"; + {{Cl|CASE}} 2: {{Cl|PRINT}} "BITMAP"; + {{Cl|CASE}} 1: {{Cl|PRINT}} "CURSOR"; + {{Cl|CASE}} 5: {{Cl|PRINT}} "DIALOG"; + {{Cl|CASE}} 17: {{Cl|PRINT}} "DLGINCLUDE"; + {{Cl|CASE}} 8: {{Cl|PRINT}} "FONT"; + {{Cl|CASE}} 7: {{Cl|PRINT}} "FONTDIR"; + {{Cl|CASE}} 12: {{Cl|PRINT}} "GROUP_CURSOR"; + {{Cl|CASE}} 14: {{Cl|PRINT}} "GROUP_ICON"; + {{Cl|CASE}} 23: {{Cl|PRINT}} "HTML"; + {{Cl|CASE}} 3: {{Cl|PRINT}} "ICON"; + {{Cl|CASE}} 24: {{Cl|PRINT}} "MANIFEST"; + {{Cl|CASE}} 4: {{Cl|PRINT}} "MENU"; + {{Cl|CASE}} 11: {{Cl|PRINT}} "MESSAGETABLE"; + {{Cl|CASE}} 19: {{Cl|PRINT}} "PLUGPLAY"; + {{Cl|CASE}} 10: {{Cl|PRINT}} "RCDATA"; + {{Cl|CASE}} 6: {{Cl|PRINT}} "STRING"; + {{Cl|CASE}} 16: {{Cl|PRINT}} "VERSION"; + {{Cl|CASE}} 20: {{Cl|PRINT}} "VXD"; + {{Cl|END SELECT}} + {{Cl|PRINT}} ")"; + {{Cl|END IF}} + {{Cl|PRINT}} {{Cl|SPACE$}}(71 - {{Cl|POS}}(0)); + {{Cl|PRINT}} dword$(bs + (idsrva(x + so - numnames))); + {{Cl|COLOR}} 7, 0 + {{Cl|LOCATE}} 7, 18 + {{Cl|IF...THEN|IF}} idsrva(x + (so - numnames)) {{Cl|AND (boolean)|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + {{Cl|PRINT}} "(descend)"; + {{Cl|ELSE}} + {{Cl|PRINT}} "(extract)"; + {{Cl|END IF}} + {{Cl|ELSE}} + {{Cl|PRINT}} {{Cl|SPACE$}}(80); + {{Cl|END IF}} + {{Cl|NEXT}} + DO + k = {{Cl|INKEY$}} + {{Cl|LOOP}} {{Cl|UNTIL}} {{Cl|LEN}}(k) + {{Cl|SELECT CASE}} k + {{Cl|CASE}} "d", "D" + dump addr + {{Cl|EXIT DO}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4800) 'up + {{Cl|IF...THEN|IF}} sc > 0 {{Cl|THEN}} + sc = sc - 1 + {{Cl|IF...THEN|IF}} sc < so {{Cl|THEN}} so = sc + {{Cl|END IF}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}5000) 'down + {{Cl|IF...THEN|IF}} sc < (numnames + numids - 1) {{Cl|THEN}} + sc = sc + 1 + {{Cl|IF...THEN|IF}} sc > (so + 11) {{Cl|THEN}} + so = sc - 11 + {{Cl|IF...THEN|IF}} so > sc {{Cl|THEN}} so = 0 'unsigned + {{Cl|END IF}} + {{Cl|END IF}} + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4700) 'home + sc = 0 + so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4F00) 'end + sc = numnames + numids - 1 + so = sc - 11 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}4900) 'pgup + sc = sc - 12 + so = so - 12 + {{Cl|IF...THEN|IF}} sc < 0 {{Cl|THEN}} sc = 0 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|MKI$}}({{Cl|&H}}5100) 'pgdn + sc = sc + 12 + {{Cl|IF...THEN|IF}} sc > (numnames + numids - 1) {{Cl|THEN}} sc = numnames + numids - 1 + so = sc - 11 + {{Cl|IF...THEN|IF}} so < 0 {{Cl|THEN}} so = 0 + {{Cl|CASE}} {{Cl|CHR$}}({{Cl|&H}}8), {{Cl|CHR$}}({{Cl|&H}}1B) 'bksp, esc + {{Cl|EXIT SUB}} + {{Cl|CASE}} {{Cl|CHR$}}({{Cl|&H}}D) 'enter + {{Cl|IF...THEN|IF}} sc < numnames {{Cl|THEN}} + dw = namsrva(sc) + {{Cl|ELSE}} + dw = idsrva(sc - numnames) + {{Cl|END IF}} + {{Cl|IF...THEN|IF}} dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}80000000~& {{Cl|THEN}} + 'the spec says its an rva, but it seems to be an offset in the section/table + processtable bs, bs + (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}7FFFFFFF&), level + 1 + {{Cl|EXIT DO}} + {{Cl|ELSE}} + 'the spec says its an rva, but it seems to be an offset in the section/table + dw = bs + dw + {{Cl|GET}} 1, 1 + dw, dat + {{Cl|GET}} 1, 1 + 4 + dw, siz + {{Cl|CLS}} + {{Cl|LOCATE}} 1, 1 'qb64 seems to default to line 2 + {{Cl|SEEK}} 1, 1 + rva2fp(dat) + {{Cl|FOR...NEXT|FOR}} dw = 1 {{Cl|TO}} siz + {{Cl|IF...THEN|IF}} dw > 400 {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|GET}} 1, , b + {{Cl|SELECT CASE}} b + {{Cl|CASE}} 7, 9 {{Cl|TO}} {{Cl|&H}}D, {{Cl|&H}}1F: {{Cl|PRINT}} "."; + {{Cl|CASE ELSE}}: {{Cl|PRINT}} {{Cl|CHR$}}(b); + {{Cl|END SELECT}} + {{Cl|NEXT}} + {{Cl|LOCATE}} 24, 1 + {{Cl|PRINT}} dword$(siz) + " bytes."; + {{Cl|LOCATE}} 23, 1 + {{Cl|LINE INPUT}} "(leave blank to cancel) Output file? "; k + {{Cl|IF...THEN|IF}} {{Cl|LEN}}(k) {{Cl|THEN}} + {{Cl|IF...THEN|IF}} {{Cl|_FILEEXISTS}}(k) {{Cl|THEN}} + {{Cl|PRINT}} + {{Cl|PRINT}} "File already exists."; + {{Cl|ELSE}} + {{Cl|OPEN}} k {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|AS}} 2 + {{Cl|SEEK}} 1, 1 + rva2fp(dat) + {{Cl|FOR...NEXT|FOR}} dw = 1 {{Cl|TO}} siz + {{Cl|GET}} 1, , b + {{Cl|PUT}} 2, , b + {{Cl|NEXT}} + {{Cl|CLOSE}} 2 + {{Cl|PRINT}} + {{Cl|PRINT}} "Done."; + {{Cl|END IF}} + {{Cl|SLEEP}}: {{Cl|DO...LOOP|DO}}: {{Cl|LOOP}} {{Cl|WHILE}} {{Cl|LEN}}({{Cl|INKEY$}}) + {{Cl|END IF}} + {{Cl|EXIT DO}} + {{Cl|END IF}} + {{Cl|END SELECT}} + {{Cl|LOOP}} +{{Cl|LOOP}} +{{Cl|END SUB}} + +{{Cl|FUNCTION}} word$ (w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +t = {{Cl|LCASE$}}({{Cl|HEX$}}(w)) +word = "0x" + {{Cl|STRING$}}(4 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t +{{Cl|END FUNCTION}} + +{{Cl|FUNCTION}} dword$ (dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +t = {{Cl|LCASE$}}({{Cl|HEX$}}(dw)) +dword = "0x" + {{Cl|STRING$}}(8 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t +{{Cl|END FUNCTION}} + +{{Cl|FUNCTION}} rva2fp~& (rva {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} w {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|INTEGER}} +{{Cl|FOR...NEXT|FOR}} w = 0 {{Cl|TO}} NumberOfSections - 1 + {{Cl|IF...THEN|IF}} rva < secsva(w) {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} +{{Cl|NEXT}} +w = w - 1 +{{Cl|IF...THEN|IF}} w > NumberOfSections - 1 {{Cl|THEN}} {{Cl|PRINT}} dword$(rva), w: {{Cl|SLEEP}} +rva2fp = rva + (secsfp(w) - secsva(w)) +{{Cl|END FUNCTION}} + +{{Cl|SUB}} dump (addr {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}}) +{{Cl|DIM}} t {{Cl|AS}} {{Cl|STRING}} +{{Cl|DIM}} dw {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} ul {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|LONG}} +{{Cl|DIM}} b {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_BYTE}} + +{{Cl|_CONTROLCHR}} OFF +{{Cl|VIEW PRINT}} +ul = addr +DO + {{Cl|COLOR}} 7, 0 + {{Cl|CLS}} 0 + {{Cl|SEEK}} 1, 1 + ul + {{Cl|FOR...NEXT|FOR}} dw = ul {{Cl|TO}} (ul {{Cl|AND (boolean)|AND}} {{Cl|&H}}FFFFFFF0) + {{Cl|&H}}15F + {{Cl|IF...THEN|IF}} (1 + ul) > {{Cl|LOF}}(1) {{Cl|THEN}} {{Cl|EXIT}} {{Cl|FOR...NEXT|FOR}} + {{Cl|GET}} 1, , b + {{Cl|IF...THEN|IF}} (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}F) = 0 {{Cl|THEN}} + t = {{Cl|LCASE$}}({{Cl|HEX$}}(dw)) + {{Cl|COLOR}} 7 + {{Cl|PRINT}} {{Cl|STRING$}}(8 - {{Cl|LEN}}(t), {{Cl|&H}}30) + t; {{Cl|SPACE$}}(2); + {{Cl|END IF}} + {{Cl|IF...THEN|IF}} (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}4) {{Cl|THEN}} {{Cl|COLOR}} 3 {{Cl|ELSE}} {{Cl|COLOR}} 2 + {{Cl|LOCATE}} , 14 + ((dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}F) * 3) + t = {{Cl|LCASE$}}({{Cl|HEX$}}(b)) + {{Cl|IF...THEN|IF}} b < {{Cl|&H}}10 {{Cl|THEN}} {{Cl|PRINT}} "0" + t; {{Cl|ELSE}} {{Cl|PRINT}} t; + {{Cl|LOCATE}} , 65 + (dw {{Cl|AND (boolean)|AND}} {{Cl|&H}}F) + {{Cl|PRINT}} {{Cl|CHR$}}(b); + {{Cl|NEXT}} + {{Cl|PRINT}} + {{Cl|COLOR}} 7 + {{Cl|LINE INPUT}} "(leave blank to cancel) Address: 0x"; t + {{Cl|IF...THEN|IF}} {{Cl|LTRIM$}}(t) = "" {{Cl|THEN}} {{Cl|EXIT DO}} + ul = {{Cl|VAL}}("&h" + t + "&") {{Cl|AND (boolean)|AND}} {{Cl|&H}}7FFFFFFF +{{Cl|LOOP}} +{{Cl|END SUB}} '' '' +{{CodeEnd}} +{{small|Code courtesy of Michael Calkins}} + + +<p style="text-align: center">([[#toc|Return to Table of Contents]])</p> + +==References== +''See also:'' +* [[Icons and Cursors]] +* [[Bitmaps]], [[_ICON]], [[$EXEICON]] +* [[SaveIcon32]] {{text|(create icons from any image)}} + + +{{PageNavigation}} diff --git a/internal/help/STOP.txt b/internal/help/STOP.txt index 1a1429cd2..91f9e4ea9 100644 --- a/internal/help/STOP.txt +++ b/internal/help/STOP.txt @@ -1,27 +1,12 @@ -The '''STOP''' statement is used to stop program execution when troubleshooting a program or to suspend event trapping. +The '''STOP''' statement is used to stop program execution. {{PageSyntax}} :: STOP -* STOP used in the Qbasic IDE does not close any files or go to the operating system. It returns to the IDE. -* In the QB64 compiler, STOP closes the program window and returns to the IDE when the code is compiled from there. -* STOP is ONLY used for debugging purposes and should not be used to exit programs! -* STOP can also be used to suspend an event trap in the following statements: [[KEY(n)]], [[ON COM (n)|COM(n)]], [[PEN]], [[PLAY]], [[STRIG(n)]], [[TIMER]], [[UEVENT]]. The trap can be turned back on with [[ON]] and returns any trap events since '''STOP''' was used. - - -''Example:'' When run in the Qbasic IDE, the program will return to the IDE at STOP. Press F5 to finish the program. -{{CodeStart}} -{{Cl|PRINT}} "start" - -{{Cl|SLEEP}} 3 - -{{Cl|STOP}} - -{{Cl|PRINT}} "resumed" -{{CodeEnd}} -: ''Explanation:'' QB64 will STOP the program and close the window as it does not have an interpreter to run the rest of the code. +* STOP ends the program. +* Since QB64 programs are compiled and not interpreted, use [[END]] or [[SYSTEM]] instead. ''See also:'' diff --git a/internal/help/SaveIcon32.txt b/internal/help/SaveIcon32.txt new file mode 100644 index 000000000..950f6f1d9 --- /dev/null +++ b/internal/help/SaveIcon32.txt @@ -0,0 +1,114 @@ +The following Icon creation procedure was adapted from Galleon's [[SAVEIMAGE]] sup-procedure that creates 8 BPP or 32 bit bitmaps: + +'''NOTE: QB64 can use .ico files natively for Windows executables with [[$EXEICON]].''' +{{CodeStart}} '' '' +DO + {{Cl|LINE INPUT}} "Use 8 bit(256 colors) or 32 bit image? ", bit$ + clrmode% = {{Cl|VAL}}(bit$) +{{Cl|LOOP}} {{Cl|UNTIL}} clrmode% = 8 {{Cl|OR (boolean)|OR}} clrmode% = 32 +{{Cl|IF...THEN|IF}} clrmode% = 8 {{Cl|THEN}} clrmode% = 256 +{{Cl|LOCATE}} 10, 10: {{Cl|PRINT}} "Do you wish to make black transparent? (Y/N) "; +K$ = {{Cl|INPUT$}}(1): {{Cl|PRINT}} K$ +{{Cl|IF...THEN|IF}} {{Cl|UCASE$}}(K$) = "Y" {{Cl|THEN}} mode% = 1 +{{Cl|_DELAY}} 1 +{{Cl|SCREEN}} {{Cl|_NEWIMAGE}}(640, 480, clrmode%) +DO + {{Cl|LOCATE}} 10, 10: {{Cl|LINE INPUT}} "Enter the icon size to use(multiple of 16): ", sz$ + size& = {{Cl|VAL}}(sz$) +{{Cl|LOOP}} {{Cl|UNTIL}} size& {{Cl|MOD}} 16 = 0 AND size& >= 16 AND size& <= 128 +DO + {{Cl|LOCATE}} 10, 10: {{Cl|LINE INPUT}} "Enter the image file name to convert to an icon: ", BMP$ + {{Cl|CLS}} +{{Cl|LOOP}} {{Cl|UNTIL}} {{Cl|_FILEEXISTS}}(BMP$) +img& = {{Cl|_LOADIMAGE}}(BMP$) +{{Cl|IF...THEN|IF}} img& = -1 {{Cl|OR (boolean)|OR}} img& = 0 {{Cl|THEN}} {{Cl|LOCATE}} 15, 25: {{Cl|PRINT}} "Image failed to load!": {{Cl|END}} + +{{Cl|IF...THEN|IF}} mode% = 0 THEN {{Cl|CLS}} , {{Cl|_RGB}}(255, 255, 255) +{{Cl|IF...THEN|IF}} clrmode% = 256 {{Cl|THEN}} {{Cl|_COPYPALETTE}} (img&) +{{Cl|_PUTIMAGE}} (0, 0)-(size& - 1, size& - 1), img&, 0 '(31, 31), img&, 0 '<<<<<<<<<<< + +{{Cl|LOCATE}} 20, 10: {{Cl|PRINT}} "Do you want to make an icon out of the image? (Y/N) "; +K$ = {{Cl|INPUT$}}(1): {{Cl|PRINT}} K$ +{{Cl|IF...THEN|IF}} {{Cl|UCASE$}}(K$) <> "Y" {{Cl|THEN}} {{Cl|END}} +SaveFile$ = {{Cl|LEFT$}}(BMP$, {{Cl|INSTR}}(BMP$, ".")) + "ico" +SaveIcon32 img&, size&, mode%, SaveFile$ + +{{Cl|END}} +' --------------------------------------------------------- + +{{Cl|SUB}} SaveIcon32 (image {{Cl|AS}} {{Cl|LONG}}, size {{Cl|AS}} {{Cl|LONG}}, mode AS {{Cl|INTEGER}}, filename {{Cl|AS}} {{Cl|STRING}}) +bytesperpixel& = {{Cl|_PIXELSIZE}}(image&) +{{Cl|IF...THEN|IF}} bytesperpixel& = 0 {{Cl|THEN}} {{Cl|PRINT}} "Text modes unsupported!": {{Cl|END}} +{{Cl|IF...THEN|IF}} bytesperpixel& = 1 {{Cl|THEN}} bpp& = 8 {{Cl|ELSE}} bpp& = 24 '256 or 32 bit color +{{Cl|IF...THEN|IF}} size& {{Cl|MOD}} 16 {{Cl|OR}} size& < 16 {{Cl|OR}} size& > 128 THEN {{Cl|PRINT}} "Size not supported!": {{Cl|END}} +x& = size& 'supports sizes from 16 to 128 only! +y& = size& +'Headers: icon count width depth colors cursor hotspots size - offset +b$= {{Cl|MKI$}}(0)+{{Cl|MKI$}}(1)+{{Cl|MKI$}}(1)+{{Cl|CHR$}}(x&)+{{Cl|CHR$}}(y&)+{{Cl|CHR$}}(0)+{{Cl|CHR$}}(0)+{{Cl|MKI$}}(0)+{{Cl|MKI$}}(0)+"????"+{{Cl|MKL$}}(22) _ + +{{Cl|MKL$}}(40)+{{Cl|MKL$}}(x&)+{{Cl|MKL$}}(2 * y&)+{{Cl|MKI$}}(1)+{{Cl|MKI$}}(bpp&)+{{Cl|MKL$}}(0)+"????" + {{Cl|STRING$}}(16, 0) +'BMP size width double height plane BPP raw size +{{Cl|IF...THEN|IF}} bytesperpixel& = 1 {{Cl|THEN}} + {{Cl|FOR...NEXT|FOR}} c& = 0 {{Cl|TO}} 255 ' read BGR color settings from image + 1 byte spacer({{Cl|CHR$}}(0)) + cv& = {{Cl|_PALETTECOLOR (function)|_PALETTECOLOR}}(c&, image&) ' color attribute to read. + b$ = b$ + {{Cl|CHR$}}({{Cl|_BLUE32}}(cv&)) + {{Cl|CHR$}}({{Cl|_GREEN32}}(cv&)) + {{Cl|CHR$}}({{Cl|_RED32}}(cv&)) + {{Cl|CHR$}}(0) 'spacer + {{Cl|NEXT}} +{{Cl|END IF}} +lastsource& = {{Cl|_SOURCE}} +{{Cl|_SOURCE}} 0 'set source as program screen. Do NOT use loaded image handle as size has changed! +{{Cl|IF...THEN|IF}} ((x& * 3) {{Cl|MOD}} 4) {{Cl|THEN}} padder$ = {{Cl|STRING$}}(4 - ((x& * 3) {{Cl|MOD}} 4), 0) +{{Cl|FOR...NEXT|FOR}} py& = y& - 1 {{Cl|TO}} 0 {{Cl|STEP}} -1 ' read target image pixel color data + r$ = "" + {{Cl|FOR...NEXT|FOR}} px& = 0 {{Cl|TO}} x& - 1 + c& = {{Cl|POINT}}(px&, py&) + {{Cl|IF...THEN|IF}} bytesperpixel& = 1 {{Cl|THEN}} r$ = r$ + {{Cl|CHR$}}(c&) {{Cl|ELSE}} r$ = r$ + {{Cl|LEFT$}}({{Cl|MKL$}}(c&), 3) + {{Cl|NEXT}} px& + d$ = d$ + r$ + padder$ +{{Cl|NEXT}} py& +{{Cl|IF...THEN|IF}} (x& {{Cl|MOD}} 32) {{Cl|THEN}} bitpad& = 32 - (x& {{Cl|MOD}} 32) 'padder bits when not multiples of 32 +{{Cl|IF...THEN|IF}} mode% {{Cl|THEN}} 'make black pixels white in AND mask so they become transparent + {{Cl|FOR...NEXT|FOR}} py& = y& - 1 {{Cl|TO}} 0 {{Cl|STEP}} -1 'read image to find black pixels + px& = 0 + {{Cl|DO...LOOP|DO}}: byte% = 0 + {{Cl|FOR...NEXT|FOR}} bit% = 7 {{Cl|TO}} 0 {{Cl|STEP}} -1 'change transparent color to suit your needs + byte% = 2 * byte% - ({{Cl|POINT}}(px&, py&) = {{Cl|_RGB}}(0, 0, 0)) 'bitpacking adds 1 when true + px& = px& + 1 + {{Cl|NEXT}} + a$ = a$ + {{Cl|CHR$}}(byte%) + {{Cl|LOOP}} {{Cl|WHILE}} px& < x& - 1 + {{Cl|IF...THEN|IF}} bitpad& {{Cl|THEN}} a$ = a$ + {{Cl|STRING$}}((bitpad& + 7) \ 8, 0) 'add padder at end of row when necessary + {{Cl|NEXT}} +{{Cl|ELSE}} a$ = {{Cl|STRING$}}(y& * ((x& + bitpad& + 7) \ 8), 0) 'totally black {{Cl|AND (boolean)|AND}} mask +{{Cl|END IF}} +d$ = d$ + a$ +{{Cl|_SOURCE}} lastsource& +{{Cl|MID$}}(b$, 43, 4) = {{Cl|MKL$}}({{Cl|LEN}}(d$)) 'raw image size with {{Cl|AND}} mask +b$ = b$ + d$ ' total file data bytes to create file +{{Cl|MID$}}(b$, 15, 4) = {{Cl|MKL$}}({{Cl|LEN}}(b$) - 22) ' size of data file minus Entry header offset +{{Cl|IF...THEN|IF}} {{Cl|LCASE$}}({{Cl|RIGHT$}}(filename$, 4)) <> ".ico" {{Cl|THEN}} ext$ = ".ico" +f& = {{Cl|FREEFILE}} +{{Cl|OPEN}} filename$ + ext$ {{Cl|FOR...NEXT|FOR}} {{Cl|OUTPUT}} {{Cl|AS}} #f&: {{Cl|CLOSE}} #f& ' erases an existing file +{{Cl|OPEN}} filename$ + ext$ {{Cl|FOR...NEXT|FOR}} {{Cl|BINARY}} {{Cl|AS}} #f& +{{Cl|PUT}} #f&, , b$ +{{Cl|CLOSE}} #f& +{{Cl|END SUB}} '' '' +{{CodeEnd}} +{{small|Code by Ted Weissgerber}} + +:''Explanation:'' The icons created can have a full black [[AND]] mask for a solid square image when mode% is zero. If mode% is a value other than 0, the AND mask routine looks for black pixels and sets the background pixel on for transparency. Icons with dimensions that are not a multiple of 32 would require padding. In the header, ???? is later replaced with size data. If the image is 24/32 BPP, the size of the [[XOR]] image data will triple because each pixel uses 3 bytes for red, green and blue values up to 255. +:{{text|To create '''.CUR''' cursor files change the second value from 1 to 2 and set the 2 cursor click hotspot offset [[INTEGER]] values.|purple}} + + +:Icons that are 16 X 16 or 48 X 48 require 2 padder bytes to be added at the end of each row increasing data size by 32 and 96. + + +''See also:'' + +*[[_ICON]], [[$EXEICON]] +*[[SAVEIMAGE]] +*[[Icons and Cursors]] +*[[Resource Table extraction|Resource Extraction]] +*[[Bitmaps]] +*[[GIF Images]] + + +{{PageNavigation}} diff --git a/internal/help/TIME$.txt b/internal/help/TIME$.txt index 8bbec2b61..fad07e88f 100644 --- a/internal/help/TIME$.txt +++ b/internal/help/TIME$.txt @@ -56,9 +56,9 @@ END FUNCTION '' '' ''See also:'' -* [[TIME$ (statement)]], [[TIMER]] -* [[DATE$]], [[DATE$ (statement)]] -* [[VAL]], [[STR$]], [[HEX]] +* [[TIMER]] +* [[DATE$]] +* [[VAL]], [[STR$]], [[HEX$]] * [[LTRIM$]], [[MID$]], [[LEFT$]] * [[IF...THEN]] diff --git a/internal/help/Variable.txt b/internal/help/Variable.txt new file mode 100644 index 000000000..316b50929 --- /dev/null +++ b/internal/help/Variable.txt @@ -0,0 +1,77 @@ +A '''variable''' is a "container" name that can hold a numerical or string value which can be referenced or changed by the program (as opposed to [[CONST]]ant values which never change). + + +<center>'''Variable names'''</center> +Variables in QB64 can be any name except the names of QB64 or Qbasic keywords and may not contain spaces or non-alphabetical/non-numerical characters (except "." and "_"). Numerical characters cannot be used as the first character of a variable or array name! '''QB64 reserves the use of a leading underscore to QB64 procedural or variable type names only!''' + + +Variable values can be passed to sub-procedures by using the name as a [[SUB]] or [[FUNCTION]] parameter in a [[CALL]]. Variable names in the main program module can be passed to sub-procedures by using [[DIM]] [[SHARED]] without using them as [[CALL]] parameters. + + +Variable names dimensioned in [[SUB]] or [[FUNCTION]] procedures can be the same as names used in the main procedure and can hold different values. [[SHARED]] sub-procedure variables can only be shared with the main program module! + + +Dot variable names are normally used with [[TYPE]] variable definitions. The first name before the dot is the name of the variable [[DIM|dimensioned]] [[AS]] the type. The name after the dot is the name of the variable assigned inside of the [[TYPE]]. + + +<center>'''Variable types'''</center> +Variables can be defined as a specific type using a variable type suffix or by using a [[DIM]] or [[REDIM]](for dynamic arrays only) statement [[AS]] a variable type of [[_BIT]], [[_BYTE]], [[INTEGER]], [[LONG]], [[SINGLE]], [[DOUBLE]], [[_INTEGER64]], [[_FLOAT]] or [[STRING]] in QB64. + + +Groups of variable names can be type defined by the first letter or list of letters of the names using [[DEFINT]], [[DEFLNG]], [[DEFSNG]], [[DEFDBL]], [[DEFSTR]] or [[_DEFINE]] [[AS]] in QB64. + + +[[$DYNAMIC]] arrays can be resized and can retain their remaining element values when used with [[REDIM]] [[_PRESERVE]] in QB64. [[ERASE]] or [[CLEAR]] removes the array entirely from memory! + + +[[$STATIC]] arrays cannot be resized, but cannot be removed either. [[ERASE]] or [[CLEAR]] will clear the array element values only! + + +<center>'''Variable values'''</center> +All numerical variables default to 0 and all string variables default to "" at the start of a program and when first referenced inside of a [[SUB]] or [[FUNCTION]] procedure except when the variable is defined as a [[STATIC]] value. + + +[[Arrays]] variable names can hold many values in one variable name by specifying a reference index enclosed in parentheses. + + +[[STATIC]] sub-procedure values keep their value after the sub-procedure is exited. They will hold an empty value when first used. + + +Variables are used to hold program data information that is attained through the program flow, either by user input, calculations or by other ways of communicaton (as with I/O, memory, TCP/IP or files). + + +Assignment of variable values can be done using the = assignment symbol (variable1.number = 500, for example). + + +To pass variable values to a sub-procedure without altering or affecting the variable name's value, parenthesis can be used around the variable name in the [[CALL]]. + + +{{PageExamples}} +''Example of different usages of variables:'' +{{CodeStart}} +max = 1000 +{{Cl|DIM}} d(max) +{{Cl|FOR...NEXT|FOR}} c = 1 {{Cl|TO}} max +d(c) = c + d(c - 1) +{{Cl|NEXT}} +{{Cl|PRINT}} "Show the result of the addition from 1 to n (1+2+3...+n)" +{{Cl|PRINT}} "n = (0-" + {{Cl|LTRIM$}}({{Cl|STR$}}(max)) + "): "; +{{Cl|INPUT}} "", n +{{Cl|IF...THEN|IF}} n <= max {{Cl|AND (boolean)|AND}} n >= 0 {{Cl|THEN}} {{Cl|PRINT}} d(n) {{Cl|ELSE}} {{Cl|PRINT}} "Invalid value (only 0 to" + {{Cl|STR$}}(max) + " is permitted)." +{{CodeEnd}} + +{{OutputStart}} +Show the result of the addition from 1 to n (1+2+3...+n) +n = (1-1000): 10 + 55 +{{OutputEnd}} + + + + + +{{PageSeeAlso}} +* [[Argument]], [[Expression]], [[Arrays]] + + +{{PageNavigation}} diff --git a/internal/help/Variable_Types.txt b/internal/help/Variable_Types.txt new file mode 100644 index 000000000..89a586818 --- /dev/null +++ b/internal/help/Variable_Types.txt @@ -0,0 +1,39 @@ +'''QB64 uses more variable types than Qbasic ever did. The variable type determines the size of values that numerical variables can hold.''' + + + +{{DataTypeTable}} + +If no suffix is used and no DEFxxx or _DEFINE command has been used and the variable hasn't been [[DIM]]med the '''default variable type is [[SINGLE]]'''. '''[[_MEM]] and [[_OFFSET]] variable types cannot be cast to other variable types!''' + + +All types dealing with number values are signed as a default. The symbol to define unsigned variables is ~ and is used just before the type suffix (~` is [[_UNSIGNED]] _BIT, ~%% is [[_UNSIGNED]] _BYTE, etc.). + + +<center>'''[[SINGLE]], [[DOUBLE]] and [[_FLOAT]] floating decimal point values cannot be [[_UNSIGNED]]!'''</center> + + +'''Defining variable types:''' + +: [[DIM]] ''variable'' [[AS]] ''type'' +: [[_DEFINE]] ''range1-range2'' [[AS]] ''value_type'' +: [[DEFINT]] ''range1-range2'' +: [[DEFLNG]] ''range1-range2'' +: [[DEFSNG]] ''range1-range2'' +: [[DEFDBL]] ''range1-range2'' + +Where ''range1'' and ''range2'' are the range of first letters to be defined as the default ''type'' when the variable is having no suffix and are not otherwise defined, the starting letter of the variable then defines the ''type'' as specified by the DEFxxx and _DEFINE statements. The QB64 types can only be defaulted using [[_DEFINE]]. + +''type'' can be any of the types listed at the top and can also be preceeded with [[_UNSIGNED]] for the unsigned version of the type. + +''variable'' is the name of the variable to be defined in the DIM statement. + + +'''More information:''' + +More information on this page: [[Data types]] + + + + +{{PageNavigation}} diff --git a/internal/help/_BUTTON.txt b/internal/help/_BUTTON.txt index dffa7c36c..2ada20121 100644 --- a/internal/help/_BUTTON.txt +++ b/internal/help/_BUTTON.txt @@ -7,6 +7,7 @@ The [[_BUTTON]] function returns -1 when specified button number on a controller {{PageDescription}} +* The '''[[_DEVICEINPUT]] function should be read first to specify which device [[_BUTTON]] is intended to check.''' * Values returned are -1 for a press and 0 when a button is released or not pressed. * The {{Parameter|button_number%}} must be a number which does not exceed the number of buttons found by the [[_LASTBUTTON]] function. * '''The number of [[_DEVICES]] must be read before using [[_DEVICE$]], [[_DEVICEINPUT]] or [[_LASTBUTTON]].''' diff --git a/internal/help/_BUTTONCHANGE.txt b/internal/help/_BUTTONCHANGE.txt index d9a4de110..c85ed28ce 100644 --- a/internal/help/_BUTTONCHANGE.txt +++ b/internal/help/_BUTTONCHANGE.txt @@ -7,6 +7,7 @@ The [[_BUTTONCHANGE]] function returns -1 or 1 when a specified button number on {{PageDescription}} +* The '''[[_DEVICEINPUT]] function should be read first to specify which device [[_BUTTONCHANGE]] is intended to check.''' * Values returned are -1 for a press and 1 when a button is released. No press or release event returns zero. * The {{Parameter|button_number%}} must be a number which does not exceed the number of buttons found by the [[_LASTBUTTON]] function. * '''The number of [[_DEVICES]] must be read before using [[_DEVICE$]], [[_DEVICEINPUT]] or [[_LASTBUTTON]].''' diff --git a/internal/help/_CONNECTIONADDRESS.txt b/internal/help/_CONNECTIONADDRESS.txt new file mode 100644 index 000000000..71a25847d --- /dev/null +++ b/internal/help/_CONNECTIONADDRESS.txt @@ -0,0 +1,45 @@ +{{DISPLAYTITLE:_CONNECTIONADDRESS}} +The [[_CONNECTIONADDRESS]] function returns a connected user's [[STRING]] IP address value. + + +{{PageSyntax}} +:{{Parameter|result$}} = [[_CONNECTIONADDRESS|_CONNECTIONADDRESS[$]]]({{Parameter|connectionHandle&}}) + + +{{PageDescription}} +* The handle can come from the [[_OPENHOST]], [[OPENCLIENT]] or [[_OPENCONNECTION]] QB64 TCP/IP functions. +* For '''[[_OPENHOST|HOST]]s''': It may return "TCP/IP:8080:213.23.32.5" where 8080 is the port it is listening on and 213.23.32.5 is the global IP address which any computer connected to the internet could use to locate your computer. If a connection to the internet is unavailable or your firewall blocks it, it returns your 'local IP' address (127.0.0.1). You might like to store this address somewhere where other computers can find it and connect to your host. Dynamic IPs which can change will need to be updated. +* For '''[[_OPENCLIENT|CLIENT]]s''': It may return "TCP/IP:8080:213.23.32.5" where 8080 is the port it used to connect to the listening host and 213.23.32.5 is the IP address of the host name it resolved. +* For '''[[_OPENCONNECTION|CONNECTION]]s''' (from clients): It may return "TCP/IP:8080:34.232.321.25" where 8080 was the host listening port it connected to and 34.232.321.25 is the IP address of the client that connected. This is very useful because the host can log the IP address of clients for future reference (or banning, for example). +* The $ sygil is optional for compatibility with older versions. + + +{{PageExamples}} +''Example:'' A Host logging new chat clients in a Chat program. See the [[_OPENHOST]] example for the rest of the code used. +{{CodeStart}} '' '' +f = {{Cl|FREEFILE}} +{{Cl|OPEN}} "ChatLog.dat" {{Cl|FOR}} {{Cl|APPEND}} {{Cl|AS}} #f ' code at start of host section before DO loop. + + +newclient = {{Cl|_OPENCONNECTION}}(host) ' receive any new client connection handles +{{Cl|IF...THEN|IF}} newclient {{Cl|THEN}} + numclients = numclients + 1 ' increment index + Users(numclients) = newclient ' place handle into array + IP$ = {{Cl|_CONNECTIONADDRESS}}(newclient) + {{Cl|PRINT}} IP$ + " has joined." ' displayed to Host only + {{Cl|PRINT (file statement)|PRINT #f}}, IP$, numclients ' print info to a log file + {{Cl|PRINT (file statement)|PRINT #}}Users(numclients),"Welcome!" ' from Host to new clients only +{{Cl|END IF}} '' '' + +{{CodeEnd}} +: ''Explanation:'' The function returns the new client's IP address to the IP$ variable. Prints the IP and the original login position to a log file. The information can later be used by the host for referance if necessary. The host could set up a ban list too. + + +{{PageSeeAlso}} +* [[_OPENCONNECTION]] +* [[_OPENHOST]] +* [[_OPENCLIENT]] +* [[_CONNECTED]] + + +{{PageNavigation}} diff --git a/internal/help/_DEFINE.txt b/internal/help/_DEFINE.txt index 550a23f93..f31d5d531 100644 --- a/internal/help/_DEFINE.txt +++ b/internal/help/_DEFINE.txt @@ -3,7 +3,7 @@ {{PageSyntax}} -:[[_DEFINE]] {{Parameter|letter}}[{{Parameter|-range}}, ...] [[AS]] [{{KW|_UNSIGNED}}] data[[type]] +:[[_DEFINE]] {{Parameter|letter}}[{{Parameter|-range}}, ...] [[AS]] [{{KW|_UNSIGNED}}] data[[Variable Types|type]] {{Parameters}} @@ -14,7 +14,7 @@ {{PageDescription}} * '''When a variable has not been defined or has no type suffix, the value defaults to a [[SINGLE]] precision floating point value.''' -* _DEFINE sets the [[type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). +* _DEFINE sets the [[Variable Types|type]] of all variable names with the starting letter(s) or letter ranges when encountered in the progression of the program (even in conditional statement blocks not executed and subsequent [[SUB]] procedures). * '''NOTE: Many Qbasic keyword variable names CAN be used with a [[STRING]] suffix ($)! You cannot use them without the suffix, use a numerical suffix or use [[DIM]], [[REDIM]], [[_DEFINE]], [[BYVAL]] or [[TYPE]] variable [[AS]] statements.''' * '''Qbasic's IDE''' added DEF statements before any [[SUB]] or [[FUNCTION]]. '''QB64''' (like QB) will change all variable types in subsequent sub-procedures to that default variable type without giving a [[ERROR Codes|"Parameter Type Mismatch"]] warning or adding the proper DEF statement to subsequent procedures. If you do not want that to occur, either remove that DEF statement or add the proper DEF type statements to subsequent procedures. * May also affect [[$INCLUDE]] procedures. diff --git a/internal/help/_DEFLATE$.txt b/internal/help/_DEFLATE$.txt index dc3fde071..dc552c079 100644 --- a/internal/help/_DEFLATE$.txt +++ b/internal/help/_DEFLATE$.txt @@ -28,7 +28,7 @@ a$ = "The quick brown fox jumps over the lazy dog. " b$ = {{Cl|_DEFLATE$}}(a$) {{Cl|PRINT}} "After using _DEFLATE$ to compress it, LEN ="; {{Cl|LEN}}(b$) -{{Cl|PRINT}} {{Cl|USING}} "(compressed size is #.###% of the original)"; (({{Cl|LEN}}(b$) * 100) / {{Cl|LEN}}(a$)) +{{Cl|PRINT USING}} "(compressed size is #.###% of the original)"; (({{Cl|LEN}}(b$) * 100) / {{Cl|LEN}}(a$)) c$ = {{Cl|_INFLATE$}}(b$) PRINT "After using _INFLATE$ to decompress it, LEN ="; {{Cl|LEN}}(c$) {{CodeEnd}} diff --git a/internal/help/_ERRORLINE.txt b/internal/help/_ERRORLINE.txt index 9eec7f0e4..1e190e8ef 100644 --- a/internal/help/_ERRORLINE.txt +++ b/internal/help/_ERRORLINE.txt @@ -28,7 +28,7 @@ DebugLine: {{PageSeeAlso}} * [[ON ERROR]] -* [[_INCLERRORLINE]], [[_INCLERRORFILE$]] +* [[_INCLERRORLINE]], [[_INCLERRORFILE$]], [[_ERRORMESSAGE$]] * [[ERR]], [[ERL]] * [[ERROR]] * [[ERROR Codes]] diff --git a/internal/help/_ERRORMESSAGE$.txt b/internal/help/_ERRORMESSAGE$.txt new file mode 100644 index 000000000..fe589a150 --- /dev/null +++ b/internal/help/_ERRORMESSAGE$.txt @@ -0,0 +1,42 @@ +{{DISPLAYTITLE:_ERRORMESSAGE$}} +The [[_ERRORMESSAGE$]] function returns a human-readable description of the most recent runtime error, or the description of an arbitrary error code passed to it. + + +{{PageSyntax}} +:{{Parameter|e$}} = [[_ERRORMESSAGE$]] +:{{Parameter|e$}} = [[_ERRORMESSAGE$]]({{Parameter|errorCode%}}) + + +{{PageDescription}} +* Used in program error troubleshooting. + + +{{PageExamples}} +''Example 1:'' Using an error handler that ignores any error. + +{{CodeStart}} '' '' + {{Cl|ON ERROR}} {{Cl|GOTO}} Errhandler + ' Main module program error simulation code + {{Cl|ERROR}} 7 ' simulate an Out of Memory Error + PRINT "Error handled...ending program" + {{Cl|SLEEP}} 4 + {{Cl|SYSTEM}} ' end of program code + + Errhandler: 'error handler sub program line label + PRINT "Error"; {{Cl|ERR}}; "on program file line"; {{Cl|_ERRORLINE}} + PRINT "Description: "; {{Cl|_ERRORMESSAGE$}}; "." + {{Cl|BEEP}} ' warning beep + {{Cl|RESUME}} NEXT ' moves program to code following the error. '' '' +{{CodeEnd}} + + +{{PageSeeAlso}} +* [[ON ERROR]] +* [[_ERRORLINE]] +* [[_INCLERRORLINE]], [[_INCLERRORFILE$]] +* [[ERR]], [[ERL]] +* [[ERROR]] +* [[ERROR Codes]] + + +{{PageNavigation}} diff --git a/internal/help/_FULLSCREEN.txt b/internal/help/_FULLSCREEN.txt index 89daefb1a..1c783a66f 100644 --- a/internal/help/_FULLSCREEN.txt +++ b/internal/help/_FULLSCREEN.txt @@ -119,7 +119,7 @@ ClearFont: {{Cl|_FULLSCREEN}} _STRETCH, _SMOOTH {{Cl|CASE}} 5 {{Cl|_FULLSCREEN}} _SQUAREPIXELS, _SMOOTH - {{Cl|END}} {{Cl|SELECT}} + {{Cl|END SELECT}} {{Cl|_LIMIT}} 30 {{Cl|LOOP}} {{Cl|UNTIL}} {{Cl|_EXIT (function)|_EXIT}} {{Cl|SYSTEM}}{{CodeEnd}} diff --git a/internal/help/_HYPOT.txt b/internal/help/_HYPOT.txt index 20b0c3e1d..eea43cde7 100644 --- a/internal/help/_HYPOT.txt +++ b/internal/help/_HYPOT.txt @@ -22,7 +22,7 @@ The [[_HYPOT]] function returns the hypotenuse of a right-angled triangle whose leg_x = 3 leg_y = 4 result = {{Cl|_HYPOT}}(leg_x, leg_y) -{{Cl|PRINT}} {{Cl|USING}} "## , ## and ## form a right-angled triangle."; leg_x; leg_y; result +{{Cl|PRINT}} USING "## , ## and ## form a right-angled triangle."; leg_x; leg_y; result {{CodeEnd}} {{OutputStart}} diff --git a/internal/help/_INCLERRORFILE$.txt b/internal/help/_INCLERRORFILE$.txt index 925221e90..cdc21b2cb 100644 --- a/internal/help/_INCLERRORFILE$.txt +++ b/internal/help/_INCLERRORFILE$.txt @@ -44,7 +44,7 @@ ERROR 250 ON LINE: 9 {{PageSeeAlso}} -* [[_INCLERRORLINE]] +* [[_INCLERRORLINE]], [[_ERRORMESSAGE$]] * [[ON ERROR]], [[ERR]] * [[ERROR]] * [[ERROR Codes]] diff --git a/internal/help/_INCLERRORLINE.txt b/internal/help/_INCLERRORLINE.txt index fafb0b4f1..9b681c0a7 100644 --- a/internal/help/_INCLERRORLINE.txt +++ b/internal/help/_INCLERRORLINE.txt @@ -45,7 +45,7 @@ ERROR 250 ON LINE: 9 {{PageSeeAlso}} -* [[_INCLERRORFILE$]] +* [[_INCLERRORFILE$]], [[_ERRORMESSAGE$]] * [[ON ERROR]], [[ERR]] * [[ERROR]] * [[ERROR Codes]] diff --git a/internal/help/_INFLATE$.txt b/internal/help/_INFLATE$.txt index f732bb5ef..1347f5ccc 100644 --- a/internal/help/_INFLATE$.txt +++ b/internal/help/_INFLATE$.txt @@ -29,7 +29,7 @@ a$ = "The quick brown fox jumps over the lazy dog. " b$ = {{Cl|_DEFLATE$}}(a$) {{Cl|PRINT}} "After using _DEFLATE$ to compress it, LEN ="; {{Cl|LEN}}(b$) -{{Cl|PRINT}} {{Cl|USING}} "(compressed size is #.###% of the original)"; (({{Cl|LEN}}(b$) * 100) / {{Cl|LEN}}(a$)) +{{Cl|PRINT USING}} "(compressed size is #.###% of the original)"; (({{Cl|LEN}}(b$) * 100) / {{Cl|LEN}}(a$)) c$ = {{Cl|_INFLATE$}}(b$) PRINT "After using _INFLATE$ to decompress it, LEN ="; {{Cl|LEN}}(c$) {{CodeEnd}} diff --git a/internal/help/_MEM.txt b/internal/help/_MEM.txt index 4221dead9..48f0c540c 100644 --- a/internal/help/_MEM.txt +++ b/internal/help/_MEM.txt @@ -1,5 +1,5 @@ {{DISPLAYTITLE:_MEM}} -The [[_MEM]] variable type can be used when working with memory blocks. It has no variable [[type]] suffix. +The [[_MEM]] variable type can be used when working with memory blocks. It has no variable [[Variable Types|type]] suffix. {{PageSyntax}} @@ -8,7 +8,7 @@ The [[_MEM]] variable type can be used when working with memory blocks. It has n {{PageDescription}} ''Variable TYPE:'' -* Memory DOT values are actually part of the built in memory variable [[type]] in QB64. The following [[TYPE]] is built in: +* Memory DOT values are actually part of the built in memory variable [[Variable Types|type]] in QB64. The following [[TYPE]] is built in: {{WhiteStart}}TYPE memory_type OFFSET AS _OFFSET 'start location of block(changes with byte position) SIZE AS _OFFSET 'size of block remaining at offset(changes with position) @@ -46,7 +46,7 @@ END TYPE :::* 16384(+ 512 + bit*)= [[_OFFSET]] type only ''Note: If a future integer, float or other type doesn't have a size that is 1,2,4,8,16,32,64,128 or 256 it won't have a size-bit set.'' -* '''Note: [[_OFFSET]] values cannot be cast to other variable [[type]]s reliably. _MEM is a reserved custom variable [[type]].''' +* '''Note: [[_OFFSET]] values cannot be cast to other variable [[Variable Types|type]]s reliably. _MEM is a reserved custom variable [[Variable Types|type]].''' * '''[[_MEM (function)|_MEM]] cannot reference variable length [[STRING]] variable values. String values must be designated as a fixed-[[LEN|length]] string.''' diff --git a/internal/help/_MEMFILL.txt b/internal/help/_MEMFILL.txt index c9faad9c5..49c95b78c 100644 --- a/internal/help/_MEMFILL.txt +++ b/internal/help/_MEMFILL.txt @@ -11,7 +11,7 @@ The [[_MEMFILL]] statement converts a value to a specified type, then fills memo * {{Parameter|memoryBlock.OFFSET}} is the starting offset of the above referenced memory block. * The {{Parameter|fillBytes}} is the number of bytes to fill the memory block. * The {{Parameter|value}} is the value to place in the memory block at the designated OFFSET position. -* A literal or variable {{Parameter|value}} can be optionally set [[AS]] a variable [[type]] appropriate for the memory block. +* A literal or variable {{Parameter|value}} can be optionally set [[AS]] a variable [[Variable Types|type]] appropriate for the memory block. {{PageDescription}} diff --git a/internal/help/_MEMGET.txt b/internal/help/_MEMGET.txt index 611d431fd..37d69b977 100644 --- a/internal/help/_MEMGET.txt +++ b/internal/help/_MEMGET.txt @@ -8,18 +8,18 @@ The [[_MEMGET]] statement reads a portion of a memory block at an OFFSET positio * {{Parameter|memoryBlock}} is a [[_MEM]] variable type memory block name created by [[_MEMNEW]] or the [[_MEM (function)|_MEM]] function. * {{Parameter|bytePosition}} is the {{Parameter|memoryBlock}}.[[OFFSET]] memory start position plus any bytes to move into the block. -* {{Parameter|destinationVariable}} is the variable assigned to hold the data. The number of bytes read is determined by the variable [[type]] used. +* {{Parameter|destinationVariable}} is the variable assigned to hold the data. The number of bytes read is determined by the variable [[Variable Types|type]] used. {{PageDescription}} * The [[_MEMGET]] statement is similar to the [[GET]] statement used in files, but the position is required. * The memory block name.[[OFFSET]] returns the starting byte position of the block. Add bytes to move into the block. * The variable type held in the memory block can determine the next {{Parameter|bytePosition}} to read. -* [[LEN]] can be used to determine the byte size of numerical or user defined variable [[type]]s regardless of the value held. +* [[LEN]] can be used to determine the byte size of numerical or user defined variable [[Variable Types|type]]s regardless of the value held. * [[STRING]] values should be of a defined length. Variable length strings can actually move around in memory and not be found. -{{PageExamples]] +{{PageExamples}} ''Example:'' Shows how to read the PSET color values from a program's [[SCREEN]] memory to an array. {{CodeStart}} '' '' {{Cl|SCREEN}} 13 diff --git a/internal/help/_MEMGET_(function).txt b/internal/help/_MEMGET_(function).txt index 693a884b5..057dfe01d 100644 --- a/internal/help/_MEMGET_(function).txt +++ b/internal/help/_MEMGET_(function).txt @@ -16,9 +16,9 @@ The [[_MEMGET]] function returns a value from a specific memory block name at th {{PageDescription}} * {{Parameter|memoryBlock}}.[[OFFSET]] returns the starting byte position of the block. Add bytes to move into the block. * The variable type held in the memory block can determine the next {{Parameter|bytePosition}} to read. -* [[LEN]] can be used to determine the byte size of numerical or user defined variable [[type]]s regardless of the value held. +* [[LEN]] can be used to determine the byte size of numerical or user defined variable [[Variable Types|type]]s regardless of the value held. * [[STRING]] values should be of a defined length. Variable length strings can actually move around in memory and not be found. -* '''_MEMGET variable values that are assigned a variable [[type]] other than a memory type do not need to be freed.''' +* '''_MEMGET variable values that are assigned a variable [[Variable Types|type]] other than a memory type do not need to be freed.''' {{PageExamples}} diff --git a/internal/help/_MEMIMAGE.txt b/internal/help/_MEMIMAGE.txt index d871241c8..01818bf9d 100644 --- a/internal/help/_MEMIMAGE.txt +++ b/internal/help/_MEMIMAGE.txt @@ -13,7 +13,7 @@ The [[_MEMIMAGE]] function returns a [[_MEM]] value referring to an image's memo {{PageDescription}} * Use the function to place images into memory access blocks for faster data access. -* All values created by this function must be freed using [[_MEMFREE]] with a valid [[_MEM]] [[type]] variable. +* All values created by this function must be freed using [[_MEMFREE]] with a valid [[_MEM]] [[Variable Types|type]] variable. * Image handle values and the memory used must still be freed using [[_FREEIMAGE]] when no longer required. diff --git a/internal/help/_MEMNEW.txt b/internal/help/_MEMNEW.txt index 5d4a78e32..3f2ddaa94 100644 --- a/internal/help/_MEMNEW.txt +++ b/internal/help/_MEMNEW.txt @@ -7,7 +7,7 @@ The [[_MEMNEW]] function allocates new memory and returns a [[_MEM]] memory bloc {{Parameters}} -* The {{Parameter|byteSize}} parameter is the desired byte size of the memory block based on the variable [[type]] it will hold. +* The {{Parameter|byteSize}} parameter is the desired byte size of the memory block based on the variable [[Variable Types|type]] it will hold. {{PageDescription}} diff --git a/internal/help/_MEMPUT.txt b/internal/help/_MEMPUT.txt index 396dcb2f7..f5f214467 100644 --- a/internal/help/_MEMPUT.txt +++ b/internal/help/_MEMPUT.txt @@ -17,7 +17,7 @@ The [[_MEMPUT]] statement writes data to a portion of a designated memory block * The _MEMPUT statement is similar to the [[PUT]] file statement, but {{Parameter|bytePosition}} is required. * The {{Parameter|memoryBlock}}.[[OFFSET]] returns the starting byte position of the block. Add bytes to move into the block. * The variable type held in the memory block can determine the next ''byte position'' to write a value. -* [[LEN]] can be used to determine the byte size of numerical or user defined variable [[type]]s regardless of the value held. +* [[LEN]] can be used to determine the byte size of numerical or user defined variable [[Variable Types|type]]s regardless of the value held. * [[STRING]] values should be of a defined length. Variable length strings can actually move around in memory and not be found. diff --git a/internal/help/_OFFSET.txt b/internal/help/_OFFSET.txt index c8ab190e3..85abe9683 100644 --- a/internal/help/_OFFSET.txt +++ b/internal/help/_OFFSET.txt @@ -10,7 +10,7 @@ The [[_OFFSET]] variable type stores the location of a value in memory. The byte * _OFFSET types can be created as signed or [[_UNSIGNED]] at the programmer's discretion. * The type suffix for _OFFSET is '''%&''' which designates the integer value's flexible size. * Offset values are only useful when used in conjunction with [[_MEM]] or [[DECLARE LIBRARY]] procedures. -* OFFSET values are used as a part of the [[_MEM]] variable [[type]] in QB64. Variable.OFFSET returns or sets the current position in memory. +* OFFSET values are used as a part of the [[_MEM]] variable [[Variable Types|type]] in QB64. Variable.OFFSET returns or sets the current position in memory. * API [[DECLARE LIBRARY|LIBRARY]] parameter or [[TYPE|type]] names may include '''lp, ptr''' or '''p''' which designates them as a pointer type. * '''Warning: _OFFSET values cannot be cast to other variable type values reliably.''' * '''Warning: Variable length [[STRING]] values can move about in memory at any time.''' If you get the _OFFSET of a variable length sting on one code line and use it on the next it may not be there anymore.''' To be safe, move variable length strings into fixed length strings first.''' diff --git a/internal/help/_OFFSET_(function).txt b/internal/help/_OFFSET_(function).txt index 74cf74870..478f08a98 100644 --- a/internal/help/_OFFSET_(function).txt +++ b/internal/help/_OFFSET_(function).txt @@ -12,7 +12,7 @@ The [[_OFFSET]] function returns the memory offset of/within a given variable. * _OFFSET function return values should be stored in [[_OFFSET]] type variables. As no other variable type is 'elastic' like [[_OFFSET]], there can be no guarantee that any other variable type can hold the value of an _OFFSET. * Returns the memory offset of variables, user-defined-types & elements, arrays & indices and the base offset of [[STRING]]s. * Offset values are currently only useful when used in conjunction with [[_MEM]] or [[DECLARE LIBRARY]] procedures. -* OFFSET values are used as a part of the [[_MEM]] variable [[type]] in QB64; {{Parameter|variable}}.OFFSET returns or sets the current position in memory. +* OFFSET values are used as a part of the [[_MEM]] variable [[Variable Types|type]] in QB64; {{Parameter|variable}}.OFFSET returns or sets the current position in memory. * '''Warning:''' QB64 variable length strings can move about in memory at any time. If you get the _OFFSET of a variable length sting on one line and use it on the next it may not be there anymore.''' To be safe, move variable length strings into fixed length strings first.''' diff --git a/internal/help/_SHL.txt b/internal/help/_SHL.txt index 5a95915ac..ea520732a 100644 --- a/internal/help/_SHL.txt +++ b/internal/help/_SHL.txt @@ -43,7 +43,7 @@ B~%% = {{Cl|_SHL}}(A~%%,8) 'shift the bit off the left 'edge' A~%% = 1 {{Cl|FOR}} I%% = 0 {{Cl|TO}} 8 {{Cl|PRINT}} {{Cl|_SHL}}(A~%%, I%%) -{{Cl|NEXT I%%}} +{{Cl|NEXT}} I%% {{CodeEnd}} {{OutputStart}} 1 diff --git a/internal/help/_SHR.txt b/internal/help/_SHR.txt index c9b076554..2b6ceefc7 100644 --- a/internal/help/_SHR.txt +++ b/internal/help/_SHR.txt @@ -42,7 +42,7 @@ The [[_SHR]] function is used to shift the bits of a numerical value to the righ A~%% = 128 {{Cl|FOR}} I%% = 0 {{Cl|TO}} 8 {{Cl|PRINT}} {{Cl|_SHR}}(A~%%, I%%) -{{Cl|NEXT I%%}} +{{Cl|NEXT}} I%% {{CodeEnd}} {{OutputStart}} 128 diff --git a/internal/help/_glTexImage2D.txt b/internal/help/_glTexImage2D.txt index 931d8dc4a..732aeb47e 100644 --- a/internal/help/_glTexImage2D.txt +++ b/internal/help/_glTexImage2D.txt @@ -147,8 +147,6 @@ The {{KW|_glPixelStore}} mode affects texture images. [[_GL|SUB _GL]] {{KW|_glActiveTexture}}, {{KW|_glBindTexture}}, {{KW|_glTexImage1D}}, {{KW|_glTexImage2DMultisample}}, {{KW|_glTexImage3D}}, {{KW|_glTexImage3DMultisample}}, {{KW|_glTexSubImage2D}}, {{KW|_glPixelStore}} -[[Image_Format#Required_formats|Required formats]] - {{PageCopyright}} diff --git a/internal/help/links.bin b/internal/help/links.bin index 042bef6fe..e40949da6 100644 --- a/internal/help/links.bin +++ b/internal/help/links.bin @@ -88,6 +88,7 @@ $ELSE,$ELSE $ELSEIF,$ELSEIF $END,$END IF _ERRORLINE,_ERRORLINE +_ERRORMESSAGE$,_ERRORMESSAGE$ $EXEICON,$EXEICON _EXIT,_EXIT (function) _FILEEXISTS,_FILEEXISTS @@ -151,7 +152,6 @@ _MOUSEINPUT,_MOUSEINPUT _MOUSEMOVE,_MOUSEMOVE _MOUSEMOVEMENTX,_MOUSEMOVEMENTX _MOUSEMOVEMENTY,_MOUSEMOVEMENTY -_MOUSEPIPEOPEN,_MOUSEPIPEOPEN _MOUSESHOW,_MOUSESHOW _MOUSEWHEEL,_MOUSEWHEEL _MOUSEX,_MOUSEX @@ -275,12 +275,9 @@ BSAVE,BSAVE BYVAL,BYVAL CALL,CALL CALL,CALL ABSOLUTE -CALLS,CALLS CASE,CASE CASE,CASE ELSE CASE,CASE IS -CDBL,CDBL -CDECL,CDECL CHAIN,CHAIN CHDIR,CHDIR CHR$,CHR$ @@ -305,8 +302,6 @@ CVS,CVS CVSMBF,CVSMBF DATA,DATA DATE$,DATE$ -DATE$,DATE$ (statement) -DECLARE,DECLARE (non-BASIC statement) DECLARE,DECLARE LIBRARY DECLARE,DECLARE DYNAMIC LIBRARY DEF,DEF SEG @@ -333,22 +328,18 @@ ENVIRON$,ENVIRON$ EOF,EOF EQV,EQV ERASE,ERASE -ERDEV,ERDEV -ERDEV$,ERDEV$ ERL,ERL ERR,ERR ERROR,ERROR EXIT,EXIT EXP,EXP FIELD,FIELD -FILEATTR,FILEATTR FILES,FILES FIX,FIX NEXT,FOR...NEXT FOR,FOR...NEXT NEXT,FOR...NEXT FOR,FOR (file statement) -FRE,FRE FREE,TIMER (statement) TIMER,TIMER (statement) FREEFILE,FREEFILE @@ -375,8 +366,6 @@ INT,INT INTEGER,INTEGER INTERRUPT,INTERRUPT INTERRUPTX,INTERRUPTX -IOCTL,IOCTL -IOCTL$,IOCTL$ KEY,KEY n KEY,KEY(n) KEY,KEY LIST @@ -420,14 +409,10 @@ NEXT,NEXT NOT,NOT OCT$,OCT$ OFF,OFF -ON,ON COM(n) ON,ON ERROR ON,ON KEY(n) -ON,ON PEN -ON,ON PLAY(n) ON,ON STRIG(n) ON,ON TIMER(n) -ON,ON UEVENT GOSUB,ON...GOSUB ON,ON...GOSUB GOSUB,ON...GOSUB @@ -446,9 +431,6 @@ PALETTE,PALETTE PALETTE,PALETTE USING PCOPY,PCOPY PEEK,PEEK -PEN,PEN -PEN,PEN (statement) -PLAY,PLAY(n) PLAY,PLAY PMAP,PMAP POINT,POINT @@ -485,12 +467,10 @@ SCREEN,SCREEN SEEK,SEEK SEEK,SEEK (statement) SELECT,SELECT CASE -SETMEM,SETMEM SGN,SGN SHARED,SHARED SHELL,SHELL SHELL,SHELL (function) -SIGNAL,SIGNAL SIN,SIN SINGLE,SINGLE SLEEP,SLEEP @@ -521,7 +501,6 @@ TO,TO TYPE,TYPE UBOUND,UBOUND UCASE$,UCASE$ -UEVENT,UEVENT UNLOCK,UNLOCK UNTIL,UNTIL VAL,VAL