diff --git a/src/doors/vbbs/data/apd.dat b/src/doors/vbbs/data/apd.dat
new file mode 100755
index 0000000000000000000000000000000000000000..105d7d9ad3afc7bb78a0dec4d829880831605dfb
--- /dev/null
+++ b/src/doors/vbbs/data/apd.dat
@@ -0,0 +1 @@
+100
\ No newline at end of file
diff --git a/src/doors/vbbs/data/file_id.diz b/src/doors/vbbs/data/file_id.diz
new file mode 100755
index 0000000000000000000000000000000000000000..daf1741655ac10dea5593d9905c99738eb1fb2b8
--- /dev/null
+++ b/src/doors/vbbs/data/file_id.diz
@@ -0,0 +1,20 @@
+--------------Virtual BBS--------------
+     You think you can do better?
+        You think this is EASY?
+    Play Virtual BBS and find out!
+
+       Virtual BBS is a game of
+       BBS and Sysop Simulation.
+
+    Work hard to build up your BBS,
+Answer Mail, Upload Files, Buy Modems,
+ Hire Workers, Hack into other BBSes.
+
+       Can yours be the #1 BBS?
+
+        Uses any dropfile type.
+        Fully multinode aware.
+         This is version 3.20
+            Release 20050514
+  Copyright 1999,2000 by Darryl Perry
+---------------------------------------
diff --git a/src/doors/vbbs/data/history.txt b/src/doors/vbbs/data/history.txt
new file mode 100755
index 0000000000000000000000000000000000000000..8dcaed446ad22011078ad57b69f7575cf19758f0
--- /dev/null
+++ b/src/doors/vbbs/data/history.txt
@@ -0,0 +1,159 @@
+Virtual BBS 3.20 by Darryl Perry, 1999-2002
+
+Revision History:
+
+Release 3.20
+    o Removed C++ code.
+    o Change name from "Virtual Sysop III" to "Virtual BBS"
+
+Release 3.10
+    o VS3 transfered to Vagabond Software
+
+The release number follows the format of MMDDYYYY.
+Release 3.05
+    o Changed the version format to Major.minor format.
+    o The Linux version is ready for beta testing.
+    o Added in-game messaging.
+    o Changed the text.dat color macros.
+    o Added more available computers, harddrives and BBS software for purchase.
+	o Added routine that will delete players who are inactive for more than 
+	  15 days.
+    o Added feature that will delete a player who leaves the game with less 
+	  than 1 point.
+	o fixed a bug that would would occur when a virus attack was encountered,
+	  and either no text was displayed, or it went into an infinate loop,
+	  displaying :END.
+
+Release 08232000
+    o Scores were showing as negative values.  Changed datatype to unsigned.
+    o The 'T'itle option displayed the Store Menu.  Fixed.
+    o Fixed some problems in the TEXT.DAT that were causing the game to
+      GPF on some window boxes.
+    o The number of possible modems and unused modem slots for the high end
+      BBS software packages were showing up as a negative value.
+    o When buying modems, it always said that 10 was the max that you can
+      buy, no matter how much money you had.  It now checks to see if you
+      have enough empty slots for your current BBS package.
+
+Release 08202000
+    o Money was showing as a negative when too much was accumulated.
+    o Fixed a problem with the corrupt polititian.  You can no longer give
+      him more than you have in the bank.  Also, you now get a little
+      private education when you donate a proper ammount.
+    o Fixed many problems with the tutors.
+    o The Break Into an Office option of the 'Use Skills' menu now works.
+    o Employees can no longer be used in personal menu.
+    o The Shoplifing option now works.
+    o Fixed a problem with the experience listing.
+    o Fixed a problem where hacking a board gave way too much of a score.
+    o Fixed a problem with the Top Ten list.  It wasn't sorting the list
+      properly.
+    o Made it so that when the 'A'nswer Chat command is used, an action is
+      used up too.  It seems that people can continue getting subscriptions
+      by hitting the 'A'nswer chat command, even if there were not pending
+      chats.
+    o Problem messages were not being displayed.  Fixed.
+    o Removed the '=' command or the real sysop menu from the game.  In order
+      to access the sysop menu, you must now start the game with the -CONFIG
+      command line parameter.  This option does not care if you are the
+      sysop or not.
+
+Release 07092000
+    o Uberhund of Darklands BBS reported:
+     
+      When a players accesses the "charge users" function, it seems that a
+      counter within the game gets incremented, but the player doesn't get
+      a turn deducted from their total. So they can hit "c" for charge users,
+      then answer "no" to the "do you want to charge users" question, and
+      they will receive things such as chat requests and subscriptions. So,
+      theoretically, a user can receive unlimited money and additional users
+      by just sitting there and hitting "c", "n" over and over again, and
+      answering chat requests and getting subscription money.
+
+      I've changed it so that the items get incremented only if the player
+      chooses 'Y'es at the charge users prompt.
+
+    o You can hold down any button that causes repetitive actions without
+      turn-loss and still receive subscriptions and chat messages (even if
+      you haven't just received a subscription
+
+      A beautiful example of this is the "a" key,  which you can hold down
+      and automagically answer any incoming chats, while generating more
+      chats (and thus more users and $) and subscriptions. I got a few
+      thousand callers and boucou dollars by doing this (especially if you
+      pause in the middle to charge your users).
+
+      I didn't want to do it this way, but if it's causing a problem, I'll
+      have to make this change.  Now, if you hit 'A', even when there is
+      no pending chat, you will have a turn decucted.
+
+    o Fixed one or two cosmetic issues in the TEXT.DAT file.
+
+Release 05142000
+    o Happy Mothers Day!
+    o When performing actions, the text would also show the ANSI color codes,
+      instead of interpreting them.  Fixed.
+
+    o If a player has less than 1 modem, one will be provided by a user.
+
+Release 04242000
+    o Changed release format from YYMMDD to MMDDYYYY.
+
+    o Removed all the text from the game and placed it in the TEXT.DAT
+      file.  This is in result of a DGROUP compiler error, which means
+      that there were too many string constants in the program.
+
+    o It has been reported that hitting 'R' when a subscripition arrives,
+      it would be possible to keep accruing money.  I was not able to
+      duplicate this phenomena.
+
+    o When using a tutor, only one action would be used, instead of the listed 
+      amount.
+
+    o When hitting "Users Now Online", the game would error out.
+
+    o No matter how many phone lines you buy at one time the same amount of
+      money was charged.
+
+    o If a harddrive level increased above the max, just high-ascii chars
+      would be displayed.  It is now not possible to go past the max.
+
+
+Release 990811
+
+    o When charging a fee, some free users would join, and some would leave.
+      It was possible for the number of free users to go below zero.  Fixed.
+
+    o If you edited a player in the sysop menu, you would not be able to
+      leave the sysop menu.  Fixed.
+
+Release 990809
+
+    o Fixed virus scan option.  TurboScan was alwasy being run when asked
+      even if answered with No.
+
+    o Fixed CPU Upgrade.  When receiving a computer upgrade resulting from
+      a (W)ork action, the text would say 'You now have a #' where '#'
+      would be the numeric value of the cpy type.  It now correctly displays
+      the textual value of the cpu type.
+
+    o Added action items #13 - Delete Modem, and #14 - Damage Phone line.
+      Made changes to MSGSA.DAT and MSGSV.DAT to reflect the changes.
+
+    o Changed MAINMENU.ANS to show the (Q)uit command.
+
+    o When doing the (U)sers command, the figures would reflect how many
+      modems the player had, and not the phone lines.  It was possible for
+      a player to have fewer phone lines than modems but be treated as if
+      he also had the same number of phone lines as modems.  Fixed.
+
+Release 990806
+
+    o Rewrote the function that increments the number of messages waiting
+      to be read.  Previously, every action was generating about 4-8 new
+      messages.  It now has a 40% chance of a single new message being
+      added to the waiting list after each action.  Also, the score is no
+      longer being reduced if mail is not read.
+
+    o If new phone lines were ordered, they were not being installed during
+      the next day's newday event.  Fixed.
diff --git a/src/doors/vbbs/data/mainmenu.ans b/src/doors/vbbs/data/mainmenu.ans
new file mode 100755
index 0000000000000000000000000000000000000000..37eb6c7192f27ffdfbf9e08656b16de6865f4ca5
--- /dev/null
+++ b/src/doors/vbbs/data/mainmenu.ans
@@ -0,0 +1,11 @@
+
+
+Virtual BBS by Darryl Perry
+ÄÄÄÄÍÍÍÍÍÍÍÍÍÍÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+(?) Displays this menu(A) Answer Chat(B) Bank
+(C) Charge Users(E) Employ Workers(H) Help System
+(I) Inspect Other BBSes    (L) List All Boards(M) Mail Box Check
+(N) Network Mail(P) Personal Actions Menu  (R) Report
+(S) Store(T) Title of BBS(U) Users Now Online
+(V) VirusScan(W) Work(Q) Quit
+ÄÄÄÄÍÍÍÍÍÍÍÍÍÍÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
diff --git a/src/doors/vbbs/data/msgsa.dat b/src/doors/vbbs/data/msgsa.dat
new file mode 100755
index 0000000000000000000000000000000000000000..50fc8779a29c5dab4925967abc3d67babd113438
--- /dev/null
+++ b/src/doors/vbbs/data/msgsa.dat
@@ -0,0 +1,372 @@
+!@#
+0
+0
+You work a little faster, but it takes more energy. Mistakes are likely.
+!@#
+1
+0
+You decide to call some of the other boards in the area and leave a few a
+messages telling people to call your BBS. This makes the sysops of some of
+those boards mad and they erase your messages and leave bad ones in place of
+them.  Over all your messages get to a few new users and they call you.
+!@#
+8
+1
+A good friend decides to help you out on your system because you look tired.
+An extra action has been added to your account.
+!@#
+9
+0
+You help out a new user on your board with a few shareware programs and he
+thanks you by uploading several new versions of other programs along with a
+few pictures that you didn't have.
+!@#
+3
+0
+You help a new user download a file on your board and he reports you to the
+police for piracy. It turns out to be a mistake in his understanding of the
+shareware ideals but the news frightens off a few of your users.
+!@#
+7
+0
+You help out a new user on your board with a few shareware programs and he
+turns out to be the head of a very large corporation. When his computer
+department upgrades the equipment in his office he donates his old computer.
+It couldn't have come at a better time because your old system died when you
+tried to move it.
+!@#
+5
+125
+You offer a spot for corporate advertising on your system to one of the local
+companies and they think it is a great deal. Their first order is a small one
+just to test things out.
+!@#
+10
+0
+Due to some investments in software companies and your help in busting a ring
+of pirate software hackers, you get a donation in the form of a hard drive
+upgrade for your BBS.
+!@#
+5
+75
+You open a new message section for a special interest group on your system and
+they are so impressed that they send you a donation.
+!@#
+1
+0
+You decide to spend some time reading through the message bases on your BBS
+and answering the messages that seem interesting. This impresses the users and
+they start writing more messages and telling more people about all of the new
+activity on your board. This helps make your users happy and attract new users.
+!@#
+0
+0
+You try to rework the layout of your menus and your users hate it.
+!@#
+0
+0
+You call some other boards and download a few new files to list on-line.
+!@#
+0
+0
+You call long distance to a BBS and download some new files.
+!@#
+0
+0
+You move a few of your files around in the directories.
+!@#
+1
+0
+You re-compress one of the file directories and erase the corrupt files.
+!@#
+0
+0
+You scan through the message bases and erase some of the old messages.
+!@#
+0
+0
+You scan the user log for fake accounts and erase them.
+!@#
+1
+0
+You defragment your file directories and erase some duplicate files.
+!@#
+0
+0
+You spend several hours packing up a file trade for another sysop.
+!@#
+0
+0
+You check the phone wires over for poor connections and clean the contacts.
+!@#
+0
+0
+You do your best to clean up a few spelling errors in your text files.
+!@#
+0
+0
+You try out a new on-line game and the users hate it.
+!@#
+1
+0
+You work out a file trade with an old friend. Your users like the new stuff.
+!@#
+0
+0
+You make a small mistake on your opening screen and your users laugh at you.
+!@#
+0
+0
+You find a small bug in the BBS software that hangs the BBS when you try to
+upload a file. You quickly get an update before your users find out.
+!@#
+0
+0
+A device driver conflict sends your software into a loop. You do some quick
+patching to get everything back on-line before your users notice.
+!@#
+0
+0
+You call the author of your BBS software to see if he will add a feature
+that you want. He thinks it is a great idea and thanks you for calling.
+!@#
+3
+0
+The phone company makes a small mistake in their computer and your BBS phone
+gets call waiting for a day. Your users think that it is your BBS that is
+kicking them off-line until you call and get things fixed.
+!@#
+0
+0
+Your cat jumps up on your keyboard while you are away and it locks the BBS
+until you get home. You toss a box of floppy disks at the cat!
+!@#
+1
+0
+You try to organize a meeting for your users and they love the idea.
+!@#
+1
+0
+You spend some time working with the new users on your system and they turn
+around and help the other users.  The word gets out that your BBS is very
+friendly.
+!@#
+1
+0
+You try to get a few of the system operators together for a meeting. They end
+up not being able to make it because of conflicting schedules.
+!@#
+3
+0
+In a freak act of kindness, your Aunt comes by and turns off your computer and
+yells in your face for forgetting to turn off your toys.  You rush to get your
+system back on-line.
+!@#
+0
+0
+You start feeling like this is a real grind and you wonder why you are
+spending all of your time and effort working on keeping this computer running
+for a bunch of childish users. They want everything from you and don't want to
+pay for it. It is, after all, your computer and your life!  What do these
+cheap skates want from you anyway?!  Gripe, snarl, gripe.
+!@#
+1
+0
+You spend another quiet night at home working on the BBS.
+!@#
+0
+0
+You check through the new uploads and recompress them.
+!@#
+0
+0
+You spill a can of beer into your keyboard and spend the rest of the night
+taking it apart, washing all the little parts and blow drying them with a
+hairdryer.  Strangely enough, it still works!
+!@#
+0
+0
+You get another letter in the mailbox saying that you won zillions of dollars
+but when you read the fine print it requires you to first buy zillions of
+dollars worth of their products before you will qualify.  Don't you just hate
+those buggers?
+!@#
+0
+0
+Your monitor looks totally fried. The picture is blurry, the colors are off.
+It looks like it should be shot and put out of its misery. Then you notice
+that the rest of the room looks just as blurry and you decide it is time to
+switch from beer to Pepsi.
+!@#
+0
+0
+Another late night working on the computer. Lots of work and not much to show
+for it. The system seems to be running a lot better though.
+!@#
+1
+0
+You spend some time writing letters to the new users. They like it and the
+volume of your mail goes up.
+!@#
+0
+0
+You clean the heads on your floppy drive after finding out that your backup
+won't load.
+!@#
+0
+0
+You make another backup of your main BBS directory. It takes forever.
+!@#
+3
+0
+You try loading another on-line game to keep your users happy. They find a
+backdoor in the program and start erasing files on your drive.
+!@#
+1
+0
+You run a contest on your board to see who can write the most messages.  The
+problem is that you end up with more mail in your mailbox!
+!@#
+0
+0
+You help out a new user and he is so happy that he offers to help you out on
+the BBS for a day.
+!@#
+1
+0
+You help out a new user and he is happy. He starts to advertise your BBS.
+!@#
+0
+0
+A large slice of pizza gets stuck to your keyboard by mistake. It takes you a
+little extra effort to get it cleaned up.
+!@#
+3
+0
+You find several users in the log files that have been hacking into your
+account files. You track them down and cut off all of their access and force
+your users to change all their passwords.
+!@#
+6
+20
+keyboard Failure!
+You damag&d s&v&ral k&ys on your k&yboard by pounding on it too hard.  You
+try to answ&r a f&w m&ssag&s and your us&rs think that it is r&ally bad lin&
+nois&. It costs you $20 to fix.
+!@#
+13
+0
+You give one of your modems to a small private school and their computer
+class joins your system.
+!@#
+14
+0
+Freak lightning storm knocks out one of your phone lines.
+Better get service soon!
+!@#
+0
+0
+Another late night tweaking and working on the software.
+!@#
+6
+20
+One of your serial ports blows a chip. It costs $20 to replace.
+!@#
+6
+20
+Your serial port blows a chip. It costs $20 to replace.
+!@#
+0
+0
+You discover a Trojan horse program in your file list and quickly erase it
+before any of your users download it.
+!@#
+1
+0
+A user complains about the look of your menus and you change them a little.
+The other users like the new look and start using more time on-line.
+!@#
+4
+0
+One of your users made the mistake of using the same password on all of the a
+boards he calls. One of the boards crashed and dumped the password list to
+the screen so all of the users could see it. To help stop the fake logons you
+force all of the users to change their password. This makes a few users mad
+at you.
+!@#
+1
+0
+A new update to your software is now available. It fixes quite a few bugs and
+offers some new features.
+!@#
+1
+0
+A user calls you very early one morning from another country and wants to
+trade some of your files. You decide to take a chance and send him a box of
+disks. Over a month later you get two boxes of disks back with the most
+exciting and unusual software you have ever seen.  You put it on-line and
+your users love it!
+!@#
+1
+0
+An old school buddy calls you on the phone after several years of living in
+another state. He asks if you would mind putting his new software on your
+system. You agree and it turns out to be the most popular software on the
+market!
+!@#
+1
+0
+A new user offers to help you with a few of the file sections. It turns out
+that he used to run one of the largest boards around a few years ago. He only
+worked for an hour or two but did more than you could do in a day.
+!@#
+0
+0
+You post a text file on your system that explains how to use the functions
+and your users love it.  They start using more of their on-line time.
+!@#
+4
+0
+One mad user starts a rumor about you and your BBS. It is totally false but a
+some of the other users still believe it. You do your best to disprove the
+lie but a few users still leave your system.
+!@#
+1
+0
+Some serious legal action is being taken against another BBS in your area.
+It scares the users on that BBS because their names are in the log files.
+You offer a special deal for members of that other BBS to join your system
+and a few of them accept.
+!@#
+0
+0
+You are worn out from all the work and your brain feels fried - extra crispy.
+!@#
+0
+0
+Several of your friends force you to take a day off. It does a world of good
+and you attack the BBS with a fresh burst of energy.
+!@#
+3
+0
+A new board opens across town from you and offers just about everything you
+have on your board. After a little checking it turns out that the sysop got
+all of his files and menu ideas from your board.
+
+Some of your users like his better.
+!@#
+0
+0
+You spend a few late nights working on some menu changes, again.
+!@#
+0
+0
+You spend some time working on the software configuration, again.
+!@#
+11
+0
+Your mother's computer just died, and being the compasionate child that
+you are, you donate your BBS computer to the cause.  Luckily, you still
+have your old system.  You dust it off and get your BBS back up and running
+before your users notice.
+:END
diff --git a/src/doors/vbbs/data/msgsr.dat b/src/doors/vbbs/data/msgsr.dat
new file mode 100755
index 0000000000000000000000000000000000000000..b2fb1ef309764c8d618723ed8ca7b139dcf0f667
--- /dev/null
+++ b/src/doors/vbbs/data/msgsr.dat
@@ -0,0 +1,279 @@
+!@#
+0
+0
+This user is very upset about your validation process.~SM
+He doesn't want to wait for you to upgrade his account.~SM
+!@# 
+0
+0
+This message is about the long time it takes to get you to~SM
+answer your mail. He wants you to give him special access.~SM
+!@#
+0
+0
+A very angry user calls you, and your mother, every curse word~SM
+that you have ever heard and some that you haven't.~SM
+!@#
+0
+0
+This user is angry that you don't allow more access to 300 baud~SM
+callers. He wants you to open a special 300 baud only line.~SM
+!@#
+0
+0
+It seems that several of the users have been playing one of the~SM
+on-line games that you found a virus in. When you erased it they~SM
+got mad and want to take it out on you.~SM
+!@#
+0
+0
+This user demands access to your private files or he will report~SM
+you to the police and the FBI.~SM
+!@#
+0
+0
+One of the few female callers that you have is very angry that~SM
+the male users treat her like dirt. She wants you to kick the~SM
+other users off of the BBS.~SM
+!@#
+0
+0
+This user complains about your "dumb" looking menus~SM
+and wants you to use more graphics.~SM
+!@#
+0
+0
+This message is complaining about the slow system speed.~SM
+!@#
+0
+0
+This message is very rude and calls your BBS "worthless junk."~SM
+!@#
+0
+0
+This user wants to know how old you are and if your mother is paying~SM
+for the BBS or if you are.~SM
+!@#
+0
+0
+This user wants you to donate your old modems to him so he can start his~SM
+own BBS. He also said that you should learn how to use the menu editor.~SM
+!@#
+0
+0
+This user is upset about how hard it is to get through to your BBS.~SM
+He wants you to add toll free phone lines just for him.~SM
+!@#
+0
+0
+One of your very young users tells you that her parents don't want her~SM
+to be able to get messages from any of the dirty old men who are members~SM
+on your system. She seems very upset.~SM
+!@#
+0
+0
+This is a list of program titles that the user wants you to put on~SM
+floppy disk and mail to him. He thinks that you owe it to him because~SM
+he only has a 1200 baud modem and can't download them.~SM
+!@#
+0
+0
+This user wants you to get a toll free line so his friend in the next~SM
+state can call and leave messages to him for free.~SM
+!@#
+0
+0
+Your automatic logon filter has cut the access of this user because his~SM
+name sounds like profanity. He has a hard time writing English but you can~SM
+tell that he doesn't think it is funny.~SM
+!@#
+0
+0
+This user is happy that he was able to get connected with your BBS, but he~SM
+doesn't want to give you access to his hard drive. He thinks that you are~SM
+taking things off of his drive that he doesn't want you to have.~SM
+!@#
+0
+0
+This user explains that he works for the local vice squad and wants you~SM
+to help him get into another BBS in town so he can find their X-rated~SM
+pictures.
+!@#
+0
+0
+This user complains about how long your opening screens are and~SM
+wants you to change it so that he can jump right from his password~SM
+to the file section without having to read all of the text screens.~SM
+!@#
+0
+0
+This user is sick of trying to get through to you. He complains about the~SM
+length of time it takes to get an answer back from you.~SM
+!@#
+0
+0
+This user doesn't understand about modems and wants you to tell him why~SM
+you don't allow more access to 300 baud users.~SM
+!@#
+0
+0
+This user doesn't like the way you set up your menus and demands~SM
+that you change them so that it doesn't look so slow on his 1200~SM
+baud modem.~SM
+!@#
+0
+0
+This user is very upset about your not being available to chat for the last~SM
+few times he has paged you. He wants you to make sure you are there when he~SM
+calls the next time.~SM
+!@#
+0
+0
+This user is very mad about your cheap modems. He claims that he can connect~SM
+with all of the other boards in town at high speed on his $50 "high speed"~SM
+modem, but your board only connects at 2400 baud.~SM
+!@#
+0
+0
+This user thinks your menus are trash. He complains about the colors you use~SM
+and the idiot words you use for the options.  He wants you to look more like~SM
+the BBS he used to call back home.~SM
+!@#
+0
+0
+This is a woman who hates the words you use on your menus. She wants you to~SM
+change all of the words to something that is more "woman friendly" or she~SM
+will tell all her friends what a terrible BBS you run.~SM
+!@#
+0
+0
+This is the parent of a young girl who is one of your users. He is very~SM
+upset about your allowing the other users to pollute his child with crude~SM
+comments about her name. He threatens you with a lawsuit.~SM
+!@#
+0
+0
+This is a sysop from another BBS. He wants special access to your user's~SM
+password files so he can check to make sure you are not doing anything~SM
+illegal.~SM
+!@#
+0
+0
+This is a message of nothing but profanity.  It questions your sexual~SM
+standing and implies illegal contact with farm animals.~SM
+!@#
+0
+0
+This user is outraged by your file area. He wants more detailed file~SM
+descriptions because he downloaded a large file at 1200 baud and now~SM
+found out that it was not what he thought it should be.~SM
+!@#
+0
+0
+This user is upset about your method of validating users.  He thinks it is~SM
+illegal for you to discriminate against people like that.~SM
+!@#
+0
+0
+This user is upset about your file area. She wants more pictures of~SM
+men and less pictures of women. The threat of a discrimination suit~SM
+is also implied.~SM
+!@#
+0
+0
+This user tries to be nice, but it is plain that they are mad. They want~SM
+you to answer your mail more often.  It has taken you too long to reply to~SM
+them and they don't think it is right.~SM
+!@#
+0
+0
+This old man is mad at you for your policy on lewd language in the teen~SM
+message section.  He said that the comments he made to those girls were~SM
+only a joke and that you are an idiot for not seeing that.~SM
+!@#
+0
+0
+This message is pure line noise and garbage except for the last line.~SM
+That line complains about the poor quality of your equipment.~SM
+!@#
+0
+0
+This message is hard to read because of the bad spelling and poor use~SM
+of grammar.  It is something about your lack of education being the~SM
+reason for your not wanting to chat with him.~SM
+!@#
+0
+0
+This lady is mad at you for allowing her daughter to receive messages~SM
+from the low moral adults on your system.  You should have known that~SMj
+her daughter lied on the questionnaire about her age.~SM
+!@#
+0
+0
+This woman is upset about your questionnaire asking her age.  She makes~SM
+it very clear that you don't need to know her age or her weight either!~SM
+!@#
+0
+0
+It is hard to read this message, but it looks like the user typed it with~SM
+their feet hitting lots of extra characters. The last line looks like it~SM
+is asking for special access.~SM
+!@#
+0
+0
+This is a new user who wants to know how old you are and if you go to~SM
+the same elementary school that he does.~SM
+!@#
+0
+0
+This user is very mad about something but doesn't make it clear in his~SM
+message what he is mad about. The cursing near the end is very harsh~SM
+and questions your morals.~SM
+!@#
+0
+0
+This is a teen user who is mad at you because you don't spend more time~SM
+chatting with him while he is on-line.~SM
+!@#
+0
+0
+This is from a user who wants you to make a list of all of the black~SM
+users on your system.  He questions the color of your skin because you~SM
+have not already made such a list.~SM
+!@#
+0
+0
+This user is very upset about your lack of spelling and grammar in~SM
+your menus and text files.  She wants you to go to night school to~SM
+learn how to write.~SM
+!@#
+0
+0
+This user is mad because you cut his access after he posted what he~SM
+thought was your password in the public message areas.  He said he~SM
+tried to call you to chat, but when you didn't answer he thought~SM
+this would get your attention.~SM
+!@#
+0
+0
+This user is upset because you locked him out after he tried to log in~SM
+with a sysop password he found in a public message base.  He thinks you~SM
+are stupid for cutting his access and wants you to post a public note~SM
+with your apology.~SM
+!@#
+0
+0
+This is a kid who wants you to give him access to all your adult and~SM
+pirated files.  He swears that he won't tell anyone where he got the~SM
+files unless you don't give him full access.~SM
+!@#
+0
+0
+This user just wants to know why you are so stupid.~SM
+!@#
+0
+0
+This is a kid hates your validation process.  He thinks you should~SM
+run your board with everything available for free to new users.~SM
+:END
+
diff --git a/src/doors/vbbs/data/msgsv.dat b/src/doors/vbbs/data/msgsv.dat
new file mode 100755
index 0000000000000000000000000000000000000000..36c20885b111c03a0991d0e776e2c255fe429cd7
--- /dev/null
+++ b/src/doors/vbbs/data/msgsv.dat
@@ -0,0 +1,28 @@
+!@#
+13
+3
+A virus infects your system. It toggles a bit on your I/O board, and
+sends high current pulses through your modems, destroying some of them.
+Hope you have enough cash to buy new ones!
+
+Some of your users hear about this and are sympathetic, but you do lose
+some users due to the incident.
+!@#
+11
+3
+A disastrous viral infection sends your read/write head crashing across
+your hard disk several million times, destroying it!
+
+Some of your users hear about this and are sympathetic, but you do lose
+some users due to the incident.
+!@#
+11
+3
+A extremely strong virus locks up your system, and eats your boot sector.
+!@#
+3
+0
+Due to not having run your virus protection for a while, A nasty one eats
+your files, cleaning your drive for you. Fortunately, you made a back up
+just last night, and after a few hours work, you are back on line. The bad
+news is that the virus scare frightens off some users due to the incident.
\ No newline at end of file
diff --git a/src/doors/vbbs/data/reset.bat b/src/doors/vbbs/data/reset.bat
new file mode 100755
index 0000000000000000000000000000000000000000..445481b764cd9c7aec8edb4c81ea3e75072f093b
--- /dev/null
+++ b/src/doors/vbbs/data/reset.bat
@@ -0,0 +1,6 @@
+@Echo off
+echo 'Deleting USERS.VB3'
+if exist users.vb3 erase users.vb3
+echo 'Deleting MAIL.VB3'
+if exist mail.vb3 erase mail.vb3
+echo 'Ready to play Virtual BBS!'
diff --git a/src/doors/vbbs/data/sysop.txt b/src/doors/vbbs/data/sysop.txt
new file mode 100755
index 0000000000000000000000000000000000000000..366589441046e45672d515a70243346f9530dbc8
--- /dev/null
+++ b/src/doors/vbbs/data/sysop.txt
@@ -0,0 +1,274 @@
+Virtual BBS
+Version 3.20
+
+(C)1999-2002 by Darryl Perry
+
+Vagabond Software:
+http://vs3.vbsoft.org/
+                           
+
+What is Virtual BBS?:
+-----------------------
+    This is a simulation of what it may be like to be a system operator
+    on one of the larger data services in the nation. It is not designed
+    to be 100% accurate or resemble any one BBS. The problems and
+    situations found in this program are the result of many years
+    of personally running a BBS.
+
+
+Virtual BBS/Sysop: Then, and Now:
+---------------------------------
+
+    Several years ago, I used to run a BBS using TBBS (The Breadboard System,
+    by eSoft.)  One of the most popular games at the time was Virtual Sysop.
+    This game could only be played on TBBS systems.
+
+    Years later, I stopped using TBBS as my bbs platform, and instead ran
+    Telegard.  I wanted to be able to play all the popular online games
+    that TBBS did not have the ability to run.  The downside to that was
+    that I was no longer going to be able to run Virtual Sysop.  The authors
+    had no intentions of porting the game over so that dropfile-type systems
+    could run the game as well.
+
+    So, the obvious solution was to create a version that could run from
+    Telegard or any other BBS software that uses a dropfile.  What you
+    now have in your hands is the result.   Since this is not a direct
+    port of the original game, (Virtual Sysop I+II were written in a
+    version of dBase III code, Virtual Sysop 3.00df was written in C using
+    the OPENDOORS library), this game will not play the same as those that
+    you may have seen on TBBS bbs systems.
+
+    It turned out that the authours of the TBBS Virtual Sysop games DID
+    have intentions of porting the game and/or converting to a web game.
+    As a result, this door has been renamed to "Virtual BBS" to avoid any
+    name comfusions as much as possible.
+
+
+DROP FILE SUPPORT:
+------------------
+
+     - DOOR.SYS       (DOOR.SYS compatible systems)
+     - DORINFOx.DEF   (QBBS/RBBS/Remote Access systems)
+     - PCBOARD.SYS    (PCBOARD systems)
+     - SFDOORS.DAT    (Spitfire systems)
+     - CALLINFO.BBS   (Wildcat previous to v3.0 systems)
+
+GAME FILES:
+---------------
+
+    The following files are required in order to run the program:
+
+    - MSGSR.DAT         -   Responses to reading the mail.
+    - MSGSA.DAT         -   Responses to the work actions.
+    - MSGSV.DAT         -   Responses to the virus infection.
+    - MAINMENU.ANS      -   The Main Menu.  Edit as you wish.
+    - VIRUS.DAT         -   List of viruii (viruses?).  Edit as you wish.
+    - VBBS.EXE          -   The game program.
+    - VBBS.TXT          -   The user documentation
+    - SYSOP.TXT         -   You're reading it now.
+    - RESET.BAT         -   Used for resetting the game.
+    - TEXT.DAT          -   The language file for the game.
+                                Edit as you wish.
+    - VBBS.DOC          -   Info on how the game is played.
+
+    The following files are created the first time that the game is run:
+
+    - USERS.VB3         -   Player info is kept here.
+    - MAIL.VB3          -   Netmail info is kept here.
+
+    The following files are not needed, but can be used to modify your
+    game, see Modifying the Game section below:
+
+    - APD.DAT			-  Actions Per Day
+    - CPU.DAT			-  Define the names of the CPU's
+    - SOFTWARE.DAT		-  Define the names of the BBS software packages.
+
+
+WARRANTY:
+---------
+
+This product is provided "as is" without warranty of any kind. The entire
+risk as to the results and performance of the program is assumed by you.
+Futhermore, the author does not warrant, guarantee, or make any other
+representations regarding the use of, or the results of the use of the
+program, and you rely on the program and results solely at your own
+risk. The author cannot and will not accept responsibility for system
+damage, loss of profit, or any other special, consequential or incidental 
+damages resulting from the use or inability to use this product.
+
+
+USAGE:
+------
+
+This product is being distributed as FREEWARE.  However, it is also BETA
+software.  You WILL encounter bugs and unavailable options.  If this game
+is to evolve, your input will be muchly appreciated.
+
+DISTRIBUTION:
+-------------
+
+You are encouraged to distribute this copy of VBBS provided the archive 
+is kept in its original and unmodified state.  
+
+
+SYSTEM REQUIREMENTS:
+--------------------
+
+DOS Only Systems:
+
+     - ANSI.SYS MUST be loaded in your CONFIG.SYS.  
+       Users who are using some other type of ANSI emulation may get
+       the system to work...ex. DVANSI.  This should be loaded at system
+       boot up, not just in each process or window.
+     
+     - SHARE.EXE MUST be loaded in your CONFIG.SYS.
+
+     - DOS 5.0 or later.
+
+Windows Systems:
+
+     - Windows 95/98/Me running Door32 compatible BBS software with DTR hack
+     - Windows NT4/2000/XP running Door32 compatible BBS software
+
+Setup:
+------
+Updating from older existing versions, v3.00df and older:
+	The current version (v3.01df) requires that the game be reset,
+	as there are changes in the data files that cannot be converted.  If
+	you have an existing installation, the new installation will overwrite
+	it, and you will need to run the reset.bat file.
+    
+
+New Installations:
+    To setup VBBS on your BBS, edit your door bat file to look like this:
+
+    @ECHO OFF
+    CD \BBS\DOOR\VBBS
+    VBBS.EXE -D C:\BBS\
+
+    The only parameter that Virtual BBS needs is the path to the dropfile.
+
+Windows Users:
+
+    For use under Win32 compatible BBS software, call the door directly.  Ex:
+
+    VBBS32.EXE -D C:\BBS\	
+
+Linux Users:
+	For linux use, you must supply the path and the door file name, in the
+	proper case.  If the dropfile is in upper case, you must supply the name
+	in upper case.
+
+	Also, only the door.sys dropfile format is working at this time.
+
+	example:
+	/home/doors/vbbs/vbbs /home/bbs/node1/door.sys
+
+Multinode Note:
+
+    Be sure and pass the proper directory where you node stores it's dropfiles.  Ex:
+
+    VBBS32.EXE -D C:\BBS\NODE*N
+
+    Consult your BBS documentation for more information.
+
+
+Modifying the Game:
+-------------------
+
+    It is possible to make minor changes to the playability of the game.
+    You will find to sysop editable files, MSGSA.DAT, MSGSV.DAT and
+    MSGSR.DAT.  They all use the same format for all files.
+
+    MSGSx.DAT:
+
+    Each time the (W)ork command is executed, a random entry from MSGSA.DAT
+    is read.  Each time a virus is encountered, a random entry from MSGSV.DAT 
+    is read.
+    Each time a PROBLEM message is read, a random entry from MSGSR.DAT is
+    read.  It is recommended that you leave the ACTION and VALUE fields set
+    to zero (0) in this file.
+
+    The format is as follows
+
+    !@#  <----Denots the beginning of a record.  Must exist for each record.>
+    0    <----ACTION #>
+    0    <----VALUE>
+    <The text of the result of a work command.>
+    <It can be any number of lines.>
+
+    Action Numbers:
+    ---------------
+    There are 14 possible actions, listed below.  Others may be added in
+    later versions.
+
+    Action                                          Value
+    ---------------------------------------------------------------------
+    0 - Nothing happens                             Not Used (0)
+    1 - Add random free users.                      Not Used (0)
+    2 - Random free users become subscribers.       Not Used (0)
+    3 - Free users leave the system.                Not Used (0)
+    4 - Paying users leave the system.              Not Used (0)
+    5 - Add money to the bank.                      Ammount to add
+    6 - Subtract money to the bank.                 Ammount to subtract
+    7 - Upgrade CPU by one, up to the max.          Not Used (0)
+    8 - Add Actions.                                Ammount to add
+    9 - Random number of free user start paying.    Not Used (0)
+   10 - Upgrade Harddrive by one, up to the max.    Not Used (0)
+   11 - Downgrade CPU by one, down to the max.      Not Used (0)
+   12 - Downgrade Harddrive, down wo the max.       Not Used (0)
+   13 - Downgrade (remove) modem.                   Not Used (0)
+
+
+   - APD.DAT
+
+   The default number of actions per day is 100.  This number can be
+   changed to you liking by including the text file APD.DAT.
+   APD.DAT (Actions Per Day) is a text file with a single line.  This
+   line contains the numberic number for the actions per day.  Anything
+   more than one line will ge ignored.  If the number is unreadable,
+   it will default to 100.
+
+   Note, players will not see the change until the day after the change.
+
+   - TEXT.DAT
+
+   With v3.01df (rev 0424200) comes a new datafile called TEXT.DAT.  This
+   file holds all the text of the game, and is configurable by the sysop.
+
+   The format is:
+
+   nnnn <text>
+
+   where nnnn is a zero padded number, and <text> is the text to be
+   displayed.  Be certain to have at least a single space between the
+   number and the text.  Any spaces more than on will be displayed as
+   part of the text.
+
+   The text of this file can now include ANSI graphics and colors.  It can
+   also include many macros.  The list of macros can be found at the top
+   of TEXT.DAT.
+
+
+
+Resetting the Game:
+-------------------
+    When you wish to begin a new game of Virtual BBS, just erase the 
+    USERS.VB3 and MAIL.VB3 files.  Or, you can use the RESET.BAT file
+    provided in this archive.
+
+Bug Reports:
+------------
+    Yes, you will undoubtedly find some bugs and wish to report them.  Here
+    is how to do it.
+
+    Email  : dperry.geo@yahoo.com
+    Netmail: Sysop at 1:211/105
+    BBS    : Cyberia BBS cyberia.darktech.org
+    Echos  : DOORGAMES, BBSDOORS and BBS_CARNIVAL
+    UseNet : alt.bbs, alt.bbs.doors, most alt.bbs.* groups.
+
+    I regularly read the above Fidonet echos.  If my echomail is flowing
+    properly, I will likely be able to find your postings there.
+
+    When making reports, please as be as specific as possible.
diff --git a/src/doors/vbbs/data/text.dat b/src/doors/vbbs/data/text.dat
new file mode 100755
index 0000000000000000000000000000000000000000..3cb6edb983729610c64508edecaebf5137308c3b
--- /dev/null
+++ b/src/doors/vbbs/data/text.dat
@@ -0,0 +1,787 @@
+; TEXT.DAT - Virtual BBS v3.20
+;
+; This file is used for the game Virtual BBS v3.01df and later.
+;
+; Lines preceded with a ';' are coments, and will not be used by the game.
+;
+; The format is:
+; NNNN <Text>
+; where NNNN is a zero-padded 4 digit number.  <Text> is the text to be
+; displayed by the game.  NNNN and <Text> is separated by a single space.
+; The <Text> starts after the first space following NNNN.
+;
+; It is possible to have multiple lines that all have the same NNNN.  The
+; game will display ALL lines that have a matching NNNN.
+;
+; ANSI graphics and colors can be included in the <Text>
+;
+; main prompt
+0001 `0F~SM[~&1:~&2:~&3]: `0F
+; main prompt with employe actions
+0002 `0F~SM[~&1:~&2:~&3.~&4]:
+0003 ~SM`0E  You aren't the sysop!~SM
+
+; New player welcome screen
+0005 `0A~SMWelcome New System Operator!~SM
+0005 `0AYou have just spent a long time and a good bit of money to get your computer~SM
+0005 `0Aand software ready to go on-line. Someone gave you an old IBM XT that they were~SM
+0005 `0Agoing to toss in the trash. You got a shareware BBS program and a cheap modem~SM
+0005 `0Aand now you are ready to start accepting calls.~SM
+
+; Exit text
+0009 ~SM~SM`0FDisconnect from your service?
+0010 ~SM~SM`0BYour line has been released to allow other users to access your service.~SM~SM
+0010 You have ~&1 actions left today.~SM~SM
+0010 Thank you for playing~SM~SM
+0011 ~SM`0FReturning to ~&1, please wait...~SM
+
+; Virus scan text
+0020 ~SM~SM`0EMurphyscan(TM) scans all drives and files for all KNOWN viruses!~SM
+0020 You have a ~&1  EST. SCAN TIME ~&2 SECONDS~SM~SM
+0021 `0ETurboScan(TM) super fast virus detection option is available but may not~SM
+0021 identify all infections accurately.  Time savings MAY be 50%% or more.~SM~SM
+0021 `0FWould you like to use the TurboScan option?
+0022 ~SM`0F          [ÄÄÄÄÄÄÄÄÄÄÄ] <<TurboScan!>>~SM
+0023 ~SM`0F          [ÄÄÄÄÄÄÄÄÄÄÄ] <FullScan>~SM
+0024 `0FProgress: ~SL
+0025 `0FÛ
+0026 ~SM`0C >>> VIRUS DETECTED <<<~SM
+0027 ~SM`0E >>> No virus found <<<~SM
+0028 ~SM`0A                   We at Murphycorp recommend you run~SM
+0028                    Murphyscan(TM) every ten (10) downloads.~SM
+0028                       Thank you for using Murphyscan(TM)!~SM~SM
+0028 `0D*not responsible for damage resulting from misuse.`03~SM
+
+0050 `0BA`03nswer Chat
+0051 `0BB`03ank
+0052 `0BC`03harge Users
+0053 `0BE`03mploy
+0054 `0BI`03nspect
+0055 `0BL`03ist BBSes
+0056 `0BM`03ail
+0057 `0BN`03etwork
+0058 `0BP`03ersonal
+0059 `0BQ`03uit
+0060 `0BR`03eport
+0061 `0BS`03tore
+0062 `0BT`03itle Change
+0063 `0BU`03sers Online
+0064 `0BV`03irus Scan
+0065 `0BW`03ork
+0066 `03 Employees help.
+0067 `0B?`03-Menu
+
+0070 ~SM`0CUnable to access the user file.~SM
+0071 ~SM`0CUnable to update your user record file.~SM
+0080 ~SM`0FPress [ENTER] to continue.
+0081 `0F [Y]: ~SL
+0082 `0F [N]: ~SL
+0083 `0FY`07es~SM
+0084 `0FN`07o~SM
+
+0090 `0AYou contact the local labor union and they inform you that your BBS is~SM
+0090 still too small. Please check back when you are a little larger. You~SM
+0090 need at least 100 lines to be able to hire employees from this office.~SM
+
+0091 `0AYou contact the local labor union and they inform you that you are in need~SM
+0091 of ~&1 worker(s) to completely cover your current hardware and software setup.~SM
+0091 This is a requirement of the union and is not negotiable. If you choose to~SM
+0091 sign with us we will claim certain rights for our members.  These rights~SM
+0091 include but are not limited to: `0F~SM~SM
+0091 ~EF 51. Employees must not work more than 8 hours a day with 1 hour for lunch.~SM
+0091 ~EF 52. Employees must have 12 paid holidays per year plus 2 weeks vacation.~SM
+0091 ~EF 53. Employee responsibility must be limited to no more than 99 lines.~SM
+0091 ~EF 54. Extra employees must be hired if the work load increases.~SM~SM
+0091 `0ADo you agree to these terms?
+
+0092 ~SM~SMThank you for joining our team. We know that you will grow to trust and~SM
+0092 respect our professional methods for dealing with your users.~SM~SM
+0092 `0E* PAYROLL: $~&1~CP
+0093 `0C** WARNING: Payroll account balance is low.~SM
+
+0094 `0E* WARNING: Payroll checks bounced. Double check bank account!~SM
+0094 You need at least $~&1~SM
+
+0095 ~SM`0BWe thank you for at least allowing us to offer our help. Please return if~SM
+0095 there is a time in the future that you would like our help.~SM
+
+0096 ~SM`0FThe union boss double checks his roster and adds ~&1 employee(s)~SM
+0096 It is too late for them to make it in for work today, but they will~SM
+0096 report to your office first thing tomorrow morning.~SM
+
+0100 ~SM~SM`0FComputer Department Store~SM~SM
+0100   `06(`0EA`06) `0BBBS Software Dept.~SM
+0100   `06(`0EB`06) `0BComputer Dept.~SM
+0100   `06(`0EC`06) `0BModem Dept.~SM
+0100   `06(`0ED`06) `0BHard Drive Dept.~SM
+0100   `06(`0EE`06) `0BPhone Company.~SM~SM
+0100 `0BChoice or `06(`0EQ`06) `0Bto Quit: ~SL
+0101 `0EA `06- `0BBBS Software Dept
+0102 `0EB `06- `0BComputer Dept
+0103 `0EC `06- `0BModem Dept
+0104 `0ED `06- `0BHard Drive Dept
+0105 `0EE `06- `0BPhone Company
+0106 `0EQ`0Buit
+
+0200 ~SM~SM`0EPhone Company For information call 555-1212`06~SM
+0200 ======================================================================~SM~SM
+0200 `06(`0EP`06)rice list           (`0ED`06)isconnect lines~SM
+0200 `06(`0EA`06)dd new lines        (`0ES`06)erivce call~SM
+0200 `06(`0EC`06)allerID             (`0ER`06)eport on account~SM
+0200 ~SM`0BChoice or `06(`0EQ`06) `0Bto Quit: ~SL
+
+0201 `0AAdd~SM
+0202 `0ACaller ID~SM
+0203 `0ADisconnect~SM
+0204 `0APrice list~SM
+0205 `0AReport~SM
+0206 `0AService call~SM
+0207 ~SM`0EYou do not have enough money for a service call.~SM
+
+0210 ~SMYou have ~&1 lines in service.~SM~SM
+0211 ~SMYou have ~&1 lines in service and ~&2 lines on order.~SM~SM
+0212 How many lines do you want to install?
+0213 ~SM~SM`0CYou cannot afford to purchase that many lines.`03~SM
+0214 You can not afford to install any more phone lines.~SM
+0215 ~SM~SMThis installation will cost $~&1.00~SM
+0215 Monthly service will be $~&2.00 in addition to current service.~SM
+0215 ~SM`0FDo you want to order them?
+0216 ~SM~SMYour order has been placed in the computer.  It often takes several days~SM
+0216 to get someone out to your location to install the lines.~SM
+
+0220 ~SM~SM`0FYou already have CallerID enabled on your phone lines. The phone company is~SM
+0220 not in the business of decoding the ID signals at your end of the line. We~SM
+0220 suggest that you contact a security firm for this kind of service.~SM
+
+0221 ~SM~SM`0FThe CallerID service will cost an additional $9.00 a month for each phone~SM
+0221 which is $~&1.00 for your current account.~SM
+0221 ~SMDo you want to add CallerID?
+0222 `06CallerID is now enabled on all your phone lines.~SM
+
+0230 ~SMYou have ~&1 lines in service and ~&2 lines on order.~SM
+0230 ~SMRemoving phone lines will cancel any new phone line orders!  No refunds will~SM
+0230 be made on the part of the phone company.  Installation costs will be lost.~SM
+0231 ~SMYou have ~&1 lines in service.~SM
+0232 ~SM`0FHow many do you want to remove? ~SL
+0233 ~SM~SM`0CRemove ~&1 line?
+
+0239   ~SM`0FPhone Service Order Center~SM
+0239   `03(All prices are per line)~SM~SM
+0239   `0EBasic Service          $20.00 per month (1 to 3 lines)~SM
+0239   Commercial Service     $50.00 per month (4 lines or more)~SM
+0239   Caller ID                9.00 per month~SM
+0239   Installation            70.00 first line~SM
+0239   Installation            35.00 all other lines~SM
+0239   Service Call            65.00 per trip~SM
+
+0238 ~SM Phone Lines: ~&1~SM
+0238  Line Damage: ~&2~SM
+0238  Phone Order: ~&3~SM
+0238    Caller ID: ~&4~SM
+0238    Last Bill: ~SM
+0238 Monthly Cost: $~&5.00 for ~&6 service.~SM
+
+0240 `0FYou have ~&1 lines needing service.~SM
+0241 `0EA service truck is sent to your location anyway just to double check.~SM
+0242 ~SMA service truck is sent out to your location and no phone trouble is found.~SM
+0242 ~SMYour service has been repaired~SM
+0243 ~SMYou see the service truck drive past your location and seconds later the~SM
+0243 ~SMphones are back in operation.
+0244 ~SMMany trucks gather outside your door and camp there for several hours.
+0244 ~SMIt doesn't look like they are doing anything more than talking to each
+0244 ~SMother. When it gets close to quitting time they all drive off and your
+0244 ~SMphones come back on.~SM
+0245 The phone lines go back into service right away.
+0246 The operator calls you on one of the trouble lines and gets a modem.
+0247 It looks like the lines are back in service.
+0248 The lines go back into service in less than 30 minutes.
+0249 The lines go back into service in less than an hour.
+0250 The service truck stops by and he takes away part of the phone wire. They~SM
+0250 left a note on your door saying that they will install new phone service~SM
+0250 at your location soon.
+0251 ~SM~SM`0FThe bill for $65.00 has been deducted from your account.~SM
+
+0260 ~SM~SM`0AA friend rushes out of the bank and bumps into you.~SM
+0260 ~SMThe tax dudes are in there! he whispers to you.~SM
+0260 ~SM`0FDo you still want to go inside?
+
+0261 ~SM~SM`0AThe bank examiner while checking your account notices that you have not~SM
+0261 paid any taxes on the interest and reports you to the IRS. They promptly~SM
+0261 send an auditor over and subtract the amount for the taxes plus charges~SM
+0261 for not filing on time. They both thank you kindly as they leave.~SM
+0261 ~SM`0FThe teller quickly pulls up your new account balance and prints it on a~SM
+0261 small piece of paper and hands it to you.~SM
+
+0262 ~SM~SM`0EThe bank reports a balance of $~&1~SM
+
+0270 ~SM~SM`0FThe few users you have decide that your small system is not worth paying for.~SM
+0270 They all say that they will not pay until your system is larger. Maybe you~SM
+0270 should put some work into the setup before trying to charge for access. At~SM
+0270 the very least you should try to attract a few more users.~SM
+
+0271 ~SM~SM`0FCharging for access to your system may cause a drop in the number of calls.~SM
+0271 Are you sure that you want to charge for access? (y/N)
+
+0272 ~SM~SMOptions~SM
+0272 (0) None      -Free access to all~SM
+0272 (1) Lifetime  -Users pay only once~SM
+0272 (2) Yearly    -Users pay each year~SM
+0272 (3) Monthly   -Users pay each month~SM
+0272 (4) Weekly    -Users pay each week~SM
+0272 (5) Hourly    -Users pay for connect time only~SM
+0272 (6) Download  -Users pay for bytes received~SM
+0272 ~SMChoice>
+
+0273 ~SM`0E~&1 users decide to pay.~SM
+0274 ~&1 users decide to leave.~SM
+
+0280 ~SM~SM`0FYou have ~&1 messages waiting to be read.~SM
+0280 ~SMWould you like to answer your mail now?
+
+0281 ~SM~SM`0EEmployees help.`0F
+0282 ~SM~SM                0%%-----------------50%%---------------100%%~SM
+0282 Answering Mail: `0C
+0283 `0CÛ
+0284 ~SM~SM`0EYou answer all of the messages.~SM
+0285 ~SM`0EYou answer all your mail.
+0286 ~SM~&1 new members join your system.
+0287 ~SM~SMYou have no messages waiting~SM~SM
+
+0290 ~SM`0EYou answer some problem messages.~SM~SM
+0291 ~SM`0FProblem Message Number: ~&1~SM~SM
+0292 ~SM`0E<`0FD`0E>elete, <`0FI`0E>gnore, <`0FP`0E>olite answer, <`0FR`0E>ude answer, <`0FL`0E>ock-out user: ~SL
+0293 `0FDelete~SM
+0294 `0FIgnore~SM
+0295 `0FPolite~SM~SM`0EYou do your best to be nice and not to cut the user down.~SM
+0296 `0FRude~SM
+0297 `0FLock out~SM
+0298 ~SM~SM                  Top 10 Systems and their Operators~SMÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0299 ~SM`09* Your employees are done for the day and have all gone home~SM~SM
+0300 ~SM~&1 free users, and
+0301 ~&1 paying customers decide to leave~SMbecause of all the busy signals.~SM~SM
+0302 ~SM~SMYour users are complaining because they can't get online~SM
+0302 because of all the busy signals.~SM~SM
+0302 You should get more modem lines NOW!~SM
+0303 ~SM`09* A chat is still pending.~SM
+0304 ~SM`09* A chat request has been made.~SM
+0305 ~SM~SM`0E* Some subscriptions arrive in the mail~SM
+
+0310 ~SM~SM`0FNo chat requests are pending.~SM
+0311 `0FThis user accidentaly hit the chat key by mistake.  He appologized~SM
+0311 for wasting you precious time.  You take pity on him and give him a~SM
+0311 a guided tour of your system.~SM~SM
+0311 He is tells all his friends about your friendly BBS, and your caller~SM
+0311 count jumps up.~SM
+
+0312 `0FThis caller is slow with typing.  He asks a few questions that are ~SM
+0312 spelled out in your bulletin section.  You are patient with him, however~SM
+0312 and he is your newest happy user.  Two days later you recieve a large~SM
+0312 donation in your mailbox.~SM
+
+0313 `0FThat caller has just logged off.  Try to be quicker next time!~SM
+
+0314 ~SM`0FThis caller is in the middle of a file transfer right now.  Try~SM
+0314 chatting with him again later.~SM
+
+0315 ~SM~SM`0FYou do not have enough actions left to do that!~SMTry again tommorrow.~SM
+
+0400 ~SMThe local system operators' group welcomes you as a member of their community!~SM
+0400 Most of them wish you the best of luck with your BBS and users.~SM
+0400 ~SM`0FThe local directory of Bulletin Board Systems needs some information from you.~SM
+0400 In order to keep our records straight we need to know the name that you call~SM
+0400 your BBS in this game. The list has space for up to 30 characters.~SM
+0401 ~SM`0E                         [..............................]~SM
+0401 `0EWhat is your BBS called? `0F
+0402 ~SM~SMThat name is already in use!  Try again?
+0403 ~SM~SMBBS name not changed.~SM
+0404 ~SM`0E                         [..............................]~SM
+0404 `0EWhat is your sysop name? `0F
+0405 ~SM~SMThat name is already in use!  Try again?
+0406 ~SM~SMSysop name not changed.~SM
+0407 ~SM~SMDo you wish to change the name of your BBS?
+
+0410 ~SM~SMYour personal command menu is now active.~SM
+0410 `0APress '?' for the list of options.~SM
+0411 `0F[personal:~&1]:
+0412 ~SM~SMExiting Personal Menu~SM~SM
+
+0413 ~SM`03ÄÄÄÄÄÄÄ`0F[Personal Commands]`0BÄÄÄÄÄÄ~SM
+0413 `03(`0BQ`03) `0FQuit Personal Menu~SM
+0413 `03(`0BL`03) `0FLearn~SM
+0413 `03(`0BU`03) `0FUse Skill~SM
+0413 `03(`0BS`03) `0FSecurity~SM
+0413 `03(`0BI`03) `0FInsurance policy~SM
+0413 `03(`0BB`03) `0FBank report~SM
+0413 `03(`0BR`03) `0FReport on BBS setup~SM
+0413 `03ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM~SM
+
+0420 ~SM~SM`0FHello and welcome. You have come to the right place. I can tell that you are~SM
+0420 a smart one. I could tell that the moment you walked in the door. Just by the~SM
+0420 way you walk I can see that you are not someone to be fooled with. That is~SM
+0420 why I am not going to give you a sales pitch and try to sign you up for some~SM
+0420 foolish insurance just to make a big commission for myself. No, I'm not that~SM
+0420 kind of guy. I would rather you be happy and enjoy the peace of mind that only~SM
+0420 comes from being prepared for the worst. Ah, yes, here is a perfect policy for~SM
+0420 someone in your situation. It covers all your investment in that nifty stuff~SM
+0420 you are running over there. The payments are very reasonable and will replace~SM
+0420 hardware and software in the event of fire, earthquake, flood, theft and most~SM
+0420 cases of dog bite. This policy has the least exclusions of any major policy in~SM
+0420 the country. I'm sure that someone as cautious as you would have no problem~SM
+0420 with any of the disclaimers. It is a perfect policy for someone like you. In~SM
+0420 fact I have already sold hundreds of these exact same policies to other sysop~SM
+0420 people in this very area. You really can't afford not to have this protection~SM
+0420 covering your large investment.~SM~SM
+0420 Buy protection?
+
+0421 ~SM~SMThat is a very wise choice. The policy will take effect in 60 days.~SM
+0421 But I'm sure that won't be a problem. It hasn't been a problem with~SM
+0421 any of the other sysop people in this area.~SM~SM
+
+0422 ~SM~SMThat is OK. I can see that you will need some time to think this over.~SM
+0422 I don't want to make you feel like you are under any pressure or anything~SM
+0422 like that. Just take your time and come back to visit me when you are~SM
+0422 ready for the best protection money can buy.~SM~SM
+
+0430 ~SM~SM`0AHigher Learning~SM
+0430 `02ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0430 `02(`0AQ`02) `0FQuit `07............. `0BLeave Higher Learning Menu~SM
+0430 `02(`0AT`02) `0FTake a class`07...... `0BCollege, Tech School, etc.~SM
+0430 `02(`0AH`02) `0FHire a tutor`07...... `0BPersonalized instruction~SM
+0430 `02(`0AB`02) `0FBribe an official`07. `0BGet inside security info~SM
+0430 `02(`0AV`02) `0FVisit a hacker`07.... `0BLearn from the underworld~SM
+0430 `02ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0430 `0F[Personal:~&1]:
+
+0435 ~SM~SM`0CAvailable tutors~SM
+0435 `05ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0435 `05(`0C0`05) `0FQuit`07.................... `0BLeave Tutor Menu~SM
+0435 `05(`0C1`05) `0FScruffy old guy`07......... `0BExpensive, knows his stuff~SM
+0435 `05(`0C2`05) `0FStern retired teacher`07... `0BVery strict, makes you learn~SM
+0435 `05(`0C3`05) `0FUniversity professor`07.... `0BOnly works after class hours~SM
+0435 `05(`0C4`05) `0FYoung lady`07.............. `0BWorks between her own classes~SM
+0435 `05(`0C5`05) `0FChild prodigy`07........... `0BVery expensive, and knows it~SM
+0435 `05ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0435 `0F[personal:~&1]:
+
+0436 ~SM~SM`0AYou do not have enough money for his services.~SM
+0437 ~SM~SM`0AYou do not have enough money for her services.~SM
+0438 ~SM~SM`0AHis service is very much in demand.  He agrees to teach you only if you~SM
+0439 ~SM~SM`0AHer service is very much in demand.  She agrees to teach you only if you~SM
+0440 agree to pay $~&2.00 and work a minimum of ~&1 actions.~SM~SM`0FDo you agree?
+
+
+0450 ~SM~SM`09Available Schools~SM
+0450 `01ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0450 `01(`090`01) `0FQuit School Menu~SM
+0450 `01(`091`01) `0FOlde Crusty Ivy University~SM
+0450 `01(`092`01) `0FGeneric County Technical Institute~SM
+0450 `01(`093`01) `0FCity Junior College~SM
+0450 `01(`094`01) `0FSchool of Experimental Transfixiation~SM
+0450 `01(`095`01) `0FBrains by Mail certification~SM
+0450 `01(`096`01) `0FSchool of Hard Knocks (teach yourself)~SM
+0450 `01ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0450 `0F[personal:~&1]:
+
+0460 ~SM~SM`0FHe wants $~&1.00 up front to let you see his stuff.~SM
+0460 He will also take anywhere from 10 to 90 actions,~SM
+0460 depending on how much he shows to you.~SM~SMDo you agree?
+
+0461 `0AHe hacks into your bank account and quickly finds out that you don't~SM
+0461 have that kind of money.  It is not a good idea to make a hacker mad.~SM
+0462 An FBI sting catches the hacker and he bargains with them by giving them~SM
+0462 your name as his source of information.~SM~SM
+0462 You have to spend 50 actions in court and $~&1.00 for your defense.~SM
+
+0463 ~SM~SM`0AHe shows you a few simple tricks. You think they are stupid, but he tells~SM
+0463 you that he has cracked a lot of big companies with those tricks.~SM
+0463 His hands moved very quickly and it looked like he made an extra hack.~SM
+0463 You wonder what the extra hack was all about. Could it involve you?~SM
+0463 ~SMIt would be a very good idea not to visit here again today.~SM~SM~SM
+0464 ~SM~SMA very wise idea~SM~SM
+
+0470 There is only one available class for this term.
+0471 There are ~&1 available classes for this term.
+0472 ~SMThe average course is ~&1 hour not including study time.~SM
+0473 The cost is $~&2.00 and ~&1 actions per credit hour.~SM~SMNumber of classes to take:
+0474            Suggested actions: ~&1~SM   How many study actions?
+0475 ~SM~SMIt is obvious to the professor that you are not serious about your~SM
+0475 education.  He allows you to drop the class so that he does not~SM
+0475 have to fail you.~SM~SM
+0476 ~SMNumber of classes: ~&1~SM
+0477 Total course cost: $~&1.00~SM
+0478 Level of study   : ~&1~SM
+0479 Days to complete : ~&1 (approximately.)~SM
+0480 ~SMIs this correct?
+0481 ~SM~SM`0EYour course grade is: ~&1
+0482   (Excellent!)~SM~SM
+0483   (Not bad)~SM~SM
+0484   (Not your best work)~SM~SM
+0485   (You should study harder)~SM~SM
+0486   (You didn't come here to learn!)~SM~SM
+0487 `09* You receive another certificate of education.~SM~SM
+0488 ~SM~SMYou do not have the amount of money that it takes for this kind of~SMclass load.  Come back when you have more money.~SM
+0490 ~SM~SMYou are the #1 BBS.  There is nobody else to inspect!~SM
+0491 ~SM~SM`09Enter a FULL or PARTIAL BBS name~SM
+0491 `0FSearch for which BBS? (?=List, <CR>=Quit): ~SL
+0492 ~SMDo you mean ~&1?
+
+0500 ~SM~SMUse Skills:~SM
+0500 `06ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0500 `06(`0EQ`06) `0FQuit.............. Exit Skills Menu~SM
+0500 `06(`0EH`06) `0FHack a BBS........ A phone line attack~SM
+0500 `06(`0EB`06) `0FBreak in Office... To take things~SM
+0500 `06(`0ES`06) `0FShoplift.......... Take from the store~SM
+0500 `06(`0ER`06) `0FRob bank.......... Get lots of money~SM
+0500 `06ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM~SM
+0500 `0F[personal:~&1]:
+
+0510 ~SM~SM`0FIt is not smart to try and take things from a computer store. Chances~SM
+0510 are very high that you will get put in jail! Their security system is~SM
+0510 very high tech and next to impossible to escape detection.~SM~SM
+0510 Do you still want to shoplift?
+
+0515 ~SM~SMu`0AYour efforts are not as skilled as you may have thought. The police show~SM
+0515 up in less than a minute and catch you in the act. The store manager has~SM
+0515 three different camera shots of you in action and quickly sends them to~SM
+0515 the local TV stations. They love the footage and play it every half hour~SM
+0515 for the next two days. You are famous and in jail! This is not a good~SM
+0515 combination. Bubba, your new roomie, likes famous cell mates a lot!~SM
+0515 ~SM`0FThe judge at your trial thinks you are photogenic and has you pose for~SM
+0515 a few more mug shots for his scrap book. He only gives you a short stay~SM
+0515 in the jail because he knows Bubba. He does charge you a Hefty fine~SM
+0515 which wipes out about half of your bank account.~SM~SM
+
+0516 ~SM~SMA Very wise choice!~SM
+
+0520 ~SM~SMIt is not smart to try and rob a bank without lots of planning. Chances~SM
+0520 are very high that you will get put in jail!~SM
+0520 ~SMDo you still want to rob the bank?
+
+0521 ~SM~SM`0AYour education and planning must not have been enough. The rent-a-cop~SM
+0521 security guard picked you off without even blinking an eye. He made it~SM
+0521 on to one of those 'cop' shows as a big time hero and got a raise out~SM
+0521 of the deal. He writes to you in your new home at the jail house to thank~SM
+0521 you for making it so easy on him and invites you to come by again when~SM
+0521 you get out again.~SM~SM
+0521 `0FThe judge at your trial thinks this is such a funny story that he gives~SM
+0521 you a 'short' term just for giving him a good laugh. He doesn't even~SM
+0521 charge you for the court time he is laughing to hard.~SM~SM
+0522 ~SM~SMA Very wise choice!~SM
+
+0530 ~SM~SMYou need an education of at least 1 to be accurate at hacking other boards.~SM~SM
+0530 It is not smart to try and hack into a BBS that has caller ID.  You could~SM
+0530 get put in jail!~SM~SM
+0530 Do you still want to hack?
+
+0531 ~SM~SMYou try hacking a random BBS and the police show up at your door even~SM
+0531 before you can hang up the phone. They put you in jail for 50 actions~SM
+0531 and charge you $~&1.00 in fines.~SM~SM
+
+0535 ~SM~SM`0FYou need a private education of at least 4 to be accurate at this.~SM~SM
+0535 This is not a smart thing to do for a novice. Breaking and entering will~SM
+0535 bring longer jail terms than hacking in most cases.~SM~SM
+0535 Do you still want to break in?
+
+0536 ~SM~SM`0AYou try breaking into a random office and the police show up at the door even~SM
+0536 before you can get anything. They put you in jail for 75 actions~SM
+0536 and charge you $180.00 in fines.~SM
+
+0537 ~SM~SM`0EA very smart move.~SM
+
+0540 ~SM~SMSecurity Menu:~SM
+0540 `06ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0540 `06(`0EQ`06) `0FQuit.............. Exit Security Menu~SM
+0540 `06(`0EB`06) `0FBurgler Alarm..... Install Office Alarm~SM
+0540 `06(`0EC`06) `0FCaller ID......... Install Caller ID~SM
+0540 `06ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0540 `0F[personal:~&1]:
+
+0541 ~SM~SM`0FYou request a special security team to come and check out your office~SM
+0541 for any possible weak security areas. They make several diagnostic checks~SM
+0541 and present you with a $~&1.00 bill for their service.~SM~SM
+0541 This will take you to the next highest level of security for your system.~SM
+0541 It will take you 10 actions to install everything.~SM~SM
+0541 Do you want to upgrade your office security?
+
+0542 ~SM~SMWe'll come back when you have the funds.~SM
+0543 ~SM~SMThey finish their work in no time, and are soon on their way.~SM
+0544 ~SM~SMMaybe later then.~SM
+
+0545 ~SM~SM`0FYou request a special phone security team to come and check out your system~SM
+0545 for any possible weak security areas. They make several diagnostic checks~SM
+0545 and present you with a $~&1.00 bill for their service.~SM~SM
+0545 This will take you to the next highest level of security for your system.~SM
+0545 It will take you 1 actions to install everything.~SM~SM
+0545 Do you want to upgrade your phone security?
+
+0546 ~SM~SMWe'll come back when you have the funds.~SM
+0547 ~SM~SMThey finish their work in no time, and are soon on their way.~SM
+
+0550 ~SM~SM`0AThe public official is not available at this time.~SM
+0550 But his office would be more than happy to accept a~SM
+0550 small "donation" from you.~SM
+0550 (Wink, wink)~SM~SM
+0550 `0FWould you like to make a donation?
+0551 ~SM~SMDonation amount:
+0552 ~SM~SM`0AThe office staff accept your check for $~&1.00 but~SM
+0552 they look a little strange. Was it not enough?~SM
+0553 ~SM~SM`0FHis office staff look you straight in the eye and~SM
+0553 tell you that they don't know where he is.~SM
+0554 ~SM`0FHis office staff tell you that he is on a cruise~SM
+0554 right now, and will get back to you when he returns.  Don't forget to vote!~SM
+
+0570 ~SM~SM`0AThis is the hardest way to learn something new. You will save some money~SM
+0570 but it will take over ~&1 actions!~SM~SM
+0570 `0FDo you still want to learn this way?
+
+0580 ~SM~SMHacking to the best of your ability...
+0581 ~SMYou made it in!~SM~SM
+0581 It looks like they only have a level ~&1 caller information system.~SM~SM
+0581 Options:~SM
+0581 `02ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0581   `02(`0AA`02) `0BDestroy their BBS software~SM
+0581   `02(`0AB`02) `0BDelete user records from their system~SM
+0581   `02(`0AC`02) `0BLower their security system one level~SM
+0581   `02(`0AD`02) `0BSend virus to attack their hardware~SM
+0581   `02(`0AE`02) `0BLeave a fake clue card~SM
+0581 `02ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0581 `0FChoice:
+0582 Ripping BBS software.....
+0583 Hacking user records.....
+0584 Hacking security system..
+0585 Uploading virus..........
+0586 Leaving fake clues.......
+0587 Success!~SM~SM
+0588 NO CARRIER~SM~SM
+0590 You make mince meat out of this sysop's BBS software.  As a result,~SM
+0590 ~&1 free users have stopped calling ~&2~SM
+0591 You wreak havok out of this sysop's user file.  As a result,~SM
+0591 ~&1 paying users have stopped calling ~&2~SM
+
+
+0700 ~SM~SM
+0701  Your nearest competition:~SM
+0702 `0E Report on the setup of ~&0~SM
+0703 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+0704 `0A   Computer: ~&1~SM
+0705     Storage: ~&2~SM
+0706      Modems: ~&3 2400bps~SM
+0707      Modems: ~&4 High Speed~SM
+0708      Modems: ~&5 Digital~SM
+0709    Software: Can support up to ~&6 line(s) <~&7> (~&8 ports unused)~SM
+0710 `0FPhone Lines: ~&9~SM
+0711 Phone Order: ~&A phone line to be installed.~SM
+0727 Line Status: ~&N phone lines are damaged.~SM
+0712       `0AUsers: ~&B free, ~&C paying.~SM
+0713  Experience: ~&D~SM
+0714   Education: ~&E Public, ~&F Private.~SM
+0715   Caller ID: ~&G~SM
+0716     Actions: ~&H left today.~SM
+0717    Messages: ~&I waiting to be read~SM
+0718   Insurance: NO COVERAGE~SM
+0719   Insurance: You're Covered!~SM
+0720 Start Score: ~&J (UP by ~&K points)~SM
+0721 Start Score: ~&J (DOWN by ~&K points)~SM
+0722 `0F      Score: ~&M points!
+0723  (WORK Harder!)
+0724  (You are the #1 BBS!)~SM
+0725  (You are ~&L away from the #1 BBS!)~SM
+0726 ~SM`0FThis is the latest available information about your nearest competition.~SM
+0726 No warranty is made on the reliability of this information. Use at your~SM
+0726 own risk. The cost of this report has been deducted from your account.~SM~SM
+
+0730 ~SM~SM`0BAvailable software packages: `0F~SM~SM
+0730 `09   Key Software Package               Price~SM
+0730 `01   ÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄ
+0732  (Step Down)
+;0733
+0734 ~SM~SMChoice (~&4) or (Q) to Quit:
+0735 ~SM`01   (`09~&1`09) ~EL30~&2 $~ER12~&3
+0736 ~SMYou have purchased a ~&1 software package.~SM~SM
+0737 ~SMCome back when you have what it takes!~SM~SM
+
+0740 ~SM~SMAvailable Computer Configurations: `0F~SM~SM
+0740 `0A   Key Computer                       $       Price~SM
+0740 `02   ÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄ
+;0741
+0742 ~SM`02   (`0A~&1`02) `0B~EL30~&2 $~ER12~&3
+0743  (step down)
+;0744
+0745 ~SM~SMChoice (~&4) or (Q) to Quit:
+0746 ~SM~SMYou have purchased a ~&1 computer~SM~SM~SM
+0747 ~SMCome back when you have what it takes!~SM~SM~SM
+
+
+0750 ~SM~SM`0BHardware prices include all mounting and connecting hardware, cables,~SM
+0750 driver software installation, testing and labor.~SM~SM
+0750  `0BModems:~SM~SM
+0750  `0DKey Description            Cost   Minimum Requirements~SM
+0750  `09ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ~SM
+0751  `06(`0D~&1`06) ~EL16~&2 $~ER9~&3   ~&4~SM
+0752   ~SM`0CYou cannot afford to purchase any modems.  Try again later.~SM~SM~SP
+0753 ~SM~SM`0BBuy Which?:(A-~&1,Q=Quit):
+0754 ~SM`0BYou can afford to purchase ~&1 ~&2 modems.~SM~SMPurchase how many? (0 to Quit):
+0755 ~SM`0BYou cannot afford to purchase that many modems.~SM~SM
+0756 ~SM`0BEach modem takes one action to install.  You have elected to~SM
+0756 install ~&1 modems~SM~SM
+0756 `0BDo you wish to continue?
+0757 ~SM~SM`0B~&1 new modems are now installed on your system.~SM~SM
+0758 ~SMAborted~SM~SM
+0759 ~SM~SM`0BYou do not need any modems.~SM~SM
+
+0760 ~SM~SM`0BAvailable Harddrive Configurations: `0F~SM~SM
+0760 `0C   Key Size                           $ Price~SM
+0760 `05   ÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄ~SM
+0761    `05(`0C~&1`05) `0B~EL30~&2 $~ER12~&3
+0762  (step down)
+0764 ~SM
+0765 ~SMChoice (~&5) or (Q) to Quit:
+0766 ~SMYou have purchased a ~&1~SM~SM
+0767 ~SMCome back when you have what it takes!~SM~SM
+
+
+0800 `0D* You have not played for ~&1 days.  You really should call more often!~SM
+0801 ~SMThe phone company has finished installing your ~&1 new phone lines.~SM
+0802 ~SM`0FThere are ~&1 players in this game.~SM
+0810 `0EChecking User Data            -
+0811 OK!
+0812 ERROR!~SM~SM Your software has detected a hacker attempt since your last call.~SM
+0813 `0E* Insurance company adjustment check arrives.~SM
+0814 `0E* Insurance company has canceled your policy.~SM
+0815 >> Check the damage report on your personal menu. <<~SM
+0816
+0817 ~SM`0ESystem hardware diagnostics   -
+0818 OK!
+0819 ERROR!
+0820 ~SM`0ESecurity system diagnostics   -
+0821 Classified.
+0822 ERROR!
+0823 OK!
+0824 ~SM`0ECaller validation diagnostics -
+0826 Classified.
+0827 ERROR!
+0828 OK!
+0829 ~SM`0EPhone Line diagnostics        -
+0830 DAMAGE!
+0831 OK!
+0832 ~SM
+0833 ~SM`0E*WARNING* - You have no working phone lines.~SM
+0834 ~SMThe Phone bill arrives in the mail.  You pay $~&1.00~SM
+0835 ~SM`0E** NOTICE ** The phone company has switched on your ~&1 new phonelines.~SM
+0836 ~SM`09* Insurance premium payment.  $1.00~SM
+0837   Your policy will soon expire.  You should think about renewing~SM
+0838   You insurance policy has been revoked due to non-payment.~SM
+0839 ~SMYour education is becomming dated!~SM
+0840 ~SM`0BYou have messages waiting.~SM
+0841 ~SM`0FPress '?' for help~SM
+0842 ~SM`0EOpMode.~SM
+0850 ~&1 new users join your system~SM
+0851 ~&1 free users subscribe to your system~SM
+0852 ~&1 users leave your system~SM
+0853 ~&1 paying users leave your system~SM
+0854 `0EYou gain $~&1, your bank account now shows $~&2.`0F~SM
+0855 ~SMYou now have a ~&1~SM
+0856 ~SM~&1 free users subscribe to your system~SM
+0857 ~SMYou now have a ~&1~SM
+0858 ~SM** WARNING **~SM
+0858 ~SMYou have no computer!  Your callers won't be able to call, and they~SM
+0858 won't like that.  You had better get a new computer SOON!~SM
+0859 ~SM`0EYou dust off your old ~&1~SMand it is now your system computer.~SM
+0860 ~SM** WARNING **~SM
+0860 You do not have a working harddrive.  You have nothing to run your BBS.~SM
+0860 You had better get a new harddrive soon!~SM
+0861 ~SM`0EYou reinstall your old ~&1~SM
+0862 ~SM~SM`0E**WARNING**~SM
+0862 `0EYou have no modems!  ~SMLuckily, one of your users loans you his old 2400 baud.~SM`03
+0862 `0EYou should get new modems soon!~SM`03
+0863 But yours is much better, so you donate it to charity.
+0864 ~SMYou call the Phone Company to hurry them up, so you can get your ordered
+0864 phone lines installed.  They charge you ~IN actions for the fast service.~SM
+0865 ~SMMaybe you had better go and order some phone lines.~SM
+
+0870 ~SM`0C********** VIRUS ATTACK DETECTED! **********`0E~SM~SM
+0871 ~SMYou vow never to forget to run your virus protection again!~SM~SM
+
+0875 `09* Disinfecting the ~&1 virus.~SM
+
+0880 ~SM~SM2400 baud users have access to ~&1 lines which are filled to ~&2%% capacity.~SM
+0881 High Speed users have access to ~&1 lines which are filled to ~&2%% capacity.~SM
+
+0890 ~SM~SM                     All Systems and their Operators~SM
+0890 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ~SM
+;0891-0895  1=Ranking, 2=BBS Name, 3=Sysop name, 4=Score, 5=Line 894,
+;           6=length of line 894, 7=line 895
+;0891 `03~ER3~&1-`0E~EL45~&5`0E Score: `0B~ER10~&4
+0891 `03~ER3~&1-`0E~EL45~&5`0E Score: `0B~ER10~&4
+0892  <--YOU!~SM
+0893 ~SM
+0894 `0E~&2 `07(`0F~&3`07)
+0895 ~EF.~&6
+
+;0900 1=# of  users, 2=# of lines, 3=Sysop, 4=ranking number,
+;0900 5=BBS Name 6=Score
+0900 `06~ER3~&4-`0E~EL45~&5 `0E Score: `0B~&6~SM   Sysop: ~&3 with ~&2 lines, ~&1 users.~SM
+0901 ~SM`03   Sysop: ~&3 with ~&2 lines,  ~&1 users.~SM
+0902 `03~&4-`06
+0903 ~EF.~&1
+0904 `0E~&5`06 `06
+0905 `0E Score: `0B~&6
+
+1000 `09(`03A`09) `02Sysop Name `0F:`0E |SA
+1001 `09(`03F`09) `02Level       `0F: |EX
+1002 `09(`03B`09) `02BBS Name   `0F: |BN
+1003 `09(`03G`09) `02Score       `0F: |SN
+1004 `09(`03C`09) `02Computer   `0F: (~IN) |CU
+1005 `09(`03H`09) `02Actions     `0F: |AC
+1006 `09(`03D`09) `02Storage    `0F: |HD
+1007 `09(`03I`09) `02Money       `0F: |AU
+1008 `09(`03E`09) `02BBS S/W    `0F: |BS
+1009 `09(`03J`09) `02Money       `0F: |AU
+1010 `0EPhone Lines:`0EModems`09:`0ESecurity`09:
+1011 `09(`03K`09) `02Installed  `0F: |PI
+1012 `09(`03N`09) `02Low speed `0F: |MA
+1013 `09(`03R`09) `02CallerID    `0F: |S2
+1014 `09(`03L`09) `02Ordered    `0F: |PO
+1015 `09(`03O`09) `02High Speed`0F: |MB
+1016 `09(`03R`09) `02Insurance   `0F: |IS
+1017 `09(`03M`09) `02Damaged    `0F: |PD
+1018 `09(`03P`09) `02Digital   `0F: |MC
+1019 `09(`03T`09) `02Alarm       `0F: |S1
+1020 `0EEducation:`0ECallers`09:`0EEmployees`09:
+1021 `09(`03U`09) `02Public     `0F: |P1
+1022 `09(`03W`09) `02Free      `0F: |UF
+1023 `09(`03Y`09) `02Employees   `0F: |EM
+1024 `09(`03V`09) `02Private    `0F: |P2
+1025 `09(`03X`09) `02Paying    `0F: |UP
+1026 `09(`03Z`09) `02Action      `0F: |EA
+1030 ~SM~SM~SM`09Player Editor: (]/[) Next/Prev, Q=Quit`0B:
+
+1040 ~SM~SM`09New Level: `0F
+1041 ~SM~SM`09New Computer: `0F
+
+; Network Mail Strings
+1100 ~SM`09S`01ubject: `1F
+1101 ~SM   `07Type message below.  <ENTER> on a blank line ends.
+1102 ~SM   [---+----+----+----+----+----+----+----+----+----+----+----+----+----+----]~SM
+1110 ~SM~SMWould you like to send something?
+1111 ~SMWhat would you like to send? ~SM
+1119 ~SM~SMWhich? [1-2, 0=Quit] :
+1120 ~SM~SMYou don't have that many actions to give.~SM
+1120 ~SMPlease try again.~SM
+1130 ~SMSend this message?
+
+1140 ~SM~SMNetwork Mail Menu~SM~SM
+1140 `07P`09)oll for mail~SM
+1140 `07S`09)end Network Mail~SM
+1140 ~SM`02Network Mail Menu: (`07Q=Quit`02)`07: ~SL
+
+1150 ~SM~SM`09Ú~EFÄ75¿~SM
+1150 `09³ `0FFrom: ~EL68~&1`09³~SM
+1150 `09³ `0FDate: ~EL68~&2`09³~SM
+1150 `09³ `0FSubj: ~EL68~&3`09³~SM
+1150 Ã~EFÄ75´~SM
+
+1151 `09À~EFÄ75Ù
+
+1160 ~SM~SMDelete this message?
+1161 ~SM~SMYour mailbox is empty~SM
diff --git a/src/doors/vbbs/data/vbbs.txt b/src/doors/vbbs/data/vbbs.txt
new file mode 100755
index 0000000000000000000000000000000000000000..cf0d19a156235b3c1bd17b695cf7767bacd813ce
--- /dev/null
+++ b/src/doors/vbbs/data/vbbs.txt
@@ -0,0 +1,320 @@
+ VBBS: The Virtual BBS Simulation.
+ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
+ (Virtual BBS, 3.0)
+ Copyright 1999 - 2002 by Darryl Perry
+ All rights reserved.
+
+ Maintained by Vagabond Software
+ http://vs3.vbsoft.org/
+
+
+This is a simulation of what it may be like to be a system operator on one of
+the larger data services in the nation. It is not designed to be 100% accurate
+or resemble any one BBS. The problems and situations found in this program are
+the result of many years of running a BBS.
+
+
+INSTRUCTIONS FOR PLAYING THE GAME
+ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+       "The local system operator's group welcomes a new member to their
+        community!  Most of them wish you the best of luck with your BBS
+        and users."
+
+
+GENERAL INTRODUCTION
+
+         Every effort has been made to make this game true to life whenever
+        possible. There are some areas that have been changed to make the game
+        more enjoyable and less like work. After all, if you would put up with
+        the pain of being a real sysop then you would be running a real BBS.
+
+         Most of the users that you will find in this simulation will not take
+        up any of your time, as do many actual users. The few that will use up
+        your time are the ones to watch. They will be giving you the most
+        trouble.
+
+
+YOUR GOAL
+
+         Your goal is to get your BBS to grow. You must attract the most users
+        and get them to take part in your system. This will make up the larger
+        part of your score in the game. Hardware and software don't count much
+        if you don't have any users.
+
+         For the most part use the golden rule and you will do ok.
+
+
+PROMPT LINE
+
+         The prompt line is made up of 3 (or 4) parts:
+ 
+            (non-paying users : paying users : actions left today)
+ 
+         The first part tells you the total number of non-paying (free) users
+        that may be talked into paying for your system.
+
+         You must have more than 50 users to start charging for access.
+
+         The second item is the total number of paying users. These people are
+        paying for your system and you should make sure that they have enough
+        phone lines to use. They tend to be very easy to make mad because they
+        are putting their money into your system. Too many busy signals and
+        they may even demand their money back.
+
+         The third part is the number of actions you have left today. There is
+        only so much one person can do in a day. Even a super sysop is
+        limited. Keep an eye on this number until you find out what takes up
+        your time and what doesn't.
+
+         If you hire employees a "point" number will be added to your actions.
+        This shows the number of employee actions available. Most employees
+        are limited in how fast they can do a job compared to the main sysop.
+        It might take an employee 2 or more actions to do something you could
+        do in 1 action.
+
+         You will find that most of the prompts are easy to understand so feel
+        free to explore.
+
+
+ANSWER MAIL
+
+         Answering mail is one of the jobs that every sysop must decide when
+        and how often to do. Most of the mail sent to a sysop is nothing more
+        than questions that the sysop has answered many times before. These
+        are called "no-brainer" messages and any sysop can answer these in his
+        sleep. It still takes time to answer them, but you are not shown the
+        text of each one as they are answered.
+
+         It is a good idea not to let the mail pile up in your box for too
+        long. When the users see that it is taking a long time for you to get
+        back to them they may get mad. This normally starts with more
+        messages, but may end up with them leaving your system.
+
+
+PROBLEM MAIL
+
+         When your system gets larger, the co-sysops will start answering more
+        and more of the "no-brainer" mail. If they find a message that they
+        can't answer, or is a problem that they don't want to answer, they
+        will send it to you. These messages are called "problem" mail. They
+        are normally from mad users who are upset about something to the point
+        of being rude. It takes special care to answer each message in a way
+        that will either cool the user down or stop him from bothering you
+        again.
+
+         Don't be so eager to lock out a user or ignore his mail. Bad things
+        can happen if you get a reputation as a censor or make the wrong
+        person mad at you. It may even get to the point that you will be
+        forced to take your system down or end up in a lawsuit.
+ 
+
+MAIN FUNCTIONS
+
+         The following commands should be the ones you spend the most time
+        with. They are (W)ork, (V)irus scan and (S)tore. Be careful. It is
+        easy to forget to keep up with your (M)ail or to keep the number of
+        free lines ahead of the number of users calling your system.
+
+
+PHONE LINE LOAD
+
+         The (U)sage function will show you a quick overview of the work load
+        percentage on each group of your phone lines. The numbers are split
+        into two different sections. The slow modems and high speed modems.
+        The slow modem users are any user with a modem not capable of 9600
+        bps. They are happy to connect with any of your available modems. The
+        high speed modem users have paid extra for their hardware and only
+        want to use the high speed lines on your system.
+
+         The users will start to complain about the busy signals if the load
+        on your phone lines starts to get too high. They will only complain
+        for a short time before they leave your board. When users leave your
+        board they normally take their friends with them. This can take a big
+        chunk out of your customer base.
+
+         It is suggested that you spend part of your time each day installing
+        modems until you are well ahead of the number of users. This will give
+        you some time to devote to building up your user base without fear of
+        overloading your phone lines.
+
+
+CHARGING FOR ACCESS
+
+         The method you select to charge your users for access to your system
+        is up to you. Just about every option is available, some more
+        successful than others. You are encouraged to consider several things
+        about charging before you actually start taking money. First, what is
+        the main thing that you will be selling. Is it bytes or time? Will the
+        users re-subscribe for more of the same access? What would you be
+        willing to pay if you were a user?
+
+         You will be able to change the way you are charging once each day by
+        going into the (C)harge option. It is suggested that you not change
+        the way you are charging very often. It can make your paying users
+        unhappy which may cost you both money and subscribers.
+
+
+FREE USERS
+
+         Keep an eye on the number of free users you have on your system. They
+        don't have anything invested in your service and can cause problems
+        between you and the phone company. It is a good idea to keep the
+        number of free users as low as possible. Some of them will subscribe
+        on their own, but others need to be "reminded" why they should
+        subscribe to your service with the (C)harge option.
+
+
+VIRUS CHECKING
+
+         When you work around communications it is likely that some point in
+        your many connections that you will attract a virus or two. It is
+        strongly suggested that you use the scanning option at least once for
+        every ten "working" actions. There are some situations that a
+        TurboScan mode will be available. But remember that this faster scan
+        may not catch all of the infected files as the regular scan. If a
+        virus is found its name will be displayed. If it is found in more than
+        one place it will be shown more than once.
+
+
+SHOPPING
+
+         The store menu allows you to purchase a wide range of items. You will
+        need to go to the store to buy just about everything for your system.
+        Not every store on the menu has the same price on the same item. You
+        should shop around until you find what you need. It is possible that
+        the "discount" stores may pull you in with a false price and charge
+        you a higher price than the full retail stores.
+
+     (PHONE SERVICE)
+         Much like the real world, the phone service in this game is not 100%
+        reliable. If you have to deal with the phone company try to keep it as
+        simple as possible. Errors are likely when you start placing orders
+        while asking for other services. When calling for repairs remember
+        that the service trucks must charge you for every trip even if they
+        don't find anything wrong with your line.
+
+         When you start adding large numbers of phone lines you will quickly
+        out grow the local phone services which will require them to run
+        special lines just for you. This will cost time, money and actions so
+        think and plan carefully before jumping into that first multi-line
+        order.
+ 
+
+PERSONAL OPTIONS
+
+         There are several options not directly related to running a BBS that
+        are available in this game. They range from going to school to get a
+        higher education and buying insurance to illegal activities like
+        hacking or burglary. These options are not available to the very new
+        player to try and make things a little less complicated for them.
+
+     (EDUCATION)
+         There are different types of education available. The public
+        education is the kind of information found most often in schools or
+        from tutors. The personal education is more of the "secret" stuff
+        normally found out from direct word of mouth. Each type will allow you
+        to do different things. A good public education will make it easier
+        for you to run your BBS or if you are in the mood, break into someone
+        else's office or take something from the store without getting cought.
+        A good personal education will make it easier to hack a BBS or rob the
+        bank.
+
+     (CALLER-ID)
+         The most useful of the personal options are the protection devices.
+        These come in two forms; Caller ID and Office Security. The Caller ID
+        is rated with a number showing the level or strength of validation
+        that is used by the hardware. Different hardware has different caller
+        validation abilities. Sometimes this equipment can be damaged by
+        someone trying to break into your system or by "age". Check it every
+        so often to make sure that it is still operational.
+
+     (SECURITY)
+         The Office Security ranges from locks on the door to very complex
+        security and access management services. Like the Caller ID it is
+        rated with a number showing the level or strength. Burglars can do
+        more damage to your system than hackers so a good security system can
+        be a very smart investment. These systems are more robust than Caller
+        ID systems, but they also have a limited lifetime.
+
+     (INSURANCE)
+         The only insurance company we could get to open an office in this
+        game was not very well known. They do cover most damage from hackers
+        or burglars, but the coverage for the first 60 days is limited. They
+        also retain the right to cancel your policy if the claim is too high.
+        The good thing is that they don't keep good records so you can sign up
+        with them as often as you like.
+
+         Illegal activities are not suggested but are there just for those who
+        can't resist. These options have a risk of being detected by the
+        police. Jail terms are stiff and can take you out of the game for
+        several real days. You must serve your time.
+
+         If you don't call back at least once each day you are in jail your
+        term will grow one day for each one you skip.
+
+     (HACKING)
+         Hacking is the safest of the "dark" actions. This is where you use
+        your "personal" education to break into other systems. You must be
+        able to out smart their validation system to gain access. Otherwise
+        the police will be notified. What you do once you are on the inside is
+        up to you.
+
+     (BREAKING IN)
+         Breaking into an office is more risky but allows you to steal items
+        and do things that hackers can't. For example, a hacker can't destroy
+        backup tapes or take a modem or computer from a BBS. Since you are in
+        a hurry, some items may break. So get all you can in the limited time
+        you have.
+
+     (ROB BANK)
+         Rob the bank is the hardest of all the options. It really is for the
+        very very experienced and should not be attempted without much strong
+        drink. The odds of you actually getting even a part of the funds from
+        the bank are so small that if you put the same time into working you
+        would be a multi-billionaire. The chance is there and the prize is not
+        small either.
+
+     (SHOPLIFTING)
+         Shoplifting is available for those who are so experienced that they
+        either want a larger challenge or a chance at the big stuff. This
+        option is very hard! The store is always trying out new security
+        hardware. The Bank is the only thing harder to break.
+
+         There is a difference in the score you get from items you steal and
+        items you buy. Sometimes the difference is small, but often it is much
+        more noticeable.
+
+         Every illegal activity leaves some kind of a trace or clue. The
+        police are not always bright enough to pick up the clue so the player
+        may have to look at the damage report in person. If the hacker or
+        thief was very good the clue will be too small to use in court. But
+        not too small to allow the player to track down who the criminal was.
+        Watch out for mad victims.
+
+         A byproduct of being the victim of a crime is that you get "mad" and
+        have an extra boost of energy. This is shown as extra actions on the
+        command line. Even if you are in jail or in debt for education you can
+        still find those extra actions. Use these wisely. Protect yourself
+        before you go off in a rage to attack your attacker.
+
+         It is also possible for the hacker or burglar to "lie" and leave a
+        fake clue. So you may end up venting your anger on the wrong person if
+        you are not careful.
+
+ 
+SCORE CALCULATION
+
+         The score is calculated on the main parts of the BBS.
+
+        They include:
+                Computer type and operating system, file storage, BBS
+                software, number of phone lines, number of modems,
+                number of users and how long it takes you to answer
+                your waiting mail.
+
+         Each part of the calculation can be affected by other parts. Keep an
+        eye on your score in the (R)eport option until you get a feel for how
+        things work. The largest part of the score is the number of users.
+        Keep your users happy and your score will grow faster.
+
+
diff --git a/src/doors/vbbs/data/virus.dat b/src/doors/vbbs/data/virus.dat
new file mode 100755
index 0000000000000000000000000000000000000000..454cd76d21cda4a20a359f79eee32c9534aa7fe4
--- /dev/null
+++ b/src/doors/vbbs/data/virus.dat
@@ -0,0 +1,912 @@
+VIRUS
+431
+AIDS II
+AMT
+ARCV (Alpha)
+ARCV (Benoit)
+ARCV (McWhale)
+ARCV (Reaper)
+ARCV (Sandwich)
+ARCV (Zaphod)
+Abraxas
+Abs-3
+Ada
+Adidas
+Akuku (Copmpletely)
+Alabama
+Albania (429)
+Alexander
+Alive
+Ambulance
+Amoeba
+Andromeda
+Andryushka (3568)
+Angarsk
+Anna
+Anthrax
+Anti-MIT
+Anti-Pascal II (480)
+AntiMon
+Aragon
+Aragorn
+Armagedon (1079)
+Arriba
+Arusiek
+Ash (1602)
+Astra (1010)
+AstraSYS (521)
+Atas (1268)
+Atas II (3215)
+Athens
+Atomic
+Attention
+Ava (550)
+BAS Joker
+BAT (HACK-TIC)
+BAT (Thailand)
+BAT (USSR B)
+BC-II Fix
+BackFont (765)
+BackFont (900\905)
+Backfind
+Bad Boy
+Bad Brains
+Baobab (1635)
+Baobab (731)
+Barrotes
+Bebe (1004)
+Beech
+Beer (3164)
+Best Wishes
+BetaBoys (Mud)
+BetaBoys (Rattle)
+Better World
+Beware
+Big Joke
+Bit Addict
+Bizarre
+Black Jec (Sad 301)
+Black Monday (Bord)
+Blaise
+Blood
+Bobas
+Boot
+Boot EXE (452)
+Boot-437
+Bootkill
+Boys (500)
+Brainy (Dream)
+Brasil
+Bravo
+Breeder
+Breeder T
+Bryansk
+Budo
+Bugsres
+Bupt
+Burger
+Burghofer
+Butterfly
+CARA
+CCCP (510)
+COD
+COMvirus
+CSL (V5)
+Caco
+Cannabis (B)
+Capital
+Carioca
+Cascade (Formiche)
+Cascade (Jojo 1703)
+Casino
+Catman
+Catphish
+Caz (1204)
+Cerburus
+Chad
+Chang
+Changsha
+Chaos
+Chcc
+Checksum (1569)
+Cheeba
+Chemnitz
+Chinese Fish
+Chips
+Cinderella II
+Civil War (561)
+Clock
+Clone
+CloneWar
+Close (960)
+Code Zero
+CoffeeShop
+Comasp (472)
+Commander Bomber
+Commfix
+Commy
+Como
+Comp (16850)
+Compagnion
+Compiler (1)
+Compiler (2)
+Cookie (7360)
+Cookie (7392)
+Copy77
+Copyright (1193)
+Coruna
+Cossiga (883)
+Costeau
+Cpw
+Crawly
+Crazy Daisy
+Crazy Eddie
+Crazy Imp (1402)
+Crazy T
+Creeper (252)
+Crew (1)
+Crew (2)
+Criminal
+Crooked
+Crunch
+Cure #6
+Cvir
+CyberTech (A)
+CyberTech (B)
+Cysta (2954)
+DM (400 B)
+DM (674)
+DOShunter
+Dada
+Danish Tiny (Stigmt)
+Dark Avenger (Korea)
+Dark Avenger (Milen)
+Dark Avenger (Slow)
+Dark End
+Darth Vader (4)
+Dash-em
+DataCrime (1514)
+Datalock (828)
+Davis
+Dead
+Dec Year
+Deicide II (2570)
+Demolition
+Denied
+Destructor
+Dewdz
+Diamond (Damage B)
+Diamond (Greemlin)
+Diamond (RockSteady)
+Diamond (Sathanyk)
+Digger
+Dir III
+Disk Killer
+Disk Plus 1
+Disk Spoiler
+Disk Washer
+Dismember
+Doom II (1240)
+Doomsday
+Dot Eater
+Dr. Qumak II
+Dr. Sort
+Dreamer
+Drop
+Drunk Avenger
+Dupacel
+Dutch (276)
+Dutch Tiny (124 B)
+Dutch Tiny (126)
+Ear (Quake-O)
+Eastern Digital
+Eddie 2
+Egg
+Eight Tunes
+Eko Terror
+Elephant
+Emmie (2365)
+Enola (1864)
+Enrico
+Eraseboot
+Error
+Europe 92
+Even Beeper
+Exe 222
+Exper
+Experiments (755)
+Explosion
+Falling Letters
+Farenheit 121
+Fatman
+Fax Free (Mosquito)
+Fax Free (Pisello)
+Fax Free (Topo)
+Fichv (2.0)
+Fichv (2.1)
+Fichv (EXE)
+Filedate 11 (570)
+Filehider (789)
+Filename
+Filler
+Finnish (709)
+Fire T
+FirstStar
+Fish 6
+Fisher (1100)
+Fisher (2420)
+Five Lo
+Flagyll
+Flame
+Flash (Gyorgyi)
+Flip (2153)
+Flip (2343)
+Flower (868)
+Flower (880)
+Forger
+Form II
+Freak
+Freddy
+Freew (718)
+Friday (ENET 37)
+Frodo (Fish 6)
+Fumble (D)
+Funeral
+Geek
+Generic ARCV Boot
+Gergana (450)
+Gingerbread
+Gliss
+Globe
+Godoy
+Goga
+Gordy
+Gorlovka
+Gosia
+Gotcha! (D)
+Grab
+Green Caterpillar
+Groove Over
+Grower
+Grune
+Guppy
+Gyro
+Ha!
+Hacktic
+Hafenstrasse (1689)
+Haifa
+Halley
+Hamster
+Happy Monday
+Happy New Year (164)
+Harakiri
+Harm
+Headcrash
+Hide and Seek
+HideNow
+Hitchcock
+Horror (1182)
+Horse (2248)
+Hungarian (482)
+Hydra
+Hymn (2144)
+Hymn (Sverdlov)
+Icelandic (Mix-1)
+Icelandic (PassGrab)
+Ieronim II (1581)
+InCom
+InDOS
+Infector (822)
+Internal (B)
+Intrep (1092)
+Intruder (2336)
+Invisible Man (3223)
+Involuntary (A)
+Involuntary (B)
+Ionkin (2372)
+Iper
+Iron Umbrella
+Israeli Chaos
+Israeli Destructor
+Italian B
+Itavir
+Itti Bitty (161)
+J-Inject
+JD (448)
+Jabberwocky (812)
+Jerusalem (AntiScan)
+Jerusalem (Austral)
+Jerusalem (Barcelon)
+Jerusalem (Carfield)
+Jerusalem (Clipper)
+Jerusalem (Czech ha)
+Jerusalem (Danube)
+Jerusalem (Dyslexia)
+Jerusalem (Einstein)
+Jerusalem (FuManchu)
+Jerusalem (GP1 1845)
+Jerusalem (Glory)
+Jerusalem (GroenLin)
+Jerusalem (Math 86)
+Jerusalem (Moctezum)
+Jerusalem (Mozart)
+Jerusalem (Mule)
+Jerusalem (Mummy 21)
+Jerusalem (System 9)
+Jerusalem (TelManeh)
+Jerusalem (Timor)
+Jerusalem (Tobacco)
+Jerusalem (Westwood)
+Jerusalem (Yellow)
+Jerusalem (Zerotime)
+Jerusalem (ZipEater)
+Joker-01
+Jos
+July (1201)
+Junior
+Justice
+K-4B
+K-Lame
+KO (Birdie)
+Kalah (499)
+Kamikaze
+Kampana (3445)
+Kaszana
+Kela (690)
+Kemerovo
+Key Bug (1596)
+Key Bug (1720)
+Key Bug (907)
+KeyDrop
+Keypress (1721)
+Keypress (1744)
+Kiev (2048)
+Kiev Boot
+Kilroy
+Kiwi (550)
+Kode 4
+Kot
+Kremikov
+Kudepsta
+Kukac (Nagytud)
+Kukac (Turbu)
+Kuku
+LPT Off
+LV
+Laufwerk
+Lazy
+Leapfrog
+Leech
+Lehigh
+Leningrad (543)
+Leningrad (600)
+Leprosy (A)
+Leprosy (Silver $)
+Lesson I
+Lesson II (358)
+Lev
+Liberty
+Lippi
+Liquid (762)
+Little Brother (361)
+Little Pieces
+Log
+Logi-Nator
+Loren
+Lower Case
+Lyceum (1788)
+Lythyum
+MG (5)
+MH-757
+MPHTI
+MPS-OPC (3.2)
+MPS-OPC (Slow Load)
+MSJ (19 Space)
+MSK (B)
+MSK (Blaze)
+MSTU (554)
+MShark (889)
+MVF (1)
+MVF (2)
+MX (14C)
+Macedonia
+Made (255)
+Made (334)
+Madismo
+Maffy (491)
+Magnitogorsk (2048B)
+Magnitogorsk II
+Malaga
+Malaise
+Malign (630)
+Maltese Amoeba (B)
+Mannequin
+Marauder (560)
+Marauder (860 B)
+Matura
+Maxwell
+Mayak (2370)
+Medical
+Meditation
+Meta
+Metallic (1739)
+Michaelangelo
+Micro 128
+Micro Cops
+Microbes
+Mierda
+Milan (BadGuy)
+Milan (Exterminator)
+Milan (New BadGuy)
+MiniMax
+Minsk Ghost
+Mirror
+Mithrandir
+Mix-2
+Mono
+Month 4-6 (A)
+Mr. G
+MtE (Insuff)
+MugShot
+Multi (A)
+Multi (B)
+MultiFace
+Munich
+Murphy (Amilia)
+Murphy (Bad Taste)
+Murphy (Delyrium A)
+Murphy (Delyrium B)
+Murphy (Diabolik)
+Murphy (Erasmus)
+Murphy (Goblin)
+Murphy (Kamasya)
+Murphy (Locker)
+Murphy (Migram)
+Murphy (Pest)
+Murphy (Smack A)
+Murphy (Smack B)
+Murphy (Swami)
+Music Bug
+Mut Int
+Mutator (459)
+Mutator (780)
+Mystic
+NCU LI
+NG
+NJH2LBC
+NOT (586)
+Nabob
+Nanite
+Nazgul
+Necropolis
+Necros
+Nice Day
+Nika
+Nina
+Nines Comp (705)
+Nines Comp (766)
+Ninja
+No Bock
+No Frills
+Nomenklatura
+Noon Beep
+November Xth (584)
+November Xth (706)
+November Xth (768 A)
+November Xth (768 B)
+November Xth (855)
+November Xth (880)
+Npox (1686)
+Npox (963)
+Null
+Number (AIDS)
+Old Yankee (Bandit)
+Old Yankee (Enigma)
+Old Yankee (Peter)
+Omega
+On 64
+Ondra
+Ontario
+Orion (365)
+Oropax
+Otto (640)
+Oxana
+PC-Flu (802)
+PC-Flu 2
+PCBB (2277)
+PCBB (3072 B)
+PDP-11
+PS-MPC Related
+PSV
+Padded
+Paramon
+Paris
+Parity Boot
+Parity Boot (B)
+Pascal (3072 B)
+Pascal (7808)
+Password
+PathHunt
+Peach
+Pentagon
+Perfume (Blank)
+Perfume (Sorry)
+Phalcon (Elvis)
+Phantom
+Phoenix (1226)
+Phoenix (Proud)
+Picket (1034)
+Pif-Paf
+Pilgrim
+Ping-Pong
+Pitch
+Piter
+Pixel (936)
+Pixel (Cancer)
+Pixel (Pixie)
+Pixel (Rosen)
+Plovdiv (1.1)
+Plovdiv (1.3 B)
+Plutto
+Pojer (1949)
+Poledne
+Polimer
+Polish Tiny (158)
+Porridge
+Possessed (2446 B)
+Power Pump (1)
+Prague (Blinker)
+Prague (Shaker)
+Pregnant
+Prime
+Print Monster
+Print Screen Boot
+Problem (863)
+Protect (2535)
+Proto_T (Lokjaw)
+PrtScr
+Prudents
+QMU (1513)
+Qrry
+Quake
+Quiet
+Quit-1992
+Quox
+RNA (1)
+RNA (2)
+Rape (Basilisk)
+RaubKopie (1888)
+RaubKopie (2219)
+Reboot
+Red Diavolyata (830)
+RedStar
+Reklama
+Relzfu
+Requires
+Revenge T
+Revolution
+Riluttanza
+Rob (A)
+Rob (B)
+Runtime
+Rush Hour
+Russian Mirror
+Russian Tiny (131)
+Russian Tiny (C 150)
+Russian Tiny (F 143)
+Rust
+Ryazan
+Rythem (1992)
+SBC
+SD-123
+SHHS (A)
+SI-492
+SVC (1.0)
+SVC (3.1)
+SVC (4.0 1740)
+SVC (6.0 4644)
+SVC (6.0 4677)
+SVir
+Saigon
+Sat War
+Saturday 14th
+Sccheck
+Scoundrel
+Screaming (Nu-Way)
+Screaming (Stranger)
+Screaming Fist (A)
+Screen + 1
+Scythe
+Seacat
+Sector 0
+Semtex (A)
+Semtex (D)
+Sentinel (4636)
+Sentinel (5402)
+Shadowbyte (723)
+Shake (A)
+Shaman
+Shanghai
+Shiet
+Shifter
+Shirley (A)
+Shirley (Vivaldi)
+Silent Night
+Silly Willy
+SillyCR (397)
+Simple
+Simulate
+Sinep
+Siskin (GoodBye 948)
+Siskin (Hero 394)
+Siskin (Resurrect)
+Sistor (2380)
+Sistor (2630)
+Skew
+SleepWalker
+Slimfast
+Slovakia (4)
+Slow Format
+Slowdown
+Slowlite
+Small (409)
+Small 2
+Small V
+Smiley Boot
+Socha
+Soft
+Sonik
+Sparse
+Spawn (3824)
+Spring
+Squawk
+Squeaker
+Squisher
+Staf
+Stahlplatte
+Stanco
+StarDot (600)
+StarDot (801)
+Starship
+Stasi
+Stealth Boot
+StinkFoot
+StinkFoot 2
+Stone (EmpireBotany)
+Stoned (Alive)
+Stoned (Anti-CMOS)
+Stoned (Bunny)
+Stoned (Cagstone)
+Stoned (Comx)
+Stoned (Dinamo)
+Stoned (Duran)
+Stoned (Empire)
+Stoned (Face)
+Stoned (Gullion)
+Stoned (June 4th)
+Stoned (Monkey)
+Stoned (Murgas)
+Stoned (NoInt)
+Storm
+Strange
+Striker
+Stupid
+Suomi
+SuperHacker
+Suriv 1 (Anti-D)
+Suriv 1 (April 1st)
+Suriv 1 (Argentina)
+Surrender
+Swe (Data Molester)
+Swedish (Headache)
+Swedish (Surfer)
+Swiss 143
+Swiss Boot
+Swiss Phoenix
+Sylvia (B)
+Syslock (Advent)
+Syslock (Cookie)
+TCKit 1.00
+TCKit 2.00
+TCS
+TP Worm TPE Related
+TU (482)
+TUQ
+TV
+Tabulero
+Tack
+Tagutil
+Taiwan (708)
+Taiwan (743)
+Talking Heads
+Tankard (556)
+Tchantches
+Teacher
+Techno
+Ten Bytes
+Ten Past 3 (A)
+Ten Past 3 (B)
+Tequila
+Terminator (918)
+Terminator II
+Terror (Dark Lord)
+Terror (Terror)
+Test-B
+Thanksgiving
+Thirteen Minutes
+Thrasher
+Thule
+Thursday
+Tic
+TimeMark (1062)
+TimeMark (1076)
+TimeMark (1083)
+Timeslice
+Timid (306)
+Tiny (198)
+Tiny (Ghost)
+Tiny-DI (101)
+Tiny-DI (110)
+Tiny-DI (127)
+Tiny-GM
+Tired
+Tiso
+Todor
+Tokyo
+Tolbuhin (1004)
+Tolbuhin (1147)
+Tolbuhin (992)
+Tolbuhin (Cracky)
+Tony (A)
+Tony (B)
+Tony Boot (A)
+Tony Boot (B)
+Tonya
+Traceback
+Traceback (3029)
+Trash
+Traveler Jack (979)
+Traveler Jack (982)
+Tremor
+Trivial (Banana)
+Trivial (Explode)
+Trivial (Hanger)
+Trivial (Hastings)
+Trivial (NKOTB)
+Trivial (Wolverine)
+Troi II
+Trojan AIDS
+Trojan AirCop
+Trojan Anthrax
+Tula
+Tula II
+Tumen (1.2)
+Turn
+Tver
+Twelve Tricks
+Twin
+USSR 707
+Ufa
+Ugur
+Unexe
+Ungame (766)
+Uruk-Hai
+V2P1\V2P2
+V2P6
+V3000
+VCS (Ruf)
+VComm
+VFSI
+VP
+VVF
+Vacsina (16)
+Vacsina (4)
+Vacsina (5)
+Vacsina (6)
+Vacsina (Mutant)
+Vacsina (Penza 1210)
+Vacsina (Penza 700)
+Vacsina EXE Loader
+Vampirus
+Vengence (A)
+Vengence (B)
+Vengence (C)
+Vengence (D)
+Vengence (E)
+Vengence (F)
+Victor
+Vienna (644 A)
+Vienna (BetaBoys)
+Vienna (Choinka)
+Vienna (Com2Con)
+Vienna (Dr. Qumak)
+Vienna (Hybryd 1306)
+Vienna (Interceptor)
+Vienna (Kiev)
+Vienna (Lisbon)
+Vienna (SicilianMob)
+Vienna (Slovakia)
+Vienna (Viperize)
+Vindicator
+Violetta (1024)
+Violetta (3840)
+VirDem (824)
+VirDem (DiskTrash)
+VirDem (Irus)
+Virdemo
+Virus-101
+Virus-90
+Vmem
+Voice
+Void Poem
+Volga
+Voodoo
+Voronezh (1600)
+Voronezh (370)
+Voronezh (600)
+Voronezh (650)
+Vorpal
+Vote
+Vriest
+WVP
+WWT (125)
+WWT (263)
+Walker
+Wanderer
+Warpcom (1)T
+Warpcom (2)T
+Wave
+We're Here
+Weak
+Whale
+Wharps
+Whirl
+Wilbur
+Wildy
+Willow
+WinVir
+Windmill
+Wisconsin
+Witcode
+Wolfcheat
+Wolfman
+Wonder
+WordSwap (1069\1085)
+WordSwap (Kiev)
+Worm 17690
+Worthless (A)
+Worthless (B)
+X-1 (562)
+X-1 (570)
+X-2
+X-Boot
+X-Fungus (A)
+XA1
+XAM
+Yafo
+Yale
+Yankee Doodle (2505)
+Yankee Doodle (XPEH)
+Yaunch
+YearBak
+Yeke (1076)
+Yeke (1204)
+Yeke (2425)
+Youth (512)
+Youth (640)
+Youth (968)
+Yukon
+Zero Bug
+Zero Hunter (B)
+Zharinov
+Zherkov (1018\1023)
+Zherkov (1882)
+Zherkov (1915)
+Zherkov (1940)
+Zherkov (1958)
+Zherkov (2968)
+Zherkov (2970)
+ZigZag
+Ziuck (1279)
+Ziuck (1372)
+Zombie
diff --git a/src/doors/vbbs/src/GNUmakefile b/src/doors/vbbs/src/GNUmakefile
new file mode 100755
index 0000000000000000000000000000000000000000..7842e1b4b71fb95cba7fbc5e1a5fdf785ef7b98b
--- /dev/null
+++ b/src/doors/vbbs/src/GNUmakefile
@@ -0,0 +1,66 @@
+#
+#  Virtual BBS makefile
+#
+##################################
+
+O	     = ./obj
+
+VPATH	 = .:linux
+
+# define tools
+CC = gcc
+LD = gcc
+RC = rc
+RM = rm -f
+MV = mv -f
+CP = cp
+
+BUILD ?= release
+
+TARGET = ./bin/vbbs
+
+#		  ${O}/mx_file.o \
+
+OBJS	=  ${O}/v3_basic.o ${O}/v3_hack.o ${O}/v3_io.o ${O}/v3_learn.o ${O}/v3_mail.o ${O}/v3_maint.o ${O}/v3_mci.o ${O}/v3_store.o ${O}/vbbsutil.o ${O}/vbbs.o ${O}/vbbs_db.o ${O}/filewrap.o
+
+LIBS	= ../lib/libODoors.a
+
+ifeq (${BUILD},debug)
+    CFLAGS    = -g -Wall -O -I. -I../include
+    CPPFLAGS  = -g -Wall -O -I. -I../include
+    LDFLAGS   = -g 
+	QUIET	:=
+else
+    CFLAGS    = -O2 -Wall -fno-common -fomit-frame-pointer -I. -I../include
+    CPPFLAGS  = -O2 -Wall -fno-common -fomit-frame-pointer -fno-exceptions -fno-rtti -I. -I../include
+    LDFLAGS   = 
+	QUIET	:=	@
+endif
+
+.PHONY : all run ${TARGET}
+.SUFFIXES: .c
+
+all: ${TARGET}
+
+bin:
+	mkdir bin
+
+obj:
+	mkdir obj
+
+${TARGET}: bin obj ${OBJS} ${LIBS}
+	@echo linking $@
+	${QUIET}${LD} ${LDFLAGS} ${OBJS} ${LIBS} -o ${TARGET}
+	${QUIET}${CP} ${TARGET} ../build
+
+clean:
+	@echo Cleaning up...
+	${QUIET}${RM} ${O}/*.o ${TARGET}
+
+${O}/%.o : %.c
+	@echo Compiling $<
+	${QUIET}${CC} -c ${CFLAGS} $< -o $@
+
+${O}/%.o : %.cpp
+	@echo $<
+	${QUIET}${CC} -c ${CPPFLAGS} $< -o $@
diff --git a/src/doors/vbbs/src/Makefile b/src/doors/vbbs/src/Makefile
new file mode 100755
index 0000000000000000000000000000000000000000..346dac4de2e21089f55f9b7804af22ae99b7b90d
--- /dev/null
+++ b/src/doors/vbbs/src/Makefile
@@ -0,0 +1,18 @@
+#
+#  VS3 makefile
+#
+##################################
+
+PLAT ?= dos
+
+ifeq ($(PLAT), dos)
+    include Makefile.dos
+endif
+
+ifeq ($(PLAT), win32)
+    include Makefile.win32
+endif
+
+ifeq ($(PLAT), linux)
+	include Makefile.linux
+endif
diff --git a/src/doors/vbbs/src/Makefile.bc45 b/src/doors/vbbs/src/Makefile.bc45
new file mode 100755
index 0000000000000000000000000000000000000000..07f23d4db25987e10a3984692003a2fe4ec3dd91
--- /dev/null
+++ b/src/doors/vbbs/src/Makefile.bc45
@@ -0,0 +1,82 @@
+#
+#  Virtual BBS makefile
+#
+##################################
+
+O	     = ./obj
+
+# define tools
+CC = bcc
+LD = tlink
+
+RM = rm -f
+MV = mv -f
+CP = cp
+
+BUILD ?= release
+
+TARGET = vbbs.exe
+EDITOR = vbbsedit.exe
+
+
+OBJS = \
+		mx_file.obj \
+	   	v3_basic.obj \
+	   	vbbs_db.obj \
+       	v3_hack.obj \
+       	v3_io.obj \
+       	v3_learn.obj \
+       	v3_mail.obj \
+		v3_maint.obj \
+       	v3_mci.obj \
+       	v3_store.obj \
+       	vbbsutil.obj \
+       	vbbs.obj
+
+EOBJS = \
+		v3_cfg.obj \
+        v3_mci.obj \
+        mx_file.obj \
+        v3_io.obj \
+		v3_basic.obj
+
+!if $d(VS3_DEBUG)
+    CFLAGS  = -2 -c -v -mm -f287 -ff- -w -M -RT- -x- -I../include
+    LDFLAGS = /v
+!else
+    CFLAGS  = -2 -O1 -c -mm -f287 -ff- -w -M -RT- -x- -I../include
+    LDFLAGS =
+!endif
+
+#.SILENT:
+
+all: $(TARGET) $(EDITOR)
+
+bin:
+	mkdir bin
+
+obj:
+	mkdir obj
+
+$(TARGET): $(OBJS)
+	echo linking $@
+	$(CP) ../lib/odoorm.lib .
+	$(LD) $(LDFLAGS) @link.lst
+	$(CP) $(TARGET) ../build
+
+$(EDITOR): $(EOBJS)
+	echo linking $@
+	$(CP) ../lib/odoorm.lib .
+	$(LD) $(LDFLAGS) c0fm.obj $(EOBJS),$(EDITOR),,odoorm.lib fp87.lib mathm.lib cm.lib
+	$(CP) $(EDITOR) ../build
+
+clean:
+	$(RM) *.obj *.exe *.map *.lib *.OBJ *.EXE *.MAP *.LIB
+
+.asm.obj:
+      $(AS) $(AFLAGS) $&.asm
+.c.obj:
+      $(CC) $(CFLAGS) $&.c
+.cpp.obj:
+      $(CC) $(CFLAGS) $&.cpp
+
diff --git a/src/doors/vbbs/src/Makefile.dos b/src/doors/vbbs/src/Makefile.dos
new file mode 100755
index 0000000000000000000000000000000000000000..b631a0fcce9e5868a435c1e00e6216189e278fe9
--- /dev/null
+++ b/src/doors/vbbs/src/Makefile.dos
@@ -0,0 +1,96 @@
+#
+#  Virtual BBS makefile
+#
+##################################
+
+O	     = ./obj
+
+# define tools
+ifeq ($(COMPILER), borland)
+CC = bcc
+LD = tlink
+else
+CC = cl
+LD = link
+RC = rc
+endif
+
+RM = rm -f
+MV = mv -f
+CP = cp
+
+BUILD ?= release
+
+TARGET = vbbs.exe
+EDITOR = vbbsedit.exe
+
+OBJS = v3_basic.obj \
+       v3_hack.obj \
+       v3_io.obj \
+       v3_learn.obj \
+       v3_mail.obj \
+       v3_mci.obj \
+       v3_store.obj \
+       vbbs.obj
+
+EOBJS = v3_cfg.obj \
+        v3_mci.obj \
+        v3_io.obj \
+		v3_basics.obj \
+
+ifeq ($(COMPILER), borland)
+ifeq ($(BUILD),debug)
+    CFLAGS  = -c -v -f287 -w -I../opendoor
+    LDFLAGS =
+else
+    CFLAGS  = -c -O2 -f287 -w -I../opendoor
+    LDFLAGS =
+endif
+else
+ifeq ($(BUILD),debug)
+    CFLAGS  = /nologo /I../opendoor /AM /W3 /G3 /Zi /FPi87 /c
+    LDFLAGS = /nologo /map /stack:4096 /codeview
+else
+    CFLAGS  = /nologo /I../opendoor /AM /W3 /G3 /O2 /FPi87 /c
+    LDFLAGS = /nologo /map /stack:4096
+endif
+endif
+
+.PHONY : all run $(TARGET) $(EDITOR)
+.SUFFIXES: .c
+
+#.SILENT:
+
+all: $(TARGET) $(EDITOR)
+
+bin:
+	mkdir bin
+
+obj:
+	mkdir obj
+
+#$(O)/ODoor.res : ODRes.rc
+#	$(RC) /fo $@ $<
+
+$(TARGET): $(OBJS)
+	echo linking $@
+	$(CP) ../opendoor/odoor.lib .
+	$(LD) $(LDFLAGS) $(OBJS),$(TARGET),,odoor.lib,nul.def
+	$(CP) $(TARGET) ../build
+
+$(EDITOR): $(EOBJS)
+	echo linking $@
+	$(CP) ../opendoor/odoor.lib .
+	$(LD) $(LDFLAGS) $(EOBJS),$(EDITOR),,odoor.lib,nul.def
+	$(CP) $(EDITOR) ../build
+
+clean:
+	$(RM) *.obj *.exe $(O)/*.obj $(O)/*.res bin/*.map bin/*.pdb bin/*.lib bin/*.exp $(TARGET)
+
+#$(O)/%.obj : %.c
+#	$(CC) $(CFLAGS) $< /Fo$@
+
+%.obj : %.c
+	$(CC) $(CFLAGS) $<
+	$(MV) $@ $@
+
diff --git a/src/doors/vbbs/src/Makefile.win32 b/src/doors/vbbs/src/Makefile.win32
new file mode 100755
index 0000000000000000000000000000000000000000..e460a7240cb6edf8cb45bf712843775890c2422a
--- /dev/null
+++ b/src/doors/vbbs/src/Makefile.win32
@@ -0,0 +1,96 @@
+#
+#  Virtual BBS makefile
+#
+##################################
+
+O	     = ./obj
+
+# define tools
+CC = cl
+LD = link
+RC = rc
+RM = rm -f
+MV = mv -f
+CP = cp
+
+BUILD ?= release
+
+TARGET = ./bin/vbbs32.exe
+
+OBJS += $(O)/mx_file.obj
+OBJS += $(O)/v3_basic.obj
+OBJS += $(O)/vbbs_db.obj
+OBJS += $(O)/v3_hack.obj
+OBJS += $(O)/v3_io.obj
+OBJS += $(O)/v3_learn.obj
+OBJS += $(O)/v3_mail.obj
+OBJS += $(O)/v3_maint.obj
+OBJS += $(O)/v3_mci.obj
+OBJS += $(O)/v3_store.obj
+OBJS += $(O)/vbbsutil.obj
+OBJS += $(O)/vbbs.obj
+
+ifeq ($(BUILD),debug)
+	TYPE      = debug
+    CFLAGS    = /nologo /I../include /MTd /W3 /G6 /GX /Zi /Fm /D "DEBUG" /D "WIN32" /D "_WINDOWS" /c
+    CPPFLAGS  = /nologo /I../include /MTd /W3 /G6 /GX /Zi /Fm /D "DEBUG" /D "WIN32" /D "_WINDOWS" /c
+    LDFLAGS   = ../lib/ODoorW.lib \
+              /NOLOGO /INCREMENTAL:no \
+              /MAP \
+              /DEBUG \
+      	      /MACHINE:I386 \
+    	      /OUT:$(TARGET) \
+      	      /SUBSYSTEM:windows
+
+else
+	TYPE      = release
+    CFLAGS    = /nologo /I../include /MT /W3 /G6 /GX /O2 /Fm /D "RELEASE" /D "WIN32" /D "_WINDOWS" /c
+    CPPFLAGS  = /nologo /I../include /MT /W3 /G6 /GX /O2 /Fm /D "RELEASE" /D "WIN32" /D "_WINDOWS" /c
+    LDFLAGS   = ../lib/ODoorW.lib \
+              /NOLOGO /INCREMENTAL:no \
+              /MAP \
+      	      /MACHINE:I386 \
+    	      /OUT:$(TARGET) \
+      	      /SUBSYSTEM:windows
+endif
+
+.PHONY : all run $(TARGET) REPORT
+.SUFFIXES: .c
+
+.SILENT:
+
+all: $(TARGET)
+
+bin:
+	mkdir bin
+
+obj:
+	mkdir obj
+
+$(O)/ODoor.res : ODRes.rc
+	$(RC) /fo $@ $<
+
+REPORT:
+	echo building $(TYPE)
+
+$(TARGET): bin obj $(OBJS) $(LIBS) REPORT
+	echo linking $@
+	$(LD) $(LDFLAGS) $(OBJS) $(LIBS)
+	$(CP) $(TARGET) ../build
+	$(CP) *.pdb	../build
+
+clean:
+	$(RM) *.obj *.exe $(O)/*.obj $(O)/*.res bin/*.map bin/*.pdb bin/*.lib bin/*.exp $(TARGET)
+
+$(O)/%.obj : %.c
+	$(CC) $(CFLAGS) $< /Fo$@
+
+$(O)/%.obj : %.cpp
+	$(CC) $(CPPFLAGS) $< /Fo$@
+
+%.obj : %.c
+	$(CC) $(CFLAGS) $<
+
+%.obj : %.cpp
+	$(CC) $(CPPFLAGS) $<
+
diff --git a/src/doors/vbbs/src/bc_str.h b/src/doors/vbbs/src/bc_str.h
new file mode 100755
index 0000000000000000000000000000000000000000..acdbcfc04f9f29e6283ec18d721c0dbfddc58781
--- /dev/null
+++ b/src/doors/vbbs/src/bc_str.h
@@ -0,0 +1,7 @@
+#ifndef BC_STR_H
+#define BC_STR_H
+
+/* compatibility for Borland C++ */
+#define strncasecmp(a, b, c) 	strncmpi(a, b, c)
+
+#endif /* BC_STR_H */
diff --git a/src/doors/vbbs/src/link.lst b/src/doors/vbbs/src/link.lst
new file mode 100755
index 0000000000000000000000000000000000000000..9b87ff62e1cc21dd049f9c4873f57d5d17b2c454
--- /dev/null
+++ b/src/doors/vbbs/src/link.lst
@@ -0,0 +1 @@
+c0m.obj v3_basic.obj v3_hack.obj v3_io.obj v3_learn.obj v3_mail.obj v3_mci.obj v3_store.obj v3_maint.obj mx_file.obj vbbs_db.obj vbbsutil.obj vbbs.obj,vbbs.exe,,odoorm.lib fp87.lib mathm.lib cm.lib
diff --git a/src/doors/vbbs/src/v3_basic.c b/src/doors/vbbs/src/v3_basic.c
new file mode 100644
index 0000000000000000000000000000000000000000..abe23392f8a8b5e49d418e230e6781a5ffe38613
--- /dev/null
+++ b/src/doors/vbbs/src/v3_basic.c
@@ -0,0 +1,576 @@
+
+#include <stdarg.h>
+
+#include "vbbs.h"
+#include "v3_defs.h"
+#include "v3_basic.h"
+#include "v3_io.h"
+#include "v3_mci.h"
+
+#if !defined(_MSC_VER) && !defined(__BORLANDC__)
+void strupr(char *text)
+{
+	unsigned int i;
+	for(i=0;i<strlen(text);i++)
+		if(text[i]>='a' && text[i]<='z')
+			text[i]-=32;
+}
+
+void strlwr(char *text)
+{
+	unsigned int i;
+	for(i=0;i<strlen(text);i++)
+		if(text[i]>='A' && text[i]<='Z')
+			text[i]+=32;
+}
+#endif /* !_MSC_VER && !__BORLANDC__ */
+
+void nl()
+{
+	mci("\r\n");
+}
+
+void paws()
+{
+	text("0080");
+	od_get_key(TRUE);
+	mci("\b\b\b\b\b\b\b`0F");
+}
+
+int yesno()
+{
+	char ch;
+	int x;
+
+	text("0081"); /* [Y] */
+	ch = od_get_answer("YN\n\r");
+	if ((ch == 'Y') || (ch == '\n') || (ch=='\r'))
+	{
+		x = TRUE;
+		text("0083"); /* Yes */
+	}
+	else
+	{
+		x = FALSE;
+		text("0084"); /* No */
+	}
+
+	return x;
+}
+
+int noyes()
+{
+	char ch;
+	int x;
+
+	text("0082"); /* [N] */
+	ch = od_get_answer("YN\n\r");
+	if ((ch == 'N') || (ch == '\n') || (ch == '\r'))
+	{
+		x = TRUE;
+		text("0084"); /* No */
+	}
+	else
+	{
+		x = FALSE;
+		text("0083"); /* Yes */
+	}
+
+	return x;
+}
+
+int printfile(char *fname)
+{
+	FILE *fptr;
+	int done=FALSE,cnt=0,x=FALSE;
+	char ttxt[161];
+
+	fptr = fopen(fname,"rt");
+	if (fptr!=NULL)
+ 	{
+		while(fgets(ttxt,161,fptr)!=NULL && !done)
+		{
+			mci(ttxt);
+			cnt++;
+			if(cnt>=20)
+			{
+				mci("~SMMore? ");
+				if (yesno())
+					cnt=0;
+				else
+					done=TRUE;
+			}
+		}
+		x = TRUE;
+	}
+
+	fclose(fptr);
+	return(x);
+}
+
+void center(char *text)
+{
+	int i;
+
+
+	for(i=0;i<(40-(mcistrlen(text)/2));i++)
+		printf(" ");
+	mci(text);
+}
+
+char moreyn()
+{
+	char ch;
+	int i, s = 13;
+
+	mci("~SMMore? [Y]: ");
+	ch = od_get_answer("YN\r\n");
+
+	for(i=0;i<s;i++)
+	{
+		printf("\b \b");
+	}
+
+	if ((ch == '\n') || (ch == '\r'))
+	{
+		ch = 'Y';
+	}
+
+	return ch;
+}
+
+int mcistrset(char *mcstr, int chop)
+{
+	int i,x;
+
+	i=strlen(mcstr);
+	if(mcistrlen(mcstr)>chop){
+		for(x=0;x<chop;x++){
+			if(mcstr[x]=='`'){
+				chop+=3;
+				}
+			}
+		if(x<i)	mcstr[x]='\0';
+		}
+	else{
+		for(x=mcistrlen(mcstr);x<chop;x++){
+			strcat(mcstr," ");
+			}
+		}
+	return 0;
+}
+
+int mcistrrset(char *mcstr, int chop)
+{
+	int i,x;
+	char t1[191];
+
+	i=strlen(mcstr);
+	if(mcistrlen(mcstr)>chop){
+		for(x=0;x<chop;x++){
+			if(mcstr[x]=='`'){
+				chop+=3;
+				}
+			}
+		if(x<i)	mcstr[x]='\0';
+		}
+	else{
+		*t1='\0';
+		for(x=mcistrlen(mcstr);x<chop;x++){
+			strcat(t1," ");
+			}
+		strcat(t1,mcstr);
+		strcpy(mcstr,t1);
+		}
+	return 0;
+}
+
+int mcistrcset(char *mcstr, int chop)
+{
+	int i,x,num,num1;
+	char t1[191];
+
+	i=strlen(mcstr);
+	if(mcistrlen(mcstr)>chop){
+		for(x=0;x<chop;x++){
+			if(mcstr[x]=='`'){
+				chop+=3;
+				}
+			}
+		if(x<i)	mcstr[x]='\0';
+		}
+	else{
+		num=chop-mcistrlen(mcstr);  /*  How many total blanks */
+		num1=(num/2);  /* How many blanks in front */
+		*t1='\0';
+		for(x=0;x<num1;x++){
+			strcat(t1," ");
+			}
+		strcat(t1,mcstr);
+		for(x=num1;x<num;x++){   /* How many blanks in back */
+			strcat(t1," ");
+			}
+		strcpy(mcstr,t1);
+		}
+	return 0;
+}
+
+void new_user()
+{
+	memset(&plyr, 0, sizeof(tUserRecord));
+	plyr.status = USED;
+	plyr.plyrnum = plyrcnt;
+	strcpy(plyr.realname,od_control.user_name);
+	strcpy(plyr.bbsname,od_control.user_name);
+	strcat(plyr.bbsname,"s BBS");
+	plyr.funds = 100;
+	plyr.pacbell_installed = 1;
+	plyr.mspeed.low = 1;
+	plyr.actions = CONFIG_ACTIONS_PER_DAY;
+ 	time(&plyr.laston);
+}
+
+void act_change(int idx, int val, int opflag)
+{
+	switch(idx)
+	{
+		case ACT_NOTHING_HAPPENS:
+            break;
+		case ACT_ADD_FREE_USERS:
+			inum = (s16)(rand_num((plyr.skill_lev+1)*6));
+			s16_2A(1, inum);
+			if (inum>0)
+			{
+				plyr.users_f += inum;
+				if(opflag)
+					text("0850");
+			}
+			upskore(inum);
+			break;
+		case ACT_ADD_PAY_USERS:
+			nl();
+			inum = (s16)(rand_num((s16)((plyr.users_f+1)/5)));
+			s16_2A(1,inum);
+			if (inum>0)
+			{
+				plyr.users_f -= inum;
+				/* users_f is unsigned
+				if (plyr.users_f<0) plyr.users_f=0; */
+				plyr.users_p += inum;
+				if (opflag) text("0851");
+			}
+			upskore(inum);
+			break;
+		case ACT_SUB_FREE_USERS:
+			nl();
+			inum = (s16)(rand_num((s16)((plyr.users_f+1)/10)));
+			s16_2A(1,inum);
+			if (inum>0)
+			{
+				plyr.users_f -= inum;
+				/* users_f is unsigned
+				if (plyr.users_f<0)	plyr.users_f=0; */
+				if (opflag) text("0852");
+			}
+			downskore(inum);
+			break;
+		case ACT_SUB_PAY_USERS:
+			inum = (s16)(rand_num((s16)((plyr.users_p+1)/10)));
+			s16_2A(1,inum);
+			if (inum>0)
+			{
+				plyr.users_p -= inum;
+				/* users_p is unsigned
+				if (plyr.users_p<0)	plyr.users_p=0; */
+				if (opflag) text("0853");
+			}
+            downskore(2);
+			break;
+		case ACT_ADD_FUNDS:
+			/* add the funds to the account */
+			plyr.funds += val;
+			/* display gains */
+			if (opflag)
+			{
+				s32_2C(1, (s32)val);
+				s32_2C(2, (s32)plyr.funds);
+				text("0854");
+			}
+			/* recalc score */
+			upskore(1);
+			break;
+		case ACT_SUB_FUNDS:
+			plyr.funds -= val;
+			if (plyr.funds < 0)
+				plyr.funds = 0;
+            downskore(1);
+			break;
+		case ACT_UPGRADE_CPU:
+			if(plyr.cpu<MAX_CPU){
+				plyr.cpu++;
+				str_2A(1,computer[plyr.cpu].cpuname);
+				if(opflag)
+					text("0855");
+				upskore(plyr.cpu);
+				}
+			else
+				if(opflag)
+					text("0863");
+			break;
+		case ACT_ADD_ACTIONS:
+			plyr.actions+=val;
+            upskore(val/2);
+			break;
+		case ACT_FREE_2_PAY:
+			inum = (s16)(rand_num((s16)((plyr.users_f+1)/5)));
+			s16_2A(1,inum);
+			if (inum>0)
+			{
+				plyr.users_f -= inum;
+				/* users_f is unsigned
+				if(plyr.users_f<0)	plyr.users_f=0; */
+				plyr.users_p += inum;
+				if (opflag) text("0856");
+			}
+			upskore(inum*(plyr.skill_lev+1));
+			break;
+		case ACT_UPGRADE_HD:
+			if(plyr.hd_size<MAX_HD){
+				plyr.hd_size++;
+				str_2A(1,harddrive[plyr.hd_size].hdsize);
+				if(opflag)	text("0857");
+				upskore(plyr.hd_size);
+				}
+			else
+				if(opflag)	text("0863");
+			break;
+		case ACT_DOWNGRADE_CPU:
+			downskore(plyr.cpu);
+			plyr.cpu--;
+			str_2A(1,computer[plyr.cpu].cpuname);
+			if(plyr.cpu<0)	plyr.cpu=0;
+			if(plyr.cpu<1)	text("0858");
+			else			text("0859");
+			break;
+		case ACT_DOWNGRADE_HD:
+			downskore(plyr.hd_size);
+			plyr.hd_size--;
+			str_2A(1,harddrive[plyr.hd_size].hdsize);
+			if(plyr.hd_size<0)	plyr.hd_size=0;
+			if(plyr.hd_size<1)	text("0860");
+			else				text("0861");
+			break;
+		case ACT_DOWNGRADE_MODEM:
+			if(plyr.mspeed.low)	plyr.mspeed.low--;
+			else	if(plyr.mspeed.high)	plyr.mspeed.high--;
+					else	if(plyr.mspeed.digital)	plyr.mspeed.digital--;
+
+			downskore(2);
+			break;
+		case ACT_PHONELINE_DAMAGE:
+			if (plyr.pacbell_installed > 0)
+			{
+				plyr.pacbell_installed--;
+				plyr.pacbell_broke++;
+			}
+			break;
+		}
+}
+
+void downskore(int sk)
+{
+	if (plyr.skore_now > (uint)sk)
+		plyr.skore_now -= sk;
+	else
+		plyr.skore_now = 0;
+}
+
+void upskore(int sk)
+{
+	plyr.skore_now += (s32)sk;
+}
+
+void fillvars()
+{
+	strcpy(harddrive[0].hdsize,"30meg 60ms");
+	strcpy(harddrive[1].hdsize,"100meg 60ms");
+	strcpy(harddrive[2].hdsize,"300meg 16ms");
+	strcpy(harddrive[3].hdsize,"1.2 Gigabytes 11ms");
+	strcpy(harddrive[4].hdsize,"6 GB 3ms");
+	strcpy(harddrive[5].hdsize,"24 GB 3ms");
+	strcpy(harddrive[6].hdsize,"40 GB Autoraid");
+	strcpy(harddrive[7].hdsize,"60 GB Autoraid");
+	strcpy(harddrive[8].hdsize,"120 GB Autoraid");
+	strcpy(harddrive[9].hdsize,"300 GB Autoraid");
+	strcpy(harddrive[10].hdsize,"500 GB Emc2");
+	strcpy(harddrive[11].hdsize,"750 GB Emc2");
+	strcpy(harddrive[12].hdsize,"1.0 Terrabytes  Emc2");
+	strcpy(harddrive[13].hdsize,"5.0 TB  Emc2");
+	strcpy(harddrive[14].hdsize,"25.0 TB  Emc2");
+	strcpy(harddrive[15].hdsize,"75.0 TB  Emc2");
+
+	harddrive[0].cost  = 500L;
+	harddrive[1].cost  = 1000L;
+	harddrive[2].cost  = 2000L;
+	harddrive[3].cost  = 2000L;
+	harddrive[4].cost  = 6000L;
+	harddrive[5].cost  = 8000L;
+	harddrive[6].cost  = 16000L;
+	harddrive[7].cost  = 32000L;
+	harddrive[8].cost  = 64000L;
+	harddrive[9].cost  = 128000L;
+	harddrive[10].cost = 512000L;
+	harddrive[11].cost = 1024000L;
+	harddrive[12].cost = 2048000L;
+	harddrive[13].cost = 4096000L;
+	harddrive[14].cost = 8192000L;
+	harddrive[15].cost = 16000000L;
+
+	harddrive[0].req=0;
+	harddrive[1].req=0;
+	harddrive[2].req=1;
+	harddrive[3].req=1;
+	harddrive[4].req=2;
+	harddrive[5].req=3;
+	harddrive[6].req=3;
+	harddrive[7].req=4;
+	harddrive[8].req=5;
+	harddrive[9].req=6;
+	harddrive[10].req=7;
+	harddrive[11].req=8;
+	harddrive[12].req=9;
+	harddrive[13].req=10;
+	harddrive[14].req=11;
+	harddrive[15].req=12;
+
+	strcpy(computer[0].cpuname,"8MHz XT clone with 512k RAM");
+	strcpy(computer[1].cpuname,"12MHz 286 with 1Meg ");
+	strcpy(computer[2].cpuname,"25MHz 386 with 4Meg ");
+	strcpy(computer[3].cpuname,"50MHz 486 with 8Meg ");
+	strcpy(computer[4].cpuname,"99MHz 586 with 16Meg");
+	strcpy(computer[5].cpuname,"166MHz Pentium with 32Meg");
+	strcpy(computer[6].cpuname,"320MHz PII with 64Meg");
+	strcpy(computer[7].cpuname,"512MHz PIII with 128Meg");
+	strcpy(computer[8].cpuname,"Mini v1");
+	strcpy(computer[9].cpuname,"Mini v11");
+	strcpy(computer[10].cpuname,"Midrange 9000");
+	strcpy(computer[11].cpuname,"2 Node Cluster (Midrange) ");
+	strcpy(computer[12].cpuname,"8 Node Cluster (Midrange) ");
+	strcpy(computer[13].cpuname,"Enterprise 10000");
+	strcpy(computer[14].cpuname,"2 Node Cluster (Enterprise)");
+	strcpy(computer[15].cpuname,"8 Node Cluster (Enterprise)");
+
+	computer[0].cost  = 0L;
+	computer[1].cost  = 1000L;
+	computer[2].cost  = 2000L;
+	computer[3].cost  = 4000L;
+	computer[4].cost  = 8000L;
+	computer[5].cost  = 16000L;
+	computer[6].cost  = 32000L;
+	computer[7].cost  = 64000L;
+	computer[8].cost  = 128000L;
+	computer[9].cost  = 256000L;
+	computer[10].cost = 512000L;
+	computer[11].cost = 1024000L;
+	computer[12].cost = 2048000L;
+	computer[13].cost = 4096000L;
+	computer[14].cost = 8192000L;
+	computer[15].cost = 16284000L;
+
+	strcpy(mtype[0].modemname,"Cheap 2400");
+	strcpy(mtype[1].modemname,"Good 2400");
+	strcpy(mtype[2].modemname,"2400 v.42bis");
+	strcpy(mtype[3].modemname,"9600");
+	strcpy(mtype[4].modemname,"9600 v.32");
+	strcpy(mtype[5].modemname,"9600ds");
+	strcpy(mtype[6].modemname,"14.4kbps v.32bis");
+	strcpy(mtype[7].modemname,"19.2kbps v.90");
+	strcpy(mtype[8].modemname,"28.0kbps v.90");
+	strcpy(mtype[9].modemname,"56kbps");
+
+	mtype[0].cost = 80L;
+	mtype[1].cost = 160L;
+	mtype[2].cost = 320L;
+	mtype[3].cost = 640L;
+	mtype[4].cost = 1280L;
+	mtype[5].cost = 5120L;
+	mtype[6].cost = 10240L;
+	mtype[7].cost = 20480L;
+	mtype[8].cost = 40960L;
+	mtype[9].cost = 81960L;
+
+	mtype[0].req=0;
+	mtype[1].req=0;
+	mtype[2].req=0;
+	mtype[3].req=1;
+	mtype[4].req=3;
+	mtype[5].req=5;
+	mtype[6].req=7;
+	mtype[7].req=9;
+	mtype[8].req=11;
+	mtype[9].req=13;
+
+	strcpy(bbssw[0].bbsname,"Renegard");
+	strcpy(bbssw[1].bbsname,"WWIII");
+	strcpy(bbssw[2].bbsname,"RemoteEntry");
+	strcpy(bbssw[3].bbsname,"WildeKat!");
+	strcpy(bbssw[4].bbsname,"Excalibur");
+	strcpy(bbssw[5].bbsname,"Majorr BBS");
+	strcpy(bbssw[6].bbsname,"TSX-Online");
+	strcpy(bbssw[7].bbsname,"Mindwire");
+	strcpy(bbssw[8].bbsname,"Compu$erver");
+	strcpy(bbssw[9].bbsname,"Another On-Line");
+
+	bbssw[0].cost = 50L;
+	bbssw[1].cost = 300L;
+	bbssw[2].cost = 1800L;
+	bbssw[3].cost = 6000L;
+	bbssw[4].cost = 36000L;
+	bbssw[5].cost = 180000L;
+	bbssw[6].cost = 600000L;
+	bbssw[7].cost = 3600000L;
+	bbssw[8].cost = 18000000L;
+	bbssw[9].cost = 60000000L;
+
+	bbssw[0].req=0;
+	bbssw[1].req=0;
+	bbssw[2].req=1;
+	bbssw[3].req=2;
+	bbssw[4].req=5;
+	bbssw[5].req=7;
+	bbssw[6].req=9;
+	bbssw[7].req=11;
+	bbssw[8].req=13;
+	bbssw[9].req=15;
+
+	bbssw[0].numlines = 1L;
+	bbssw[1].numlines = 2L;
+	bbssw[2].numlines = 16L;
+	bbssw[3].numlines = 32L;
+	bbssw[4].numlines = 64L;
+	bbssw[5].numlines = 256L;
+	bbssw[6].numlines = 1024L;
+	bbssw[7].numlines = 8192L;
+	bbssw[8].numlines = 51200L;
+	bbssw[9].numlines = 100000L;
+
+	strcpy(skill_txt[0],"Absolute Beginner");
+	strcpy(skill_txt[1],"Beginner");
+	strcpy(skill_txt[2],"Novice");
+	strcpy(skill_txt[3],"Average");
+	strcpy(skill_txt[4],"Above Average");
+	strcpy(skill_txt[5],"Expert");
+	strcpy(skill_txt[6],"Expert Master");
+	strcpy(skill_txt[7],"Guru");
+	strcpy(skill_txt[8],"Fountain of Modem Knowledge");
+	strcpy(skill_txt[9],"Sysop");
+
+	scant[0]=30;
+	scant[1]=60;
+	scant[2]=90;
+	scant[3]=120;
+	scant[4]=240;
+	scant[5]=300;
+
+	CONFIG_ACTIONS_PER_DAY=100;
+}
diff --git a/src/doors/vbbs/src/v3_basic.h b/src/doors/vbbs/src/v3_basic.h
new file mode 100755
index 0000000000000000000000000000000000000000..91035283078f3129b1c43f1ff00e363374c8ce68
--- /dev/null
+++ b/src/doors/vbbs/src/v3_basic.h
@@ -0,0 +1,29 @@
+#ifndef VBBS_BASIC_H
+#define VBBS_BASIC_H
+
+#include <time.h>
+
+#if !defined(_MSC_VER) && !defined(__BORLANDC__)
+void strupr(char *text);
+void strlwr(char *text);
+#endif /* !_MSC_VER && !__BORLANDC__ */
+
+int exist(char *fname);
+void nl(void);
+void paws(void);
+int yesno(void);
+int noyes(void);
+int printfile(char *fname);
+void center(char *text);
+int tm_copy(struct tm *fr, struct tm *to);
+char moreyn(void);
+int mcistrset(char *mcstr, int chop);
+int mcistrrset(char *mcstr, int chop);
+int mcistrcset(char *mcstr, int chop);
+void new_user(void);
+void act_change(int idx, int val, int opflag);
+void downskore(int sk);
+void upskore(int sk);
+void fillvars(void);
+
+#endif /* VBBS_BASIC_H */
diff --git a/src/doors/vbbs/src/v3_cfg.c b/src/doors/vbbs/src/v3_cfg.c
new file mode 100644
index 0000000000000000000000000000000000000000..893e52119f45b4c8fd8ed878d6b3ece9afd3c6dd
--- /dev/null
+++ b/src/doors/vbbs/src/v3_cfg.c
@@ -0,0 +1,438 @@
+/*****************************************************************************
+ *
+ * File ..................: v3_cfg.c
+ * Purpose ...............: Game Configuration
+ * Last modification date : 30-Sept-2000
+ *
+ *****************************************************************************
+ * Copyright (C) 1999-2000
+ *
+ * Darryl Perry		FIDO:		1:211/105
+ * Sacramento, CA.
+ * USA
+ *
+ * This file is part of Virtual BBS.
+ *
+ * This Game is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Virtual BBS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Virutal BBS; see the file COPYING.  If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *****************************************************************************/
+
+#include <math.h>
+
+#include "vbbs.h"
+#include "v3_defs.h"
+#include "v3_cfg.h"
+#include "v3_io.h"
+#include "v3_mci.h"
+#include "v3_basic.h"
+
+/* this fixes "floating point formats not linked" run-time error */
+#if defined(__BORLANDC__)
+extern _floatconvert;
+#pragma extref _floatconvert
+#endif /* defined(__BORLANDC__) */
+
+/* from v3_defs.h */
+int16   actcount,
+		vircount,
+		vtxtcount,
+		vlcnt,
+		plyrcnt,
+		msgsrcount,
+		subscribe_arrive,
+		CONFIG_ACTIONS_PER_DAY,
+		inum, inum2,
+		virusscan,
+		chatstat;
+int16 	scant[6];
+char 	LG, TS[81];
+
+char 	gamedir[_MAX_PATH];
+
+tUserRecord plyr, othr, tmpplyr;
+tUserIdx	UsersIdx[MAX_USERS];
+hackrec 	hacker;
+
+hdtype  	harddrive[MAX_HD];
+cputype 	computer[MAX_CPU];
+modemtype  	mtype[MAX_MODEM];
+bbstype 	bbssw[20];
+char		skill_txt[10][30];
+
+void main(int argv, char *argc[])
+{
+	char ch1;
+	int done=0;
+
+	init(argv,argc);
+
+	while(!done){
+		mci("~SCVirtual BBS's REAL sysop menu~SM");
+		mci("~SM(A) Player Editor");
+		mci("~SM(Q) Quit");
+		mci("~SMCommand: ");
+		ch1=od_get_answer("AQ");
+		switch(ch1){
+			case 'A':
+				pickplyr();
+				break;
+			case 'Q':
+				mci("~SM~SMExiting Sysop Menu...~SM~SM");
+				done=1;
+				break;
+        	}
+        }
+}
+
+
+void plyredit(int i)
+{
+	int x, done=0;
+	char ch, ttxt[512];
+	char laston_str[64];
+
+	plyrcnt=0;
+	while(readplyr(&othr,plyrcnt++));
+	plyrcnt--;
+
+	readplyr(&othr,i);
+	strftime(laston_str, 64, "%m/%d/%Y %H:%M", localtime(&othr.laston));
+
+	while(!done)
+	{
+		od_clr_scr();
+		mci("`0EVirtual BBS");
+		mci("~SCPùLùAùYùEùR  EùDùIùTùOùR~SM~SM");
+		mci("#%02d/%02d ~SM",
+			othr.plyrnum+1,
+			plyrcnt);
+		mci("`0FRealname   `0F: %-30s      Last on     `0F: %s~SM",
+			othr.realname,
+			laston_str);
+		mci("~SM(A) Sysop Name : %-32s (F) Level       : %d",
+			othr.sysopname,othr.skill_lev);
+		mci("~SM(B) BBS Name   : %-32s (G) Score       : %ld",
+			othr.bbsname,othr.skore_now);
+		mci("~SM(C) Computer   : (%2d) %-27.27s (H) Actions     : %d",
+			othr.cpu+1,computer[othr.cpu].cpuname,othr.actions);
+		mci("~SM(D) Storage    : %-32s (I) Money       : %1.0f",
+			harddrive[othr.hd_size].hdsize,othr.funds);
+		mci("~SM(E) BBS S/W    : %-32s",bbssw[othr.bbs_sw].bbsname);
+		mci("~SM~SMPhone Lines:                 Modems:                     Security:");
+        mci("~SM(K) Installed  : %-11d (N) Low speed : %-11d (R) CallerID    : %d",
+			othr.pacbell_installed,othr.mspeed.low,othr.callid);
+		mci("~SM(L) Ordered    : %-11d (O) High Speed: %-11d (R) Insurance   : %d",
+			othr.pacbell_ordered,othr.mspeed.high,othr.insurance);
+		mci("~SM(M) Damaged    : %-11d (P) Digital   : %-11d (T) Alarm       : %d",
+			othr.pacbell_broke,othr.mspeed.digital,othr.security);
+		mci("~SM~SMEducation:                   Users:                      Empoyees");
+		mci("~SM(U) Public     : %-9.2f (W) Free      : %-11ld (Y) Employees   : %d",
+			othr.education[0],othr.users_f,othr.employees);
+		mci("~SM(V) Private    : %-9.2f (X) Paying    : %-11ld (Z) Action      : %d",
+			othr.education[1],othr.users_p,othr.actions);
+		mci("~SM~SMCommand : ");
+
+		ch=od_get_answer("1ABCDEFGHIJKLMNOPQRSTUVWXYZ[]");
+		nl();nl();
+		switch(ch){
+			case 'A':
+				mci("~SMNew Sysop Name: ");
+				*ttxt='\0';
+				od_input_str(ttxt,30,32,126);
+				if(strlen(ttxt)>0)
+					strcpy(othr.sysopname,ttxt);
+				break;
+			case 'B':
+				mci("~SMNew BBS Name: ");
+				*ttxt='\0';
+				od_input_str(ttxt,30,32,126);
+				if(strlen(ttxt)>0)
+					strcpy(othr.bbsname,ttxt);
+				break;
+			case 'C':
+				mci("~SM~SMSelect new Computer.~SM");
+				for(x=0;x<MAX_CPU;x++){
+					mci("%-2d %s~SM",x,computer[x].cpuname);
+					}
+				mci("~SMPick One (0-%d) : ",MAX_CPU-1);
+				*ttxt='\0';
+				od_input_str(ttxt,2,'0','9');
+				othr.cpu=atoi(ttxt);
+				break;
+			case 'D':
+				mci("~SM~SMSelect new Storage.~SM");
+				for(x=0;x<MAX_HD;x++){
+					mci("%-2d %s~SM",x,harddrive[x].hdsize);
+					}
+				mci("~SMPick One (0-%d) : ",MAX_HD-1);
+				*ttxt='\0';
+				od_input_str(ttxt,2,'0','9');
+				othr.hd_size=atoi(ttxt);
+				break;
+			case 'E':
+				mci("~SM~SMSelect new BBS Software.~SM");
+				for(x=0;x<MAX_SW;x++){
+					mci("%-2d %s~SM",x+1,bbssw[x].bbsname);
+					}
+				mci("~SMPick One (0-%d) : ",MAX_SW-1);
+				*ttxt='\0';
+				od_input_str(ttxt,2,'0','9');
+				othr.bbs_sw=atoi(ttxt)-1;
+				break;
+			case 'F':
+				text("New Skill Level: ");
+				*ttxt='\0';
+				od_input_str(ttxt, 2, '0', '9');
+				othr.skill_lev=atoi(ttxt);
+				break;
+			case 'G':
+				text("~SMNew Score: ");
+				*ttxt='\0';
+				od_input_str(ttxt, 5, '0', '9');
+				othr.skore_now=atoi(ttxt);
+				break;
+			case 'H':
+				mci("~SMActions Amount: ");
+				*ttxt='\0';
+				od_input_str(ttxt,10,'0','9');
+				othr.actions=atol(ttxt);
+				break;
+			case 'I':
+				mci("~SMNew Funds Amount: ");
+				*ttxt='\0';
+				od_input_str(ttxt,10,'0','9');
+				othr.funds = (float)atof(ttxt);
+				break;
+			case 'K':
+				mci("~SMInstalled Phone Lines: ");
+				*ttxt='\0';
+				od_input_str(ttxt,5,'0','9');
+				othr.pacbell_installed = atoi(ttxt);
+				break;
+			case 'L':
+				mci("~SMOrdered Phone Lines: ");
+				*ttxt='\0';
+				od_input_str(ttxt,5,'0','9');
+				othr.pacbell_ordered = atoi(ttxt);
+				break;
+			case 'M':
+				mci("~SMDamaged Phone Lines: ");
+				*ttxt='\0';
+				od_input_str(ttxt,5,'0','9');
+				othr.pacbell_broke = atoi(ttxt);
+				break;
+			case 'N':
+				mci("~SMLow Speed Modems: ");
+				*ttxt='\0';
+				od_input_str(ttxt,5,'0','9');
+				othr.mspeed.low = atoi(ttxt);
+				break;
+			case 'O':
+				mci("~SMHigh Speed Modems: ");
+				*ttxt='\0';
+				od_input_str(ttxt,5,'0','9');
+				othr.mspeed.high = atoi(ttxt);
+				break;
+			case 'P':
+				mci("~SMDigital Modems: ");
+				*ttxt='\0';
+				od_input_str(ttxt,5,'0','9');
+				othr.mspeed.digital = atoi(ttxt);
+				break;
+			case 'U':
+				mci("~SMNew Public Education Amount: ");
+				*ttxt='\0';
+				od_input_str(ttxt,6,33,126);
+				othr.education[0] = (float)atof(ttxt);
+				break;
+			case 'V':
+				mci("~SMNew Private Education Amount: ");
+				*ttxt='\0';
+				od_input_str(ttxt,6,33,126);
+				othr.education[1] = (float)atof(ttxt);
+				break;
+			case 'W':
+				mci("~SMFree Users: ");
+				*ttxt='\0';
+				od_input_str(ttxt,10,'0','9');
+				othr.users_f=atoi(ttxt);
+				break;
+			case 'X':
+				mci("~SMPaying Users: ");
+				*ttxt='\0';
+				od_input_str(ttxt,10,'0','9');
+				othr.users_p=atoi(ttxt);
+				break;
+			case 'Y':
+				mci("~SMEmployees: ");
+				*ttxt='\0';
+				od_input_str(ttxt,3,'0','9');
+				othr.employees=atoi(ttxt);
+				if(othr.employees>254)	othr.employees=254;
+				if(othr.employees<1)	othr.employees=0;
+				break;
+			case 'Z':
+				mci("~SMEmployee Actions: ");
+				*ttxt='\0';
+				od_input_str(ttxt,3,'0','9');
+				othr.employee_actions=atoi(ttxt);
+				if(othr.employee_actions>254)	othr.employee_actions=254;
+				if(othr.employee_actions<1)		othr.employee_actions=0;
+				break;
+			case ']':
+				saveplyr(&othr,i);
+				i++;
+				if (i>=plyrcnt)	i=0;
+				readplyr(&othr,i);
+				break;
+			case '[':
+				saveplyr(&othr,i);
+            	i--;
+				if(i<=0)	i=plyrcnt;
+				readplyr(&othr,i);
+				break;
+        	case 'Q':
+				readplyr(&plyr,0);
+				done=1;
+				break;
+			}
+		saveplyr(&othr,i);
+		}
+}
+
+void pickplyr()
+{
+	int page=0,i,pnum,done=0;
+	char ch,ttxt[21],string[121];
+
+	while (!done)
+	{
+		od_clr_scr();
+		mci("~SMPlayer Listings~SM");
+		mci("~SMNum Realname             Handle               BBS Name             Score~SM");
+		od_repeat('\xC4', 78);
+		nl();
+		for(i=0;i<15;i++)
+		{
+			if(readplyr(&othr,i+(page*15))==TRUE)
+			{
+				sprintf(string,"%-3.3d %-20.20s %-20.20s %-20.20s %-ld",
+					othr.plyrnum+1,
+					othr.realname,
+					othr.sysopname,
+					othr.bbsname,
+					othr.skore_now);
+				mci(string);
+			}
+			else
+			{
+				sprintf(string,"%-3.3d %-20.20s %-20.20s %-20.20s %-ld",
+					i+(page*15),
+					"No Record",
+					"",
+					"",
+					0L);
+				mci(string);
+			}
+			nl();
+		}
+		od_repeat('\xC4',78); nl();
+		mci("Player Edit : ]/[=Next/Prev, Q=Quit : ");
+		ch=od_get_answer("AMD[]Q");
+		switch(ch)
+		{
+		case ']':
+			page++;
+			break;
+		case '[':
+			page--;
+			if (page<0) page = 0;
+			break;
+		case 'A':
+			new_user();
+			plyrcnt++;
+			saveplyr(&othr,othr.plyrnum);
+			break;
+		case 'D':
+			nl();
+			mci("Delete which player? : ");
+			*ttxt='\0';
+			od_input_str(ttxt,3,'0','9');
+			pnum=atoi(ttxt)-1;
+			readplyr(&othr,pnum);
+			mci("~SM~SMDelete %s (%s) of %s?",
+				othr.sysopname,othr.realname,othr.bbsname);
+			if(yesno()=='Y'){
+				othr.status=DELETED;
+				saveplyr(&othr,othr.plyrnum);
+				}
+			break;
+		case 'M':
+			mci("~SMModify which player? : ");
+			*ttxt='\0';
+			od_input_str(ttxt,3,'0','9');
+			pnum=atoi(ttxt)-1;
+			plyredit(pnum);
+			break;
+		case 'Q':
+			done=1;
+			break;
+		}
+	}
+}
+
+#ifdef ODPLAT_WIN32
+void init(LPSTR lpszCmdLine, int nCmdShow)
+#else
+void init(int argc, char *argv[])
+#endif
+{
+#ifdef ODPLAT_WIN32
+	strcpy(gamedir, ".\\");
+#else
+	char* ptr;
+	strcpy(gamedir, argv[0]);
+	ptr = strrchr(gamedir, '\\');
+	ptr[1] = 0;
+#endif
+
+	strcpy(od_control.od_prog_name, "Virtual BBS");
+        strcpy(od_control.od_prog_version, "Version 3.10df");
+	strcpy(od_control.od_prog_copyright, "Copyright 1999 by Darryl Perry");
+	strcpy(od_control.od_logfile_name, "vbbs.log");
+	strcpy(od_registered_to, "Darryl Perry");
+	od_parse_cmd_line(argc, argv);
+	od_registration_key = 10664;
+	od_init();
+	vbbs_randomize();
+	fillvars();
+}
+
+void vbbs_randomize()
+{
+	// seed the random number generator
+	srand((unsigned int)time(NULL));
+}
+
+// returns 0 to (num-1)
+int rand_num(int num)
+{
+	float max = (float)num;
+	int rnum;
+
+	rnum = (int)(max*rand()/(RAND_MAX+1.0f));
+
+	return rnum;
+}
+
diff --git a/src/doors/vbbs/src/v3_cfg.h b/src/doors/vbbs/src/v3_cfg.h
new file mode 100755
index 0000000000000000000000000000000000000000..b4d51719aad344789ca0da9f9e6841710c3c2fd8
--- /dev/null
+++ b/src/doors/vbbs/src/v3_cfg.h
@@ -0,0 +1,9 @@
+#ifndef _V3_CFG_H_
+#define _V3_CFG_H_
+
+void sysopmenu(void);
+void plyredit(int i);
+void pickplyr(void);
+
+#endif
+
diff --git a/src/doors/vbbs/src/v3_defs.h b/src/doors/vbbs/src/v3_defs.h
new file mode 100755
index 0000000000000000000000000000000000000000..3c013b1b1783e14fb76a37ab7d954bec9f6d771a
--- /dev/null
+++ b/src/doors/vbbs/src/v3_defs.h
@@ -0,0 +1,38 @@
+#ifndef _V3_DEFS_H_
+#define _V3_DEFS_H_
+
+#define MAX_CPU		15
+#define MAX_HD		15
+#define MAX_SW 	   	10
+#define MAX_SKILL	10
+
+extern s16   actcount,
+		vircount,
+		vtxtcount,
+		vlcnt,
+		plyrcnt,
+		msgsrcount,
+		subscribe_arrive,
+		CONFIG_ACTIONS_PER_DAY,
+		inum, inum2,
+		virusscan,
+		chatstat;
+extern s16 		scant[6];
+extern char 	LG, TS[81];
+
+extern char		gamedir[_MAX_PATH];
+
+extern classtype classes[5];
+
+extern tUserRecord plyr, othr, tmpplyr;
+extern tUserIdx	UsersIdx[MAX_USERS];
+extern hackrec 	hacker;
+
+extern hdtype  	harddrive[MAX_HD];
+extern cputype 	computer[MAX_CPU];
+extern modemtype  	mtype[MAX_MODEM];
+extern bbstype 	bbssw[20];
+extern char		skill_txt[10][30];
+
+#endif
+
diff --git a/src/doors/vbbs/src/v3_hack.c b/src/doors/vbbs/src/v3_hack.c
new file mode 100644
index 0000000000000000000000000000000000000000..1d155c51a12962dbeba4783ef3da4ae687cf8342
--- /dev/null
+++ b/src/doors/vbbs/src/v3_hack.c
@@ -0,0 +1,399 @@
+/*****************************************************************************
+ *
+ * File ..................: v3_hack.c
+ * Purpose ...............: Hacking functions
+ * Last modification date : 30-Sept-2000
+ *
+ *****************************************************************************
+ * Copyright (C) 1999-2000
+ *
+ * Darryl Perry		FIDO:		1:211/105
+ * Sacramento, CA.
+ * USA
+ *
+ * This file is part of Virtual BBS.
+ *
+ * This Game is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Virtual BBS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Virutal BBS; see the file COPYING.  If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *****************************************************************************/
+
+#include "vbbs.h"
+#include "v3_defs.h"
+#include "v3_hack.h"
+#include "v3_io.h"
+#include "v3_mci.h"
+#include "v3_basic.h"
+
+void bribe()
+{
+	char istr[21];
+	s32 tlong;
+
+	text("0550");
+	if(noyes()=='Y')
+	{
+		text("0551");
+		od_input_str(istr,9,'0','9');
+		tlong = atol(istr);
+		if(plyr.funds >= (float)tlong)
+		{
+			plyr.funds -= (float)tlong;
+			s32_2C(1,tlong);
+			text("0552");
+			if(tlong < plyr.education[1]*1000)
+				text("0553");
+			else
+			{
+				text("0554");
+				plyr.education[1] += 0.1f;
+			}
+		}
+		else
+			text("0553");
+	}
+    nl();
+    plyr.actions--;
+    paws();
+}
+
+
+void hacking()
+{
+	int		ii=0, x, mm, nn, oo=0;
+	char	ch;
+
+	text("0580");
+	if((plyr.education[0]+plyr.education[1])>othr.security){
+		s16_2A(1,othr.security);
+		text("0581");
+		ch=od_get_answer("ABCDE");
+		switch(ch){
+			case 'A': text("0582");break;
+			case 'B': text("0583");break;
+			case 'C': text("0584");break;
+			case 'D': text("0585");break;
+			case 'E': text("0586");break;
+			}
+		if((plyr.education[0]+plyr.education[1])>othr.security){
+			ii = rand_num((int)plyr.education[0]+(int)plyr.education[1]);
+			if (ii>othr.security)
+			{
+				text("0587");
+				plyr.actions-=95;
+				switch(ch){
+					case 'A':
+					{
+						int tmp_users = (int)othr.users_f;
+						inum = tmp_users;
+						tmp_users -= rand_num(tmp_users)/6;
+						inum -= tmp_users;
+						othr.users_f = (s32)tmp_users;
+						s16_2A(1,inum);
+						str_2A(2,othr.bbsname);
+						text("0590");
+						break;
+					}
+					case 'B':
+					{
+						int plyr_users = (int)plyr.users_p;
+						int othr_users = (int)othr.users_p;
+						inum = plyr_users;
+						othr_users -= rand_num(othr_users)/6;
+						inum -= plyr_users;
+						othr.users_p = othr_users;
+						s16_2A(1,inum);
+						str_2A(2,othr.bbsname);
+						text("0591");
+						break;
+					}
+					case 'C':
+						othr.security -= 1;
+						if (othr.security < 0)
+							othr.security = 0;
+						break;
+					case 'D':
+						x = rand_num(3);
+						switch(x){
+							case 0:	/* modem */
+								mm = othr.mspeed.low + othr.mspeed.high + othr.mspeed.digital;
+								nn = mm/3;
+								if(nn>1)
+									oo = rand_num(nn);
+								if(oo>othr.mspeed.low && othr.mspeed.low>0)
+									oo=othr.mspeed.low;
+								else{
+									if(oo>othr.mspeed.high &&
+										othr.mspeed.high>0)
+										oo=othr.mspeed.high;
+									else
+										if(oo>othr.mspeed.digital &&
+											othr.mspeed.digital>0)
+											oo=othr.mspeed.digital;
+
+									}
+
+								mci("~SMYour virus send pulses to the modem port, causing them to overheat.");
+								mci("~SMAs a result, %d modems are fried!",oo);
+
+								break;
+							case 1:	/* computer */
+								mci("~SMYour virus causes the computer to go into an endless loop, trying to ");
+								mci("~SMcalculate the value of pi to the nth degree.  It causes the cpu to ");
+								mci("~SMoverheat and finally burst into flames.");
+								othr.cpu=0;
+								break;
+							case 2:	/* HDD */
+								mci("~SMYour virus causes the computer to try to write data to a single spot");
+								mci("~SMon the hard drive over, and over, and over, and over again.  The result");
+								mci("~SMis that the media has been scraped off the disk by the heads.");
+								/* othr.hdd=0; */
+								break;
+							}
+						break;
+					case 'E':
+						break;
+					}
+				}
+			else
+				text("0588");
+		}
+
+		plyr.skore_now+=(ii*2);
+		saveplyr(&plyr,plyr.plyrnum);
+		saveplyr(&othr,othr.plyrnum);
+	}
+
+	mci("~SM~SM");
+}
+
+void burgle()
+{
+	char ch;
+	int done=FALSE;
+
+	text("0535");
+	if(noyes()=='Y'){
+		if(findBBS()==-1)	return;
+		if(plyr.education[1]<=4 || plyr.education[1] <= othr.security){
+			plyr.actions-=75;
+			plyr.funds-=180.0f;
+			text("0536");
+			}
+		else{
+			mci("~CR~CRCongratulations!  You made it in!");
+			while(!done){
+				mci("~CRNow, what do you want to do now?:~CR");
+				mci("A) Take Modems~CR");
+				mci("B) Take Computer~CR");
+				mci("C) Take Hard Drive~CR");
+				mci("D) Take BBS Software~CR");
+				mci("Q) Never mind.~CR");
+				mci("~CRWhich? (A-D, or Q to Quit) : ");
+				ch=od_get_answer("ABCDQ");
+				switch(ch){
+					case 'Q':
+						mci("~CRYou find nothing of value here.~CR");
+						done=TRUE;
+						break;
+					case 'A':
+						break;
+					case 'B':
+						if(plyr.cpu<othr.cpu){
+							plyr.cpu=othr.cpu;
+							othr.cpu=0;
+							mci("~CRYou now have a %s~CR",computer[plyr.cpu].cpuname);
+							done=TRUE;
+							saveplyr(&othr,othr.plyrnum);
+							}
+						else{
+							mci("~CRYou already have better than what you can find in here.");
+							mci("~CRBetter try something else.~CR");
+							}
+						break;
+					case 'C':
+						if(plyr.hd_size<othr.hd_size){
+							plyr.hd_size=othr.hd_size;
+							othr.hd_size=0;
+							mci("~CR~CRYou now have a %s~CR",harddrive[plyr.hd_size].hdsize);
+							done=TRUE;
+							saveplyr(&othr,othr.plyrnum);
+							}
+						else{
+							mci("~CRYou already have better than what you can find in here.");
+							mci("~CRBetter try something else.~CR");
+							}
+						break;
+					case 'D':
+						if(plyr.bbs_sw<othr.bbs_sw){
+							plyr.bbs_sw=othr.bbs_sw;
+							othr.bbs_sw=0;
+							mci("~CR~CRYou now have a %s software package~CR",bbssw[plyr.bbs_sw].bbsname);
+							done=TRUE;
+							saveplyr(&othr,othr.plyrnum);
+							}
+						else{
+							mci("~CRYou already have better than what you can find in here.");
+							mci("~CRBetter try something else.~CR");
+							}
+						break;
+					}
+				}
+			}
+		}
+	else
+		text("0537");
+}
+
+void use_skill()
+{
+	s32_2A(1, plyr.actions);
+	text("0500");
+	switch(od_get_answer("QHBSR"))
+	{
+    case 'Q':
+        nl();nl();
+        return;
+    case 'H':
+        hack();
+        break;
+    case 'B':
+        burgle();
+        break;
+    case 'S':
+        shoplift();
+        break;
+    case 'R':
+        robbank();
+        break;
+  	}
+}
+
+void shoplift()
+{
+	int done=FALSE;
+	char ch;
+
+	text("0510");
+	if(noyes()=='Y'){
+		if(plyr.education[1] >= rand_num(10)){
+			mci("~CR~CRCongratulations!  You made it in!");
+			while(!done){
+				mci("~CRNow, what do you want to do now?:~CR");
+				mci("A) Take Modems~CR");
+				mci("B) Take Computer~CR");
+				mci("C) Take Hard Drive~CR");
+				mci("D) Take BBS Software~CR");
+				mci("Q) Never mind.~CR");
+				mci("~CRWhich? (A-D, or Q to Quit) : ");
+				ch=od_get_answer("ABCDQ");
+				switch(ch){
+					case 'Q':
+						mci("~CRYou find nothing of value here.~CR");
+						done=TRUE;
+						break;
+					case 'A':
+						break;
+					case 'B':
+						if(plyr.cpu<MAX_CPU){
+							plyr.cpu++;
+							mci("~CRYou now have a %s~CR",computer[plyr.cpu].cpuname);
+							done=TRUE;
+							}
+						else{
+							mci("~CRYou already have better than what you can find in here.");
+							mci("~CRBetter try something else.~CR");
+							}
+						break;
+					case 'C':
+						if(plyr.hd_size<MAX_HD){
+							plyr.hd_size++;
+							mci("~CR~CRYou now have a %s~CR",harddrive[plyr.hd_size].hdsize);
+							done=TRUE;
+							}
+						else{
+							mci("~CRYou already have better than what you can find in here.");
+							mci("~CRBetter try something else.~CR");
+							}
+						break;
+					case 'D':
+						if(plyr.bbs_sw<MAX_SW){
+							plyr.bbs_sw++;
+							mci("~CR~CRYou now have a %s software package~CR",bbssw[plyr.bbs_sw].bbsname);
+							done=TRUE;
+							}
+						else{
+							mci("~CRYou already have better than what you can find in here.");
+							mci("~CRBetter try something else.~CR");
+							}
+						break;
+					}
+				}
+			}
+		else{
+			text("0515");
+			plyr.actions-=(150*(plyr.rapsheet+1));
+			plyr.rapsheet++;
+			plyr.funds-=(plyr.funds/2.0f);
+			paws();
+			}
+        }
+    else
+		text("0516");
+	plyr.actions++;
+}
+
+void robbank()
+{
+	text("0520");
+	if (yesno())
+	{
+		plyr.actions = -CONFIG_ACTIONS_PER_DAY;
+		text("0521");
+		paws();
+	}
+	else
+		text("0522");
+}
+
+void hack()
+{
+	int i;
+	float TFloat;
+
+	text("0530");
+	if(yesno()){
+        if(findBBS()==-1)
+			return;
+
+		if(plyr.education[0] >= 1.0 || plyr.education[1]>=1.0){
+			i = rand_num((int)othr.education[0]+(int)othr.education[1]+othr.security+othr.callid);
+			if(i<((int)plyr.education[0]+(int)plyr.education[1]))
+				hacking();
+			else{
+				mci("~CR~CRSorry.  You failed to hack into this BBS.~CR");
+				mci("Their security is just to good for your~CR");
+				mci("level of education.~CR~CR");
+				}
+			}
+		else{
+            plyr.rapsheet++;
+        	plyr.actions-=(plyr.rapsheet*50);
+			plyr.funds-=plyr.funds/2.0f;
+			TFloat=plyr.funds/2.0f;
+			s32_2C(1,(s32)TFloat);
+			text("0531");
+			paws();
+            }
+		}
+}
diff --git a/src/doors/vbbs/src/v3_hack.h b/src/doors/vbbs/src/v3_hack.h
new file mode 100755
index 0000000000000000000000000000000000000000..a536cf8f2d12d46cb92facb51489bc607543262f
--- /dev/null
+++ b/src/doors/vbbs/src/v3_hack.h
@@ -0,0 +1,13 @@
+#ifndef _V3_HACK_H_
+#define _V3_HACK_H_
+
+void bribe(void);
+void hacking(void);
+void burgle(void);
+void use_skill(void);
+void shoplift(void);
+void robbank(void);
+void hack(void);
+
+#endif
+
diff --git a/src/doors/vbbs/src/v3_io.c b/src/doors/vbbs/src/v3_io.c
new file mode 100644
index 0000000000000000000000000000000000000000..a0a16dae4a532ea75f20dff08430f1426686c0fe
--- /dev/null
+++ b/src/doors/vbbs/src/v3_io.c
@@ -0,0 +1,522 @@
+/*****************************************************************************
+ *
+ * File ..................: v3_io.c
+ * Purpose ...............: File I/O routines
+ * Last modification date : 30-Sept-2000
+ *
+ *****************************************************************************
+ * Copyright (C) 1999-2000
+ *
+ * Darryl Perry		FIDO:		1:211/105
+ * Sacramento, CA.
+ * USA
+ *
+ * This file is part of Virtual BBS.
+ *
+ * This Game is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Virtual BBS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Virutal BBS; see the file COPYING.  If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *****************************************************************************/
+
+#include <fcntl.h>
+#include <filewrap.h>
+#include "vbbs.h"
+#include "v3_defs.h"
+#include "v3_io.h"
+#include "v3_mci.h"
+#include "v3_basic.h"
+#ifdef FIXME
+#include "mx_file.h"
+#endif
+
+int fexist(char *fname)
+{
+	FILE *fptr;
+	int x;
+
+	fptr=fopen(fname,"rb");
+	if(fptr==NULL)	x=FALSE;
+	else{
+		x=TRUE;
+		fclose(fptr);
+		}
+	return(x);
+}
+
+int countplyrs()
+{
+	int count = 0;
+	// build the filename
+	char path[_MAX_PATH];
+	sprintf(path,"%susers.vb3",gamedir);
+	// open the file
+	FILE* fptr = fopen(path, "rb+");
+	if (fptr)
+	{
+		fseek(fptr, 0L, SEEK_END);
+		count = ftell(fptr) / sizeof(tUserRecord);
+		fclose(fptr);
+	}
+
+	return count;
+}
+
+int saveplyr(tUserRecord *user, int usernum)
+{
+	FILE *fptr;
+	int x=FALSE;
+	char path[_MAX_PATH];
+
+	sprintf(path,"%susers.vb3",gamedir);
+	fptr=fopen(path,"rb+");
+	if(fptr==NULL){
+		fptr=fopen(path,"wb");
+		x=fwrite(user,sizeof(tUserRecord),1,fptr);
+		}
+	else{
+		if(fseek(fptr,(long)usernum*sizeof(tUserRecord),SEEK_SET)==0)
+			x=fwrite(user,sizeof(tUserRecord),1,fptr);
+		}
+	fclose(fptr);
+	return(x);
+}
+
+int readplyr(tUserRecord* user, int usernum)
+{
+	int rval = TRUE;
+	char path[FILENAME_MAX];
+	FILE* fptr;
+
+	sprintf(path,"%susers.vb3",gamedir);
+	fptr = fopen(path,"rb+");
+	if (fptr)
+	{
+		if (fseek(fptr, (long)usernum*sizeof(tUserRecord), SEEK_SET) == 0)
+			rval = fread(user, sizeof(tUserRecord), 1, fptr);
+		else
+			rval = FALSE;
+		fclose(fptr);
+	}
+	else
+	{
+		rval = FALSE;
+		od_printf("\r\nERROR: Unable to Read User Record!\r\n");
+		memset(user, 0, sizeof(tUserRecord));
+	}
+
+	return rval;
+}
+
+int readapd()
+{
+	FILE *fptr;
+	char ttxt[21];
+	char path[_MAX_PATH];
+
+	sprintf(path,"%sapd.dat",gamedir);
+	fptr=fopen(path,"rt");
+	if(fptr==NULL)
+		return(100);
+	else
+		{
+		fgets(ttxt,20,fptr);
+		fclose(fptr);
+		}
+	return(atoi(ttxt));
+}
+
+void read_vtext(int vnum)
+{
+	FILE *fptr;
+	int  count=0,actidx=0,actval=0;
+	char string[90];
+	char path[_MAX_PATH],*x;
+
+	sprintf(path,"%smsgsv.dat",gamedir);
+	if((fptr=fopen(path,"rt"))==NULL)
+		return;
+	else{
+		while(fgets(string,81,fptr)!=NULL){
+			if(string[0]=='!' && string[1]=='@' && string[2]=='#'){
+				count++;
+				if(count==vnum){
+					fgets(string,81,fptr);
+					actidx=atoi(string);
+					fgets(string,81,fptr);
+					actval=atoi(string);
+					fgets(string,81,fptr);
+					do{
+						mci("\r`0E");
+						mci(string);
+						x=fgets(string,81,fptr);
+						}while(x!=NULL && string[0]!='!' && string[1]!='@' && string[2]!='#');
+					}
+				}
+			}
+		}
+	fclose(fptr);
+	mci("\r");
+	act_change(actidx,0,0);
+	act_change(actval,0,1);
+}
+
+int count_vtext()
+{
+	FILE *fptr;
+	int  count=0;
+	char string[90];
+	char path[_MAX_PATH];
+
+	// try to open the virus data files
+	sprintf(path,"%smsgsv.dat",gamedir);
+	fptr = fopen(path, "rb");
+	// display an error if unsuccessful
+	if (!fptr)
+	{
+		od_set_color(L_RED, D_BLACK);
+		od_printf("WARNING: unable to open: %s\n", path);
+		return 0;
+	}
+	// count the strings in the file
+	while (fgets(string,81,fptr) != NULL)
+	{
+		if(string[0]=='!' && string[1]=='@' && string[2]=='#')
+			count++;
+	}
+	// close the data file
+	fclose(fptr);
+
+	return(count);
+}
+
+void read_actions(int actno)
+{
+	FILE *fptr;
+	int  count=0,actidx=0,actval=0,done=FALSE;
+	char string[90];
+	char path[_MAX_PATH];
+	int  next_line = 0;
+
+	sprintf(path,"%smsgsa.dat",gamedir);
+	fptr = fopen(path, "rt");
+	if (fptr)
+	{
+		while(fgets(string,81,fptr) != NULL && !done )
+		{
+			if(strcmp(string,":END") == 0)
+				done = TRUE;
+			if(string[0] == '!' && string[1] == '@' && string[2] == '#' && !done)
+			{
+				count++;
+				if (count == actno)
+				{
+					fgets(string,81,fptr);
+					actidx = atoi(string);
+					fgets(string,81,fptr);
+					actval = atoi(string);
+					fgets(string,81,fptr);
+					// grab next line
+					next_line = -1;
+					while (next_line)
+					{
+						// display what we got
+						stripCR(string);
+						mci("`0F");
+						mci(string);
+						mci("~SM");
+						// grab a new line
+						fgets(string,81,fptr);
+						// check it out
+						if ((string[0] == '!' && string[1] == '@' && string[2] == '#') ||
+							(string[0] == ':' && string[1] == 'E' && string[2] == 'N' && string[3] == 'D'))
+							next_line = 0;
+					}
+				}
+			}
+		}
+		fclose(fptr);
+		mci("~SM");
+		act_change(actidx, actval, 1);
+	}
+}
+
+int count_actions()
+{
+	FILE *fptr;
+	int  count=0;
+	char string[90];
+	char path[_MAX_PATH];
+
+	sprintf(path,"%smsgsa.dat",gamedir);
+	if ((fptr=fopen(path,"rb"))==NULL)
+		return 0;
+	else
+	{
+		while (fgets(string,81,fptr)!=NULL)
+		{
+			if (string[0]=='!' && string[1]=='@' && string[2]=='#')
+				count++;
+		}
+	}
+
+	fclose(fptr);
+
+	return(count);
+}
+
+int count_virus()
+{
+	FILE *fptr;
+	int  count = 0;
+	char string[90];
+	char path[_MAX_PATH];
+
+	sprintf(path,"%smsgsv.dat",gamedir);
+	if((fptr=fopen(path,"rb"))==NULL)
+		return 0;
+	else
+		while(fgets(string,81,fptr)!=NULL)
+			if(string[0]=='!' && string[1]=='@' && string[2]=='#')
+				count++;
+	fclose(fptr);
+	return(count);
+}
+
+int count_cpu()
+{
+	FILE *fptr;
+	int l1;
+	char ttxt[81];
+	char path[_MAX_PATH];
+
+	sprintf(path,"%scpu.dat",gamedir);
+	fptr=fopen(path,"rt");
+	if(fptr==NULL){
+		return(MAX_CPU);
+		}
+	else
+		{
+		l1=0;
+		while(fgets(ttxt,80,fptr)!=NULL){
+			stripCR(ttxt);
+			strcpy(computer[l1].cpuname,ttxt);
+			computer[l1].cost=((l1*l1)*100)+(l1*10);
+			l1++;
+			}
+		if(l1>19)	l1=19;
+		}
+	return(l1);
+
+}
+
+int count_msgsr()
+{
+	FILE *fptr;
+	int  count=0;
+	char string[90];
+	char path[_MAX_PATH];
+
+	sprintf(path,"%smsgsr.dat",gamedir);
+	if((fptr=fopen(path,"rb"))==NULL)
+		return 0;
+	else
+		while(fgets(string,81,fptr)!=NULL)
+			if(string[0]=='!' && string[1]=='@' && string[2]=='#')
+				count++;
+	fclose(fptr);
+	return(count);
+}
+
+void read_msgsr(int actno)
+{
+	FILE *fptr;
+	int  count=0;
+	char string[91];
+	char path[_MAX_PATH];
+
+	sprintf(path,"%smsgsr.dat",gamedir);
+	if((fptr=fopen(path,"rt"))==NULL){
+		mci("~SMUnable to open msgsr.dat~SM");
+		return;
+		}
+	else{
+		while(fgets(string,91,fptr)!=NULL){
+			if(strcmp(string,":END")==0)	break;
+			if(string[0]=='!' && string[1]=='@' && string[2]=='#'){
+				count++;
+				if(count==actno){
+					fgets(string,91,fptr);
+					fgets(string,91,fptr);
+					fgets(string,91,fptr);
+					do{
+						stripCR(string);
+						mci(string);
+						fgets(string,91,fptr);
+						}while(string[0]!='!' && string[1]!='@' && string[2]!='#');
+					}
+				}
+			}
+		}
+	fclose(fptr);
+}
+
+void viruslist()
+{
+	FILE *fptr;
+	int  count,k;
+	char path[_MAX_PATH];
+
+	sprintf(path,"%svirus.dat",gamedir);
+
+    k = rand_num(vlcnt);
+
+    if((fptr=fopen(path,"rt"))==NULL) {
+        nl();
+		od_printf("Error opening VIRUS.DAT");nl();
+        nl();
+        return;
+        }
+	else {
+        count=0;
+		while(fgets(TS,61,fptr)!=NULL && count!=k)
+			count++;
+		stripCR(TS);
+		str_2A(1,TS);
+		text("0875");
+		}
+	fclose(fptr);
+}
+
+int vlcount()
+{
+	FILE *fptr;
+	int  count=0;
+	char path[_MAX_PATH];
+
+	sprintf(path,"%svirus.dat",gamedir);
+
+    if((fptr=fopen(path,"rt"))==NULL)
+		return -1;
+	else{
+		while(fgets(TS,81,fptr)!=NULL)
+			count++;
+		}
+	fclose(fptr);
+    return(count);
+}
+
+void writemail(char *mfile, char *msg)
+{
+	FILE *fptr;
+	fptr = fopen(mfile,"at");
+	if (fptr == NULL)
+	{
+		fptr = fopen(mfile,"wt");
+		if (fptr == NULL)
+		{
+			mci("~SM~SMERROR saving mail.");
+			return;
+		}
+	}
+	fputs(msg,fptr);
+	fclose(fptr);
+}
+
+void basedir(char *retstr)
+{
+	int i;
+	for(i=strlen(retstr)-1;i>0;i--){
+		if(retstr[i]=='/'){
+			retstr[i+1]='\0';
+			return;
+			}
+		}
+}
+
+int readmaildat(mailrec *mr, int letter)
+{
+	FILE *fptr;
+	int x=FALSE;
+	char path[_MAX_PATH];
+
+	sprintf(path,"%smail.vb3",gamedir);
+	fptr=fopen(path,"rb+");
+	if(fptr!=NULL) {
+		if(fseek(fptr,(long)letter*sizeof(mailrec),SEEK_SET)==0)
+			x=fread(mr,sizeof(mailrec),1,fptr);
+		fclose(fptr);
+		}
+
+	return(x);
+}
+
+int savemaildat(mailrec *mr, int letter)
+{
+	FILE *fptr;
+	int x=FALSE;
+	char path[_MAX_PATH];
+
+	sprintf(path,"%smail.vb3",gamedir);
+	fptr=fopen(path,"rb+");
+	if(fptr==NULL){
+		fptr=fopen(path,"wb");
+		x=fwrite(mr,sizeof(mailrec),1,fptr);
+		}
+	else{
+		if(fseek(fptr,(long)letter*sizeof(mailrec),SEEK_SET)==0)
+			x=fwrite(mr,sizeof(mailrec),1,fptr);
+		}
+	fclose(fptr);
+	return(x);
+}
+
+#ifdef FIXME
+mx_file gLockFile;
+#else
+int	gLockFile;
+#endif
+
+int vbbs_io_lock_game(const char* fullname)
+{
+	char path[FILENAME_MAX];
+
+	// open our lock file
+	sprintf(path, "%slock.vb3", gamedir);
+	if ((gLockFile=open(path,O_RDWR|O_CREAT|O_BINARY,S_IREAD|S_IWRITE)) < 0)
+		return -1;
+	// attempt to lock it
+	if (lock(gLockFile, 0, 256))
+	{
+		close(gLockFile);
+		return -1;
+	}
+	// write the user rec
+	char username[256];
+	sprintf(username, "%s", fullname);
+	write(gLockFile, &username, 256);
+
+	return 0;
+}
+
+void vbbs_io_unlock_game()
+{
+	// clear username
+	char username[256];
+	memset(username, 0, 256);
+	lseek(gLockFile, 0, SEEK_SET);
+	write(gLockFile, &username, 256);
+	// unlock the file
+	unlock(gLockFile, 0, 256);
+	// close it
+	close(gLockFile);
+}
diff --git a/src/doors/vbbs/src/v3_io.h b/src/doors/vbbs/src/v3_io.h
new file mode 100755
index 0000000000000000000000000000000000000000..b0782a212ea422071b608ff06a96f34bb4a6c96b
--- /dev/null
+++ b/src/doors/vbbs/src/v3_io.h
@@ -0,0 +1,28 @@
+#ifndef _V3_IO_H_
+#define _V3_IO_H_
+
+int fexist(char *fname);
+int countplyrs();
+int saveplyr(tUserRecord *user, int usernum);
+int readplyr(tUserRecord *user, int usernum);
+int readapd(void);
+void read_vtext(int vnum);
+int count_vtext(void);
+void read_actions(int actno);
+int count_actions(void);
+int count_virus(void);
+int count_cpu(void);
+int count_msgsr(void);
+void read_msgsr(int actno);
+void viruslist(void);
+int vlcount(void);
+void basedir(char *retstr);
+void writemail(char *mfile, char *msg);
+int readmaildat(mailrec *mr, int letter);
+int savemaildat(mailrec *mr, int letter);
+
+int vbbs_io_lock_game(const char* fullname);
+void vbbs_io_unlock_game(void);
+
+#endif
+
diff --git a/src/doors/vbbs/src/v3_learn.c b/src/doors/vbbs/src/v3_learn.c
new file mode 100644
index 0000000000000000000000000000000000000000..8f30f263ac2fbf66b4e77aa6a4ab9e7cdb16c2d4
--- /dev/null
+++ b/src/doors/vbbs/src/v3_learn.c
@@ -0,0 +1,273 @@
+/*****************************************************************************
+ *
+ * File ..................: v3_learn.c
+ * Purpose ...............: Learning and Schooling routines.
+ * Last modification date : 30-Sept-2000
+ *
+ *****************************************************************************
+ * Copyright (C) 1999-2000
+ *
+ * Darryl Perry		FIDO:		1:211/105
+ * Sacramento, CA.
+ * USA
+ *
+ * This file is part of Virtual BBS.
+ *
+ * This Game is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Virtual BBS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Virutal BBS; see the file COPYING.  If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *****************************************************************************/
+
+
+#include "vbbs.h"
+#include "v3_defs.h"
+#include "v3_learn.h"
+#include "v3_hack.h"
+#include "v3_mci.h"
+#include "v3_basic.h"
+
+
+void learn()
+{
+	s32_2A(1, plyr.actions);
+	text("0430");
+	switch(od_get_answer("QTHBV"))
+	{
+	case 'Q':
+		nl();
+		nl();
+		return;
+	case 'T':
+		school();
+		break;
+	case 'H':
+		hire_tutor();
+		break;
+    case 'B':
+        bribe();
+        break;
+	case 'V':
+		visit_hacker();
+		break;
+	}
+}
+
+void hire_tutor()
+{
+	char	ch,mf;
+    int		actns[5] = { 100, 100, 100, 80, 50 },
+    		edlev[5] = { 1, 1, 1, 2, 2 },
+			num1;
+    float	mcosts[5] = { 0.202f,
+                          0.101f,
+                          0.0508f,
+                          0.0501f,
+                          0.502f };
+	float TFloat = 0.0f;
+
+	s32_2A(1, plyr.actions);
+	text("0435");
+	ch=od_get_answer("012345");
+       if(ch=='0')
+       	return;
+	else{
+		num1=ch-'0';
+		mf=0;
+		if(((num1+2) % 2)==1)	mf=1;
+		if((float)plyr.funds*mcosts[num1-1]<mcosts[num1-1]*1000000L){
+			if(mf==1)	text("0436");
+			else    	text("0437");
+			}
+		else{
+			TFloat=mcosts[num1-1]*100000L;
+			inum=actns[num1-1];
+			if(mf) 	text("0438");
+			else	text("0439");
+			s16_2A(1,inum);
+			s32_2C(2,(s32)TFloat);
+			text("0440");
+			if(yesno()){
+                plyr.funds-=(plyr.funds*mcosts[num1-1]);
+				plyr.education[1]+=edlev[num1-1];
+				}
+			}
+		}
+	plyr.actions--;
+}
+
+void visit_hacker()
+{
+	int 	j;
+	float TFloat = 0.0f;
+	s32 TLong = 0L;
+
+	TFloat = (float)((plyr.skill_lev+1)*1900);
+	u32_2C(1,(u32)TFloat);
+	text("0460");
+	if(noyes()=='Y'){
+		if(plyr.funds<TLong){
+			text("0461");
+			plyr.actions--;
+            }
+		else{
+			if(plyr.hacktoday>0){
+                plyr.actions-=50;
+				TLong = (s32)(plyr.funds/2.0f);
+				plyr.funds -= (float)TLong;
+				s32_2C(1,TLong);
+				text("0462");
+				}
+			else{
+				plyr.funds/=10.0f;
+            	j = rand_num(80)+10;
+            	plyr.actions-=j;
+				plyr.education[1] += 0.2f;
+				plyr.hacktoday=1;
+				text("0463");
+				}
+            }
+        }
+	else
+		text("0464");
+}
+
+void school()
+{
+	s32_2A(1, plyr.actions);
+	text("0450");
+	switch(od_get_answer("0123456")){
+		case '0':
+			return;
+		case '1':
+			takeclass(0);
+			break;
+		case '2':
+			takeclass(1);
+			break;
+		case '3':
+			takeclass(2);
+			break;
+		case '4':
+			takeclass(3);
+			break;
+		case '5':
+			takeclass(4);
+			break;
+        case '6':
+           	hardknocks();
+            break;
+		}
+}
+
+void takeclass(int classnum)
+{
+
+	char	grades[6]="ABCDF",ttxt[6];
+	int		istrs[2],ii;
+	float   olded,edu;
+	float TFloat = 0.0f;
+	s32 TLong = 0L;
+
+	nl();
+	nl();
+	inum = rand_num(classes[classnum].classes_available+1);
+	if(inum<1)
+		inum=1;
+	s16_2A(1,inum);
+	if(inum<2)
+		text("0470");
+	else
+		text("0471");
+	inum=classes[classnum].average_hours;
+	s16_2A(1,inum);
+	s16_2A(2,inum);
+	text("0472");
+	TLong=classes[classnum].cost;
+	inum=classes[classnum].apch;
+	s16_2A(1,inum);
+	text("0473");
+	*ttxt='\0';
+	od_input_str(ttxt, 2, '0', '9');
+	istrs[0]=atoi(ttxt);
+    if(istrs[0]<1)
+    	return;
+	if(istrs[0]>inum)
+		istrs[0]=inum;
+	inum=classes[classnum].average_hours*classes[classnum].apch;
+	s16_2A(1,inum);
+	text("0474");
+	*ttxt='\0';
+	od_input_str(ttxt, 3, '0', '9');
+	istrs[1]=atoi(ttxt);
+	if((istrs[1]<=(classes[classnum].apch/2))){
+		text("0475");
+		plyr.actions--;
+        return;
+		}
+	inum=istrs[0];
+	s16_2A(1,inum);
+	text("0476");
+	inum=classes[classnum].cost*istrs[0];
+	s16_2A(1,inum);
+	text("0477");
+	inum=istrs[1];
+	s16_2A(1,inum);
+	text("0478");
+	TFloat=(float)((((float)istrs[1]*(float)istrs[0])/(float)CONFIG_ACTIONS_PER_DAY));
+	u32_2C(1, (u32)TFloat);
+	text("0479");
+	if(plyr.funds>=classes[classnum].cost*istrs[0]){
+		text("0480");
+		if(noyes()=='Y'){
+			edu=((float)istrs[0])/10;
+			olded=plyr.education[0];
+			plyr.funds-=(classes[classnum].cost*istrs[0]);
+			plyr.education[0]+=edu;
+			plyr.actions-=(istrs[1]*istrs[0]);
+			ii = rand_num(5);
+			char_2A(1,grades[ii]);
+			text("0481");
+			switch(ii){
+				case 0: text("0482"); break;
+				case 1: text("0483"); break;
+				case 2: text("0484"); break;
+				case 3: text("0485"); break;
+				case 4: text("0486"); break;
+				}
+			if((int)plyr.education[0]>(int)olded)
+				text("0487");
+			}
+		else{
+			plyr.actions--;
+        	}
+    	}
+    else
+		{
+		text("0488");
+		plyr.actions--;
+        }
+    paws();
+}
+
+void hardknocks()
+{
+	inum = rand_num(51)+100;
+	s16_2A(1,inum);
+	text("0570");
+	if(yesno())
+	{
+		plyr.actions-=inum;
+        plyr.education[1]++;
+    }
+}
+
diff --git a/src/doors/vbbs/src/v3_learn.h b/src/doors/vbbs/src/v3_learn.h
new file mode 100755
index 0000000000000000000000000000000000000000..f1d5548341d07614d38f1c15bd29000c6fffafb6
--- /dev/null
+++ b/src/doors/vbbs/src/v3_learn.h
@@ -0,0 +1,12 @@
+#ifndef _V3_LEARN_H_
+#define _V3_LEARN_H_
+
+void learn(void);
+void hire_tutor(void);
+void visit_hacker(void);
+void school(void);
+void takeclass(int classnum);
+void hardknocks(void);
+
+#endif
+
diff --git a/src/doors/vbbs/src/v3_mail.c b/src/doors/vbbs/src/v3_mail.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e2f60ff1baa0a585d093cac65aef4feb613991a
--- /dev/null
+++ b/src/doors/vbbs/src/v3_mail.c
@@ -0,0 +1,287 @@
+/*****************************************************************************
+ *
+ * File ..................: v3_mail.c
+ * Purpose ...............: Intergame mail routines
+ * Last modification date : 17-Mar-2000
+ *
+ *****************************************************************************
+ * Copyright (C) 1999-2000
+ *
+ * Darryl Perry		FIDO:		1:211/105
+ * Sacramento, CA.
+ * USA
+ *
+ * This file is part of Virtual BBS.
+ *
+ * This Game is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Virtual BBS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Virutal BBS; see the file COPYING.  If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *****************************************************************************/
+
+#include <string.h>
+#include "vbbs.h"
+#include "v3_defs.h"
+#include "v3_io.h"
+#include "v3_mail.h"
+#include "v3_mci.h"
+#include "v3_basic.h"
+
+char rettxt[81];
+const char* strMailItems[] =
+{
+	"action",
+	"dollar"
+};
+
+int countmail()
+{
+	mailrec mr;
+	int i=0;
+
+	while(readmaildat(&mr,i))	i++;
+	return i;
+}
+
+void sendmail()
+{
+	FILE *fptr1,*fptr2;
+	char ch;
+	char tpath[161];
+	char path[161];
+	char ttxt[161];
+	char ttxt1[161];
+	int done=FALSE,done1=FALSE,lcnt=1;
+	long lnum;
+	mailrec mail;
+
+	sprintf(tpath,"%smailtxt.tmp",gamedir);
+	if(fexist(tpath))	remove(tpath);
+	sprintf(path,"%smailtxt.vb3",gamedir);
+
+	// clear out mail
+	memset(&mail, 0, sizeof(mailrec));
+	mail.idx=countmail();
+	mail.letternum=mail.idx;
+	if(findBBS()==-1)
+		return;
+	mail.from=plyr.plyrnum;
+	mail.to=othr.plyrnum;
+	mail.deleted=FALSE;
+	mail.fsys=0;
+	mail.tosys=0;
+	(void)time(&mail.date);
+
+	text("1100"); //mci("~SM`09S`01ubject: `1F");
+	*mail.subject='\0';
+	od_input_str(mail.subject,68,32,127);
+	text("1101"); //mci("~SM   `07Type message below.  <ENTER> on a blank line ends.");
+	text("1102"); //mci("~SM   [---+----+----+----+----+----+----+----+----+----+----+----+----+----+----]");
+	while(!done)
+	{
+		mci("`07%3d`02:`0F",lcnt);
+		*ttxt = '\0';
+		od_input_str(ttxt,75,32,127);
+		if(ttxt[0] == '\0')
+		{
+			done = TRUE;
+		}
+		else
+		{
+			sprintf(ttxt1,"%04d `09³ `07%-74s`09³~SM\n", mail.letternum, ttxt);
+			mcimacros(ttxt1);
+			writemail(tpath,ttxt1);
+			lcnt++;
+			*ttxt = '\0';
+		}
+	}
+	text("1110"); //mci("~SM~SMWould you like to send something? ");
+	if(yesno()){
+		text("1111"); //mci("~SMWhat would you like to send? ~SM");
+		mci("~SM(1) Actions           : %d",plyr.actions);
+		commafmt_s32(ttxt, 21, (s32)plyr.funds);
+		mci("~SM(2) Money             : %s",ttxt);
+		text("1119"); //mci("~SM~SMWhich? [1-2, 0=Quit] : ");
+		ch=od_get_answer("123456780");
+		switch(ch){
+			case '0': break;
+			case '1':
+				done1=FALSE;
+				while(!done1){
+					mci("~SMSend how many actions? [0-%d]: ",plyr.actions);
+					od_input_str(ttxt,10,'0','9');
+					if (strlen(ttxt)>0)
+					{
+						lnum=atoi(ttxt);
+						if (lnum>(int)plyr.actions)
+						{
+							// mci("~SM~SMYou don't have that many actions to give.~SM");
+							// mci("~SMPlease try again.~SM");
+							text("1120");
+						}
+						else
+						{
+							mci("~SMSend %d actions to %s?", lnum, othr.sysopname);
+							if (yesno())
+							{
+								mail.amount = (int)lnum;
+								mail.item = ch-'0';
+								plyr.actions -= lnum;
+								done1 = TRUE;
+							}
+						}
+					}
+					else
+						done1=TRUE;
+					}
+				break;
+			case '2':
+				commafmt_s32(ttxt, 21, (s32)plyr.funds);
+				mci("~SMSend how much money? [0-%s]: ",ttxt);
+				od_input_str(ttxt,10,'0','9');
+				lnum=atol(ttxt);
+				if(lnum<=plyr.funds){
+					commafmt_s32(ttxt, 21, (s32)lnum);
+					mci("~SMSend $%s? [Yes]: ",ttxt);
+					if(yesno()){
+						mail.item = ch-'0';
+						mail.amount = (int16)lnum;
+						plyr.funds -= (float)lnum;
+						}
+					}
+				break;
+			}
+		}
+	text("1130"); // mci("~SMSend this message?");
+	if(yesno()){
+		mail.idx=countmail();
+		savemaildat(&mail,mail.idx);
+		fptr1=fopen(path,"at");
+		fptr2=fopen(tpath,"rt");
+		while(fgets(ttxt,161,fptr2)!=NULL){
+			fputs(ttxt,fptr1);
+			}
+		fclose(fptr1);
+		fclose(fptr2);
+
+		}
+	if(fexist(tpath))	remove(tpath);
+}
+
+void network()
+{
+	while(1)
+	{
+		text("1140"); // Network Mail Menu
+		switch(od_get_answer("PSQ"))
+		{
+		case 'P':	readnetmail();	break;
+		case 'S':	sendmail();		break;
+		case 'Q':	mci("Quit~SM");	return;
+		}
+	}
+}
+
+void viewmail(int letter)
+{
+	FILE *fptr;
+	char ltr[6], path[_MAX_PATH], ttxt[500], ttxt1[500];
+
+	sprintf(ltr,"%04d ",letter);
+
+	sprintf(path,"%smailtxt.vb3",gamedir);
+	fptr = fopen(path,"rt");
+	if (fptr)
+	{
+		while (fgets(ttxt,161,fptr) != NULL)
+		{
+			if (strncmp(ttxt,ltr,4) == 0)
+			{
+				stripCR(ttxt);
+				strcpy(ttxt1,ttxt+5);
+				mci("%s",ttxt1);
+			}
+		}
+	}
+}
+
+void showhdr(mailrec *mr)
+{
+	struct tm *tm;
+	char ttxt[81] = {"01/01/1900"};
+
+	tm=localtime(&mr->date);
+	strftime(ttxt,80,"%m/%d/%C%Y  %H:%M%p",tm);
+	str_2A(1,othr.sysopname);
+	str_2A(2,ttxt);
+	str_2A(3,mr->subject);
+	// mci("~SM`09Ú~EFÄ75~SM");
+	// mci("`09³ `0FFrom: ~EL68~&1`09³~SM");
+	// mci("`09³ `0FDate: ~EL68~&2`09³~SM");
+	// mci("`09³ `0FSubj: ~EL68~&3`09³~SM");
+	// mci("[~EFÄ75]~SM");
+	text("1150");
+}
+
+void showfooter(void)
+{
+	text("1151");
+}
+
+void readnetmail()
+{
+	int mnum;
+	int foundone = FALSE;
+	mailrec mail;
+
+	mnum = 0;
+	while (readmaildat(&mail,mnum))
+	{
+		if ((mail.tosys == 0) && (mail.to == plyr.plyrnum) && (mail.deleted == FALSE))
+		{
+			foundone = TRUE;
+			showhdr(&mail);
+			viewmail(mail.letternum);
+			showfooter();
+			if (mail.item > 0)
+			{
+				readplyr(&othr,mail.from);
+				if (mail.amount > 1)
+					mci("~SM!!! %s has sent you %d %ss.", othr.sysopname, mail.amount, strMailItems[mail.item-1]);
+				else
+					mci("~SM!!! %s has sent you %d %s.", othr.sysopname, mail.amount, strMailItems[mail.item-1]);
+				if (mail.item == 1)
+				{
+					plyr.actions += mail.amount;
+				}
+				else if (mail.item == 2)
+				{
+					plyr.funds += mail.amount;
+				}
+				// clear item and amount so they don't get it again
+				mail.amount = 0;
+				mail.item = 0;
+			}
+			text("1160"); // mci("~SM~SMDelete this message? [Yes]: ");
+			if (yesno())
+			{
+				mail.deleted = TRUE;
+			}
+		}
+		savemaildat(&mail,mnum);
+		mnum++;
+	}
+	if (!foundone)
+	{
+		text("1161"); // mci("~SM~SMYour mailbox is empty~SM");
+	}
+}
diff --git a/src/doors/vbbs/src/v3_mail.h b/src/doors/vbbs/src/v3_mail.h
new file mode 100755
index 0000000000000000000000000000000000000000..893d449a1f3b65c92dd9937e084c23915d4fbd01
--- /dev/null
+++ b/src/doors/vbbs/src/v3_mail.h
@@ -0,0 +1,12 @@
+#ifndef _V3_MAIL_H_
+#define _V3_MAIL_H_
+
+void maketmpmsg(char *tpath,char *from, char *fromsys, char *datetxt, char *subj);
+void sendmail(void);
+void network(void);
+int countmail(void);
+void viewmail(int letter);
+void readnetmail(void);
+
+#endif
+
diff --git a/src/doors/vbbs/src/v3_maint.c b/src/doors/vbbs/src/v3_maint.c
new file mode 100644
index 0000000000000000000000000000000000000000..e1e76425398a1ce3a73c6de30ab9dc022b42df29
--- /dev/null
+++ b/src/doors/vbbs/src/v3_maint.c
@@ -0,0 +1,103 @@
+/*****************************************************************************
+ *
+ * File ..................: v3_maint.c
+ * Purpose ...............: Daily maint
+ *
+ *****************************************************************************/
+
+#include "vbbs.h"
+
+#include "v3_defs.h"
+#include "vbbs_db.h"
+#include "vbbsutil.h"
+#include "v3_io.h"
+
+#include "v3_maint.h"
+
+static void compact_players()
+{
+	char cur_path[_MAX_PATH];
+	char new_path[_MAX_PATH];
+	tUserRecord plyr;
+	int  p;
+
+	// make all the paths
+	sprintf(cur_path,"%susers.vb3",gamedir);
+	sprintf(new_path,"%susers.new",gamedir);
+	// get the player count
+	int total_players = countplyrs();
+	// open the current file and new file
+	FILE* fcur = fopen(cur_path, "rb");
+	FILE* fnew = fopen(new_path, "wb");
+	// abort if we couldn't open the files
+	if (!fcur || !fnew)
+		return;
+	// new player count
+	s16 players = 0;
+	// read each player, and write them if they survive
+	for (p=0; p<total_players; p++)
+	{
+		// grab the player
+		fread(&plyr, sizeof(tUserRecord), 1, fcur);
+		// check for deletion
+		if (plyr.status != DELETED)
+		{
+			// add him to the count
+			plyr.plyrnum = players++;
+			// write them to the new file
+			fwrite(&plyr, sizeof(tUserRecord), 1, fnew);
+		}
+	}
+	// close both files
+	fclose(fcur);
+	fclose(fnew);
+	// rid ourselves of the old one
+	remove(cur_path);
+	rename(new_path, cur_path);
+}
+
+static void validate_players()
+{
+	tUserRecord plyr;
+	int	p;
+
+	// get the player count
+	int total_players = countplyrs();
+	// read each player, and write them if they survive
+	for (p=0; p<total_players; p++)
+	{
+		// grab the player
+		readplyr(&plyr, p);
+
+		// check number of modems
+		if (plyr.mspeed.low < 0)		plyr.mspeed.low = 0;
+		if (plyr.mspeed.high < 0)		plyr.mspeed.high = 0;
+		if (plyr.mspeed.digital < 0)	plyr.mspeed.digital = 0;
+		// check funds
+		if (plyr.funds < 0.0f) 			plyr.funds = 0.0f;
+
+		// write them to the new file
+		saveplyr(&plyr, p);
+	}
+}
+
+void v3_maint_daily()
+{
+	// get today
+	u32 today = vbbs_util_getday();
+	// get last maint
+	record sys_rec;
+	gSystemDB_read(&sys_rec);
+	// check for maint
+	if (sys_rec.last_maint != today)
+	{
+		// compact all the players
+		compact_players();
+		// check for errors
+		validate_players();
+		// update sys record
+		gSystemDB_update(&sys_rec);
+		sys_rec.last_maint = today;
+		gSystemDB_commit(&sys_rec);
+	}
+}
diff --git a/src/doors/vbbs/src/v3_maint.h b/src/doors/vbbs/src/v3_maint.h
new file mode 100755
index 0000000000000000000000000000000000000000..18532796edb564e44e85da95eba18b3ee1e41472
--- /dev/null
+++ b/src/doors/vbbs/src/v3_maint.h
@@ -0,0 +1,6 @@
+#ifndef V3_MAINT_H
+#define V3_MAINT_H
+
+void v3_maint_daily();
+
+#endif // V3_MAINT_H
diff --git a/src/doors/vbbs/src/v3_mci.c b/src/doors/vbbs/src/v3_mci.c
new file mode 100644
index 0000000000000000000000000000000000000000..4dbd9f9ed0a042fe21da6d38644e4ef900ac5d1e
--- /dev/null
+++ b/src/doors/vbbs/src/v3_mci.c
@@ -0,0 +1,553 @@
+/*****************************************************************************
+ *
+ * File ..................: v3_mci.c
+ * Purpose ...............: Formatted output
+ * Last modification date : 16-Mar-2001
+ *
+ *****************************************************************************
+ * Copyright (C) 1999-2001
+ *
+ * Darryl Perry		FIDO:		1:211/105
+ * Sacramento, CA.
+ * USA
+ *
+ * This file is part of Virtual BBS.
+ *
+ * This Game is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Virtual BBS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Virutal BBS; see the file COPYING.  If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#if defined(_MSC_VER)
+#include "vc_strings.h"
+#elif defined(__BORLANDC__)
+#include "bc_str.h"
+#else
+#include <strings.h>
+#endif
+
+#include "vbbs.h"
+#include "v3_defs.h"
+#include "v3_mci.h"
+#include "v3_basic.h"
+
+char A[24][81];
+
+#define NUL '\0'
+
+size_t commafmt_s32(char* buf,      /* Buffer for formatted string  */
+                int bufsize,        /* Size of buffer               */
+                s32 N)              /* Number to convert            */
+{
+      int len = 1, posn = 1, sign = 1;
+      char *ptr = buf + bufsize - 1;
+
+      if (2 > bufsize)
+      {
+ABORT:      *buf = NUL;
+            return 0;
+      }
+
+      *ptr-- = NUL;
+      --bufsize;
+      if (0L > N)
+      {
+            sign = -1;
+            N = -N;
+      }
+
+      for ( ; len <= bufsize; ++len, ++posn)
+      {
+            *ptr-- = (char)((N % 10L) + '0');
+            if (0L == (N /= 10L))
+                  break;
+            if (0 == (posn % 3))
+            {
+                  *ptr-- = ',';
+                  ++len;
+            }
+            if (len >= bufsize)
+                  goto ABORT;
+      }
+
+      if (0 > sign)
+      {
+            if (0 == bufsize)
+                  goto ABORT;
+            *ptr-- = '-';
+            ++len;
+      }
+
+      strcpy(buf, ++ptr);
+      return (size_t)len;
+}
+
+size_t commafmt_u32(char* buf,		/* Buffer for formatted string  */
+                int bufsize,        /* Size of buffer               */
+                u32 N)              /* Number to convert            */
+{
+      int len = 1, posn = 1;
+      char *ptr = buf + bufsize - 1;
+
+      if (2 > bufsize)
+      {
+ABORT:      *buf = NUL;
+            return 0;
+      }
+
+      *ptr-- = NUL;
+      --bufsize;
+
+      for ( ; len <= bufsize; ++len, ++posn)
+      {
+            *ptr-- = (char)((N % 10L) + '0');
+            if (0L == (N /= 10L))
+                  break;
+            if (0 == (posn % 3))
+            {
+                  *ptr-- = ',';
+                  ++len;
+            }
+            if (len >= bufsize)
+                  goto ABORT;
+      }
+
+      strcpy(buf, ++ptr);
+      return (size_t)len;
+}
+
+
+void text(char *lnum)
+{
+	FILE *fptr;
+	char ttxt[161];
+	char path[_MAX_PATH];
+
+	sprintf(path,"%stext.dat",gamedir);
+
+	fptr=fopen(path,"rt");
+	if(fptr==NULL) {
+		mci("~SMUnable to open text.dat~SM~SM");
+		}
+	else {
+		while(fgets(ttxt,161,fptr)!=NULL){
+			if(strncasecmp(lnum,ttxt,strlen(lnum))==0){
+				stripCR(ttxt);
+				memmove(ttxt,ttxt+5,strlen(ttxt)-4);
+				mci(ttxt);
+				}
+			}
+		}
+	fclose(fptr);
+}
+
+void mcigettext(char *lnum, char *outtext)
+{
+	FILE *fptr;
+	char path[_MAX_PATH];
+
+	sprintf(path,"%stext.dat",gamedir);
+	fptr=fopen(path,"rt");
+	if(fptr==NULL) {
+		mci("~SMUnable to open %s~SM~SM",path);
+		}
+	else {
+		while(fgets(outtext,161,fptr)!=NULL){
+			if(strncasecmp(lnum,outtext,strlen(lnum))==0){
+				stripCR(outtext);
+				memcpy(outtext,outtext+5,strlen(outtext)-4);
+				break;
+				}
+			}
+		}
+	fclose(fptr);
+}
+
+void mcimacros(char *ttxt)
+{
+	mciAnd(ttxt);
+}
+
+void mci(char *fmt, ...)
+{
+	va_list argptr;
+	char buffer[512];
+
+	va_start(argptr, fmt);
+	vsprintf(buffer, fmt, argptr);
+	va_end(argptr);
+
+	mciEseries(buffer);
+	mcimacros(buffer);
+	mcihidden(buffer);
+	mcicolor(buffer,od_control.user_ansi);
+	mcifuncts(buffer);
+}
+
+void stripCR(char *ttxt)
+{
+	while(strstr(ttxt,"\n"))	strrepl(ttxt,500,"\n","");
+	while(strstr(ttxt,"\r"))	strrepl(ttxt,500,"\r","");
+}
+
+
+char *strrepl(char *Str, size_t BufSiz, const char *OldStr, const char *NewStr)
+{
+	int OldLen, NewLen;
+	char *p, *q;
+
+	if(NULL == (p = strstr(Str, OldStr)))
+		return Str;
+	OldLen = strlen(OldStr);
+	NewLen = strlen(NewStr);
+	if ((strlen(Str) + NewLen - OldLen + 1) > BufSiz)
+		return NULL;
+	memmove(q = p+NewLen, p+OldLen, strlen(p+OldLen)+1);
+	memcpy(p, NewStr, NewLen);
+	return q;
+}
+
+void mciAnd(char *ttxt)
+{
+	while(strstr(ttxt,"~&0"))	strrepl(ttxt,500,"~&0",A[0]);
+	while(strstr(ttxt,"~&1"))	strrepl(ttxt,500,"~&1",A[1]);
+	while(strstr(ttxt,"~&2"))	strrepl(ttxt,500,"~&2",A[2]);
+	while(strstr(ttxt,"~&3"))	strrepl(ttxt,500,"~&3",A[3]);
+	while(strstr(ttxt,"~&4"))	strrepl(ttxt,500,"~&4",A[4]);
+	while(strstr(ttxt,"~&5"))	strrepl(ttxt,500,"~&5",A[5]);
+	while(strstr(ttxt,"~&6"))	strrepl(ttxt,500,"~&6",A[6]);
+	while(strstr(ttxt,"~&7"))	strrepl(ttxt,500,"~&7",A[7]);
+	while(strstr(ttxt,"~&8"))	strrepl(ttxt,500,"~&8",A[8]);
+	while(strstr(ttxt,"~&9"))	strrepl(ttxt,500,"~&9",A[9]);
+	while(strstr(ttxt,"~&A"))	strrepl(ttxt,500,"~&A",A[10]);
+	while(strstr(ttxt,"~&B"))	strrepl(ttxt,500,"~&B",A[11]);
+	while(strstr(ttxt,"~&C"))	strrepl(ttxt,500,"~&C",A[12]);
+	while(strstr(ttxt,"~&D"))	strrepl(ttxt,500,"~&D",A[13]);
+	while(strstr(ttxt,"~&E"))	strrepl(ttxt,500,"~&E",A[14]);
+	while(strstr(ttxt,"~&F"))	strrepl(ttxt,500,"~&F",A[15]);
+	while(strstr(ttxt,"~&G"))	strrepl(ttxt,500,"~&G",A[16]);
+	while(strstr(ttxt,"~&H"))	strrepl(ttxt,500,"~&H",A[17]);
+	while(strstr(ttxt,"~&I"))	strrepl(ttxt,500,"~&I",A[18]);
+	while(strstr(ttxt,"~&J"))	strrepl(ttxt,500,"~&J",A[19]);
+	while(strstr(ttxt,"~&K"))	strrepl(ttxt,500,"~&K",A[20]);
+	while(strstr(ttxt,"~&L"))	strrepl(ttxt,500,"~&L",A[21]);
+	while(strstr(ttxt,"~&M"))	strrepl(ttxt,500,"~&M",A[22]);
+	while(strstr(ttxt,"~&N"))	strrepl(ttxt,500,"~&N",A[23]);
+}
+
+
+void mciEseries(char *ttxt)
+{
+	char *p,t1[512],ch=0,dump[41];
+	int i,num=0,num1=0;
+
+	while(strstr(ttxt,"~EC"))	strrepl(ttxt,500,"~EC","\x1b[");
+
+	while ((p=strstr(ttxt,"~EE")) != 0)	/*  Create pattern of spaces to len n */
+	{
+		if(isdigit(*(p+3))){
+			num=*(p+3)-'0';
+			}
+		if(isdigit(*(p+4))){
+			num*=10;
+			num+= (*(p+4)-'0');
+			}
+
+		for(num1=0;num1<num;num1++) t1[num1]=' ';
+
+		t1[num1]='\0';
+		sprintf(dump,"~EE%c%d",ch,num);
+		strrepl(ttxt,500,dump,t1);
+	}
+
+	while((p=strstr(ttxt,"~EF")) != 0)	/*  Create fill pattern of c to len n */
+	{
+		ch=*(p+3);
+		if(isdigit(*(p+4))){
+			num=*(p+4)-'0';
+			}
+		if(isdigit(*(p+5))){
+			num*=10;
+			num+= (*(p+5)-'0');
+			}
+
+		for(num1=0;num1<num;num1++) t1[num1]=ch;
+
+		t1[num1]='\0';
+		sprintf(dump,"~EF%c%d",ch,num);
+		strrepl(ttxt,500,dump,t1);
+	}
+
+	while((p=strstr(ttxt,"~EL")) != 0)
+	{
+		i=3;num=0;
+		while(isdigit( *(p+i) ) ){
+			num=(num*10) + (*(p+i)-'0');
+			i++;
+			}
+
+		t1[0]=*(p+i); i++;
+		t1[1]=*(p+i); i++;
+		t1[2]=*(p+i); i++;
+		t1[3]='\0';
+
+		sprintf(dump,"~EL%d%s",num,t1);
+		mcimacros(t1);
+		mcistrset(t1,num);
+		strrepl(ttxt,500,dump,t1);
+	}
+
+	while((p=strstr(ttxt,"~EC")) != 0) /* Center & Justify, expand to n */
+	{
+		dump[0]=*(p+3); dump[1]=*(p+4); dump[2]='\0'; num=atoi(dump);
+		t1[0]=*(p+5); t1[1]=*(p+6); t1[2]=*(p+7); t1[3]='\0';
+
+		sprintf(dump,"~EK%d%s",num,t1);
+		mcimacros(t1);
+		mcistrcset(t1,num);
+		strrepl(ttxt,500,dump,t1);
+	}
+	while((p=strstr(ttxt,"~EN")) != 0)	/* Strip all spaces*/
+	{
+		t1[0]=*(p+3); t1[1]=*(p+4); t1[2]=*(p+5); t1[3]='\0';
+
+		sprintf(dump,"~EN%s",t1);
+		mcimacros(t1);
+		while(strstr(t1," "))	strrepl(t1,500," ","");
+		strrepl(ttxt,500,dump,t1);
+	}
+
+	while((p=strstr(ttxt,"~ER")) != 0)
+	{
+		i=3;num=0;
+		while(isdigit( *(p+i) ) ){
+			num=(num*10) + (*(p+i)-'0');
+			i++;
+			}
+
+		t1[0]=*(p+i); i++;
+		t1[1]=*(p+i); i++;
+		t1[2]=*(p+i); i++;
+		t1[3]='\0';
+
+		sprintf(dump,"~ER%d%s",num,t1);
+		mcimacros(t1);
+		mcistrrset(t1,num);
+		strrepl(ttxt,500,dump,t1);
+	}
+	while((p=strstr(ttxt,"~EU")) != 0)	/* Convert to upper case */
+	{
+		t1[0]=*(p+3); t1[1]=*(p+4); t1[2]=*(p+5); t1[3]='\0';
+
+		sprintf(dump,"~EU%s",t1);
+		mcimacros(t1);
+		strupr(t1);
+		strrepl(ttxt,500,dump,t1);
+	}
+	while((p=strstr(ttxt,"~EW")) != 0)	/* Convert to lower case */
+	{
+		t1[0]=*(p+3); t1[1]=*(p+4); t1[2]=*(p+5); t1[3]='\0';
+
+		sprintf(dump,"~EW%s",t1);
+		mcimacros(t1);
+		strlwr(t1);
+		strrepl(ttxt,500,dump,t1);
+	}
+	while((p=strstr(ttxt,"~ES")) != 0)
+	{
+		ttxt[p-ttxt]='\0';
+		mcicolor(p+3,FALSE);
+		strcat(ttxt,p+3);
+	}
+}
+
+int mcistrlen(char *ttxt)
+{
+	int i, count, len;
+
+	len = count = strlen(ttxt);
+	for(i=0;i<len;i++)
+	{
+		if(ttxt[i]=='`')
+		{
+			count-=3;
+		}
+	}
+
+	return(count);
+}
+
+int mcistrlenH(char *ttxt)
+{
+	int i, count, len;
+
+	len = count = strlen(ttxt);
+	for(i=0;i<len;i++)
+	{
+		if(ttxt[i]=='`')
+		{
+			count-=3;
+		}
+	}
+
+	return(count);
+}
+
+int oct2dec(char oct)
+{
+	int x=0;
+	if(isdigit(oct))	x=oct-'0';
+	if(isalpha(oct))	x=oct-'A'+10;
+	return(x);
+}
+
+void mcicolor(char *ttxt, int onoff)
+{
+	char *p;
+	char mcistr[5];
+	char outstr[21];
+	int nFG, nBG, nIN, nBK, co[8] = { 0,4,2,6,1,5,3,7 };
+
+	while ((p=strchr(ttxt,'`')) != 0)
+	{
+		if (isdigit(*(p+1)) || (*(p+1)>='A' && *(p+1)<='F') )
+		{
+			mcistr[0]='`';
+			mcistr[1]=*(p+1);
+			mcistr[2]=*(p+2);
+			mcistr[3]='\0';
+
+			nFG = nBG = nIN = nBK = 0;
+
+			/* Deal with the background first */
+			nBG = oct2dec(mcistr[1]);
+			if (nBG>7) { nBG-=8; nBK=1; }
+
+			nFG = oct2dec(mcistr[2]);
+			if (nFG>7) { nFG-=8; nIN=1; }
+
+			/* if onoff==TRUE, replace MCI codes with ANSI color */
+			/* if onoff==FALSE, strip out the MCI codes */
+			if(onoff)
+			{
+				if (nBK)
+					sprintf(outstr,"\x1b[%d;%d;%d;%dm", nIN,nBK*5,co[nFG]+30,co[nBG]+40);
+				else
+					sprintf(outstr,"\x1b[%d;%d;%dm", nIN,co[nFG]+30,co[nBG]+40);
+			}
+			else
+				strcpy(outstr,"");
+			strrepl(ttxt,500,mcistr,outstr);
+		}
+		else
+		{
+			/* replace ` with ' if it is not part of an MCI code */
+			strrepl(ttxt,500,"`","'");
+		}
+	}
+}
+
+void mcihidden(char *ttxt)
+{
+	int i;
+	char outstr[81];
+
+	while(strstr(ttxt,"~SL"))	strrepl(ttxt,500,"~SL","");	// end of line
+	while(strstr(ttxt,"~SM"))	strrepl(ttxt,500,"~SM","\r\n");
+	while(strstr(ttxt,"~SC"))	{
+		if(od_control.user_ansi)
+			strrepl(ttxt,500,"~SC","\x1b[2J\x1b[1;1H");
+		else{
+			for(i=0;i<20;i++)
+				outstr[i]='\n';
+			outstr[i]='\0';
+			strrepl(ttxt,500,"~SC",outstr);
+			}
+		}
+}
+
+void mcifuncts(char *ttxt)
+{
+	int cnt=0;
+	while(strstr(ttxt,"~SP"))	{
+		strrepl(ttxt,500,"~SP","");
+		cnt++;
+	}
+	od_disp_emu(ttxt, TRUE);
+	while(cnt){
+		paws();
+		cnt--;
+		}
+}
+
+void stripSC(char *ttxt)
+{
+	while(strstr(ttxt,"~SC"))	strrepl(ttxt,500,"~SC","");
+}
+
+void str_2A(int numa, char *ttxt)
+{
+	strcpy(A[numa], ttxt);
+}
+
+void s16_2A(int numa, s16 num)
+{
+	sprintf(A[numa], "%d", num);
+}
+
+void u16_2A(int numa, u16 num)
+{
+	sprintf(A[numa], "%u", num);
+}
+
+#ifdef VBBS_DOS
+void s32_2A(int numa, s32 lnum)
+{
+	sprintf(A[numa], "%ld", lnum);
+}
+
+void u32_2A(int numa, u32 lnum)
+{
+	sprintf(A[numa], "%lu", lnum);
+}
+#else // VBBS_WIN32 && VBBS_LINUX
+void s32_2A(int numa, s32 lnum)
+{
+	sprintf(A[numa], "%d", lnum);
+}
+
+void u32_2A(int numa, u32 lnum)
+{
+	sprintf(A[numa], "%u", lnum);
+}
+#endif
+
+void char_2A(int numa, char chr)
+{
+	sprintf(A[numa], "%c", chr);
+}
+
+void s32_2C(int numa, s32 lnum)
+{
+	commafmt_s32(A[numa], 21, lnum);
+}
+
+void u32_2C(int numa, u32 lnum)
+{
+	commafmt_u32(A[numa], 21, lnum);
+}
+
diff --git a/src/doors/vbbs/src/v3_mci.h b/src/doors/vbbs/src/v3_mci.h
new file mode 100755
index 0000000000000000000000000000000000000000..9161c8114c38f11cc50575589a6d29ff0372ff8f
--- /dev/null
+++ b/src/doors/vbbs/src/v3_mci.h
@@ -0,0 +1,32 @@
+#ifndef _V3_MCI_H_
+#define _V3_MCI_H_
+
+size_t commafmt_s32(char* buf, int bufsize, s32 N);
+size_t commafmt_u32(char* buf, int bufsize, u32 N);
+
+void text(char *lnum);
+void mcigettext(char *lnum, char *outtext);
+void mcimacros(char *ttxt);
+void mcicolor(char *ttxt, int ansi);
+void mcihidden(char *ttxt);
+void mcifuncts(char *ttxt);
+char *strrepl(char *Str, size_t BufSiz, const char *OldStr, const char *NewStr);
+void mci(char *fmt, ...);
+void mciEseries(char *ttxt);
+void stripCR(char *ttxt);
+int mcistrlen(char *ttxt);
+void mciAnd(char *ttxt);
+
+// argument writing functions
+void char_2A(int numa, char chr);
+void str_2A(int numa, char *ttxt);
+void s16_2A(int numa, s16 num);
+void u16_2A(int numa, u16 num);
+void s32_2A(int numa, s32 lnum);
+void u32_2A(int numa, u32 lnum);
+
+void s32_2C(int numa, s32 lnum);
+void u32_2C(int numa, u32 lnum);
+
+#endif
+
diff --git a/src/doors/vbbs/src/v3_store.c b/src/doors/vbbs/src/v3_store.c
new file mode 100644
index 0000000000000000000000000000000000000000..75b1ba547b993fe45687564bd26ba8dff2c5b728
--- /dev/null
+++ b/src/doors/vbbs/src/v3_store.c
@@ -0,0 +1,533 @@
+/*****************************************************************************
+ *
+ * File ..................: v3_store.c
+ * Purpose ...............: Store routines
+ * Last modification date : 20-Mar-2000
+ *
+ *****************************************************************************
+ * Copyright (C) 1999-2000
+ *
+ * Darryl Perry		FIDO:		1:211/105
+ * Sacramento, CA.
+ * USA
+ *
+ * This file is part of Virtual BBS.
+ *
+ * This Game is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Virtual BBS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Virutal BBS; see the file COPYING.  If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *****************************************************************************/
+
+
+#include "vbbs.h"
+#include "v3_store.h"
+#include "v3_defs.h"
+#include "v3_mci.h"
+#include "v3_basic.h"
+#include "v3_defs.h"
+
+void store()
+{
+	char ch1;
+	int done = 0;
+
+	while (!done)
+	{
+		text("0100"); // Computer Department Store
+		ch1 = od_get_answer("ABCDEQ");
+		switch (ch1)
+		{
+		case 'A':
+			text("0101"); // BBS Software Dept
+			buy_bbs_sw();
+			break;
+		case 'B':
+			text("0102"); // Computer Dept
+			buy_computer();
+			break;
+		case 'C':
+			text("0103"); // Modem Dept
+			buy_modems();
+			break;
+		case 'D':
+			text("0104"); // Hard Drive Dept
+			buy_harddrive();
+			break;
+		case 'E':
+			text("0105"); // Phone Company
+			phone_co();
+			break;
+		case 'Q':
+			text("0106"); // Quit
+			nl();
+			done = 1;
+			break;
+		}
+	}
+}
+
+void phone_co()
+{
+	char ch,ichar[20];
+	int numcanbuy,i1,i2;
+	long cost;
+
+	while(1){
+		text("0200");
+		ch=od_get_answer("QPACDSR");
+		switch(ch){
+			case 'A':
+				numcanbuy = (int)(plyr.funds/50.0f);
+				text("0201");	// Add
+				do
+				{
+					s32_2C(1,plyr.pacbell_installed);
+					s32_2C(2,plyr.pacbell_ordered);
+					if (plyr.pacbell_ordered>0)
+						text("0211"); // You have n lines in service
+					else
+						text("0210"); // You have n lines in service and n lines on order
+					if (numcanbuy>1)
+					{
+						text("0212"); // How many lines do you want to install?
+						*ichar = '\0';
+						od_input_str(ichar, 7, '0', '9');
+						inum = atoi(ichar);
+						if (inum>numcanbuy)
+						{
+							text("0213"); // You cannot afford to purchase that many lines.
+							inum = -1;
+						}
+					}
+					else
+					{
+						text("0214"); // You can not afford to install any more phone lines.
+						return;
+					}
+				} while(inum<0);
+				if (inum > 0)
+				{
+					i1 = 35;
+					if (plyr.pacbell_installed+plyr.pacbell_ordered>1)
+						i1 = 70;
+					i2 = 20;
+					if (plyr.pacbell_installed+plyr.pacbell_ordered>3)
+						i2 = 50;
+					s16_2A(1, i1);
+					s32_2C(2, plyr.pacbell_installed+plyr.pacbell_ordered);
+					text("0215"); // This installation will cost ...
+					if (yesno())
+					{
+						text("0216"); // Your order has been placed in the computer ...
+						plyr.funds -= i1;
+						plyr.pacbell_ordered += inum;
+					}
+				}
+				break;
+			case 'C':
+				text("0202");
+				i1=20;
+				if(plyr.pacbell_installed+plyr.pacbell_ordered>3)
+					i1=50;
+				if(plyr.callid)
+					text("0220");
+				else {
+					i2=plyr.pacbell_installed*i1;
+					s16_2A(1,i2);
+					text("0221");
+					if(yesno()) {
+						plyr.callid=1;
+						text("0222");
+						}
+					}
+				break;
+			case 'D':
+				text("0203");
+				do{
+					s32_2C(1,plyr.pacbell_installed-plyr.pacbell_broke);
+					s32_2C(2,plyr.pacbell_ordered);
+					if(plyr.pacbell_ordered>0)
+						text("0230");
+					else
+						text("0231");
+					text("0232");
+					od_input_str(ichar, 7, '0', '9');
+					inum=atoi(ichar);
+					if ( inum <= (int)plyr.pacbell_installed && inum>0){
+						s16_2A(1,inum);
+						text("0233");
+						if(yesno()){
+							plyr.pacbell_installed-=inum;
+							plyr.pacbell_ordered=0;
+							}
+						}
+				}while(inum<0);
+				break;
+			case 'P':
+				text("0204");
+				text("0239");
+				break;
+			case 'R':
+
+				s32_2C(1,plyr.pacbell_installed+plyr.pacbell_broke);
+				s32_2C(2,plyr.pacbell_broke);
+				s32_2C(3,plyr.pacbell_ordered);
+				if(plyr.callid)	str_2A(4,"Deactivated");
+				else			str_2A(4,"Active");
+				if(plyr.pacbell_installed>3){
+					cost=plyr.pacbell_installed*50;
+					str_2A(6,"Commercial");
+					}
+				else{
+					cost=plyr.pacbell_installed*20;
+					str_2A(6,"Residential");
+					}
+				if(plyr.callid)	cost+=9;
+				s32_2C(5,cost);
+				text("0205");
+				text("0238");
+				break;
+			case 'S':
+				text("0206");
+				nl();
+				if(plyr.funds>=65.0f){
+					s32_2C(1,plyr.pacbell_broke);
+					text("0240");
+					if(plyr.pacbell_broke<1)
+						text("0241");
+					else
+						switch(rand_num(9)){
+							case 0: text("0242");break;
+							case 1: text("0243");break;
+							case 2: text("0244");break;
+							case 3: text("0245");break;
+							case 4: text("0246");break;
+							case 5: text("0247");break;
+							case 6: text("0248");break;
+							case 7: text("0249");break;
+							case 8: text("0250");break;
+						}
+					text("0251");
+					plyr.funds -= 65.0f;
+					plyr.pacbell_installed+=plyr.pacbell_broke;
+					plyr.pacbell_broke=0;
+					}
+				else
+					text("0207");
+				break;
+			case 'Q': return;
+			}
+		}
+}
+
+void buy_modems()
+{
+	char ck, ch;
+	char ichar[21], kys[11] = "Q";
+	int  cbo = 0;
+	s32 xnum = 0;
+
+	s32 num_needed = (s32)(bbssw[plyr.bbs_sw].numlines) - (s32)(plyr.mspeed.low+plyr.mspeed.high+plyr.mspeed.digital);
+	if (num_needed>0)
+	{
+		// display purchase banner
+		text("0750");
+		// show modems available
+		ck = 0;
+		for (inum=0;inum<10;inum++)
+		{
+			if (((int)plyr.funds) >= mtype[inum].cost && ((int)plyr.cpu) >= mtype[inum].req)
+			{
+				LG = inum+65;
+				kys[inum+1] = LG;
+				kys[inum+2] = '\0';
+				ck = (char)inum;
+				cbo = 1;
+				char_2A(1, LG);
+				str_2A(2, mtype[inum].modemname);
+				s32_2C(3, mtype[inum].cost);
+				str_2A(4, computer[mtype[inum].req].cpuname);
+				text("0751");
+			}
+		}
+		// see if we were unable to buy any
+		if (!cbo)
+		{
+			text("0752");
+			return;
+		}
+		// find out which one we want to buy
+		ck += 65;
+		char_2A(1, ck);
+		text("0753");
+		ch = od_get_answer(kys);
+		// show answer
+		mci("%c\r\n", ch);
+		// check for exit
+		if (ch=='Q')
+			return;
+		// calculate what we can afford
+		s32 afford = (s32)(plyr.funds / (float)(mtype[ch-65].cost));
+		if (afford > num_needed)
+			afford = num_needed;
+		if (afford > plyr.actions)
+			afford = plyr.actions;
+		strcpy(TS,mtype[ch-65].modemname);
+		xnum = -1L;
+		do
+		{
+			s32_2C(1, afford);
+			str_2A(2, mtype[ch-65].modemname);
+			text("0754"); // You can afford ...
+			od_input_str(ichar, 7, '0', '9');
+			xnum = atol(ichar);
+			if (xnum>num_needed)
+			{
+				text("0755");
+				xnum = -1L;
+            }
+		} while(xnum<0L);
+
+		if (xnum == 0L)
+			return;
+
+		u32_2A(1,xnum);
+		text("0756");
+		if (yesno())
+		{
+            if((ch-65)<3)
+				plyr.mspeed.low += (unsigned int)xnum;
+			else
+				plyr.mspeed.high += (unsigned int)xnum;
+			plyr.funds -= (float)(mtype[ch-65].cost*xnum);
+			UseActions((int)xnum);
+			text("0757");
+		}
+		else
+			text("0758");
+	}
+	else
+		text("0759");
+}
+
+void security_menu()
+{
+	char ch;
+
+	while(1){
+		s32_2A(1, plyr.actions);
+		text("0540");
+		ch=od_get_answer("BCQ");
+		switch(ch){
+			case 'C': buy_alarm(); break;
+			case 'B': buy_security();	break;
+			case 'Q': return;
+			}
+		}
+}
+
+void buy_security()
+{
+	inum = (plyr.security+1)*100;
+	s16_2A(1,inum);
+	text("0541");
+	if (yesno())
+	{
+		if (plyr.funds<(plyr.security+1)*100)
+			text("0542");
+		else
+		{
+			text("0543");
+			plyr.funds-=((plyr.security+1)*100);
+			plyr.security += 1;
+			plyr.actions -= 10;
+        }
+    }
+	else
+		text("0544");
+}
+
+
+void buy_alarm()
+{
+	inum=(int)plyr.callid+10;
+	s16_2A(1,inum);
+	text("0545");
+	if(yesno())
+    	{
+		if(plyr.funds<(plyr.security+10))
+			text("0546");
+		else
+        	{
+			plyr.funds-=(((int)plyr.security+1)+10);
+			plyr.security += 1;
+			plyr.actions--;
+			text("0547");
+			}
+		}
+	else
+		text("0548");
+}
+
+void buy_insurance()
+{
+	text("0420");
+	if(yesno())
+		{
+		text("0421");
+		plyr.insurance=7;
+		}
+	else
+		text("0422");
+}
+
+void buy_bbs_sw()
+{
+    unsigned int i;
+	int		num1,cnt=1;
+    char    ch1,kys[12]="Q";
+	s32 TLong = 0L;
+
+    text("0730");
+    for(i=0;i<MAX_SW;i++) {
+        if (((int)plyr.funds) >= bbssw[i].cost && ((int)plyr.cpu) >= bbssw[i].req)
+		{
+            kys[cnt++]='A'+i;
+            kys[cnt]='\0';
+            LG='A'+i;
+        }
+        else
+            LG=' ';
+        sprintf(TS,"%-30s",bbssw[i].bbsname);
+        TLong=bbssw[i].cost;
+		char_2A(1,LG);
+		str_2A(2,bbssw[i].bbsname);
+		s32_2C(3,bbssw[i].cost);
+        text("0735");
+        if (plyr.bbs_sw>=i)
+            text("0732");
+        text("0733");
+        }
+	str_2A(4,kys);
+    text("0734");
+    ch1=od_get_answer(kys);
+    if(ch1=='Q')
+        return;
+    num1=ch1-65;
+    if(plyr.funds >= (float)bbssw[num1].cost) {
+        plyr.funds -= (float)bbssw[num1].cost;
+        plyr.bbs_sw=num1;
+		str_2A(1,bbssw[plyr.bbs_sw].bbsname);
+        text("0736");
+        UseActions(1);
+        }
+    else
+        text("0737");
+}
+
+void buy_computer()
+{
+    s16 	i;
+	s16		num1;
+    char    ch1, kys[23]="Q";
+
+    for(i=1;i<23;i++)
+        kys[i] = (char)NULL;
+
+    text("0740");
+    for(i=0;i<MAX_CPU;i++)
+	{
+        if (plyr.funds>=computer[i].cost)
+		{
+            kys[i+1] = 'A'+i;
+            LG = 'A'+i;
+        }
+        else
+        {
+            kys[i+1] = 0;
+            LG = ' ';
+        }
+		char_2A(1,LG);
+		str_2A(2,computer[i].cpuname);
+		s32_2C(3,computer[i].cost);
+        text("0742");
+        if (plyr.cpu>=i)
+            text("0743");
+        text("0744");
+	}
+    strcpy(TS,kys);
+	str_2A(4,kys);
+    text("0745");
+    ch1 = od_get_answer(kys);
+    if (ch1 == 'Q')
+        return;
+    num1 = ch1-65;
+    if (plyr.funds >= (float)computer[num1].cost)
+	{
+        plyr.funds -= (float)computer[num1].cost;
+        plyr.cpu = num1;
+		str_2A(1,computer[plyr.cpu].cpuname);
+        text("0746");
+        UseActions(1);
+	}
+    else
+        text("0747");
+    paws();
+}
+
+void buy_harddrive()
+{
+	int		i, num1,cnt=1;
+    char    ch1,ch2,kys[10]="Q";
+
+
+    text("0760");
+    for(i=0;i<MAX_HD;i++)
+        {
+        if(plyr.funds>=computer[i].cost)
+            {
+            kys[cnt++]='A'+i;
+            kys[cnt]='\0';
+            ch2='A'+i;
+            }
+        else
+            ch2=' ';
+        strcpy(TS,harddrive[i].hdsize);
+		char_2A(1,ch2);
+		str_2A(2,harddrive[i].hdsize);
+		s32_2C(3,harddrive[i].cost);
+        text("0761");
+        if (plyr.hd_size >= i)
+            text("0762");
+        text("0764");
+        }
+	str_2A(5,kys);
+    text("0765");
+    ch1=od_get_answer(kys);
+    if(ch1=='Q')
+        return;
+    num1=ch1-65;
+    if (plyr.funds >= (float)harddrive[num1].cost && ((int)plyr.cpu) >= harddrive[num1].req)
+	{
+        plyr.funds -= (float)harddrive[num1].cost;
+        plyr.hd_size=num1;
+        UseActions(1);
+		str_2A(1,harddrive[plyr.hd_size].hdsize);
+        text("0766");
+    }
+    else
+        text("0767");
+    paws();
+}
+
+
diff --git a/src/doors/vbbs/src/v3_store.h b/src/doors/vbbs/src/v3_store.h
new file mode 100755
index 0000000000000000000000000000000000000000..ad472e8afaf0ab7d6d9c61d37e35670869ac5617
--- /dev/null
+++ b/src/doors/vbbs/src/v3_store.h
@@ -0,0 +1,16 @@
+#ifndef _V3_STORE_H_
+#define _V3_STORE_H_
+
+void store(void);
+void phone_co(void);
+void buy_modems(void);
+void security_menu(void);
+void buy_security(void);
+void buy_alarm(void);
+void buy_insurance(void);
+void buy_bbs_sw(void);
+void buy_computer(void);
+void buy_harddrive(void);
+
+#endif
+
diff --git a/src/doors/vbbs/src/vbbs.c b/src/doors/vbbs/src/vbbs.c
new file mode 100644
index 0000000000000000000000000000000000000000..ae24c0645f0e6b00789adbb043f97b37fcc89a36
--- /dev/null
+++ b/src/doors/vbbs/src/vbbs.c
@@ -0,0 +1,1505 @@
+/*****************************************************************************
+ *
+ * File ..................: vbbs.c
+ * Purpose ...............: Main file
+ * Last modification date : 15-Mar-2001
+ *
+ *****************************************************************************
+ * Copyright (C) 1997-2001
+ *
+ * Darryl Perry		FIDO:		1:211/105
+ * Sacramento, CA.
+ * USA
+ *
+ * This file is part of Virtual BBS.
+ *
+ * This Game is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Virtual BBS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Virutal BBS; see the file COPYING.  If not, write to the
+ * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *****************************************************************************/
+
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+
+#if defined(_MSC_VER)
+#include "vc_strings.h"
+#elif defined(__BORLANDC__)
+#include "bc_str.h"
+#include <alloc.h>
+#else
+#include <sys/poll.h>
+#include <strings.h>
+#endif
+
+#include "vbbs.h"
+#include "v3_defs.h"
+#include "v3_basic.h"
+#include "v3_io.h"
+#include "v3_mci.h"
+#include "v3_mail.h"
+#include "v3_store.h"
+#include "v3_maint.h"
+#include "vbbs_db.h"
+
+time_t today;
+int report_flag = FALSE;
+static int gNeedCleanup = FALSE;
+
+classtype classes[5] =
+{
+	{ 1,  4, 4, 240 },
+  	{ 2, 10, 2,  40 },
+  	{ 3,  6, 2,  50 },
+  	{ 4,  5, 5, 190 },
+  	{ 5,  6, 1,  20 }
+};
+
+// from v3_defs.h
+s16   	actcount,
+		vircount,
+		vtxtcount,
+		vlcnt,
+		plyrcnt,
+		msgsrcount,
+		subscribe_arrive,
+		CONFIG_ACTIONS_PER_DAY,
+		inum, inum2,
+		virusscan,
+		chatstat;
+s16 	scant[6];
+char 	LG, TS[81];
+
+char 	gamedir[_MAX_PATH];
+
+tUserRecord plyr, othr, tmpplyr;
+tUserIdx	UsersIdx[MAX_USERS];
+hackrec 	hacker;
+
+hdtype  	harddrive[MAX_HD];
+cputype 	computer[MAX_CPU];
+modemtype  	mtype[MAX_MODEM];
+bbstype 	bbssw[20];
+char		skill_txt[10][30];
+
+#ifdef ODPLAT_WIN32
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
+{
+  	init(lpszCmdLine, nCmdShow);
+	vbbs_main();
+	return 0;
+}
+#else
+int main(int argc, char *argv[])
+{
+  	init(argc, argv);
+	vbbs_main();
+	return 0;
+}
+#endif
+
+void vbbs_main()
+{
+  	char ch = '\0',ttxt[91];
+
+	while(1)
+  	{
+		/* check for menu display */
+		if (!plyr.expert)
+		{
+			/* toggle expert field */
+			plyr.expert = 1;
+			/* show main menu */
+			sprintf(ttxt,"%smainmenu.ans",gamedir);
+			od_send_file(ttxt);
+		}
+
+		status();
+
+#if defined(__BORLANDC__) && defined(DEBUG)
+		od_printf("mem: %dk\n", coreleft()/1024);
+#endif
+
+		/* Main Prompt */
+		/* The s16_2A and other int2x functions are found in v3_mci.c */
+		u32_2A(1, plyr.users_f);
+		u32_2A(2, plyr.users_p);
+		s32_2A(3, plyr.actions);
+		s32_2A(4, plyr.employee_actions);
+		if(plyr.employee_actions>0)		text("0002");
+		else							text("0001");
+		ch = od_get_answer("ABCEHILMNPQRSTUVWX?");
+		/* Perform the appropriate action based on the user's choice */
+		switch(ch)
+		{
+		case 'A':
+			text("0050");
+			if(plyr.actions+plyr.employee_actions>0)	ans_chat();
+			else										not_enough();
+			break;
+		case 'B':
+			text("0051");
+			bank();
+			break;
+		case 'C':
+			text("0052");
+			if(plyr.actions+plyr.employee_actions>0)	charge();
+			else										not_enough();
+			break;
+		case 'E':
+			text("0053");
+			employ();
+			break;
+		case 'H':
+			nl();
+			od_send_file("vbbs.txt");
+			break;
+		case 'I':
+			text("0054"); /* Inspect */
+			if ((plyr.actions+plyr.employee_actions>0) && (plyr.funds >= 1.0f))
+			{
+				inspect();
+				advance();
+			}
+			else
+				not_enough();
+			break;
+		case 'L':
+			text("0055");
+			bbslist();
+			break;
+		case 'M':
+			text("0056"); /* Mail */
+			if (plyr.actions+plyr.employee_actions>0)
+				readmail();
+			else
+				not_enough();
+			break;
+		case 'N':
+			text("0057");
+			if(plyr.actions+plyr.employee_actions>0){
+				network();
+				}
+			else
+				not_enough();
+			break;
+		case 'P':
+			text("0058");
+			if(plyr.actions+plyr.employee_actions>0)
+				personal();
+			else
+				not_enough();
+			break;
+		case 'Q':
+			text("0059");
+			q2bbs();
+			break;
+		case 'R':
+			text("0060"); // Report
+			saveplyr(&plyr, plyr.plyrnum);
+			VBBS3_Report(&plyr, FALSE);
+			break;
+		case 'S':
+			text("0061");
+			if(plyr.actions+plyr.employee_actions>0)
+			{
+				store();
+				advance();
+			}
+			else
+				not_enough();
+			break;
+		case 'T':
+			text("0062");
+			text("0407");
+			if(!noyes()){
+				nl();
+				change_title();
+				change_handle();
+				}
+			nl();
+			break;
+		case 'U':
+			text("0063");	// Users Online
+			users_online();
+			break;
+		case 'V':
+			text("0064");
+			if (plyr.actions+plyr.employee_actions>0)
+			{
+				vbbsscan();
+				advance();
+			}
+			else
+				not_enough();
+			break;
+		case 'W':
+			text("0065"); // Work
+			if (check_first())
+			{
+				if (plyr.employee_actions>0)
+					text("0066"); // Employees help.
+				if (plyr.actions+plyr.employee_actions>0)
+				{
+					actions();
+					UseActions(1);
+					advance();
+				}
+				else
+					not_enough();
+			}
+			else
+				not_enough();
+			break;
+		case '?':
+			text("0067"); // Menu
+			sprintf(ttxt,"%smainmenu.ans",gamedir);
+			od_send_file(ttxt);
+			break;
+		}
+  	}
+}
+
+
+int ReadOrAddCurrentUser(void)
+{
+	int got_user = FALSE;
+
+	plyrcnt = 0;
+
+	while (readplyr(&othr,plyrcnt++) != FALSE)
+	{
+		if (strcmp(othr.realname, od_control.user_name) == 0)
+		{
+			got_user = TRUE;
+			plyr = othr;
+		}
+	}
+
+	plyrcnt--;
+
+	if (!got_user && (plyrcnt < MAX_USERS))
+	{
+		new_user();
+		text("0005");
+		change_title();
+		change_handle();
+		if (saveplyr(&plyr,plyr.plyrnum)==FALSE)
+			got_user = FALSE;
+		else
+		{
+			got_user = TRUE;
+			plyrcnt++;
+		}
+	}
+
+	return got_user;
+}
+
+void vbbs_cleanup(void)
+{
+	if (gNeedCleanup)
+	{
+		/* clear our flag so this only happens once */
+		gNeedCleanup = FALSE;
+		/* save the player */
+		if (plyr.plyrnum >= 0)
+			saveplyr(&plyr, plyr.plyrnum);
+		// close all databases
+		gSystemDB_shutdown();
+		/* make sure the lock file gets removed */
+		vbbs_io_unlock_game();
+	}
+}
+
+void q2bbs()
+{
+	/* delete players with a score less than 1 */
+	if (plyr.skore_now<1)
+	{
+		plyr.status=DELETED;
+	}
+	text("0009");	/* Disconnect from your service? */
+	if (yesno())
+	{
+		/* display actions left */
+		s32_2A(1, plyr.actions);
+		text("0010");
+		paws();
+		topten();
+		paws();
+		str_2A(1, "BBS");
+		text("0011");
+		/* save player and cleanup lockfile */
+		vbbs_cleanup();
+		/* exit open doors */
+		od_exit(0, FALSE);
+	}
+	else
+		nl();
+}
+
+void employ()
+{
+	int y;
+
+	y=plyr.mspeed.high+plyr.mspeed.low+plyr.mspeed.digital;
+	inum2=(y/100)+1;
+	s16_2A(1,inum2);
+	nl();
+	nl();
+	if(y<100)
+		text("0090");
+	else{
+		text("0091");
+		if(yesno()){
+			u32_2A(1,(y*2000)*4);
+			text("0092");
+			if(((y*2000)*4)>plyr.funds)
+				text("0093");
+			if((u32)(plyr.employees*2000)>plyr.funds)
+				text("0094");
+			}
+		else{
+			text("0095");
+			UseActions(1);
+			return;
+			}
+		text("0096");
+		plyr.employees+=inum2;
+		}
+}
+
+void actions()
+{
+	int chance = rand_num(100) + 1; /* 1 - 100 */
+
+	nl();
+	nl();
+
+	/* if we haven't scanned lately, small chance of a virus */
+	if ((virusscan > 10) && (chance <= 15))
+		virus_det();
+	else
+	{
+		/* grab a random action */
+		int action = rand_num(actcount) + 1;
+		/* display the results */
+		read_actions(action);
+	}
+}
+
+void exit_callback(void)
+{
+	/* make sure we cleaned up */
+	vbbs_cleanup();
+}
+
+#ifdef ODPLAT_WIN32
+void init(LPSTR lpszCmdLine, int nCmdShow)
+#else
+void init(int argc, char *argv[])
+#endif
+{
+	char vbbstext[121];
+
+ #if defined(VBBS_WIN32)
+	char cmd_line[256];
+	char* ptr;
+
+	// copy in the full command line
+	strcpy(cmd_line, GetCommandLine());
+	// find the first space
+	ptr = strchr(cmd_line, ' ');
+	// if there is no space, use the current directory
+	if (ptr)
+	{
+		// make it the end of the string
+		*ptr = 0;
+		// find the last slash
+		ptr = strrchr(cmd_line, '\\');
+		// if no slash, then use current directory
+		if (ptr)
+		{
+			// skip the slash
+			ptr++;
+			// make it the end
+			*ptr = 0;
+			// if the first char is a quote, then it's a special case
+			if (cmd_line[0] == '\"')
+				strcpy(gamedir, cmd_line+1);
+			else
+				strcpy(gamedir, cmd_line);
+		}
+		else
+		{
+			strcpy(gamedir, ".\\");
+		}
+	}
+	else
+	{
+		strcpy(gamedir, ".\\");
+	}
+ #elif defined(VBBS_DOS)
+	char* ptr;
+	strcpy(gamedir, argv[0]);
+	ptr = strrchr(gamedir, '\\');
+	ptr[1] = 0;
+ #else
+	char* ptr;
+	strcpy(gamedir, argv[0]);
+	ptr = strrchr(gamedir, '/');
+	ptr[1] = 0;
+ #endif
+	basedir(gamedir);
+
+	strcpy(od_control.od_prog_name, "Virtual BBS");
+    strcpy(od_control.od_prog_version, "Version "VBBS_VERSION);
+	strcpy(od_control.od_prog_copyright, "Copyright 1999-2002 by Darryl Perry");
+	strcpy(od_control.od_logfile_name, "vbbs.log");
+	strcpy(od_registered_to, "Darryl Perry");
+#ifdef ODPLAT_WIN32
+	// call new parse cmd line
+  	od_control.od_cmd_show = nCmdShow;
+	od_parse_cmd_line(lpszCmdLine);
+#else
+	od_parse_cmd_line(argc, argv);
+#endif
+	//od_registration_key = 123456L; /* open doors reg code goes here */
+	od_init();
+	vbbs_randomize();
+	od_clr_scr();
+	fillvars();
+
+	sprintf(vbbstext,"/n%s, The Virtual BBS Simulation Game", od_control.od_prog_name);
+  	mci(vbbstext);
+
+	nl();
+	od_repeat('\304',78);nl();
+	mci(od_control.od_prog_copyright); nl();
+	mci("Copyright 2002-2004 by Michael Montague"); nl();
+	mci("Version %s", VBBS_VERSION); nl();
+	nl();
+	mci("Maintained by Vagabond Software"); nl();
+	mci("http://vs3.vbsoft.org/"); nl();
+
+	// tell open doors never to write EXITINFO.BBS
+	od_control.od_extended_info = 0;
+	// create a multinode lock-out file for the time being
+	if (vbbs_io_lock_game(od_control.user_name))
+	{
+		nl();
+		od_printf("Another user is currently playing Virtual BBS.  Please try again later.\r\n");
+		paws();
+		// exit open doors
+		od_exit(1, FALSE);
+	}
+	// set our exit function to clean up the node file
+	od_control.od_before_exit = exit_callback;
+	// set the dirty flag
+	gNeedCleanup = TRUE;
+	// set an invalid player
+	plyr.plyrnum = -1;
+	// get today
+	time(&today);
+	// open all the databases
+	gSystemDB_init();
+	// do daily maint
+	v3_maint_daily();
+	// initialize game variables
+	CONFIG_ACTIONS_PER_DAY = readapd();
+	actcount = count_actions();
+	vtxtcount = count_vtext();
+	msgsrcount = count_msgsr();
+	vlcnt = vlcount();
+	plyrcnt = countplyrs();
+	subscribe_arrive = -99;
+#ifdef DEBUG
+	// show the user name we got
+	od_printf("User: %s\r\n", od_control.user_name);
+#endif
+	// get current user or add him
+	if (!ReadOrAddCurrentUser())
+	{
+		nl();
+		od_printf("Unable to access user file.  File may be locked or full.\r\n");
+		paws();
+		vbbs_io_unlock_game();
+		od_exit(1, FALSE);
+	}
+	// display a message if they haven't played recently
+	get_time_diff();
+	// if player ordered phone lines, they are now available
+	if (plyr.pacbell_ordered>0)
+	{
+		s32_2C(1,plyr.pacbell_ordered);
+		text("0801");
+		plyr.pacbell_installed += plyr.pacbell_ordered;
+		plyr.pacbell_ordered = 0;
+	}
+	s16_2A(1,plyrcnt);
+	text("0802");
+	plyr.skore_before=plyr.skore_now;
+	text("0810");
+	if ((plyr.hackin[1] == 0) && (plyr.hackin[2] == 0))
+		text("0811");
+	else
+	{
+		text("0812");
+		if (plyr.insurance>0)
+		{
+			text("0813");
+			text("0814");
+			plyr.funds += 200;
+			plyr.insurance = 0;
+		}
+		text("0815");
+		if (plyr.hackin[1] == 0)
+			text("0816");
+	}
+	text("0817");
+	if(plyr.cpu>=0 && plyr.cpu<11)	text("0818");
+	else                            text("0819");
+
+	text("0820");
+	if(plyr.security<1)				text("0821");
+	else	if(plyr.security==-1.0)	text("0822");
+			else					text("0823");
+
+	text("0824");
+	if(plyr.callid<1)				text("0826");
+	else	if(plyr.callid==-1.0)	text("0827");
+			else					text("0828");
+	text("0829");
+	if(plyr.pacbell_broke)			text("0830");
+	else							text("0831");
+	if(plyr.pacbell_installed<1)
+		text("0833");
+	if(plyr.lastbill>5)
+	{
+		if(plyr.pacbell_installed>3)
+			inum=plyr.pacbell_installed*50;
+		else
+			inum=plyr.pacbell_installed*20;
+		if(plyr.callid)
+			inum+=9;
+		inum+=4;
+		s16_2A(1,inum);
+		text("0834");
+		plyr.funds-=inum;
+		plyr.lastbill=0;
+	}
+	else
+		plyr.lastbill++;
+
+	if ((today-plyr.laston)>(1440L*60L))
+	{
+		if (plyr.actions >= 0)
+			plyr.actions = 0;
+		plyr.actions += CONFIG_ACTIONS_PER_DAY;
+		if (plyr.employees>0)
+			plyr.employee_actions += (unsigned int)((float)plyr.employees * (CONFIG_ACTIONS_PER_DAY*0.8f));
+		plyr.laston = today;
+		if (plyr.pacbell_ordered>0)
+		{
+			s32_2C(1,plyr.pacbell_ordered);
+			text("0835");
+			plyr.pacbell_installed+=plyr.pacbell_ordered;
+			plyr.pacbell_ordered=0;
+		}
+		if(plyr.insurance>0){
+			if(plyr.funds>=1){
+				plyr.funds--;
+				text("0836");
+                plyr.insurance--;
+                if(plyr.insurance<3)
+					text("0837");
+				}
+			else{
+				text("0838");
+				plyr.insurance=0;
+				}
+			}
+            plyr.hacktoday=0;
+		if(plyr.education[0]>0.0 || plyr.education[1]>0.0){
+			text("0839");
+			plyr.education[0] -= 0.2f;
+			if (plyr.education[0]<0.0f)
+				plyr.education[0] = 0.0f;
+			plyr.education[1] -= 0.2f;
+			if(plyr.education[1]<0.0f)
+				plyr.education[1] = 0.0f;
+			saveplyr(&plyr,plyr.plyrnum);
+			}
+		}
+
+	chatstat = -(rand_num(CONFIG_ACTIONS_PER_DAY/3)+(CONFIG_ACTIONS_PER_DAY/6));
+	if (plyr.msgs_waiting)
+		text("0840");
+
+	text("0841");
+	text("0842");
+}
+
+void virus_det()
+{
+	// get random virus
+	int virus = rand_num(vtxtcount) + 1;
+	// display the results
+	text("0870");
+	read_vtext(virus);
+	text("0871");
+	virusscan = 0;
+}
+
+void VBBS3_Report(tUserRecord* pl, int bInspect)
+{
+	int rankplayer = rankplyr(pl->plyrnum);
+	s32 total_modems = pl->mspeed.low + pl->mspeed.high + pl->mspeed.digital;
+	s32 score_diff = (s32)pl->skore_now - (s32)pl->skore_before;
+	u32 unused_ports = 0;
+
+	// calculate unused ports
+	if (bbssw[pl->bbs_sw].numlines < total_modems)
+		unused_ports = bbssw[pl->bbs_sw].numlines - total_modems;
+	
+	str_2A(0, pl->bbsname);
+	str_2A(1, computer[pl->cpu].cpuname);
+	str_2A(2, harddrive[pl->hd_size].hdsize);
+	s16_2A(3, pl->mspeed.low);
+	s16_2A(4, pl->mspeed.high);
+	s16_2A(5, pl->mspeed.digital);
+	u32_2A(6, bbssw[pl->bbs_sw].numlines);
+	str_2A(7, bbssw[pl->bbs_sw].bbsname);
+	u32_2A(8, unused_ports);
+	s16_2A(9, pl->pacbell_installed);
+	s16_2A(10, pl->pacbell_ordered);
+	s16_2A(23, pl->pacbell_broke);
+	u32_2A(11, pl->users_f);
+	u32_2A(12, pl->users_p);
+	str_2A(13, skill_txt[pl->skill_lev]);
+	s16_2A(14, (int)pl->education[0]); //float
+	s16_2A(15, (int)pl->education[1]); //float
+	s16_2A(16, pl->callid);
+	s32_2A(17, pl->actions);
+	s16_2A(18, pl->msgs_waiting);
+	u32_2A(19, pl->skore_before);
+	s32_2A(20, score_diff);
+	s16_2A(21, rankplayer);
+	u32_2A(22, pl->skore_now);
+
+									text("0700"); // ~SM~SM
+	if (bInspect)					text("0701"); // Your nearest competition:~SM
+									text("0702"); // Report on the setup of
+									text("0703"); // ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+									text("0704"); // Computer:
+									text("0705"); // Storage:
+	if (pl->mspeed.low>0)			text("0706"); // Modems: ~&3 2400bps
+	if (pl->mspeed.high>0)  		text("0707"); // Modems: ~&4 High Speed
+	if (pl->mspeed.digital>0)  		text("0708"); // Modems: ~&5 Digital
+									text("0709"); // Software: Can support up to ~&6 line(s) <~&7> (~&8 ports unused)
+									text("0710"); // Phone Lines: ~&9
+	if (pl->pacbell_ordered>0)		text("0711"); // Phone Order: ~&A phone line to be installed.
+	if (pl->pacbell_broke>0)		text("0727"); // Line Status: ~&N phone lines are damaged.~SM
+									text("0712"); // Users: ~&B free, ~&C paying.
+
+	if (!bInspect)
+	{
+									text("0713"); // Experience: ~&D~SM
+									text("0714"); // Education: ~&E Public, ~&F Private.~SM
+									text("0715"); // Caller ID: ~&G~SM
+									text("0716"); // Actions: ~&H left today.~SM
+		if (pl->msgs_waiting>0)		text("0717"); // Messages: ~&I waiting to be read~SM
+		if (pl->insurance>0)		text("0719"); // Insurance: NO COVERAGE~SM
+		else						text("0718"); // Insurance: You're Covered!~SM
+		if (pl->skore_before<pl->skore_now)
+		{
+									text("0720"); // Start Score: ~&J (UP by ~&K points)~SM
+		}
+		if (pl->skore_before>pl->skore_now)
+		{
+									text("0721"); // Start Score: ~&J (DOWN by ~&K points)~SM
+		}
+									text("0722"); // Score: ~&M points!
+		if (pl->skore_now<1)		text("0723"); // (WORK Harder!)
+		if (rankplayer == 0)		text("0724"); // (You are the #1 BBS!)~SM
+		else						text("0725"); // (You are ~&L away from the #1 BBS!)~SM
+	}
+	else
+	{
+		text("0726"); // ~SM`0FThis is the latest available information about your nearest competition.~SM
+		plyr.funds -= 1.0f;
+	}
+}
+
+void bank()
+{
+	s32_2C(1,(s32)plyr.funds);
+	if(plyr.funds>=100000.0f) {
+		text("0260");
+		if(noyes())
+        	return;
+        else
+			{
+			text("0261");
+			plyr.funds-=(plyr.funds/5.0f);
+            }
+        }
+	text("0262");
+}
+
+void charge()
+{
+	char t1[2];
+	int	j,k;
+
+	if((plyr.users_f+plyr.users_p)<50)
+		text("0270");
+	else{
+		text("0271");
+		if(yesno()){
+			text("0272");
+			t1[0]=od_get_answer("0123456");
+			t1[1]='\0';
+			plyr.charge_lev=atoi(t1);
+			if(plyr.charge_lev>0){
+				j = rand_num((int)(plyr.users_f/2));
+				k = rand_num((int)(plyr.users_f-j));
+				plyr.users_p+=j;
+				plyr.users_f-=j;
+				plyr.users_f-=k;
+				if(plyr.users_f<1)
+					plyr.users_f=0;
+				inum=j;
+				s16_2A(1,inum);
+				text("0273");
+				inum=k;
+				s16_2A(1,inum);
+				text("0274");
+				}
+			advance();
+			}
+		}
+}
+
+void delay1(int msec)
+{
+	/* this releases time slices properly in dos or windows */
+	od_sleep(msec);
+}
+
+void readmail()
+{
+	unsigned int i;
+	int j,k,ll,q;
+
+	if(plyr.msgs_waiting>0)
+	{
+		s16_2A(1,plyr.msgs_waiting);
+		text("0280"); /* You have n messages waiting to be read. Would you like to answer your mail now? */
+		if(yesno())
+		{
+			upskore(plyr.msgs_waiting);
+			if (plyr.employee_actions>0)
+				text("0281"); // Employees help.
+			k = (40/plyr.msgs_waiting);
+			if (k<1)
+			{
+            	k = 1;
+				plyr.msgs_waiting = 40;
+			}
+			text("0282");
+			for(i=0,ll=0;i<plyr.msgs_waiting;i++)
+			{
+				for(q=0;q<k;q++){
+					fflush(stdout);
+					text("0283");
+					}
+				if(plyr.employee_actions>0)
+					delay1(250);
+				else
+					delay1(500);
+                ll+=k;
+			}
+			if (ll<41)
+				for (q=ll;q<41;q++)
+					text("0283");
+			delay1(500);
+			UseActions(1);
+			plyr.msgs_waiting=0;
+			j = rand_num(100);
+//			mci(" (%d)",j);
+			if(j>69){
+				prob_mail();
+				text("0284");
+			} else	{
+                nl();
+				j = rand_num((plyr.skill_lev+1)*2);
+				text("0285");
+				if(j>0)
+					{
+					inum=j;
+					s16_2A(1,inum);
+					text("0286");
+					plyr.users_f+=j;
+					}
+				nl();
+				}
+			}
+        }
+	else
+		text("0287");
+}
+
+void prob_mail()
+{
+	int 	k,i,j,tmp1[7]={1,2,5,0,8,9,0},tmp2[7]={0,0,50,0,5,0,0};
+
+	text("0290");
+
+	if(plyr.msgs_waiting>2)
+		j = rand_num(3);
+	else
+		j=plyr.msgs_waiting-1;
+
+	for(i=j;i>=0;i--)
+	{
+		inum=i+1;
+		UseActions(1);
+		s16_2A(1,inum);
+		text("0291");
+		k = rand_num(msgsrcount);
+		read_msgsr(k);
+		text("0292");
+		switch(od_get_answer("DIPRL"))
+		{
+		case 'D':
+			text("0293");
+			act_change(ACT_SUB_FREE_USERS,((plyr.skill_lev+1)*8),1);
+            downskore((plyr.skill_lev+1)*10);
+			break;
+		case 'I':
+			text("0294");
+			act_change(ACT_SUB_FREE_USERS,1,1);
+            downskore(plyr.skill_lev/5);
+			break;
+		case 'P':
+			text("0295");
+			j = rand_num(7);
+			act_change(tmp1[j],tmp2[j],1);
+			upskore((plyr.skill_lev+1)*8);
+			break;
+		case 'R':
+			text("0296");
+			act_change(ACT_SUB_FREE_USERS,1,1);
+			downskore((plyr.skill_lev+1)*4);
+			break;
+		case 'L':
+			text("0297");
+			act_change(ACT_SUB_PAY_USERS,1,1);
+			downskore((plyr.skill_lev+1)*8);
+			break;
+		}
+	}
+}
+
+void topten()
+{
+	int i;
+	text("0298");
+	sort_users();
+	for(i=0;i<10 && i<plyrcnt;i++){
+		inum2=i+1;
+		if(readplyr(&othr,UsersIdx[i].recno)!=FALSE)
+			toptenrecord(UsersIdx[i].recno);
+        }
+}
+
+void vbbsscan()
+{
+	int 	i,j,k,ts=1;
+
+	str_2A(1,harddrive[plyr.hd_size].hdsize);
+	s16_2A(2,(plyr.hd_size+1)*60);
+	text("0020");
+
+	if(plyr.hd_size>2){
+		text("0021");
+		if(yesno()){
+			ts=2;
+			text("0022");
+			}
+		else{
+			ts=1;
+			text("0023");
+			}
+		}
+	else{
+		ts=1;
+		text("0023");
+		}
+
+	text("0024");
+	for(i=0;i<13;i++){
+		fflush(stdout);
+		text("0025");
+		delay1(250);
+		}
+	nl();
+	j = rand_num(virusscan*3/ts);
+	if(j>virusscan)	{
+		text("0026");
+		k = rand_num(6)+1;
+        for(;k>0;k--)
+        	viruslist();
+		}
+	else
+		text("0027");
+
+	text("0028");
+	if(ts==2)
+		virusscan -= rand_num(5)+5;
+	else
+		virusscan = 0;
+	UseActions(1);
+	upskore(10-abs(virusscan));
+}
+
+int capacity(void)
+{
+	unsigned long totusr, tmp1;
+	/* unsigned long tmp2; */
+	int totmdms;
+
+	totusr = plyr.users_f+plyr.users_p;
+	totmdms = plyr.mspeed.low+plyr.mspeed.high+plyr.mspeed.digital;
+	inum = plyr.pacbell_installed;
+	if (inum>totmdms)
+		inum = totmdms;
+
+	/* not currently used
+	if ((plyr.mspeed.high+plyr.mspeed.digital)>0)
+		tmp2 = totusr/(plyr.mspeed.high+plyr.mspeed.digital);
+	else
+		tmp2 = 0;
+	*/
+
+	if (inum>0)
+		tmp1 = totusr/inum;
+	else
+		tmp1 = 0;
+	inum2 = (int)(tmp1/4);
+
+	return inum2;
+}
+
+/* this fixes a bug in the MSVC optimizer (v1.52) */
+#if defined(_MSC_VER) && !defined(_WIN32)
+#pragma optimize ("", off)
+#endif
+
+int check_first()
+{
+/*	int cap; */
+/*	int tmp1, tmp2; */
+
+	if (plyr.actions<1)
+		return FALSE;
+
+	/* FIXME: this function is completely broken */
+#if 0
+	/* calculate the bbs capacity */
+	cap = capacity();
+	/* see if we have any modems */
+	if (cap > 0)
+	{
+		/* more than 75% full? */
+		if (cap > 75)
+		{
+			/* more than 90% full? */
+			if (cap > 90)
+			{
+				tmp1 = rand_num((int)plyr.users_f)/8;
+				tmp2 = rand_num((int)plyr.users_p)/8;
+				plyr.users_f -= tmp1;
+				plyr.users_p -= tmp2;
+				inum = tmp1;
+				int16_2A(1, inum);
+				text("0300");
+				inum = tmp2;
+				int16_2A(1, inum);
+				text("0301");
+			}
+			else
+				text("0302"); /* Your users are complaining ... */
+		}
+	}
+	else
+	{
+		text("0862");  /* WARNING You have no modems ... */
+		plyr.mspeed.low = 1;
+	}
+#endif
+
+	return TRUE;
+}
+
+#if defined(_MSC_VER) && !defined(_WIN32)
+#pragma optimize ("", on)
+#endif
+
+void status()
+{
+	if(chatstat>=0){
+		if(chatstat>0){
+			text("0303");
+			}
+		else{
+			text("0304");
+			}
+		}
+
+	if (subscribe_arrive>0 && plyr.users_p>0)
+	{
+		text("0305");
+		act_change(ACT_ADD_FUNDS,(int)((plyr.users_p/3)*(plyr.charge_lev+1)),1);
+		subscribe_arrive = -99;
+	}
+	if(plyr.skill_lev>10)	plyr.skill_lev=10;
+
+	if(plyr.msgs_waiting!=0){
+		if (rand_num(100)>50){
+			inum = (int)(plyr.users_p/6);
+			if (inum>((int)plyr.msgs_waiting)){
+				inum2 = rand_num(plyr.msgs_waiting);
+				if(inum2>((int)plyr.users_p)){
+					mci("~CR~CRYour paying users don't like it when you ignore your emails.");
+					act_change(ACT_SUB_PAY_USERS,inum2,1);
+					}
+				}
+			}
+		else{
+			inum = ((int)plyr.users_f/6);
+			if(inum>((int)plyr.msgs_waiting)){
+				inum2 = rand_num((int)plyr.msgs_waiting);
+				if(inum2>((int)plyr.users_f)){
+					mci("~CR~CRYour free users don't like it when you ignore your emails.");
+					act_change(ACT_SUB_FREE_USERS,inum2,1);
+					}
+				}
+			}
+		}
+}
+
+void users_online()
+{
+	int totmdms;
+
+	totmdms = plyr.mspeed.low+plyr.mspeed.high+plyr.mspeed.digital;
+	inum = plyr.pacbell_installed;
+	if (inum>totmdms)
+		inum = totmdms;
+
+	inum2 = capacity();
+
+	s16_2A(1,inum);
+	s16_2A(2,inum2);
+
+	text("0880");
+	if ((plyr.mspeed.high+plyr.mspeed.digital)>0)
+	{
+		inum-=plyr.mspeed.low;
+		inum2 = (int)(inum2/4);
+		s16_2A(1,inum);
+		s16_2A(2,inum2);
+		text("0881");
+	}
+}
+
+void UseActions(int numacts)
+{
+	s16 j;
+
+	if (plyr.employee_actions>0)
+	{
+		j = rand_num(9)+1;
+		if (plyr.employee_actions<j)
+		{
+			plyr.actions--;
+			text("0300");
+		}
+		plyr.employee_actions -= j;
+		if (plyr.employee_actions<0)
+			plyr.employee_actions = 0;
+	}
+	else
+	{
+		plyr.actions -= numacts;
+	}
+}
+
+void advance()
+{
+	u32 level = (((plyr.skill_lev+1)*(plyr.skill_lev+1))*1000);
+	if (level<plyr.skore_now)
+		plyr.skill_lev++;
+	if (rand_num(10)>4)
+		plyr.msgs_waiting++;
+	virusscan++;
+	chatstat++;
+    subscribe_arrive++;
+}
+
+void ans_chat()
+{
+	int j;
+
+	if(chatstat<0)
+		text("0310");
+	else{
+		nl();
+		nl();
+		j = rand_num(4);
+		switch(j){
+			case 0:
+				text("0311");
+				act_change(ACT_ADD_FREE_USERS,0,1);
+				break;
+			case 1:
+				text("0312");
+				act_change(ACT_ADD_FUNDS,50,1);
+				break;
+			case 2:
+				text("0313");
+				downskore((plyr.skill_lev+1)*2);
+				break;
+			case 3:
+				text("0314");
+				downskore((plyr.skill_lev+1)*3);
+				break;
+			}
+		}
+	chatstat = -rand_num(CONFIG_ACTIONS_PER_DAY/3);
+	advance();
+	UseActions(1);
+}
+
+void not_enough()
+{
+	text("0315");
+}
+
+void bbslist()
+{
+	char ttxt[512];
+	text("0890");
+	sort_users();
+	for(inum=0;inum<MAX_USERS && inum<plyrcnt;inum++){
+		inum2=inum+1;
+		readplyr(&othr,UsersIdx[inum].recno);
+		s16_2A(1,inum+1);
+		str_2A(2,othr.bbsname);
+		str_2A(3,othr.sysopname);
+		u32_2A(4,othr.skore_now);
+		mcigettext("0894",ttxt);
+		mcimacros(ttxt);
+		str_2A(5,ttxt);
+		s16_2A(6,strlen(ttxt));
+		mcigettext("0895",ttxt);
+		mcimacros(ttxt);
+		str_2A(7,ttxt);
+		mciEseries(ttxt);
+		text("0891");
+		if (UsersIdx[inum].recno == (int)plyr.plyrnum)
+			text("0892");
+		else
+			text("0893");
+		}
+}
+
+void toptenrecord(int i)
+{
+	u32 lines, users;
+
+	readplyr(&othr,i);
+	users = (u32)(othr.users_f+othr.users_p);
+	lines = othr.mspeed.high+othr.mspeed.low+othr.mspeed.digital;
+	// FIXME: should pacbell_installed be unsigned?
+	if (lines > (u32)(othr.pacbell_installed))
+		lines = othr.pacbell_installed;
+	// FIXME: should bbssw[].numlines be unsigned?
+	if (lines > (u32)(bbssw[othr.bbs_sw].numlines))
+		lines = (u32)bbssw[othr.bbs_sw].numlines;
+
+	u32_2A(1,users);
+	u32_2A(2,lines);
+	str_2A(3,othr.sysopname);
+	str_2A(5,othr.bbsname);
+	u32_2A(6,othr.skore_now);
+	s16_2A(4,rankplyr(i)+1);
+	text("0900");
+}
+
+void change_title()
+{
+	char	tstr[31];
+	int     foundone=0,i;
+
+	text("0400");
+	do{
+		text("0401");
+		*tstr='\0';
+		od_input_str(tstr,30,32,127);
+		if(strlen(tstr)>0){
+			sort_users();
+			foundone=TRUE;
+			for(i=0;i<MAX_USERS && i<plyrcnt;i++){
+				readplyr(&othr,UsersIdx[i].recno);
+				if(strcmp(othr.bbsname,tstr)==0 && strcmp(othr.realname,plyr.realname)!=0){
+					text("0402");
+					foundone=FALSE;
+					}
+				}
+			}
+		else
+			sprintf(tstr,"%s's BBS",plyr.realname);
+		}while(!foundone);
+	strcpy(plyr.bbsname,tstr);
+}
+
+
+void change_handle()
+{
+	char	tstr[31];
+	int     foundone=0,i;
+
+	do{
+		text("0404");
+		*tstr='\0';
+		od_input_str(tstr,30,32,127);
+		if(strlen(tstr)>0){
+			sort_users();
+			foundone=TRUE;
+			for(i=0;i<MAX_USERS && i<plyrcnt;i++){
+				readplyr(&othr,UsersIdx[i].recno);
+				if(strcmp(othr.sysopname,tstr)==0 && strcmp(othr.realname,plyr.realname)!=0){
+					text("0405");
+					foundone=FALSE;
+					}
+				}
+			}
+		else
+			strcpy(tstr,plyr.realname);
+		}while(!foundone);
+	strcpy(plyr.sysopname,tstr);
+}
+
+void personal()
+{
+	text("0410");
+	while(1){
+		s32_2A(1, plyr.actions);
+		text("0413");
+		text("0411");
+		switch(od_get_answer("QLUSIBRD?")){
+			case 'Q':
+				text("0412");
+				return;
+			case 'L':
+				if(plyr.actions>0)
+				{
+					learn();
+					advance();
+                }
+				else
+                	not_enough();
+				break;
+            case 'U':
+				if(plyr.actions>0){
+					use_skill();
+					advance();
+					}
+				else
+					not_enough();
+				break;
+			case 'S':
+				if(plyr.actions>0){
+					security_menu();
+                    advance();
+                    }
+                else
+                	not_enough();
+                return;
+			case 'I':
+				if(plyr.actions>0){
+					buy_insurance();
+                    advance();
+                    }
+                else
+                	not_enough();
+				break;
+			case 'B':
+                bank();
+				break;
+			case 'R':
+				saveplyr(&plyr,plyr.plyrnum);
+				VBBS3_Report(&plyr, FALSE);
+				paws();
+				break;
+			}
+		}
+}
+
+void inspect()
+{
+	int 		myrank;
+	tUserRecord	inspect;
+
+	UseActions(1);
+
+    sort_users();
+    myrank = rankplyr(plyr.plyrnum);
+    if (myrank<1)
+		text("0490");
+	else
+	{
+		saveplyr(&plyr, plyr.plyrnum);
+		readplyr(&inspect, UsersIdx[myrank-1].recno);
+		VBBS3_Report(&inspect, TRUE);
+    }
+}
+
+int	findBBS()
+{
+	char istr[36],tstr1[36],tstr2[36];
+	int  i,x=-1,done=FALSE;
+
+	sort_users();
+	while(!done){
+		text("0491");
+		*istr='\0';
+		od_input_str(istr,35,32,127);
+		if(istr[0]=='\0')  {done=TRUE; x=-1; }
+		if(istr[0]=='?' && !done) bbslist();
+		else {
+			if(!done){
+				strcpy(tstr1,istr);
+				strupr(tstr1);
+				for(i=0;i<MAX_USERS && i<plyrcnt;i++) {
+					readplyr(&othr,UsersIdx[i].recno);
+					strcpy(tstr2,othr.bbsname);
+					strupr(tstr2);
+					if(strstr(tstr2,tstr1)) {
+						str_2A(1,othr.bbsname);
+						text("0492");
+						if(yesno()){
+							x=i;
+							done=TRUE;
+							}
+						}
+					}
+				}
+			}
+		}
+	readplyr(&othr,UsersIdx[x].recno);
+	return(x);
+}
+
+void sort_users()
+{
+	tUserIdx	temp;
+	unsigned int ii,out,in;
+
+	saveplyr(&plyr,plyr.plyrnum);
+
+	ii=0;
+	for(ii=0;ii<MAX_USERS;ii++)
+		UsersIdx[ii].skore=-1L;
+
+	ii=0;
+	while(readplyr(&othr,ii)){
+		UsersIdx[ii].skore=othr.skore_now;
+		UsersIdx[ii].recno=othr.plyrnum;
+		ii++;
+		}
+
+	for(out=0; out<ii-1;out++)
+		for(in=out+1;in<ii;in++)
+			if(UsersIdx[out].skore<UsersIdx[in].skore){
+				temp=UsersIdx[out];
+				UsersIdx[out]=UsersIdx[in];
+				UsersIdx[in]=temp;
+				}
+}
+
+long filesize(FILE *stream)
+{
+   long curpos, length;
+
+   curpos = ftell(stream);
+   fseek(stream, 0L, SEEK_END);
+   length = ftell(stream);
+   fseek(stream, curpos, SEEK_SET);
+   return length;
+}
+
+int rankplyr(int plyrno)
+{
+	int i;
+
+	sort_users();
+    for(i=0;i<MAX_USERS && i<plyrcnt;i++)
+    	if(UsersIdx[i].recno==plyrno)
+        	return(i);
+	return(-1);
+}
+
+
+void get_time_diff()
+{
+	time_t tx, secdif;
+	int inum;
+
+	/* get current time */
+	time(&tx);
+	/* calculate the second difference */
+	secdif = plyr.laston - tx;
+	/* count up the number of days */
+	inum = 0;
+	while (secdif>(1440L*60L))
+	{
+		secdif -= (1440L*60L);
+		inum++;
+	}
+	/* complain if they don't play every day */
+	s16_2A(1,inum);
+	if (inum>1) text("0800");
+}
+
+void vbbs_randomize()
+{
+	/* seed the random number generator */
+	srand((unsigned int)time(NULL));
+}
+
+/* returns 0 to (num-1) */
+int rand_num(int num)
+{
+	float max = (float)num;
+	int rnum;
+
+	rnum = (int)(max*rand()/(RAND_MAX+1.0f));
+
+	return rnum;
+}
+
diff --git a/src/doors/vbbs/src/vbbs.h b/src/doors/vbbs/src/vbbs.h
new file mode 100755
index 0000000000000000000000000000000000000000..4faffe59402c62be3ec7d618dd4dc63afd42db3a
--- /dev/null
+++ b/src/doors/vbbs/src/vbbs.h
@@ -0,0 +1,263 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "OpenDoor.h"
+
+/* OpenDoors target platform. */
+#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32)
+#define VBBS_WIN32
+#elif defined(__GNUC__)
+#define VBBS_LINUX
+#else
+#define VBBS_DOS
+#endif /* !WIN32 */
+
+#if defined(VBBS_DOS)
+	#include <dos.h>
+	#include <io.h>
+	#include <share.h>
+#endif
+#if defined(VBBS_LINUX)
+	#include <unistd.h>
+	#include <termios.h>
+	#include <limits.h>
+	#define _MAX_PATH PATH_MAX
+#endif
+
+#include "OpenDoor.h"
+
+#define VBBS_VERSION "v3.2 [0009]"
+
+/* setup cross platform types */
+typedef CHAR	s8;
+typedef BYTE	u8;
+typedef	INT16	s16;
+typedef	WORD	u16;
+typedef	INT32	s32;
+typedef	DWORD	u32;
+
+#define int8   s8
+#define uint8  u8
+#define int16  s16
+#define uint16 u16
+#define int32  s32
+#define uint32 u32
+
+/* random number functions */
+void vbbs_randomize(void);
+int rand_num(int num);
+
+#define MAX_USERS                 255
+#define FILE_ACCESS_MAX_WAIT      20
+#define	OPEN			  		  0
+#define USED			  		  1
+#define	DEAD			  		  2
+#define	DELETED			  			3
+#define UNREAD			  			2
+#define INUSE			  			1
+#define BLANK			  			0
+#define MYNET			  			0
+#define ACT_NOTHING_HAPPENS       	0
+#define ACT_ADD_FREE_USERS        	1
+#define ACT_ADD_PAY_USERS         	2
+#define ACT_SUB_FREE_USERS        	3
+#define ACT_SUB_PAY_USERS         	4
+#define ACT_ADD_FUNDS             	5
+#define ACT_SUB_FUNDS             	6
+#define ACT_UPGRADE_CPU           	7
+#define ACT_ADD_ACTIONS           	8
+#define ACT_FREE_2_PAY            	9
+#define ACT_UPGRADE_HD           	10
+#define ACT_DOWNGRADE_CPU        	11
+#define ACT_DOWNGRADE_HD         	12
+#define ACT_DOWNGRADE_MODEM      	13
+#define ACT_PHONELINE_DAMAGE     	14
+#define	HACK_BBS_SW		  			1
+#define	HACK_USERBASE		  		2
+#define	HACK_SECURITY		  		3
+#define	HACK_VIRUS		  			4
+#define	HACK_FAKECLUE		  		5
+#define	HACK_BURGLERY		  		6
+#define MAX_MODEM 		 			10
+#define MAX_HDD						20
+
+#pragma pack(1)
+
+typedef struct
+{
+	s16 low, high, digital;
+} modemspeed;
+
+typedef struct
+{
+	s16 yr, mn, dy;
+} dt;
+
+typedef struct
+{
+	char 	realname[36];
+	char	sysopname[36];
+	char	bbsname[36];
+	char	reserved_char[256];
+	u16		reserved_int1;
+	s16		plyrnum;
+	u16		status;
+	u16		expert;
+	u16		reserved_int2;
+	u16		reserved_int3;
+	u16		callid;
+	u16		lastbill;
+	s16		cpu;
+	s16		hd_size;
+	u16		msgs_waiting;
+	u16		skill_lev;
+	u16		insurance;
+	u16		rapsheet;
+	u16		bbs_sw;
+	u16		net_lev;
+	u16		charge_lev;
+	u16		hacktoday;
+	u16		hackin[5];
+	u16		breakincnt;
+	u16		damagedby;
+	s16		employee_actions;
+	u16		employees;
+	s16 	pacbell_ordered;
+	s16		pacbell_installed;
+	s16		pacbell_broke;
+	s16		security;
+	s16		reserved_int[12];
+	float 	education[2];
+	float	funds;
+	float	reserved_fl[3];
+	u32		skore_before;
+	u32		reserved_long2;
+	u32		skore_now;
+	s32		actions;
+	u32		users_p;
+	u32		users_f;
+	u32		reserved_long[1];
+	modemspeed	mspeed;
+	time_t 	laston;
+} tUserRecord;
+
+typedef struct
+{
+	s16 	towho, tosys, from, fromsys, hacktype;
+	double	otherdata;
+	char	hackmsg[4][81];
+} hackrec;
+
+typedef struct
+{
+	s32 	skore;
+	s16	recno;
+} tUserIdx;
+
+typedef struct
+{
+   char  modemname[20];
+   s32 cost;
+   s16 req;
+} modemtype;
+
+typedef struct
+{
+	char  	cpuname[41];
+	s32   	cost;
+} cputype;
+
+typedef struct
+{
+	char	hdsize[31];
+	s32		cost;
+	s16		req;
+} hdtype;
+
+typedef struct
+{
+    char	bbsname[31];
+    s32  	cost;
+    s16   	req;
+    s32 	numlines;
+} bbstype;
+
+typedef struct
+{
+    s16 	classes_available,
+			average_hours,
+			apch,cost;
+} classtype;
+
+typedef struct
+{
+	s16  fsys;
+	s16  tosys;
+	s16  from;
+	s16  to;
+	s16  letternum;
+	s16  item;
+	s16  amount;
+	s16  deleted;
+	s16  idx;
+	char   subject[81];
+	time_t date;
+} mailrec;
+
+#pragma pack()
+
+#ifdef ODPLAT_WIN32
+void init(LPSTR lpszCmdLine, int nCmdShow);
+#else
+void init(int argc, char *argv[]);
+#endif
+void vbbs_main(void);
+void BeforeExitFunction(void);
+int ReadOrAddCurrentUser(void);
+void WriteCurrentUser(void);
+void finddate(s32 *tday);
+void q2bbs(void);
+char onekey(char *list);
+void employ(void);
+void actions(void);
+void virus_det(void);
+void bank(void);
+void charge(void);
+void readmail(void);
+void prob_mail(void);
+void topten(void);
+void vbbsscan(void);
+void status(void);
+void users_online(void);
+void UseActions(int numacts);
+void advance(void);
+void ans_chat(void);
+void not_enough(void);
+void bbslist(void);
+void change_title(void);
+void change_handle(void);
+void toptenrecord(int i);
+char *transform(s32 inum);
+void viruslist(void);
+int vlcount(void);
+void personal(void);
+void init_users_dat(void);
+void inspect(void);
+int	findBBS(void);
+int GetUser(int record);
+void sort_users(void);
+long filesize(FILE *stream);
+int rankplyr(int plyrno);
+void get_time_diff(void);
+void learn(void);
+void use_skill(void);
+void security_menu(void);
+int check_first(void);
+
+void VBBS3_Report(tUserRecord* pl, int bInspect);
+
diff --git a/src/doors/vbbs/src/vbbs_db.c b/src/doors/vbbs/src/vbbs_db.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b0aa9d70a92830aa90580435d144728cb01fb07
--- /dev/null
+++ b/src/doors/vbbs/src/vbbs_db.c
@@ -0,0 +1,101 @@
+/*****************************************************************************
+ *
+ * File ..................: v3_db.cpp
+ * Purpose ...............: File DB routines
+ *
+ *****************************************************************************
+ * Copyright (C) 1999-2002  Darryl Perry
+ * Copyright (C) 2002-2003  Michael Montague
+ *
+ * This file is part of Virtual BBS.
+ *
+ *****************************************************************************/
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <filewrap.h>
+
+#include "vbbs.h"
+#include "v3_defs.h"
+#include "vbbs_db.h"
+
+// our system db object
+#ifdef FIXME
+vbbs_db_system gSystemDB;
+#endif
+
+int	db_file=-1;
+
+/////////////////////////////
+// vbbs_db_system functions
+int db_init()
+{
+	// build the path
+	char path[_MAX_PATH];
+	sprintf(path, "%ssystem.vb3", /*global*/ gamedir);
+	// open the file
+	if ((db_file=open(path,O_RDWR|O_BINARY|O_CREAT,S_IREAD|S_IWRITE)) < 0)
+	{
+		printf("unabled to open %s\n", path);
+		return -1;
+	}
+
+	return 0;
+}
+
+void db_shutdown()
+{
+	// closes the file and removes all locks
+	close(db_file);
+}
+
+int db_read(record* rec)
+{
+	// seek to read location
+	long offset = 0L * sizeof(record);
+	if (lseek(db_file, offset, SEEK_SET) < 0L)
+		return -1;
+	// read the record
+	if (read(db_file, rec, sizeof(record)) != sizeof(record))
+		return -1;
+
+	return 0;
+}
+
+int db_update(record* rec)
+{
+	long offset = 0L * sizeof(record);
+	if (lock(db_file, offset, sizeof(record)))
+		return -1;
+	if (lseek(db_file, offset, SEEK_SET) < 0L)
+	{
+		unlock(db_file, offset, sizeof(record));
+		return -1;
+	}
+	if (read(db_file, rec, sizeof(record)) != sizeof(record))
+	{
+		unlock(db_file, offset, sizeof(record));
+		return -1;
+	}
+
+	return 0;
+}
+
+int db_commit(record* rec)
+{
+	long offset = 0L * sizeof(record);
+	if (lseek(db_file, offset, SEEK_SET) < 0L)
+	{
+		unlock(db_file, offset, sizeof(record));
+		return -1;
+	}
+	if (write(db_file, rec, sizeof(record)) != sizeof(record))
+	{
+		unlock(db_file, offset, sizeof(record));
+		return -1;
+	}
+	if (unlock(db_file, offset, sizeof(record)))
+		return -1;
+
+	return 0;
+}
diff --git a/src/doors/vbbs/src/vbbs_db.h b/src/doors/vbbs/src/vbbs_db.h
new file mode 100644
index 0000000000000000000000000000000000000000..71e8ff58d891b1af9c7a93a9bba49980e99e8b1d
--- /dev/null
+++ b/src/doors/vbbs/src/vbbs_db.h
@@ -0,0 +1,39 @@
+#ifndef V3_DB_H
+#define V3_DB_H
+
+#ifdef FIXME
+#include "mx_file.h"
+#endif
+
+///////////////////////////////////
+//  holds all global system data
+struct vbbs_db_system_record
+{
+	u32 last_maint;
+};
+
+typedef struct vbbs_db_system_record record;
+
+// returns -1 on error, 0 on success
+int db_init(void);
+void db_shutdown(void);
+
+// use for getting a snapshot of the data
+// returns -1 on error, 0 on success
+int db_read(record* rec);
+
+// used for writing data safely
+// returns -1 on error, 0 on success
+int db_update(record* rec);
+int db_commit(record* rec);
+
+extern	int	db_file;
+
+#define gSystemDB_init		db_init
+#define gSystemDB_shutdown	db_shutdown
+#define gSystemDB_read		db_read
+#define gSystemDB_update	db_update
+#define	gSystemDB_commit	db_commit
+#define	gSystemDB_file		db_file
+
+#endif
diff --git a/src/doors/vbbs/src/vbbsutil.c b/src/doors/vbbs/src/vbbsutil.c
new file mode 100644
index 0000000000000000000000000000000000000000..4bfa4968afbf384ad6a95b6f8ee4ba20cd603f7a
--- /dev/null
+++ b/src/doors/vbbs/src/vbbsutil.c
@@ -0,0 +1,21 @@
+/*****************************************************************************
+ *
+ * File ..................: vbbsutil.cpp
+ * Purpose ...............: Misc Utilties
+ *
+ *****************************************************************************
+ * Copyright (C) 1999-2002  Darryl Perry
+ * Copyright (C) 2002-2003	Michael Montague
+ *
+ *****************************************************************************/
+
+#include "vbbs.h"
+#include "vbbsutil.h"
+
+u32 vbbs_util_getday()
+{
+	time_t t = time(NULL);
+	return (t / (24L * 60L * 60L));
+}
+
+
diff --git a/src/doors/vbbs/src/vbbsutil.h b/src/doors/vbbs/src/vbbsutil.h
new file mode 100644
index 0000000000000000000000000000000000000000..541a7ebdbc50e50b3d139346119021e127d3a891
--- /dev/null
+++ b/src/doors/vbbs/src/vbbsutil.h
@@ -0,0 +1,7 @@
+#ifndef VBBS_UTIL_H
+#define VBBS_UTIL_H
+
+u32 vbbs_util_getday();
+
+#endif // VBBS_UTIL_H
+
diff --git a/src/doors/vbbs/src/vc_strings.h b/src/doors/vbbs/src/vc_strings.h
new file mode 100755
index 0000000000000000000000000000000000000000..3fd313449726c2e9392960013551530f9505eb87
--- /dev/null
+++ b/src/doors/vbbs/src/vc_strings.h
@@ -0,0 +1,7 @@
+#ifndef VC_STRINGS_H
+#define VC_STRINGS_H
+
+// compatibility for Microsoft Visual C
+#define strncasecmp(a, b, c) 	_strnicmp(a, b, c)
+
+#endif // VC_STRINGS_H
diff --git a/src/doors/vbbs/todo.txt b/src/doors/vbbs/todo.txt
new file mode 100755
index 0000000000000000000000000000000000000000..89715fa7adbe27ec513313e1e76b9f3e346f81a1
--- /dev/null
+++ b/src/doors/vbbs/todo.txt
@@ -0,0 +1,21 @@
+Virtual Sysop 3 TODO:
+
+  [ ] no matter how many phone lines you buy at the phone store, they always tell
+      you that they will charge you $35.00 for installation.  They lie!  They
+      charge you $35.00 x the number of lines being installed.
+  [ ] education not working properly.  (not adding education, not deducting money)
+  [ ] Hardware loss too often ... game balance issue.
+  [ ] mail message reading/writing should be improved
+  [ ] user file i/o should be more multinode friendly
+  [ ] add packing routines for the mail file
+  [ ] improve all daily maint to keep the game cleaner
+  [ ] make one function to calculate available modems
+  [ ] report shows wrong number of actions
+  [ ] need to rewrite how user data is handled
+  [ ] write function to calculate score, don't save it in user record
+  [ ] need to filter user text input to remove unwanted characters
+  [ ] check monitary transations to make sure they check balances before hand
+  [ ] add logging to reduce cheating bugs
+
+Fixed
+