forge Documentation

note-point

NOTE and POINT

The NOTE and POINT statements provide native random-access file positioning in FORGE, enabling indexed record retrieval and efficient file operations.

Overview

NOTE and POINT allow you to:

  • Write a file sequentially
  • Remember "where you are" (sector + byte)
  • Later jump back to an exact spot for indexed retrieval

This is the classic Atari BASIC method for:

  • Mailing list databases (records)
  • User/password/email databases
  • Message bases (BBS)
  • Fast "index files" (record pointers)

Syntax

NOTE #iochn, sectVar, byteVar / NO.

Get Current File Position

Gets the current file position for channel iochn and stores the sector number (16-bit) into sectVar and the byte offset within the sector (8-bit) into byteVar.

  • #_iochn_ - IOCB channel number (like #1)
  • _sectVar_ - 16-bit integer destination (sector, 0-65535)
  • _byteVar_ - 8-bit integer destination (byte offset, 0-255)

Example:

NOTE #1, SEC, BYT

POINT #iochn, sectExpr, byteExpr / PO.

Set File Position

Sets the file position for channel iochn to the specified sector sectExpr (16-bit) and byte offset byteExpr (8-bit) within that sector.

  • #_iochn_ - IOCB channel number
  • _sectExpr_ - Sector number expression (0-65535)
  • _byteExpr_ - Byte offset expression (0-255)

Example:

POINT #1, SEC, BYT

Semantics

NOTE Behavior

NOTE captures the current logical file position for that channel.

  • The returned (sector, byte) represents where the next read/write will occur.
  • After INPUT #1, A$, NOTE would report the position after that line.

POINT Behavior

POINT moves the channel to the requested file position:

  • The next read/write starts from that spot
  • This enables indexed / random access reads

Device Support

Works With

  • "D:" disk files (DOS/CIO handlers that implement NOTE/POINT)
  • Most normal filesystem-backed handlers

Undefined / Error-Prone On

  • Screen/editor devices ("E:", "K:")
  • Devices that don't implement seek (depends on handler)

Rule: If the handler can't do it, ERR() will report a CIO error.

Types and Ranges

FORGE uses 16-bit integers by default, so:

  • sectVar: 0..65535 (WORD)
  • byteVar: 0..255 (BYTE, but stored as integer)

Typical DOS-style use is byteVar in the 0..127 range (128-byte sectors), but the compiler should not enforce that — let the handler decide.

Error Handling

If NOTE or POINT fails, it behaves like other CIO calls:

  • ERR() is set to the CIO status code
  • Caller can check like:
NOTE #1, S, B
IF ERR() <> 1 THEN ? "NOTE failed: "; ERR()

Common failure reasons:

  • Channel not open
  • Device doesn't support NOTE/POINT
  • Invalid position (POINT out of range)

AUX1 Preservation

Built-in behavior requirement:

NOTE and POINT must internally use the same AUX1 mode used when OPEN was performed
✅ No user-visible AUX1 parameter
✅ No "4 vs 8 mismatch" bugs

This automatic AUX1 preservation makes NOTE/POINT safer than manual XIO calls.

Examples

Example 1: Indexed Record Retrieval

Write a file and build a pointer index in RAM:

DIM SEC(200), BYT(200)
N=0

OPEN #1,8,0,"D:USERS.DAT"

FOR I=1 TO 10
  ' save the position where this record starts
  NOTE #1, SEC(N), BYT(N)
  
  PRINT #1,"user";I;",pass";I;",email";I;"@site.com"
  N=N+1
NEXT I

CLOSE #1
? "Wrote ";N;" records."

Later: open and jump directly to record #5:

OPEN #1,4,0,"D:USERS.DAT"

REC=5
POINT #1, SEC(REC), BYT(REC)
INPUT #1,A$
? "Record ";REC;": ";A$

CLOSE #1

This is exactly how you build:

  • User DB lookups
  • Message retrieval by record number
  • Indexed reads without scanning the whole file

Example 2: BBS Message Base

Append-only message bases are perfect for NOTE/POINT because old pointers never move.

Writing messages:

DIM MSGSEC(500), MSGBYT(500)
MSGCNT=0

OPEN #1,8,0,"D:MSGS.TXT"

' Store where message starts
NOTE #1, MSGSEC(MSGCNT), MSGBYT(MSGCNT)

PRINT #1,"[MSG #";MSGCNT;"] Hello world!"
MSGCNT=MSGCNT+1

CLOSE #1

Reading back message #0 later:

OPEN #1,4,0,"D:MSGS.TXT"
POINT #1, MSGSEC(0), MSGBYT(0)
INPUT #1,A$
? A$
CLOSE #1

Example 3: Building an Index File

' Write data file and index
DIM INDEX_SEC(1000), INDEX_BYT(1000)
REC_COUNT = 0

OPEN #1, 8, 0, "D:DATA.TXT"
OPEN #2, 8, 0, "D:INDEX.DAT"

FOR I = 1 TO 100
  ' Save position before writing record
  NOTE #1, INDEX_SEC(REC_COUNT), INDEX_BYT(REC_COUNT)
  
  ' Write record
  PRINT #1, "Record "; I; " data here"
  
  ' Save index entry
  PRINT #2, INDEX_SEC(REC_COUNT), INDEX_BYT(REC_COUNT)
  
  REC_COUNT = REC_COUNT + 1
NEXT I

CLOSE #1
CLOSE #2

Using the index:

' Read index
DIM INDEX_SEC(1000), INDEX_BYT(1000)
REC_COUNT = 0

OPEN #2, 4, 0, "D:INDEX.DAT"
REPEAT
  INPUT #2, INDEX_SEC(REC_COUNT), INDEX_BYT(REC_COUNT)
  REC_COUNT = REC_COUNT + 1
UNTIL ERR() <> 1
CLOSE #2

' Read specific record
OPEN #1, 4, 0, "D:DATA.TXT"
REC_NUM = 42
POINT #1, INDEX_SEC(REC_NUM), INDEX_BYT(REC_NUM)
INPUT #1, RECORD$
? "Record "; REC_NUM; ": "; RECORD$
CLOSE #1

Best Practices

  1. Save positions before writing - Use NOTE before each record write
  2. Store indexes in arrays - Keep sector/byte pairs in memory for fast access
  3. Validate positions - Check ERR() after NOTE and POINT
  4. Use consistent file modes - Open files the same way when reading/writing
  5. Handle errors gracefully - Some devices don't support NOTE/POINT

Troubleshooting

NOTE/POINT fails:

  • Check channel is open
  • Verify device supports NOTE/POINT
  • Check ERR() for specific error code

Wrong position returned:

  • Ensure file was opened with correct mode
  • Check for file modifications between NOTE and POINT
  • Verify sector/byte values are correct

Data corruption:

  • Don't modify file between NOTE and POINT
  • Ensure file is closed properly
  • Check for concurrent access

Related Topics