retrocomputacion / retrobbs

A multimedia BBS software written in Python for Turbo56K enabled terminals running on Commodore 64 computers
GNU General Public License v3.0
37 stars 4 forks source link
audio bbs c64 commodore python streaming youtube
![logo](docs/retrobbs.png) # RetroBBS VERSION 0.50 dev (c)2020-2023 By Pablo Roldán(Durandal) & Jorge Castillo(Pastbytes)

Table of contents

  1. Introduction
    1. Release history
    2. The Turbo56K protocol
    3. The TML language
    4. Features
    5. Requirements
  2. Configuration file
    1. Internal Functions
  3. Plug-in System
    1. Included Plug-Ins
    2. More Plug-ins
  4. Common modules
  5. Encoders
  6. Installation/Usage
    1. The intro/login sequence
    2. SID SongLength
    3. User accounts / Database management
    4. Messaging system
    5. Temporal directory
  7. TO-DO List
    1. Known bugs
  8. Acknowledgements

1 Introduction

RetroBBS is a bulletin board system specifically developed to work in conjunction with Turbo56k protocol-capable terminals, such as Retroterm for the Commodore 64.

RetroBBS is written in Python3 and uses several 3rd party modules to provide a rich, multimedia online experience for 8-bit computers.

Even though this is the third rewrite of this script, it is still in an early development stage, expect to find many bugs and ugly/non-pythonic code inside.
Starting from v0.50 the BBS is transitioning to neutral encoding, slowly removing hard-coded PETSCII strings and C64 format images. With the goal of supporting other retro platforms.


1.1 Release history

v0.10 (16/08/2021):

Initial release

v0.20 (15/11/2022):

New features:

v0.25 (14/11/2022):

New features:

v0.50 (02/01/2024):

New features:

Changes/Bug fixes:


1.2 The Turbo56K protocol

Turbo56k was created by Jorge Castillo as a simple protocol to provide high-speed file transfer functionality to his bit-banging 57600bps RS232 routine for the C64. Over time, the protocol has been extended to include 4-bit PCM audio streaming, bitmap graphics transfer and display, SID music streaming and more.

RetroBBS will refuse incoming connections from non-Turbo56K compliant terminals.


1.3 The TML language

Introduced in v0.50, TML, standing for Turbo Markup Language is a markup and scripting language inspired by the type-in program listings in magazines from the 1980s. The language's goal is to allow the description of control codes and other platform specific characteristics in plain text. With the added power of allowing the access of internal BBS functions and plugins. Read the dedicated documentation for more info.


1.4 Features

RetroBBS is quite customizable and expandable. The use of a configuration file (config.ini by default) and built-in file transfer, stream and display functions permits building a custom set of menus and file galleries. In addition, the plug-in system allows adding extra functionality with full support from the configuration file.

The BBS is multithreaded and the number of simultaneous incoming connections can be customized in the configuration file.

Current built-in functions:

Included plug-ins:


1.5 Requirements

Python version 3.7 or above

Python modules:

External software:


2 Configuration file

RetroBBS uses the standard INI format for its configuration file (accepts the extended value interpolation method as used by the configparse Python module), the default file is config.ini, located in the root install directory:

[SECTION]
key = value

Please study the example config.ini file included in this package for more information.

When the BBS is idle (no visitors connected), it will reload the config file if it detects it has been modified. All settings will be updated, but network settings will only take place upon restart.

Sections:

[MAIN]

Global BBS settings

key description
bbsname Name of the BBS
menues Total number of menu pages, not counting the main menu page
ip IP V4 address on which the BBS will be accessible, default is 127.0.0.1
port port number on which the BBS will be accessible
lines Number of connection slots
language language for transmitted texts, only partially implemented as of 0.25
welcome Welcome message on connection
goodbye Log off message
busy Message shown when all the connection slots are in use
dateformat Format in which dates will be printed out, client-side:
0 = dd/mm/yyyy
1 = mm/dd/yyyy
2 = yyyy/mm/dd

[BOARDS]

Settings for the available messaging boards

key description
boardX (Where X > 0) Board name
boardXview Minimum userclass that can read messages on this board (0 = public)
boardXpost Minimum userclass that can post messages on this board (No less than 1)

[PATHS]

Directory paths to different BBS files, some are used internally, others are referenced in menu entry definitions. All paths must end with '/'.

key description
bbsfiles Path to files used for login sequences and other general BBS information.
audio Path to files for the audio library
images Path to pictures for the Image gallery
downloads Path to files for the program library
temp Path to temporary files created by the BBS or it's plugins

Custom paths can be added here as needed

[PLUGINS]

Any configuration options for installed plug-ins must be added under this section.

[MAINMENU]

Defines the name and number of sections of the main menu. key description
title Title for the main menu
sections Number of sections on the main menu
prompt Prompt message to print at the bottom of the menu page

[MAINMENUSECTIONy]

(Where 1 <= y <= {MAINMENU:sections}) Defines section 'y' of the main menu. key description
title Title for this section (optional)
entries Number of entries in this section
columns Number of columns per line, valid values are 1 or 2, default is 2
Common menu entry keys: key description
entryZtitle (Where 1 <= Z <= {entries}) Entry title
entryZkey Key press associated with this entry (UPPERCASE only)
entryZdesc Entry description text, optional, only when the section is configured for 1 column
entryZfunc Internal function or plug-in associated with this entry.
Depending on the function, specific entry keys may be needed (See next chapter)
Defaults to LABEL if omitted.
entryZlevel (Optional) Minimum userclass required to access this entry, default 0 (public)
entryZmode (Optional) Only display this entry if the client's platform matches.
Multiple entries with same entryZkey but different entryZmode are allowed.
Function/plug-in specific entry keys: key description
entryZpath A file system path
entryZext File extensions to match, comma-separated list
entryZid Menu ID number
entryZurl An URL address

[MENUx]

(Where 1 <= x <= {MAIN:menues}) Defines the name and number of sections in menu 'x'

Keys: Same as in MAINMENU.

[MENUxSECTIONy]

(Where 1 <= x <= {MAIN:menues} and 1 <= y <= {MAINMENU:sections}) Defines section 'y' of menu 'x'

Keys: Same as MAINMENUSECTIONy.


2.1 Internal Functions

The following are the function names providing access to internal BBS functionality from the config file.

Function PCMPLAY:

Enters PCM streaming mode and streams the audio file specified in the parameters.

Configuration file parameter keys:

key description
entryZpath[^1] Path to the audio file to stream (must be one of the supported formats)

Function CHIPPLAY:

Streams the specified chiptune music file.

Configuration file parameter keys:

key description
entryZpath Path to the music file to stream (must be one of the supported formats)
entryZplayt Playtime in seconds
entryZsubt Subtune to play

Function SIDPLAY: -DEPRECATED-! use CHIPPLAY instead

Streams the specified .SID or .MUS music file.

Configuration file parameter keys:

key description
entryZpath Path to the music file to stream (must be one of the supported formats)
entryZplayt Playtime in seconds
entryZsubt Subtune to play

Function SWITCHMENU:

Switches the BBS to a different menu.

Configuration file parameter keys:

key description
entryZid ID number of the menu to switch to

Function BACK:

Switches the BBS back to the previous menu.

Configuration file parameter keys: NONE

Function EXIT:

Shows the logoff prompt and terminates the connection if the user confirms to do so.

Configuration file parameter keys: NONE

Function SLIDESHOW:

Display/streams all the supported files in the specified directory in sequential (alphabetical) order, the user must press RETURN to skip to the next file.

Supported file types are:

Configuration file parameter keys:

key description
entryZpath Path to the slideshow files

Function FILES:

Display the list of program files in a directory, the user-selected file will be transferred to memory/viewed/saved to disk, depending on the file type and the user choice.

Configuration file parameter keys:

key description
entryZpath Path to the program files, default is '/programs'
entryZsave Set to True to allow saving the files to disk.
entryZext Optional comma separated list of file extensions to display. If omitted the file extensions will be shown on the file browser.

Function IMAGEGALLERY:

Display the list of images in a directory, the user-selected file will be transferred and displayed.

Configuration file parameter keys:

key description
entryZpath Path to the image directory, default is '/images'
entryZsave Set to True to allow saving the files to disk.

Function AUDIOLIBRARY:

Display the list of audio files in a directory, the user-selected file will be streamed.

Configuration file parameter keys:

key description
entryZpath Path to the audio files, default is '/sound'

Function GRABFRAME:

Grab and display a video frame. File can be in any video format supported by OpenCV

Configuration file parameter keys:

key description
entryZpath Path to the video file, can be a local path or a URL

Function USEREDIT:

Display the user profile editor.

Configuration file parameter keys: NONE

Function USERLIST:

Display the list of registered users.

Configuration file parameter keys: NONE

Function INBOX:

Display the user's personal message inbox

Configuration file parameter keys: NONE

Function BOARD:

Display the message list for the specified board.

Configuration file parameter keys: key description
entryZid Board ID (>0)

See the example config.ini for recommended usage.

Function LABEL:

Display non-interactive text in a menu. Combine it with an entry description text in 1 column mode for a menu description that doesn't have an associated key.

[^1]: Replace Z in the configuration file parameters with the entry ID number.

Function SENDFILE:

Send a file to the client, call the appropriate transfer routine. Optionally, show a file dialog or download to disk.
Supported file types include: JPG, GIF, PNG, ART, OCP, KOA, KLA, DD, DDL, BOTI, MP3, WAV, TXT, SEQ, TML and PRG If the save option is enabled, any unsupported file will be transferred to disk

Configuration file parameter keys: key description
entryZpath File path
entryZdialog Set to True to display a file dialog if available
entryZsave Set to True to save the file to disk

3 Plug-In system

RetroBBS implements a simple plug-in system, on startup the BBS will import all python modules found in the \<plugins> directory.

All plug-in modules should implement at least two functions:

setup() : This function must returns a tuple consisting of the plug-in name in uppercase, which will be used as the callable function on the config file. And a list of parameters, each element being a tuple itself. This tuple is made of the parameter name to use in the config file, and the corresponding default value in case the parameter is not found.

Example of the returned tuple for a plugin that will use the name 'CHAT' with parameters 'channel' and 'nick', which default to 'offtopic' and 'John' respectively:

('CHAT',[('channel','offtopic'),('nick','John')])

plugfunction(conn, \<extra parameters>) : The BBS will call this function to perform the plug-in's task.
The first parameter \<conn> is a Connection object (see Chapter 4) to which the plug-in should direct its output.
Any extra parameters will follow, with the same names as returned by setup().


3.1 Included Plug-Ins

Astronomy Picture Of the Day (apod.py):

Retrieves and displays the text and picture from NASA's Astronomy Picture Of the Day.

IRC Client (irc_client.py):

Basic and very experimental IRC client.

key description
entryZserver[^1] IRC server URL. Default is irc.libera.chat
entryZport IRC server port. Default is 6667
entryZchannel IRC channel to enter upon connection. Default is NONE

Maps (maps.py) (new 0.50):

Explore the world through maps based on Openstreetmaps. Maps are rendered using the Stamen Design's Toner tiles. The map tiles are served by Stadia Maps, an API key is required for the plugin to work. To get the API key a free Stadia Maps account is required.

Mindle (mindle.py) (new 0.50):

Guess the word in this Wordle game clone. Solution list includes words from computer science, retrocomputing, programming, videogames and technology.
Registered users can play for a place in the high score table.

Oneliner (oneliner.py):

User-generated messages of up to 39 characters. The last 10 messages are stored in a JSON file located in the \<plugins> directory.

RSS feed reader (newsfeed.py):

Retrieves the latest ten entries from the specified RSS feed, upon user selection of the entry, it scrapes the target website for text and relevant picture. The plug-in is primarily targeted at WordPress sites, if it can't find the content it expects in the linked URL then the article text from the RSS feed itself will be displayed.

Weather (weather.py) (new 0.25):

Displays current weather and forecast for the next 2-3 days as a Hires image. On first run it will display the weather corresponding to the passed Connection object's IP. Further weather forecasts can be queried by typing a new location.

WebAudio streamer (webaudio.py):

On the fly conversion and streaming of online audio sources (Shoutcast, YouTube or other sources).

Wikipedia (wiki.py):

Search and display Wikipedia articles, displays relevant article image if found.

YouTube snapshot (youtube.py):

Display a frame from the specified YouTube video. It will grab the latest frame if the video is a live stream. Otherwise, it grabs a random frame.

key description
entryZurl full URL to the YouTube video
entryZcrop comma-separated list of image coordinates for cropping the video frame

3.2 More Plug-ins

Other plug-ins not included in the distribution or by 3rd parties:


4 Common modules

Located inside the \<common> directory you'll find modules which integrate what could be called the BBS' API. The use of some of these modules is mandatory when writing a new plug-in.

common.audio - Audio/SID streaming:

AudioList(conn,title,speech,logtext,path):

Creates and manages an PCM audio/SID file browser.

PlayAudio(conn,filename, length = 60.0, dialog=False):

Converts and streams a PCM audio file to \<conn>.

CHIPStream(conn, filename,ptime, dialog=True):

Stream register writes data to the guest's sound chip

SIDStream(conn, filename,ptime, dialog=True): -DEPRECATED-! Use CHIPStream instead

Stream a SID file to \<conn>

check the SID streaming protocol

class PCMStream(fn, sr) :

Receive an audio stream from FFmpeg in chunks.

PCMStream.read(size): Read a chunk of data size bytes in length. Returns a byte string

PCMStream.stop(): Terminates an audio stream, and closes FFmpeg.

common.bbsdebug - Log output to stdout:

_LOG(message, _end='\n', date=True, id=0, v=1):

Prints \<message> on stdout. \<message> can be any expression valid for the print function.
The message will end in a newline by default, you can change this by passing a different end string in the \<_end> parameter.
By default, the message will be preceded by the current date and time, disable this by passing False in the \<date> parameter.

Also defined in this module is the class, which enumerates a few ANSI codes for use in the log messages.

common.c64cvt - Image conversion to raw C64 formats: (-DEPRECATED-)

c64imconvert(Source, gfxmode=1, lumaD=0, fullD=6, preproc=True):

Converts PIL image object \<Source> into C64 graphic data.

Returns a tuple (e_img,cells,screen,color,bg_color) where:

common.imgcvt - Image conversion to a native graphic format:

gfxmodes

Enum containing all the graphic modes supported by RetroBBS.

Current supported values:

C64HI: Commodore 64 hires bitmap
C64MULTI: Commodore 64 multicolor bitmap

dithertype

Enum containing the available dithering methods:

NONE: No dithering
BAYER2: 2x2 Bayer Ordered dither
BAYER4: 4x4 Bayer Ordered dither
BAYER4ODD: 4x4 Bayer Ordered dither, horizontal lines
BAYER4EVEN: 4x4 Bayer Ordered dither, Vertical lines
BAYER4SPOTTY: 4x4 Bayer Ordered dither, spotty
YLILUOMA: Yliluoma type 1 dither, very slow
CLUSTER: Cluster dither
FLOYDSTEINBERG: Floyd-Steinberg error diffusion dither

cropmodes

Enum containing the possible image position/crop/zoom presets:

LEFT: No scaling, positioned to the center-left and cropped to the target image size.
TOP: No scaling, positioned to the top-center and cropped to the target image size.
RIGHT: No scaling, positioned to the center-right and cropped to the target image size.
BOTTOM: No scaling, positioned to the bottom-center and cropped to the target image size.
T_LEFT: No scaling, positioned to the top-left and cropped to the target image size.
T_RIGHT: No scaling, positioned to the top-right and cropped to the target image size.
B_LEFT: No scaling, positioned to the bottom-left and cropped to the target image size.
B_RIGHT: No scaling, positioned to the bottom-right and cropped to the target image size.
CENTER: No scaling, centered and cropped to the target image size.
FILL: Scaled and cropped to fill the whole target image size.
FIT: Scaled to fit completely inside the target image size.
H_FIT: Scaled and cropped to fit the target width.
V_FIT: Scaled and cropped to fit the target height.

ColorProcess class

A simple class defining the image processing values:

Creating a ColorProcess without parameters and passing it to convert_To will result in no image processing being performed.

convert_To(Source, gfxmode:gfxmodes=gfxmodes.C64MULTI, preproc:ColorProcess=None, dither:dithertype=dithertype.BAYER8, threshold=4, cmatch=1, g_colors=None)

Convert a PIL image to a native graphic format.

Returns a PIL image rendering of the result, a list of buffers containing the native data (platform/mode dependent), and a list of global colors

get_IndexedImg(mode:gfxmodes, bgcolor=0)

Returns a PIL "P" image with the dimensions and palette of mode, filled with bgcolor color index.

open_Image(filename)

Open a native image file, returns a PIL image object, native image data and graphic mode

common.classes - Internal use only

common.connection

Implements the Connection class, this is the class used to communicate with clients, all plug-ins must include this module. Only properties and methods to be used by plug-ins are described below.

Connection class properties:

Connection class methods:

QueryFeature(cmd): Query the client's terminal if command cmd is supported. Returned value is saved during the client's session. The query transaction will happen only the first time for each command.
If the command exist the returned value is the number of parameter bytes needed (up to 127). Otherwise the return value will have it's 7th bit set.

Sendall(cadena): Converts string \<cadena> to a binary string and sends it to the client.

Sendallbin(cadena): Sends binary string \<cadena> to the client.

Flush(ftime): Flush the receiving buffer for \<ftime> seconds.

Receive(count): Receives \<count> binary chars from the client.
Returns: binary string.

ReceiveKey(keys=b'\r'): Wait for a received character from the client matching any of the characters in the \<keys> binary string.
Returns: The received matching char as a binary string.

ReceiveKeyQuiet(keys=b'\r'): Same as ReceiveKey, but no logging is ever performed, disregarding logging level. Use it when a password or other sensitive user data must be received.

ReceiveStr(keys, maxlen = 20, pw = False): Interactive reception with echo. The call is completed on reception of a carriage return.

Set \<pw> to True to echo * for each character received, ie, for password entry.
Returns: ASCII string received.

ReceiveInt(minv, maxv, defv, auto = False): Interactive reception of a positive integer with echo. The user will be restricted to entering a number between \<minv> and \<maxv>, if the user presses RETURN instead, the function will return \<defv>.
If \<auto> is True, the function will return automatically when the user enters the maximum number of digits possible within the limits, or by pressing DEL when there's no digit entered. In which case, this function will return None.

ReceiveDate(prompt, mindate, maxdate, defdate): Interactive reception of a calendar date with echo. The user will be restricted to enter a date between \<mindate> and \<maxdate>, if the user presses RETURN instead, the function will return \<defdate>. The date format will follow the user preference if set, otherwise the global BBS date format will be used. Returns a datetime.date object

SendTML(data, registers: dict = {'_A':None,'_S':'','_I':0}): Parse and send a \<data> TML script to the client, optionally initialize the TML parser \<registers>. Returns a dictionary with the last states of the TML parser registers.

common.dbase - Database management:

getUsers():

Get a list of (id, username) pairs. Both id and username are strings.

getUserPrefs(id, defaults={}):

Get a dictionary containing the preferences corresponding to the user \<id>. Pass the \<defaults> values in case the user has no/incomplete preferences.

updateUserPrefs(id,prefs:dict):

Update the preferences corresponding to user \<id> with the contents of the \<prefs> dictionary

common.filetools - Functions related to file transfer:

SendBitmap(conn, filename, dialog=False, save= False, lines=25, display=True, gfxmode:gfxmodes=gfxmodes.C64MULTI, preproc:ColorProcess=None, dither:dithertype=dithertype.BAYER8):

Convert image to C64 mode and send it to the client. Important: The parameter order has changed since v0.25

SendProgram(conn:Connection, filename):

Sends program file into the client memory at the correct address in turbo mode

SendFile(conn:Connection, filename, dialog = False, save = False):

Calls the right transfer function for each supported file type. If selected, will display a dialog beforehand.

SendRAWFile(conn:Connection, filename, wait = True):

Sends a file directly without processing

TransferFile(conn:Connection, file, savename, seq = False):

Starts a file transfer to disk, pending the client acceptance.

SendText(conn:Connection, filename, title = '', lines = 25):

Display a text (.txt) or sequential (.seq) file.

Text files are displayed through common.helpers.More.

Sequential files are scanned for PETSCII control codes and interpreted accordingly.

SendCPetscii(conn:Connection, filename, pause = 0):

Display a .c formatted C64 text screen, as exported by PETSCII or PETMate. Multiple frames per file are supported

SendPETPetscii(conn:Connection, filename):

Display a .PET formatted C64 text screen, as exported by PETMate. Returns immediately

common.helpers

Misc functions that do not fit anywhere else at this point. Functions might get deprecated and/or moved to other modules in the future.

valid_keys: A string containing the valid characters to be used as user input.

menu_colors: List containing the odd/even color pairs for menu entries -DEPRECATED-.

font_bold: Default bold Imagefont for use on bitmaps, 16px height.

font_big: Default big Imagefont for use on bitmaps, 24px height.

font_text: Default text Imagefont for use on bitmaps, 16px height.

formatX(text, columns = 40, convert = True)

Formats the \<text> into \<columns> columns with word wrapping, \<convert> selects if PETSCII conversion is performed.

More(conn, text, lines, colors=default_style):

Paginates \<text>, sends it to \<conn>, the user must press RETURN to get next page(s). Supports most PETSCII control codes, including color and cursor movement.

text_displayer(conn, text, lines, colors=default_style):

Displays text in a text window lines in height. Scrolling up and down with the cursor keys.

crop(text, length)

Cuts \<text> to max \<length> characters, adding an ellipsis to the end if needed.

gfxcrop(text, width, font = font_text):

Cuts \<text> to max \<width> pixels using \<font>, adding an ellipsis to the end if needed.

format_bytes(b):

Convert an integer \<b> depicting a size in bytes to a string rounded up to B/KB/MB/GB or TB

catalog(path, dirs = False, full = True):

Return a list of files (and subdirectories) in the specified top directory

common.petscii - PETSCII <-> ASCII tools and constants

Many control codes and graphic characters are defined as constants in this module, it is recommended to inspect it to learn more.

PALETTE: A tuple containing the C64 palette control codes in the correct order

NONPRINTABLE: A list of all the non-printable PETSCII characters

toPETSCII(text, full = True):

Converts \<text> from UTF-8 to PETSCII, if \<full> is True, some characters are replaced with a visually similar PETSCII equivalent.

toASCII(text):

Converts \<text> from PETSCII to plain ASCII, no extra care is taken to convert PETSCII graphic characters to their ASCII equivalents

common.style:

Defines the BBS style, this module is in a very early stage.

The bbsstyle class is defined here, and the default_style instance of this class is initialized. Read the module source to find about the different class properties.

RenderMenuTitle(conn,title):

Sends the menu title header with text \<title> to \<conn>, using the default style. The client screen is cleared and charset is switched to lowercase. Text mode is not enforced, the caller must ensure that text mode or a text window is active on the client.

KeyPrompt(text,style=default_style,TML=False):

Returns the key prompt string for \<text>. The prompt takes the form [<text>] using the colors defined by \<style>
Set TML to True to return a TML string instead. IMPORTANT: TML string output will become the default in the future.

KeyLabel(conn,key,label,toggle,style=default_style):

Renders menu option \<label> for assigned \<key> in the selected \<style>, boolean \<toggle> switches between odd/even styles.
The result is sent to \<conn>

RenderDialog(conn,height,title):

Renders the background for file view/play/transfer dialogs. \<conn> Connection object \<height> Desired height rows for the dialog in screen \></strong> Optional title string</p> <h2>common.turbo56k:</h2> <p>Defines the <em><a rel="noreferrer nofollow" target="_blank" href="https://github.com/retrocomputacion/retrobbs/blob/master/turbo56k.md">Turbo56k</a></em> protocol constants and helper functions</p> <p>The following functions return either a string or a binary string for use with the Connection.Sendall() or Connection.Sendallbin() methods.</p> <h3>to_Text(page, border, background, bin = False):</h3> <p>Switch the client screen to text mode.</p> <ul> <li><strong>\<page></strong> is the text memory page to use</li> <li><strong>\<border></strong> and <strong>\<background></strong> set the corresponding client screen colors</li> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>to_Hires(page,border, bin = False):</h3> <p>Switch the client screen to Hires graphic mode.</p> <ul> <li><strong>\<page></strong> is the bitmap memory page to use</li> <li><strong>\<border></strong> is the client screen border color</li> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>to_Multi(page, border, background, bin = False):</h3> <p>Switch the client screen to multicolor graphic mode.</p> <ul> <li><strong>\<page></strong> is the bitmap memory page to use</li> <li><strong>\<border></strong> and <strong>\<background></strong> set the corresponding client screen colors</li> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>customTransfer(address, bin = False):</h3> <p>Sets the destination address for the next block transfer command.</p> <ul> <li><strong>\<address></strong> a valid 16-bit integer value for the destination memory address</li> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>presetTransfer(preset, bin= False):</h3> <p>Set the destination address for the next block transfer to the one defined by <strong>\<preset></strong></p> <ul> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>blockTransfer(data):</h3> <p>Transfer the binary string <data> to the client.<br>This function returns the entire command sequence to complete the transfer as a byte string, including <strong>\<data></strong>. Normal usage is calling <code>SendAllbin</code> with the result of this function as the parameter</p> <h3>to_Screen(bin = False):</h3> <p>Selects the client screen as the output.</p> <ul> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>to_Speech(bin = False):</h3> <p>Selects the optional hardware speech synthesizer as text output.</p> <ul> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>reset_Turbo56K(bin = False):</h3> <p>Return a command sequence that enables the cursor, disables split screen and resets text window limits.</p> <ul> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>set_CRSR(column, row, bin= False):</h3> <p>Sets the client's text cursor position to <strong>\<column></strong>, <strong>\<row></strong> coordinates</p> <ul> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>Fill_Line(row, char, bin= False):</h3> <p>Fill the client screen <strong>\<row></strong> with <strong>\<char></strong> (in C64 screencode), fill color is the last used.</p> <ul> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>enable_CRSR(bin = False):</h3> <p>Enables the client's text cursor.</p> <ul> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>disable_CRSR(bin = False):</h3> <p>Disables the client's text cursor.</p> <ul> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>split_Screen(line, multi, bgtop, bgbottom, bin = False):</h3> <p>Splits the client's screen into a bitmap top and a text bottom parts.</p> <ul> <li><strong>\<line></strong> the text screen row on which the split occurs</li> <li><strong>\<multi></strong> boolean, <code>True</code> for Multicolor mode on the top part, <code>False</code> for Hires</li> <li><strong>\<bgtop></strong> Background color for the top part, only used when Multicolor mode is selected</li> <li><strong>\<bgbottom></strong> Background color for the bottom part</li> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h3>set_Window(top, bottom,bin = False):</h3> <p>Set the <strong>\<top></strong> and <strong>\<bottom></strong> limits for the client text output, this includes scrolling and screen clearing.</p> <ul> <li><strong>\<bin></strong> selects the return string type</li> </ul> <h2>common.video:</h2> <p>Video related routines.</p> <h3>Grabframe(conn:Connection, path, crop, length = None, pos = None):</h3> <p>Grab's a frame from the specified video file/stream.</p> <ul> <li><strong>\<conn></strong> connection to send the image to</li> <li><strong>\<path></strong> video file/stream path or URL</li> <li><strong>\<crop></strong> a tuple with the 4 corners coordinates for cropping the video frame, or None</li> <li><strong>\<length></strong> video playtime in milliseconds. Pass None to let <em>Grabframe</em> to figure the playtime, or 0 to indicate a live stream</li> <li><strong>\<pos>></strong> Grab the frame at <code>pos</code> milliseconds. Pass None for random frame. Ignored if the video is a live stream</li> </ul> <hr /> <h1>5 Encoders</h1> <p>Starting on v0.50 RetroBBS is moving towards an encoding agnostic implementation. This means reducing to the minimum instances of hard coded platform specific strings and control codes, replacing them with generic ASCII/Unicode strings and <em>TML</em> tags.</p> <p>For this purpose a new <code>Encoder</code> class has been created.</br> This class provides platform specific encoding/decoding of strings, as well as defining the basic control codes and color palette.</p> <p>Currently, only the <code>PET64</code> and <code>PET264</code> encoders are implemented, corresponding to the <em>Commodore 64</em> and <em>Commodore Plus/4</em> PETSCII encodings respectively.</p> <hr /> <h1>6 Installation/Usage</h1> <p>After ensuring you have installed all the required python modules and extra software, just unpack this archive into a directory of your choice.<br> If you're upgrading a previous installation, make sure to not overwrite your configuration files with the ones included as example.</p> <p><strong>NOTICE</strong>: Starting at v0.20, all text parameters in the config file are expected to be encoded in <em>ASCII</em>, if you're updating from v0.10, remember to convert your <em>PETSCII</em> parameters.</p> <p>You can run this script from a command line by navigating to the Installation directory and then issuing:</p> <pre><code>python retrobbs.py</code></pre> <p>or</p> <pre><code>python3 retrobbs.py</code></pre> <p>depending on your python install.</p> <p>Optional arguments:</p> <ul> <li><code>-v[1-4]</code> sets the verbosity of the log messages, a value of 1 will only output error messages, while a value of 4 will output every log line.</li> <li><code>c [file name]</code> sets the configuration file to be used, defaults to <code>config.ini</code></li> </ul> <hr /> <h1>6.1 The intro/login sequence</h1> <p>Once a connection with a client is established and a supported version of <em>Retroterm</em> is detected, the client will enter into split screen mode and display the <code>splash.art</code> bitmap file found in the <code>bbsfiles</code> path preset. The user will then be asked if he wants to log in or continue as a guest.</p> <p>After a successful login or directly after choosing guest access, the supported files in the subdirectory <code>[bbsfiles]/intro</code> will be shown/played in alphabetical order.</p> <p>Starting in v0.50 an example <em>TML</em> script is placed at the end of the <code>[bbsfiles]/intro</code> sequence. This script will greet a logged-in user and show the amount of unread public and private messages if any.</p> <hr /> <h1>6.2 SID SongLength</h1> <p>Currently, the SID streaming routines are only accessed from the <code>AUDIOLIBRARY</code> and <code>SLIDESHOW</code> internal functions. These functions will set the song length by searching for the <code>.ssl</code> files corresponding the <code>.sid</code> files found, defaulting to 3 minutes when not found.<br> The <code>.ssl</code> format is used by the songlength files part of the <em>High Voltage SID Collection</em> (<a rel="noreferrer nofollow" target="_blank" href="http://hvsc.c64.com">http://hvsc.c64.com</a>). <em>HVSC</em> uses a <code>SONGLENGTHS</code> subdirectory to store the <code>.ssl</code> files, <em>RetroBBS</em> can also read these files in the same directory where the <code>.sid</code> files are located.</p> <hr /> <h1>6.3 User accounts / Database management</h1> <p><em>RetroBBS</em> now supports the creation of user accounts, this allows for the restriction of BBS areas according to user classes and the incorporation of the messaging system.</p> <p><em>TinyDB</em> is used as the database backend. The database is a <em>JSON</em> file located in the <code>bbsfiles</code> directory.</p> <p>Upon registering, the user will be shown the file <code>rules.txt</code> located in <code>bbsfiles/terms</code>, you should edit this file according to your needs.</p> <p>When registering, the user will be asked the following data:</p> <ul> <li>Password (stored as a salted hash in the database)</li> <li>First and last names</li> <li>Country of origin</li> <li>Date of birth (Date format is defined by the <code>dateformat</code> parameter in the config file)</li> </ul> <p>A registered user will have a userclass=1 by default. Unregistered users (guests) have a userclass=0. Admins/Sysops are those with a userclass=10.</p> <p>You can use user classes 2 to 9 for more access granularity as you see fit.</p> <p>A separate script for database management is included in the form of <code>dbmaintenance.py</code><br>Execute it by issuing the following command (while the BBS is not running):</p> <pre><code>python dbmaintenance.py or python3 dbmaintenance.py</code></pre> <p>With this script you can:</p> <ul> <li>Edit user data, and change their user class.</li> <li>Delete users</li> <li>Add users</li> </ul> <p>The script will also do a quick integrity check on the database file.</p> <p><strong>IMPORTANT</strong>: When setting up a new BBS (or upgrading from v0.10) use dbmaintenance.py to create your account and set your class as 10 to assign yourself as admin/sysop.</p> <hr /> <h1>6.4 Messaging system</h1> <p>The messaging system permits unlimited public or semipublic boards plus a personal messages board for each registered user.</p> <p>At the time of writing, this early implementation supports messages of up to 720 characters in length, organized in 18 rows of 40 columns each. The message editor works on a per-line basis, completing a by pressing <code>RETURN</code>, passing the 40 characters limit, or selecting another line to edit (by pressing <code>F3</code>). On entering the editor, if the user is starting a new message thread, they will be asked first to enter a topic for the thread. Once done with the editing, the user should press <code>F8</code> and will be prompted if they want to continue editing, send the message, or cancel the message.</p> <p>A user with admin/sysop user class (10) can delete threads or individual messages (deleting the first message in a thread will delete the whole thread).</p> <hr /> <h1>6.5 Temporal directory</h1> <p>The path preset <code>temp</code> is used by the BBS or it's plugins to store temporal files.</p> <p>Currently, only the SID streaming function makes use of this path.</p> <p>If you're running the BBS from a Raspberry Pi or other SBC that uses an SD card as main storage we recommend creating a RAM disk and point the <code>temp</code> path to it. This will reduce the wear on your SD card.</p> <h3>Creating a RAM disk</h3> <p>First create a mount point:</p> <pre><code>sudo mkdir /mnt/ramdisk</code></pre> <p>(You can replace <em>ramdisk</em> by any valid name of your choice)</p> <p>Next you have to mount your new RAM disk:</p> <pre><code>sudo mount -t tmpfs -o rw,size=1M tmpfs /mnt/ramdisk</code></pre> <p>Here the "1M" means the RAM disk will have a size of 1 Megabyte, this is more than enough for current use by the BBS, but this can change in the future.</p> <p>To make this change permanent you'll need to add the previous command to your fstab file.</p> <p>First make a backup of your fstab file:</p> <pre><code>sudo cp -v /etc/fstab /etc/fstab.backup</code></pre> <p>Next open /etc/fstab in your favorite text editor (as administrator), and add the following line at the end of the file:</p> <pre><code>sudo mount -t tmpfs -o rw,size=1M tmpfs /mnt/ramdisk</code></pre> <p>And save it.</p> <p>On your next reboot /mnt/ramdisk should be mounted and ready to use.</p> <p>Lastly change the <code>temp</code> path in your configuration file:</p> <pre><code class="language-ini">... [PATHS] temp = /mnt/ramdisk/ ...</code></pre> <hr /> <h1>7 TO-DO List</h1> <ul> <li>More code cleanup, move more functions out of the main script and into their corresponding modules.</li> <li>Work towards user style customization</li> <li>Localization</li> <li>Custom logout sequence, similar to the login one</li> <li>Figure out a way to remove hard-coded filetype handling.</li> </ul> <hr /> <h1>7.1 Known bugs/issues</h1> <ul> <li>Config file parser still doesn't check for errors, a poorly built configuration file will cause a crash on startup.</li> <li>If updating from v0.10, the messages already existing in the oneliners.json file will have the wrong encoding. New messages will display correctly.</li> </ul> <hr /> <h1>8 Acknowledgements</h1> <h2>Development team</h2> <ul> <li>Jorge Castillo (Pastbytes) - Original idea, creator and developer of <em>Turbo56K</em>, <em>Retroterm</em> and <em>RetroBBS</em></li> <li>Pablo Roldán (Durandal) - Developer of <em>RetroBBS</em>, extension of <em>Turbo56K</em> protocol</li> </ul> <h2>Thanks</h2> <p>Thanks go to the following persons who helped in the testing of <em>RetroBBS</em></p> <ul> <li>Thierry Kurt</li> <li>Ezequiel Filgueiras</li> <li>Juan Musso</li> <li>Vaporatorius</li> <li>Gabriel Garcia</li> <li>Roberto Mandracchia</li> <li>ChrisKewl - <a rel="noreferrer nofollow" target="_blank" href="http://twitter.com/chriskewltv">twitter.com/chriskewltv</a></li> </ul> <h2>External software, support files</h2> <ul> <li>SIDdump by Lasse Öörni (cadaver)</li> <li>FFmpeg by the FFmpeg team</li> <li>Betterpixels font by AmericanHamster</li> <li>karen2blackint font by PaulSpades</li> <li>Map tiles by <a rel="noreferrer nofollow" target="_blank" href="http://stamen.com">Stamen Design</a>, under <a rel="noreferrer nofollow" target="_blank" href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a rel="noreferrer nofollow" target="_blank" href="http://openstreetmap.org">OpenStreetMap</a>, under <a rel="noreferrer nofollow" target="_blank" href="http://www.openstreetmap.org/copyright">ODbL</a>.</li> </ul> <hr /></div> </div> <div class="footer"> <ul class="body"> <li>© <script> document.write(new Date().getFullYear()) </script> Githubissues.</li> <li>Githubissues is a development platform for aggregating issues.</li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script> <script src="/githubissues/assets/js.js"></script> <script src="/githubissues/assets/markdown.js"></script> <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.4.0/build/highlight.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.4.0/build/languages/go.min.js"></script> <script> hljs.highlightAll(); </script> </body> </html>