Copy Link
Add to Bookmark
Report

Qbasic Developers Forum issue 3

eZine's profile picture
Published in 
Qbasic Developers Forum
 · 28 Dec 2019

  

-=-=-=-=-=-=-=-=-=-=-=-=-=-
= Qbasic =
- Developers -
= Forum =
-=-=-=-=-=-=-=-=-=-=-=-=-=-
ISSUE III

Qbasic Developers Forum is a FREE newsletter made for Advanced Basic
Programming. BASICA/GW-BASIC, Qbasic, and QuickBasic coding methods
are discussed. It is written by Acidus Software. To obtain membership
Email me at:

LordAcidus@aol.com

************************************
*The FAT (Feature Allocation Table)*
************************************
(Editorials)
-From the AcidPool

(Articles)

-Creating a Soul
OS Programming in Qbasic

-Booting your computer
What a CPU does at booting, and HOW rebooting works

(Every Issue)
-Face Lift
Making your code more-readable

-Quick Tips

-Abort

------------------
From the Acid Pool
------------------

Hello folks, after many months. Most of my online friends thought I
was dead. I wouldn't let the world get off so easily. I'm here and so is
Issue 3. OPERATING SYSTEMS. Those are the topic of conversation. I hope you
enjoy it. As for the delay, School and other factors pushed this back and
back. I also wanted to include a copy of my OS in it. But, let me tell you
something cool. When I write for this Newsletter, I think of a topic that no
one has really covered, and then I go and start writing. As I write, I think
of new ideas, or better ways to do things. I learn a lot from writing these
things. I do a lot of research on all my topics. Also, I kept finding better
and better ways to do things, and my Old OS looked older and slower. So I
have begun to re-write AcidOS 3.0, with all the new things I discuss in the
issue.

Issue 4 is all in my head. I have TONS of ideas, and at least 15
working articles for up coming issues. While researching and trying stuff
on my computer, I found several new areas that I didn't even know about.
Which goes to show you folks, just like when I wrote Voices of Liberty(tm),
I learned so much. Big projects make you think. Enjoy the issue:

---------------
Creating a Soul
---------------

This article deals with operating systems, and trying to write your
own. This is very, very difficult. They are few good books on the subject,
and building one takes several years. Qbasic is hardly the language to even
try it in. The operating system is a lot more then a "c:\" or a arrow and
windows; that is about 10% of it. Then you have the stuff that turns on the
disk motors, moves the read/write heads of the hard drive, reads and writes
to RAM, loads and runs the drivers, reads in the keyboard, communicates with
BIOS, etc, etc. It takes FOREVER to do it. And, if you mess up in your code,
you can PERMENENTLY damage/destroy/disable any/all of your computer.

Wow, you're still here. Its scary, OS programming. First of all it
is very rewarding (But then again those people that have 2 years of their
life to blow don't really have anything else in their lives that is rewarding
either, so OS programming wins by default). Also Qbasic wasn't designed for
systems programming. I mean, you have to go back-assward and other weird
stuff just to read/write areas of RAM and communicates with Ports. ASM in
Qbasic is all but impossible. OS programming is almost always done in C or
C++. The C Language was created for the sake of writing the operating system
UNIX. So, OS programming is very hard, takes along time, and you don't have
the tools to do it.

You have two options. One: cry like baby, curse technology, and
become the Unabomber, or the 2nd one: cheat. But this isn't just any
cheating, this is MICROSOFT cheating. We'll make a pseudo-OS, like Windows.

YES YES YES, no matter what anybody says Windows 3.1 and 95 are NOT
operating systems. THEY AREN'T. I scream this because it pisses me of to
read and hear people say they are. They are SHELL OS's. IF you own a Windows
computer, what loads first? MS-DOS! And Windows 95 computer is just a MS-DOS
ver 7.0 computer with "win" in its MSDOS.SYS file or whatever its
autoexec.bat file is called. Windows 98 I believe is the same way. WINDOWS IS
NOT an OPERATING SYSTEM! This wouldn't turn into my I HATE MICROSOFT rant,
but if Microsoft calls Windows an OS, we can call our program an OS too,
because ours will run after DOS loads up as well.

This helps out a lot. DOS takes care of all the hardware low level
stuff, and we make a new user interface like windows.

There are two ways to create a pseudo OS. The Big program method, and
the "Ant Method". (Please note I'm making these names up, so don't go down to
your local bookstore and try to impress the red-head in your Physics class
who works there by asking for a book on "Ant method programming." She likes
Andy damn it! Not you. NO ONE LOVES YOU)

Well folks, back in spring 97, I got an old IBM XT. I made it my goal
to create one program that I could do everything with. It was really my first
Qbasic program. It was called AcidOS 2.5. Why 2.5? Well, I had made 2 "OS's"
for the TI-85 in TI-BASIC before. All these primitive OS's were of the Big
massive program school. Just think of a personal organizer. Then throw in a
simple word processor, a phone dialer, 2 games, and some other small programs
and you had AcidOS 2.5. (it slices and dices and doubles as lip wax, and is
only $19.95!) Sounds like Windows right. But Windows doesn't have all those
programs in one huge .EXE. But AcidOS was a big .BAS file with everything in
it. There was no way to customize, add to, or modify in anyway the program
without "hard coding" it in. By "Hard coding" I mean opening the file and
changing the code, and the saving it. All changes had to be written in. When
you add a new program to Windows, you don't have to re-install a version of
Windows that has the program in it do you. That would suck.

And it did suck, because I was just beginning Qbasic programming, so
I was re-writing AcidOS 2.5 everyday. It was more like AcidOS 2.578439.
So, I developed what I now call the "Ant method."

Making any Taoist proud, I looked to nature for my answers. If a big
bad ass program couldn't cut it, what would? Simple, a lot of little
machines working together. This is also called a Collective. I know you
nerdy bastards watch Star Trek, so think the Borg. What you have is a lot
of little things working together to do a bigger job than one could do. Bee
and ant colonies work like this. This is a new school of thought in robotics
as well. Ideally, you have small little beings, that you program to do a
simple task. Several of these simple tasks do a be problem. Each of these
little things can be programmed to do anything, though most are specialized.
If you still don't understand, think about the cells in your body. Please
understand that this isn't a lame idea of mine, but a real scientific theory
that evolution seems to show works.

Now with operating systems, you can have 3 different types of
structure, and 2 different user interfaces. By, structure, I mean the way
the operating system runs and manages all the other programs. The 3 types of
structure are Linear, Multi-tasking, and Task swapping.

Linear is the simplest type of OS structure. MS-DOS is an example of
this. It contains a few INTERNAL commands to manage your files: COPY,
DEL, RENAME, CD, DIR, and things like that. All other Disk functions, like
defrag, format, scandisk, are EXTRANAL programs. when you run an external
program, the processor runs only that program, until you quit or you hit the
power switch. When the program is done, control goes back to the OS. You
can't run several programs at once. I know so bustard is going to Email me,
chewing me out about TSR's and other crap like that, well Screw You! If you
don't know what I'm ranting about, don't worry about it.

Just as with the ants and bees, you need a "queen program." This
queen program isn't very big, but has an important job. It manages all the
other little programs. If you have a spreadsheet and a game running, the
queen must know what areas of memory are used by what programs, which program
you can see, and what part of what program is running. This is where
Multi-tasking comes in.

Multi-tasking. Dude. Just sit back and marvel at it. It lets you play
a game of Star Craft, then quickly flip to the word processor you were
writing your report on if your mom comes in. Not just that, but everything
is multi-tasking now. If you want to stay hot, you need to learn this. Ok,
so, what is multi-tasking? How does it work? Why does Offspring decide to
release a crappy song such as "Pretty fly" as the first single off their CD,
when the rest of the CD is so much better? Well, I hope to answer the first
two.

Multi-tasking literally means to have many tasks running at once. The
only way to do this would be to have multiple processors in your computer,
one for each task. This isn't cool for home use. It cost to damn much. So,
what you need to do is have one processor do a lot of things. But modern day
processors can only like to do one thing at a time. Just like those jerkoffs
at the DMV. They do one thing and do it until its done (and as slowly as
possible.) When you multi-task, you sit down at a table with your processor
and say "Listen you, I have 3 programs I'm running, you better do them all."
The poor processor only has one hand, and thus can only do one thing at a
time. However, he has a lot of time. Half a second is an eternity to a chip.
So what they to is say, OK, I have to do three tasks Hmmm. Well, then, I
will work on program1 for 20 nanoseconds, and then program2 for 20 , then
program3 for 20 as well. Opps, I have no new tasks. Ok, then I will go back
and work on program1 again for 20 nanoseconds. (Yes, you processor can talk,
and it tells you to burn things, just like your Rice Krisby's do)

Well, ok, how do this work? Well, this is the hardware side of
multi-tasking. You see, the Intel 80386 had some cool modes. The chip could
kind of divide itself up, into little computers (ant theory.) Each of these
mini-computers used its own area of memory, and didn't know the other parts
existed. Every time a new task was started, the processor created a little
part for that program. All chips before the 80386 couldn't do this. The 80286
has some modes as well, but these modes (the mini-computers) couldn't be
opened and closed without restarting the machine. This is why you can't
multi-task on a 286. You use something called Task swapping, which I will
discuss later.

Anyway, the 386 had these separate little computers running each
task. But since you have one processor. The "queen" program told the
computer which task to run, and where in memory it was. Only one task is
worked on at once. The processor moves to the next task when the queen
program gets an interrupt. WHAT THE HELL IS HE TALKING ABOUT? HE WENT FROM
QUEEN BEES AND ANTS TO TIMER INTERRUPTS! WHAT THE HELL IS A TIMER INTERRUPT?

Your computer keeps track of time with a little piece of crystal.
This thing wiggles like it is being tickled when electricity goes through it.
The computer counts the vibrations of the crystal, and is able to figure out
seconds, and minutes. Older crystals don't vibrate as fast as new ones. These
crystals are what restricts the speed of the motherboard. The wiggling of
this crystal generates an interrupt. If you don't understand, don't worry,
here it is in simple terms: You have some rock in your computer. Its magic.
When you shock it, it moves. After it moves so many times, it send a signal
to the computer that says "Heah, so much time has gone by!"

Now, what the queen program does, is when it gets this interrupt, it
says "ok, the processor has been working on program1 for so long, I better
get it to stop on program1 and go to program2 and work on that until I get
another interrupt. The processor then stops working on program1, and goes and
works on program2. Now remember, the little parts of the processor don't know
the others exist. It seems to that part that it is the only program running,
and when the processor goes and works on another part, the previous part just
thinks the processor is taking a coffee break. This is very important. Since
all the parts are independent of each other, you can close a bad part. In
windows, you can use [ctrl]+[alt]+[Del] and close a program that is messing
up. But it doesn't mess up the rest of your computer. The queen program just
shuts down that part of the chip. That part of the chip can be used again at
any time.

GENERAL PROTECTION FAULT AT 43FB:001C. We've all seen something like
this when using Windows, though they aren't as common in Windows 95/98. These
are caused by lack of space in memory. Remember I said that each little
mini-computer, or part of the processor doesn't know the others exist, and
has its own area on memory. Well, GPF's are caused when two mini-computers
use the same area of memory. Program2 writes some data to some part of
memory. Later when the processor gets to Program5, Program5 writes here as
well. Since each part doesn't know the others exist, they see "ghosts". You
see, program2 KNOWS that it wrote to this area of memory. But when it is its
turn, and program2 tries to read what it put there, it sees that something
is wrong: the data is different. Since program2 thinks it is all alone, it
doesn't understand why the data is different. At this point one of two things
can happen. One, the program chokes, and locks-up. The other is it takes the
different data is used anyway. This is bad, because the computer could think
you have -3.1459 hard drives or something. The program will soon (like 1
nanosecond later) choke, and you get the choice between "IGNORE" and "CLOSE."
Ignore almost never works, because if two programs are using the same memory
to store crap, it is very likely other "ghosts" will appear, and cause more
errors.

Well guess what folks, Intel is a bastard, and hasn't responded to
lots of Email (each one containing more foul language then the previous)
about the proper ASM code to switch modes. I stumbled across a way to
multi-task using C in old book from the mid 80's, but it was a way to
multi-task SUB programs. Still, I am studying the text, and very carefully
testing things in C. If I get it to work, I'll see if I can convert it to
Qbasic, so I will get back to you about it.

Ok, to create our OS, since we are following the Ant Method, we will
make a "queen" program. What it will do is keep track of all the programs
that are running. There is no way to switch processor modes in Qbasic (and
set up the little mini-computer's or parts of the chip), so there is no way
to multi-task. So, we will have to relay on an older method, used by Windows
2.0 (Yes there was a Windows 2.0, and a Dos 2.1 for that matter, and 20lb
"laptops" that were so slow CS majors had nightmares about them. They bolt
awake in the middle of the night screaming "FOR THE LOVE OF GOD, MAKE THE CGA
MONITER STOP FLICKERING!" Its very sad)

Windows 2.0 was for the XT's and 286's. It ran programs by something
called "Task Swapping." What this is just a low-tech version of
multi-tasking. Instead of making lots of little computers to run each task,
and switching between them, Task Swapping takes an easy route. What it does,
is save everything about a program, and then load another program for the
processor to work on. The hard part is saving all the data, and then being
able to go back and resume your work on it. First the program file itself
must be found. Then Loaded. Then load up all the old data, variables, etc.
Then restore the screen to the way it looked before you changed tasks. Then
dig through the program until you find where it left off, and then run the
program.

Tasking swapping is an easy process to understand, but implementing
it is a whole different manner. First of all is compatibility. You must have
it. MS-DOS programs from 1982 still run in Windows 98. Unfortunately, I have
no idea how to Task Swap DOS programs. So, into our OS, we must build in
support to run DOS programs. You might think you do this with a simple
SHELL statement. Yes you can, but if you are using Windows 98, then Run your
OS, then shell out run programs, you are going to run out of memory REALLY
DAMN FAST. I'll show you how to get around this later. You must also have
support for normal .BAS files. You must create support for our *NEW* .BAS
files. New .BAS files? Yes. Just like windows programs make use of Windows
options, our new .BAS files must do the same.

Alright. everyone, GO OUT. Right now, call up a friend, go hang out.
You have already taken in a crap load of knowledge. I got headaches designing
this next part. The idea is simple, it is just very long and hard to explain
and do.

THE OS KERNAL

The OS kernel is the queen program I've been talking about. It must
handle input from you, as well as load and manager running tasks. This is the
bulk of your program. However you want to do this is your own deal, but there
are something's that it MUST have. The reason I say MUST, is that if every OS
written in Qbasic handles task swapping differently, No one will benefit.
Code for one machine won't work on another. And remember, your OS must handle
at least 3 different types of code: DOS, old Qbasic, and the New Qbasic that
we will write.

Allow me to be specific. When I say New Qbasic, I mean Qbasic
programs that include some extra code that will allow it to be minimized and
restored. Not to be on a Power trip, but I call Qbasic programs that have
this "AcidOS compatible." I do this because as near as I can tell, I made the
first tasking swapping OS in Qbasic, AcidOS 3.1 in the Spring of 1998. I ask
that people who use my method of minimizing and restoring to put somewhere
in the Program that it is "AcidOS Compatible."

One thing to point out, Unlike Windows programs, AcidOS compatible
programs run just fine in Qbasic. They are written in Qbasic. In fact, when I
tell you the method I use, you beginners will say "Is that all" and you
advanced guys will be slamming your head against the wall for not thinking
of it.

First off, lets ID some possible problems. We can't use Shell to
run really any BIG programs (over 250,000.) because of memory restrictions.
This all goes back to a little something called the 640K memory barrier, and
is complicated. All you need to know is for the most part, when you enter
DOS or run a DOS program in Windows, you have a max of 640k to deal with.
Many people will yell at me about this, but since this isn't my article on
memory, I'm not going to get into all this. For simple OS programming like
this, all you need is 640k. So, we must find a way to quit your OS, run the
.EXE/.COM/.BAT you selected, and then return to the OS, all without the user
having to enter in any commands.

Second, we must allow .BAS Files to run in Qbasic which is loaded into
memory, so that changes can be made. The computer must then reload the OS
and restore all the old settings once Qbasic is closed. This means we can't
use the RUN statement, because it would not reload the OS when done.

Third, we must set up a way for AcidOS compatible files to take
advantage of their abilities when run in an AcidOS compatible operating
system, yet if you use them in Qbasic, then they act like a normal .BAS file.
This must be exact so everything is compatible. So If I run an AcidOS
compatible program through AcidOS compatible operating, I can minimize it,
and have several "running" at once, yet if I run it just through Qbasic, they
act like normal Qbasic Programs.

HANDLING THE FILES TYPES.

For .EXE we get sneaky. Since we can't use the SHELL commands to run
our .EXE files, we ACUALLY have to exit our OS, run the program, and get back
to the OS without the user knowing. How? that is a questioned that bugged me
all of Winter break in late 1997. Finally, I came across some old files from
GW-BASIC that did something called keyboard-stuffing.

What Key-stuffing is, is you make the computer think the user type in
some keys. You know how the computer can be doing something, and you can type
on the keyboard. Then when the computer is done, it can read all those keys
you hit. Well, there is a special part of your memory that is called the
Keyboard Buffer. When you type a key, it is put in the Buffer. The computer
reads from the buffer not the keyboard. So, you can put stuff into this
Buffer, and then the computer thinks that the user typed it in. So we, make
a BATCH file that has 2 lines. The 1st is the .EXE file we want to run, the
2nd is another Keyboard stuffer program. If we have in our Batch file our
OS.exe file, the Batch file stays loaded in memory. This is only a small
amount of memory used, but you will get errors after you run a few .EXEs.

To overcome this, we will have a program called Stuffbuf.exe which
will stuff the buffer for us. That way, when the .BAT file ends, DOS will
re-load our OS. Here is the concept map of all this in plain English

-The User selects .EXE to run
-The OS creates a .BAT file with the .EXE to run, and the StuffBuf.exe
program
-The OS then stuffs the Keyboard buffer with the name of our .BAT file, and
exits.
-DOS takes over, and sees that their are characters in the Keyboard buffer,
and it reads in the characters, and then runs that .BAT file
-The .BAT file runs, and it runs the .EXE program.
-The user uses the .EXE program, and when he quits, the .BAT file runs the
stuffbuf program.
-The stuffbuf program will put the name of your OS.exe file into the Keyboard
buffer. The line will look something like: StuffBuf AcidOS
-The .BAT file ends, frees up memory, and then DOS says, well Hell, There is
something in the keyboard buffer (THE NAME OF OUR OS), and runs the .EXE
file of our OS. (I my case AcidOS.EXE)

Here is the Code from AcidOS 4.1. The SUB RunEXEFile is called, where
Filename$ is the path and name of the File you want to run. StuffBuffer is the
Sub that puts the name of our Batch file into the Keyboard buffer. The name
I used is "_.bat". Finally, StuffBuf is the .EXE file that also stuffs the
keyboard buffer.


SUB RunEXEfile (filename$)
a% = FREEFILE
OPEN "_.bat" FOR OUTPUT AS #a%
PRINT #a%, "@echo off"
PRINT #a%, filename$
PRINT #a%, path$ + "stuffbuf acid"
CLOSE #a%
StuffBuf "_.bat"
SYSTEM
END SUB


SUB StuffBuffer (batch$)
Stuf$ = LEFT$(batch$, 14) + CHR$(13)
Length = LEN(Stuf$)
DEF SEG = 0
POKE 1050, 30
POKE 1052, 30 + Length * 2
FOR a% = 1 TO Length
POKE 1052 + a% * 2, ASC(MID$(Stuf$, a%))
NEXT
SYSTEM
END SUB

Here is an example of it working: I want to run QBASIC.EXE
-The OS writes a Batch file named _.BAT
It looks like this:
@ECHO OFF
C:\DOS\QBASIC.EXE
C:\ACIDOS\STUFFBUF ACID
-My OS stuffs the Buffer with "_.BAT" and exits
-DOS takes over and sees that ".BAT" is in the keyboard buffer
-DOS runs _.BAT
-_.BAT runs C:\DOS\QBASIC.EXE
-The user fiddles with it, does what ever, and Quits
-The next line in "_.BAT", which is "STUFFBUF ACID", is run
-The Keyboard buffer now has "ACID"+ an enter key in it.
-_.BAT has no more lines, and returns control to DOS, freeing the memory it
was using
-DOS sees that "ACID"+ an enter key is in the Keyboard Buffer, and runs ACID
-ACID runs, Checks for flags (I'll talk about it later) sees that it isn't
being started for the first time, and that it is being run after having
run a .EXE file, and loads its old settings.

All the user has seen of this is AcidOS, then Qbasic, then AcidOS
again just the way it was before. DAMN THATS COOL! We ran a .EXE file, saved
a lot of memory, and the User didn't even know! Ok, That was a little tricky,
but I hoped you followed. Are you being to see how this isn't just ideas and
concepts, but things you can really do, tangible things! Its a rush. What you
just wrote is basically Windows 3.x in Standard mode.

OK now we know how to run .EXE files. To run .BAS files is easy.
We can't just use the RUN statement, because then we can't get the computer
to automatically go back to our OS. But, what if the program is an AcidOS
compatible .BAS, and has the ability to be minimized, and moved, and other
cool stuff. I don't really want to get into AcidOS compatible Programs right
now, but they will ALL have certain code in them that will Identify them.
What your OS will do is scan through the .BAS file, and look for these
special lines of code that ALL AcidOS compatible programs have. If the OS
detects these, then it will run it a special way I will talk about in the
next section. If the .BAS lacks these, then it is a plain old .BAS file, and
has to be run a separate way, so that the OS runs when the .BAS is done.

To do this, we basically use the same method as running a .EXE file.
we run QBASIC.EXE as the file, and use /RUN [filename] to load an run the
.BAS. I have a SUB in AcidOS 4.1 called RunBASFile. It looks like this

SUB RunBASfile (filename$)
a% = FREEFILE
OPEN "_.bat" FOR OUTPUT AS #a%
PRINT #a%, "@echo off"
PRINT #a%, "c:\dos\qbasic /run "+filename$
PRINT #a%, path$ + "stuffbuf acid"
CLOSE #a%
StuffBuf "_.bat"
SYSTEM
END SUB

Well, hell, That was easy. It works just like to other method. Next,
we have to have a way to run our AcidOS compatible .BAS files. This is kind
of hard. What we are going to do is make .BAS files that run just like
normal .BAS files, but if they are run through AcidOS compatible Operating
systems, they can be used in Task swapping. You can minimize these files, and
return to them later. Just like Windows.

Just for the record, these enhanced programs that take advantage of
AcidOS compatible commands will be called AcidOS programs for the rest of
the article. Originally, they would be .BAS files, but about halfway through
writing this article, I found a way to used compiled .BAS files, and for
that matter, AcidOS files can be written in ANY computer language, as long as
it is compiled into an .EXE file.

First things first. How do I get an AcidOS program to see that it is
being run in AcidOS. Remember, we what it so that AcidOS programs can run
both in and out of AcidOS, just like DOS programs can be run in or out of
Windows. Originally, I was going to use the COMMON key word, and use this
to pass on important information from the queen program to the other
programs, by running them with CHAIN. However, If I did this, The OS itself
and all AcidOS programs would to be written in Qbasic only, and could never
be compiled, because COMMON can't share variables across .EXEs. Instead, I
used RAM to set "flags".

Ok, history lesson time folks. If you read "Boolean Hell" in last
issue, then you know all about truth tables. You also learned all about
Binary. Well, every thing on a computer is measured by 8ths. A Kilobyte
isn't 1000 bytes (Kilo means 1000 people) it is 1024 bytes. Because 1024
is the closest number to 1000 that is divisible by 8. Knowing this, look
at your screen. I don't want to get to detailed, because I have an article
for next issue written all about screen memory, but here goes. In RAM, there
is an area that holds what's on the screen. When you are dealing with the
standard text screen, you have 25 lines, and 80 rows. this makes 2000 little
places for a characters on your screen. You then have ANOTHER 2000 little
places need to hold the color for each place. So 2000+2000=4000 places need
in RAM to store screen data.

BUT WAIT! everything on computers MUST be divisible by 8. So, in RAM,
there is REALLY 4096 bytes of RAM for screen data. But the computer only uses
4000 of this. You have a 96 byte scratch pad! You can shove stuff in there,
and run a ton of other programs, and then go back and look, and what ever you
put in will still be there. (This isn't ALWAYS true, starting Windows and
other stuff will purge the data, but for our purposes of OS making, we don't
need to worry about this)

So, what we do, is have our OS put some a little "flag" into memory,
and run a program. If that program is AcidOS compatible, it checks in RAM for
this flag, and if it finds it, the program knows it was run through AcidOS.
Normally, all the settings information would be put into RAM, and another
program started, and then when it ends, the settings are read from memory.
the only problem with this is that I don't know how to "lock" areas of memory
so that other programs can't use them. And since we only have 96K of memory
to work with, we will just put in strings of characters, to communicate
between programs.

Ok, there are 2 video buffers on your computer, 1 for color, 1 for
monochrome monitors. Everyone basically uses color monitors now, BUT, even
Windows 95 runs on monochrome monitors, so for compatibility, we must
support this. What our OS will do is determine which Video buffer the
computer is using, and use the last 96K of it. To do this you use the
following code:

DEF SEG = 0
IF PEEK(&H463) = &HB4 THEN
DEF SEG = &HB000 'Its MONO!
ELSE
DEF SEG = &HB800 'Its COLOR!
END IF

Please note, this isn't what the monitor is, but what the video
card is. I am writing this on a 386 with a Super VGA card, but with a
monochrome VGA monitor. What the above code does is look and see what buffer
the computer is using. I will discuss more about Video buffers in the next
issue.

OK, so, we are now at the starting address of the Video Buffer. The
Buffer is 4096k long, though the last 96k aren't used. To access them, use
PEEK, and POKE. We use 4001 because 4000 is the end of the Video buffer that
the computer uses.

POKE(4001),65 '65 is the ASCII code for "A"
PRINT CHR$(PEEK(4001)) 'This prints "A" on the screen

Well, we would use POKE(4001) by the main program to put a little flag into
memory, and then our AcidOS programs can simply use PEEK do detect this flag.
If they don't see it, they assume that they are being run outside of AcidOS,
and function like normal files. This files can be .EXE .BAS .PAS .C .CPP, or
any language. Now, there is a chance that the value at 4001 is the same as
our flag, but was put their on accident. I know this chance is small, but
imagine running a normal .EXE, that you didn't know was AcidOS compatible,
and when you quit, your computer freezes, because it tries to load up an
operating system that doesn't exist!

To minimize this, the OS will set 4 flags in a row. The string "OS*1"
will be put into memory into 4001-4004 of the Video Buffer. The possibility of
these values being put into those memory address in that order by any other
program are basically NIL. But, Heah, If you throw a pen at the top of the
table enough times, it will go through without leaving a hole (its true, ask
your physics teacher) Another plus for this is that the OS is now upgradable.
If I am working on an OS that allows split screen action, and have several
different windows open at once. Operating systems that can use this will use
the string "OS*2." This way old programs can run on Newer OS's. Also, a
program that is capable of using these functions can tell from the Init string
if the OS can support it, and adjust itself. Here is the code I used in

AcidOS 4.0:
SUB SetOSFlags

DEF SEG = 0
IF PEEK(&H463) = &HB4 THEN
DEF SEG = &HB000
ELSE
DEF SEG = &HB800
END IF
OSint$ = "OS*1"
FOR a% = 4001 TO 4004
POKE (a%), ASC(MID$(osint$, a% - 4000, 1))
NEXT

END SUB

AcidOS programs should use the following code to detect if AcidOS is
Running:

FUNCTION DetectOS%
OSint$ = " "
FOR a% = 4001 TO 4004
MID$(OSint$, a% - 4000) = CHR$(PEEK(a%))
NEXT
IF LEFT$(OSint$, 3) = "OS*" THEN
DetectOS% = 1
END FUNCTION
ELSE
DetectOS% = 0
END IF
END FUNCTION

Well, there is alot of Data to make available to the AcidOS program.
In fact, alot more than we could cram into 92 (96-4 for the init string)
bytes. So, what we do is save this information in an ASCII file, and let the
AcidOS program take what it needs. For example, I built in a Print Manager
into AcidOS 4.0. Now, I might be running a game, or something that doesn't
want to add files to or even use the printing buffer. The information will be
put in the ASCII file, but the program is only programmed to take what it
needs.

Well, this was a brain-racking experience. I need to think of every
possible thing a program could want. Since I might create something in the
future, like that multi-windows thing, I needed to include things that might
not be needed now. Here is the list of things I put in the OS.INI file:

Path of AcidOS
Path of program running
Screen mode of OS
Where in the program (if at all) it was minimized

My OS.INI file for AcidOS 4.0 when I run "Voices of Liberty"(TM)
looks like this:
C:\AcidOS\
C:\Games\VOL\
0
0
When I run it again, after I have minimized it, it looks like:
C:\AcidOS\
C:\Games\VOL\
0
72

Every time you run or switch to a program, a new OS.INI is written. In
addition to these, I created 4 Signal bytes in RAM. These signal bytes tell
the conditions under which a program is being called. There are 2 signal
bytes for AcidOS programs, and then 2 signal bytes for AcidOS that tell
AcidOS the return state of the programs being called. Here are the
conditions:

Signals from AcidOS to a program:
AA=Normal start up.
The program hasn't been running in minimized format. The program runs
normally from the beginning.
BB=Minimized start up,
The program was running, and it is resumed. All previous settings are
loaded, and the screen is loaded, and the program resumes roughly where it
left off
CC=Shut Down
This signal tells the program that the either the whole OS or this program
alone has been shut down by the user. The AcidOS program, should clear out
all its files that hold saved information, and prompt the user to save if
that program offers saving. (Ex: you shut down a word processor like Acidus
Software's Typist, Typist receives this signal, and asks the user if they
want to save the document they were working on.

Signals From a program to AcidOS:
AA=Normal Ending
The program has been exited by the user, and all work on it is terminated
(ex: you select Exit, or something like that, and the program ends)
BB=First time minimized
The program has been minimized, but this is the first time it has been.
This is important, because the OS then has to make a minimized icon, or in
someway create a NEW link to the program.
CC=Minimized program
The program was minimized again, it was already running on the computer.
This can't be confused with 11, because the OS needs to UPDATE the link to
the program, not create a new one.
DD=Error in the program
The program erred. The program will make a file named "ERROR.DAT" in
the programs path explaining what caused the error.

Here are the following subs to create signal flags:

SUB OSSignalFlags (code$)
'Set flags for Program to read
DEF SEG = 0
IF PEEK(&H463) = &HB4 THEN
DEF SEG = &HB000
ELSE
DEF SEG = &HB800
END IF
POKE (4009), ASC(LEFT$(code$, 1))
POKE (4010), ASC(RIGHT$(code$, 1))
END IF

SUB ProgramSignalFlags (code$)
DEF SEG = 0
IF PEEK(&H463) = &HB4 THEN
DEF SEG = &HB000
ELSE
DEF SEG = &HB800
END IF
POKE (4011), ASC(LEFT$(code$, 1))
POKE (4012), ASC(RIGHT$(code$, 1))
END IF


Please note that only AcidOS compatible programs will recognize these
codes. If I run Qbasic through AcidOS, I can't minimize it. BUT, if I run
"Voices of Liberty" (TM) from Acidus Software, it can be minimized. Also, I
will be telling you how to use the signals sent back and forth between AcidOS
and AcidOS programs, so you can write AcidOS programs. AcidOS programs can be
in .BAS format or a compiled .EXE. You can write AcidOS programs in any
language other than Qbasic, as long as you compile it into an EXE.

Lets look at that OS.INI file. First off I put the path of the OS as
the First line. In my OS, I had it add a line to your autoexec.bat, declaring
"OS = C:\AcidOS" which is the directory that my OS is in on my 386. You can
easily get this by using the ENVIRON$("OS") command, but I included it
anyway, because not everyone's OS will be like mine. Also, I included the path
of the program being run. I did this because it makes things a lot easier.
If I run "Voices of Liberty"(TM) though AcidOS, it will know what directory
to load its files from: here is an example:

BLOAD ProgramPath$ + "Nuke.gfx" ,0

This way, you wouldn't get any funky errors. I also included the
screen mode of the OS, so if in the future, I can possibly have several
windows on the screen at once. AcidOS 4.0 is all TEXT based, and has no
graphics. So It uses Screen mode 0. Your can be in any mode you want. I
decided to put nothing else in the OS.INI file for the OS*1 standard.
OS*2 might have more, I'm not sure. I'm not even sure If I will make an OS*2
standard.

Minimizing and closing appear magical, but are really quite simple.
Basically you write your program so that when a certain key is pressed (I used
F1), The program stops, saves all its variables, and its location into a file,
put up a little flag for AcidOS, and fills the 2 Signal bytes with its return
conditions. To make a program stop, use the "KEY" and "ON KEY" statements.
Again here is code directly from an AcidOS program called "Cents"(TM)


a% = DetectOS% 'Our Function that looks and sees if it was run in AcidOS
ON KEY(1) GOSUB MinimizeProgram 'Map the keys
ON KEY(2) GOSUB CloseProgram 'Map the keys
IF a% THEN 'If OS was detected, enable Minimize/Close keys
KEY(1) ON 'F1
KEY(2) ON 'F2
ELSE 'If Not, disable
KEY(1) OFF
KEY(2) OFF
END IF

The DetectOS% is the Function that looks into RAM for the "OS*"
string. If it returns a true, then KEY 1 and 2 are turned on. These are
F1 and F2. I use F1 to minimize, and F2 to close. This little bit of code
also shows how if DetectOS% doesn't find an OS, then Minimize and Close
cannot be used at all, thus avoiding errors if you ran "Cents"(TM) alone.
Note: I just used F1 and F2, you can use any keys you want, just be sure to
tell the user which keys do what. Also, you can have these items selectable
on pull down menus if you want.

Ok, So, you have your program, and you press F1 to minimize it, and
the program jumps to MinimizeProgram:. Next, you must save the contents of
the screen. Saving and loading screen images can be tricky, because each
different video mode has a different way of storing data. I will tell you
how to save screen images in screen mode 0 right now, because, that is how
I did it with AcidOS. If you have graphics, you will merely have to write a
sub program that redraws the screen. I will have a future article which talks
about this. Remember those Video buffer things? Well, what you are going to do
is go to the start of the Video buffer in memory, and simply copy the next
4000 bytes into a file. It is that easy. I don't really want to get into
how BLOAD and BSAVE work, so here it is plain and simple. You set an address
with DEF SEG, and with BSAVE, tell the filename you want to copy x number of
bytes to. In this case, we would use something like:

SUB SaveScreenImage (ProgramPath$)
DEF SEG = 0
IF PEEK(&H463) = &HB4 THEN
DEF SEG = &HB000
ELSE
DEF SEG = &HB800
END IF
BSAVE ProgramPath$ + "Screen.gfx", 0, 4000
END SUB

That just figures out which video Buffer is being used, and goes to
the starting address of it. BSAVE then saves 4000 bytes
(80 rows * 25 lines * (1 character + 1 color value) = 4000 bytes), into a
file named "Screen.gfx" in the directory the program was run in. We got
ProgramPath$ by opening the "OS.INI" file. Also, you must save all the
variables in you Program as a file. How you want to do this is your own thing.
I used "OPEN ProgramPath$ + "Set.ini" FOR INPUT AS #" so I could save
strings, easily, though you can really use any way you want. Now, we need
to make a little flag for AcidOS to check for when it re-load, so AcidOS
knows it isn't being run the first time, but really coming back from a
program. We do this just like we did with "OS*1", we will use instead "PG*1"
PG stands for ProGram and it can use up to OS*1 features. Again, this
sharing of information about what the OS and what the programs are capable
of doing allow for Upgrades later. Instead of using Memory address 4001-4004
away from the start of the video buffer, we will use 4005-4008. Here
is the code, for a program to put the Flag into memory:

SUB SetPGFlags

DEF SEG = 0
IF PEEK(&H463) = &HB4 THEN
DEF SEG = &HB000
ELSE
DEF SEG = &HB800
END IF
PGint$ = "PG*1"
FOR a% = 4005 TO 4008
POKE (a%), ASC(MID$(PGint$, a% - 4004, 1))
NEXT

END SUB

The last thing that going in your "set.ini" is the location in the
program where you were. Remember all those losers that told you NEVER to use
GOTOs, well, SCREW THEM! What you do is have throughout your program have
PlaceInside% = 1, or 2 or what ever. You should place these right after
labels, and at the beginning of loops. When they minimize, this gets saved.
When they return, you will have a little hunk of code that is basically a
series of "IF THEN GOTO"'s that will take you roughly back to where you were.
BECAREFUL: You can run into problems During FOR LOOPS, and GOSUBS. You could
return to the program in the middle of a GOSUB, hit a return, and the program
chokes. Another thing to watch out for are open files. You might want to
keep track of them, so you don't get all those nasty FILE I/O errors

Also if, you are in a FOR LOOP, and you return, it doesn't work
anymore, even if you save the counter variable in the FOR LOOP. To bypass this
you can convert all your FOR NEXTs until DO WHILEs like so:

FOR a% = 1 to 100
Dump%(a%) = a%
NEXT

a% = 1
DO
Dump%(a%) = a%
a% = a% + 1
LOOP WHILE a% <= 100

I'm sure there are alot of ways to track were in the program you were,
but this is the easiest way I found. Again, this is something that you can do,
your own way, and don't have to follow my method, though I like it. Finally,
use the SYSTEM command to kick out of the program. AcidOS loads up, sees the
flags, and reloads its settings, with the program minimized:

When you run a minimized program, here's what happens: AcidOS creates
a new "OS.INI", and saves its settings. It then uses the RunEXEFile SUB, and
kicks out to DOS. DOS runs _.bat, and the EXE file you selected. The file
checks for the "OS*" flag in memory, and if it fins it, open "OS.INI" The
program looks at the 2 Signal bytes, and sees what the OS told it to do.
It sees that it has already been minimized, and it first loads up the screen
image. To do this, it uses the following Code:

SUB LoadScreenImage (ProgramPath$)
DEF SEG = 0
IF PEEK(&H463) = &HB4 THEN
DEF SEG = &HB000
ELSE
DEF SEG = &HB800
END IF
BLOAD ProgramPath$ + "Screen.gfx", 0
END SUB

Next, it loads up the old data. This is how I do it, though how you
decide to save your data is cool.

DIM MapData%(10)
OPEN ProgramPath$ + "SET.INI" FOR INPUT AS #1

INPUT #1, PlaceInside% 'THIS IS THE LOCATION OF WHERE IT LEFT OFF

FOR x%=1 to 10
INPUT #1, MApData%(x%)
NEXT

Line INPUT #1, Name$
input #1, ...
input #1, ...
input #1, ...

CLOSE

Then you need to resume the program. I used ON GOTO. I have never had
to use this statement before, and it is really quite dumb. But it works here.

ON PlaceInside% GOTO Main, Test, EnemyMove, PlayerMove, cool

What this command does is take the value of PlaceInside%. IF it =1
then it goes to label Main. IF it =2 then it goes to label Test. 3 takes you
to EnemyMove..etc..etc. See, this is very helpful here, but it is normally
worthless. The program goes to the label and resumes.

ISN'T THAT DAMN COOL? THAT TOOK ME THE BETTER PART OF A YEAR TO THINK OUT AND
PREFECT! WELL, DAMNIT, IT WAS HARD, SO YOU BETTER LIKE IT WHETHER YOU LIKE IT
OR NOT!

OK Folks, here is the cool part, YOUR ALMOST DONE. And The last part
is totally up to you. I have told you how to get your OS to run an outside
.EXE, .COM, and .BAT files; how to run a .BAS file, and how to run a .BAS
file with special options like minimizing. I also told you what the programs
tell the OS when they restart it. Notice I never really told you how your OS
should LOOK. That is your choice. If you want to write a GUI like WINDOWS, go
for it. Your OS can be text based, Graphics based, Have a mouse, have a
joystick, have icons, have a menu bar, have modem support, anything! I will
have an article in either the next issue or the one after that on cosmetic
things like that. I will also send you a copy of my OS in the next issue, so
you can see how I did it.

This stuff is very hard, and I'm sure their are parts in this article
that weren't clear to everyone, and I'm sorry for that. I have had 3 people
read this, and have modified it accordingly. IF you have any questions, please
E-mail me, and I will publish them in the next issue with an answer, so
everyone can understand it.

---------------------
Booting your computer
---------------------

In issue 1, I showed you how to reboot the computer. I didn't explain
how it worked. So, here you go, your computer boots like so:

1-Power switch turned on.
2-Power supply performs a POST test. This check to make sure power goes to
all parts of your computer, the voltage is right, and the current from the
wall is at a steady flow. If you have an AT keyboard (all of you should),
the LEDs blink once during this phase.
3-The timing chip on your motherboard sends the OK signal to your Processor,
telling it to stop resetting. Until the processor receives this, It keeps
resetting itself, and is incapable of any work.
4-The processor than goes begins to execute ROM BIOS. ROM BIOS is the man
behind the curtain. It communicates (for the most part) between the
Operating System (DOS, Windows 98) and the hardware. IBM did a good thing
however. They saw that as the computer grew, the BIOS would change to work
with the advancing technology. So, they decided to have the BIOS ALWAYS go
to FFFF:0000 in memory. At this location is a JMP command. JMP is an
Assembler command just like GOTO. JMP gives the address of the where the
BIOS started. What this means, that even though every BIOS is different in
size and location, ALL computers have the address of where the BIOS is
written at address FFFF:0000. So, On my old IBM XT and on a Pentium II,
the computer has to look at address FFFF:0000 to find the correct address
of the operating system.

So, to reboot the computer, you simply go to the address at FFFF:0000
and do the JMP instruction there. This works of every computer that follows
IBM PC-compatible. I have heard AT&T, old TI, and old HP computers don't work
like this, but you will not find them around anymore. To DO an instruction
you use "Call Absolute" in Qbasic. You must start any compiling form of
Qbasic (such as QB4.5 or QB7.x) with "qb /l" for "Call Absolute" to be
recognized.

5-9-BIOS scans for a Video card, and other Card with onboard BIOS systems.
(such as a SCSI adapter, Network card, or EIDE card) If one is found, it is
checked.
10-BIOS checks the WORD value at address 0000:0472 for a value of 1234h. A
WORD is 2 bytes (16 bits). If this word = 1234h, then this means the
Computer does a Warm boot. A Warm boot is like you hit the reset button.
The computer resets, but doesn't do a RAM test(or some other tests for
that matter). If the word at 0000:0472 doesn't = 1234h, then a Cold boot
is done. A cold boot is as if the power had been off, and you turned the
computer on. The computer scans for a Video card, and does a RAM test.

Also, for some reason "OUT &h64, &hfe" reboots your machine as well.
I don't understand this. OUT is for ports, like serial and printer ports, the
speaker, and other weird stuff like that. This only works on 386+ machines.
Because of this, I believe it has something to do with the ability of 386+
chips to switch into different modes. But I really don't know. I got a lot of
crap from people slamming me, saying that OUT was the best way. Well, none
of those Bastards could tell me how it worked, so I shut them up pretty fast.


---------
Face Lift
---------

I tell you what, I look back on my older programs. and I have NO
idea how I was able to write them. All the lines are against the left
side. I used 1 letter variables for EVERYTHING. And I used a crap load of
GOTOs. I can't write them, let alone try and upgrade them to use some
of the speed methods I talked about last issue, or 256 colors. I'll tell
you what folks, go out and learn another computer language like C++, it
will help alot. I'm taking it at school in AP Computer Science. I learned
so many ways to increase the power of my code. And the style you use can be
adapted to other programming languages.

I started using Qbasic in March 1997. Before that I have mastered
TI-BASIC, and briefly used GW-Basic. Coming from TI, I NEVER used DO loops.
I used a ton of GOTOs. Also, I couldn't indent on the TI for readability when
dealing with nested statements. Nested statements are when you have FORs,
DOs, IFs, WHILEs inside other FORs, DOs, Ifs, WHILEs. It is very hard to
follow in what "level" so to speak, you are in. Observe the following:

if x%>100 then
if len(key$) then
for a%=1 to 70
hit=round%(a%*7)
next
else
do
for x=1 to 80
if x=pht% then
beep
exit do
end if
next
hit=hit-1
loop
end if

This doesn't do anything. I just made it up. But it is very hard
to tell which lines of code are executed under what conditions. You can't
easily see which IFs go with which END IFs, DOs with LOOPs, or FORs with
NEXTs. Now, if you will look at the next example you will see a simple way
to see what matches with what, and you will understand what I mean about
"levels"

if x%>100 then
if len(key$) then
for a%=1 to 70
hit=round%(a%*7)
next
else
do
for x=1 to 80
if x=pht% then
beep
exit do
end if
next
hit=hit-1
loop
end if

That is much easier to read. When you write programs that do alot of
decision making, this will become a problem unless you level your code. See
what I said about other languages influencing you. TI-BASIC caused me to
code like that, and It took me over a year and a half to break the habit.
also, COMMENT THE HELL OUT OF YOUR PROGRAMS. Comments add space to your
.BAS file, and that's all. If you compile, the comments are ignored by the
compiler. Comments are a big help. The following is a little bit of Code
that AcidOS 4.3 uses:

OPEN path$ + "applist.sys" FOR INPUT AS #1

'The next block of code reads from the file "AppList.sys" the name of
'a file. It closes any open files in the range 101-(100+NumOfGroups%)
'and then opens the file as that file number

FOR X% = 1 TO NumOfGroups% 'for all the Groups...
E% = 100 + X% '101 thur 100 +NumOfGroups% RESERSVED
CLOSE E% 'make sure file E% is closed
LINE INPUT #1, Appfile$ 'Open the Group file
OPEN path$ + Appfile$ FOR RANDOM AS E%
NEXT
CLOSE #1

TIMER ON 'resume timer control

The comments are clear, and tell what is going on. Don't make them
too long, 3-4 lines at the very most. Also notice how I broke the code into
Chunks. Chunking is another great way to help make you programs more
readable, by using blank lines to group chunks of code. Not using comments
can be horrible. When I was writing AcidOS 3.0, I got stuck about 60% of
the way through. I left it for about 4 months. When I came back, I had no
idea how the basic Icons/applications were detected and loaded, let alone my
original problem with minimizing application to simulate Multi-tasking. You
can read my article of about AcidOS later in this issue. Anyway, I had to
re-write the whole thing from scratch. Comments allow you do keep hundreds
of files and always be able to figure out what is going on in any of them
anywhere. If you think this sounds stupid (and believe me, I did back when
I started), it is just because you are not writing very complicated or
long programs yet.

Another way I keep track of what is going on inside my programs are
with variable and Function/sub names. In the last 2 issues, you may have
noticed in my examples, I have weird names. It's to help YOU. Make big names
for your variables to describe what they are. Don't use "n%", use
"NumOfGoodsInStock%". Always use a mixture of UPPER and lower case, so you
can read the name quickly inside of "switchisactive%", you see
"SwitchIsActive%."

People may tell you to use "."'s in your variable names. I disagree
because "."'s are mainly used when you declare your own data type using TYPE.
If you don't know what I am referring to don't worry. TYPE is kind-of
advanced, so just get in the habit of NOT using "."'s in your names. Note
that your variable names in your .BAS file are completely different from the
variables names in the complied .EXE. The compiled names are picked by the
compiler, and are very short, so the length of the names you pick doesn't
affect the size or speed of the compiled program.

Lastly GOTOs. Everyone says they are bad, and they are. It is easy
to fall in the habit of using them all the time. As you program more and
more, you will find ways around them, by using DO :LOOPS. Sometimes you
do need to use a GOTO. That's alright. I recommend having a notepad next to
you and keep track of all the label names you use, so as not to mix them up.
Also, I would put a comment line " '*********" both above and below the
label so it is easy to see. People's biggest complaints with GOTOs are that
it is difficult to find the matching label for it. People also claim that
GOTOs show poor programming skills, and don't have to be used. Well, here
is the trade off. It is POSSIBLE to write a program without any GOTOs, but
it is nearly Impossible. You would have a ton of DO LOOPs. and need to use a
lot of variables as "flags" to exit the DO LOOPs. These extra variables make
your program bigger. So, use GOTOs, just not a lot.

----------
Quick Tips
----------

Drawing a circle with a grid of pixels looks so-so at best. The worse
is if you trying to draw a Filled circle, you get a lot of dots that
don't get filled in. To see what I'm talking about, run the following.

Screen 1
for rad=1 to 100
circle(100,100),rad
next

See, to fix this, draw 2 circles right next to each other. This SUB
"FillCircle" should help:

SUB FillCircle (CenterX%,CenterY%,BeginRadLength%,EndRadLength,Colour%)
For X%= BeginRadLength% to EndRadLength%-1 'Notice, 1 pixel less
Circle(CenterX%,CenterY%),x%,Colour%
Circle(CenterX%-1,CenterY%),x%,Colour% 'the second circle fixes that
next
end sub

-----
ABORT
-----
Damn, this issue is as long as issues 1 and 2 put together. Some-
times something completely un-related to the topic at hand gives you an idea.
For example, when I wrote that part about OUT in the reboot article, I began
to wonder if I can uses IN and OUT to communicate between 2 computers using a
NULL Modem cable through LPT ports. In fact, I just picked up a magazine
called "Popular Electronics" (I thought it was Popular Science) and inside
are plans to wireless transmitters and receivers. Later, it talks about
creating an interface for LPT ports. I am currently reading up on a lot of
subjects related to this, to see if I can transmit computer data between 2
machines without wires. Toddles.


← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos from Google Play

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT