[H] HOMEATARI MUTINEER / DOCUMENTATION / 1.3.183

Core Programmers Guide

Write and integrate modular Atari BASIC applications for Mutineer.

Browse documentation

Atari Mutineer Core Programmers Guide

Atari Mutineer is a set of standalone Atari BASIC programs loaded with RUN. REMMS owns communications and session state so the current program can be discarded without losing caller identity or connection state.

See Runtime Architecture for the end-to-end flow, REMMS Programmers Guide for the resident API, and Data And File Formats for disk layouts.

Runtime Modules

RUNBBS -> APPMGR -> WFC -> APPMGR -> LOGIN -> APPMGR -> CORE
CORE -> APPMGR -> DOORS / MESGAREA / FILEBASE / SYSCHAT / XFERSEL
ModuleResponsibility
RUNBBSinitialize REMMS and request WFC
APPMGRresolve stable key, validate access, prepare route, and RUN
WFCanswer calls, terminal detection, local dashboard
LOGINlogin, registration, registration confirmation, and profile editing
COREmain caller command loop and subsystem dispatch
MESGAREAmulti-base scan/read/enter/kill
FILEBASEmulti-area list/download/upload/info
DOORScatalog lookup, access check, and external door launch
SYSOPsysop availability/config actions
SYSCHATline-mode caller/sysop chat
XFERSELtransfer protocol selection and native protocol dispatch
INIToffline board initialization
FILEMGRoffline file-area maintenance
MSGMGRoffline message-base maintenance

LOGIN is the supported login, registration, and user profile implementation.

Common BASIC Routines

Reusable routines live under source/text/inc/. A module includes one at a physical line-number base:

2005 INCLUDE "console_open_tail.inc"

Include files use strictly increasing relative lines beginning at 0. The preprocessor adds the directive base to every included line and to branch targets that name another line in the same include. Targets not declared by the include remain absolute, so calls to module-owned routines keep their normal physical numbers. Includes cannot include other includes.

Keep module declarations, menu policy, error destinations, and domain logic in the owning .bas file. Use a shared include only when its variable and error contracts match every consumer. Keep shared routines small and explicit so a module's line ownership remains easy to inspect.

Application Registry

The packed runtime registry is D1:>DATA>APPREG.DAT.

Rows contain:

handle,key,return,type,flags,access,route,term,name,path

Current stable keys:

KeyNameDefault return
$0001WFC$0000
$0008LOGIN$0001
$0010CORE$0001
$0020DOORS$0010
$0030MESGAREA$0010
$0040FILEBASE$0010
$0045SYSCHAT$0010
$0050SYSOP$0010
$0060XFERSEL$0040

Modules dispatch by writing the requested key to session +90/+91, the optional return key to +92/+93, saving owned session state, and running D1:>CORE>APPMGR.

When adding a module, reserve a stable key, decide the return key, define the minimum access level, and decide whether APPMGR should enter it as a caller module or a local-only tool. Caller modules inherit the current terminal mode, line-feed mode, user identity, access level, time limit, and online state from the REMMS session block.

Online Module Contract

Every supported online module:

  1. Discovers API, public state, and session through $03E8.
  2. Validates session magic 77 and supported version 1..3.
  3. Restores identity, modes, access, user number, session deadline, and any module-specific byte.
  4. Calls USR(ROPEN) for a remote session.
  5. Sets mode host and route both; local sessions set both to local.
  6. Opens caller-facing E: and K: channels as needed.
  7. Calls USR(RSTAT) at input boundaries and returns to WFC if session +87 is no longer online.
  8. Saves owned fields before another RUN.

Do not assume BASIC variables or IOCBs survive RUN. Do not parse RING, CONNECT, or NO CARRIER in BASIC; that belongs to REMMS.

Module Design Checklist

Use this checklist for a new caller-facing module:

  • Read RAPI, RPUB, and SS from the discovery record.
  • Validate PEEK(SS)=77 and PEEK(SS+1)=6.
  • Restore only the session fields the module owns.
  • If PEEK(SS+87)=1, call USR(ROPEN,0) and then USR(RMODE,1):USR(RROUTE,2).
  • If PEEK(SS+87)=8, treat it as a local sysop session and use local route.
  • Open caller-facing E: and K: channels after route/mode is set.
  • Use a timed prompt in the same shape as the other modules: [ HH:MM:SS Command >, [ HH:MM:SS Msg Command >, or [ HH:MM:SS File Command >.
  • Before disk reads or writes during a remote call, suspend the modem owner with USR(RCLOSE,1), perform bounded disk work, close disk IOCBs, and resume with USR(ROPEN,0).
  • Call USR(RSTAT) or USR(REVENT) at blocking input boundaries.
  • On carrier loss or fatal REMMS status, call USR(RFAIL,reason) and run WFC.
  • Before dispatching another module, store caller identity, access, time, modes, and module-specific handoff bytes back to SS.

Avoid global side effects. A module should not clear all 192 session bytes, change the answer-rings policy, close R: with hangup semantics, or alter terminal mode unless that is the explicit command being handled.

Prompts And Menus

Menus are ordinary text files and are reloaded whenever a parent command loop regains control. Prompts are generated by the module so they can include time-left and the right command noun. Do not embed or cache menu text in BASIC.

Main prompt:

[ HH:MM:SS Command >

Message prompt:

[ HH:MM:SS Msg Command >

File prompt:

[ HH:MM:SS File Command >

Door prompt:

[ HH:MM:SS Door Command >

HH:MM:SS is the caller's remaining session time. Local sysop sessions may use the same prompt shape with unrestricted or configured local time.

Use the resident pager for long caller-facing displays. Use direct output only for short status lines, prompts, and command responses.

Session Fields Used By BASIC

OffsetMeaning
+0/+1magic/version
+2..+42handle length/text
+43..+83secondary identity length/text
+84ATASCII mode
+85line-feed mode
+86expert/transfer mode
+871 remote online, 8 local sysop handoff
+90..+93requested/return stable keys
+96transient module or transfer mode
+97current message/file/door handoff byte
+102current runtime app handle
+122delayed remote byte
+123access level
+124/+125user number high/low
+126/+127session end minute high/low
+155/+156exit reason and pending-stat flag
+159/+160answer-after rings and ring count
+161/+162next/return runtime handles
+163..+191transfer pathname length/text

Many modules clear all 192 bytes before constructing a new handoff. When adding a field, update remms/src/constants.inc, every store/restore routine that owns it, the contract checker, and the REMMS documentation together.

REMMS Module Skeleton

1000 IF PEEK(1000)<>82 OR PEEK(1001)<>69 OR PEEK(1002)<>77 THEN RUN "D1:>CORE>WFC"
1010 RAPI=PEEK(1004)+256*PEEK(1005):RPUB=PEEK(1006)+256*PEEK(1007):SS=PEEK(1010)+256*PEEK(1011)
1020 RMODE=RAPI+3:RROUTE=RAPI+6:ROPEN=RAPI+9:RSTAT=RAPI+15:RGET=RAPI+18:RPUT=RAPI+21:RTGET=RAPI+27
1030 IF PEEK(SS)<>77 OR PEEK(SS+1)<1 OR PEEK(SS+1)>3 THEN RUN "D1:>CORE>WFC"
1040 IF PEEK(SS+87)=1 THEN R=USR(ROPEN):IF R<>0 THEN RUN "D1:>CORE>WFC"
1050 IF PEEK(SS+87)=1 THEN R=USR(RMODE,1):R=USR(RROUTE,2)
1060 OPEN #3,12,0,"E:":OPEN #4,4,0,"K:"
1070 R=USR(RSTAT):IF PEEK(SS+87)<>1 THEN RUN "D1:>CORE>WFC"

For text input, call RTGET; retry on $0100 (256) and hand carrier/fatal/timeout results to RFAIL. Use raw RGET/RPUT only for terminal detection and binary protocols. Text editors use canonical ATASCII 7E for destructive backspace and 7F for a one-space tab, and ignore unsupported extended editing controls.

Return Paths

Use APPMGR for normal module switches. Write the requested app key to SS+90/+91, write the desired return key to SS+92/+93, save module state, and run D1:>CORE>APPMGR.

Use direct RUN "D1:>CORE>WFC" only after explicit logoff, local shutdown, carrier loss, fatal REMMS failure, or an unrecoverable application failure. Use direct RUN "D1:>CORE>CORE" only for local-only maintenance flows that have already restored their session state.

Disk Ownership Pattern

Remote modules should follow this shape around disk work:

2600 IF ONLINE<>1 THEN RETURN
2610 R=USR(RCLOSE,1):RETURN
2620 IF ONLINE<>1 THEN RETURN
2630 R=USR(ROPEN,0):R=USR(RMODE,1):R=USR(RROUTE,2):RETURN

Open disk files only between the suspend and resume calls. For long displays, read a chunk into a string, close the disk file, resume R:, emit the buffered text, and repeat. Do not wait for caller input while a disk IOCB is open.

CORE Command Surface

CORE currently dispatches:

  • A: ASCII/ATASCII toggle.
  • B: bulletins.
  • C: caller list.
  • D: doors.
  • E: feedback.
  • F: filebase.
  • G: confirmed goodbye.
  • H or ?: help/function list.
  • I: information.
  • L: line-feed toggle.
  • M: message area.
  • Q: quick logoff.
  • T: text files.
  • W: welcome.
  • X: expert prompt toggle.
  • Y: sysop chat/fallback.

WFC remote entry offers login, new user, and goodbye. Its local controls are START for local sysop CORE, SELECT for offline tools, and OPTION for shutdown.

Persistence

  • Users: USERS.DAT, USERS.IDX, NEXTUSER.DAT, ACL.CFG.
  • Caller history: CALLERS.DAT.
  • Feedback: FEEDBACK.DAT.
  • Messages: MSGBASE.CFG and MESG?.MET/.DAT/.IDX.
  • Files: FILE?.MET/.DAT/.IDX.
  • Doors: offline DOORS.CFG, runtime DOORCAT.DAT, generated DOORMNU, and the configured external disk/path.

INIT, MSGMGR, and FILEMGR own offline creation, verification, rebuild, and compaction. Runtime modules should preserve existing record sizes and pointer semantics described in Data And File Formats.

Current Implementation Notes

  • The active runtime registry is APPREG; APPMGR reads bounded packed records.
  • REMMS wraps and chains E:, K:, and R:. Local E:/K: calls go directly to the saved handlers; IOCB 5 is reserved for R:.
  • Page-six helpers load menu data in blocks and emit the local copy with one CIO buffer operation. Remote bytes still use the normal REMMS translation and carrier-failure path.
  • CORE, MESGAREA, FILEBASE, DOORS, MSGMAIL, and MSGMOD reload their packaged text menu on every parent-loop return. DOORS uses the fixed-record door catalog instead of parsing CSV while callers wait.
  • Terminal detection is performed by WFC from the first caller return before normal line input.
  • Every bundled door uses the REMMS API and the canonical text-input contract.