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$,NOTEwould 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
- Save positions before writing - Use
NOTEbefore each record write - Store indexes in arrays - Keep sector/byte pairs in memory for fast access
- Validate positions - Check
ERR()afterNOTEandPOINT - Use consistent file modes - Open files the same way when reading/writing
- 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
- Statements - Complete statement reference
- CIO Reference - Central I/O operations
- XIO Reference - Extended I/O commands
- Device I/O - File operations