5.1 Introduction

The purpose of this chapter is to provide a list of all important ROM addresses. In addition to this, the use of the first three pages of memory is analysed in depth.

Many of the important subroutines are explained elsewhere in this book so only brief descriptions are provided here.

Where a ROM address is given you will find the version 1.0 presented first, followed by the version 1.1 address in parenthesis.

5.2 Use of page 0 memory

Any unspecified locations can be assumed to be used by the ROM but to be of no significance.

#00 – #0B – Unused by BASIC.

#10 – #11 – Address of current HIRES position.

#12 – #13 – Address of start of current line (in TEXT mode).

#14 – #15 – Used by the 8912 register load subroutine.

#18 – #19 – Used to point to the start of error messages.

#1A – #C – Contains a jump to the routine which prints ‘Ready’.

#1F – #20 – Address of last PLOT position.

#21 – #23 – Contains the DEF USR jump.

#28 – The type of data which resulted from formula evaluation; 0 means numeric, #FF means a string.

#29 – A flag that indicates whether the last variable used was an integer.

#2A – A flag which is used in several places.

#33 – #34 – Various uses, but often used to store a line number that is being located.

#35 – #83 – The BASIC input buffer. This is used to store anything that is typed, including immediate commands and INPUT data (which explains why an immediate command cannot use INPUT). This area is also used in version 1.0 during cassette operations – see Chapter 4.

#86 – Address of last temporary string.

#88 – #90 – A table of temporary strings.

#9A – #9B – Start of BASIC pointer.

#9C – #9D – Start of variables pointer.

#9E – #9F – Start of arrays pointer.

#A0 – #A1 – End of arrays pointer.

#A2 – #A3 – Pointer to next free string space.

#A6 – #A7 – Highest available memory location available to BASIC.

#A8 – #A9 – Current line number (read-only).

#AA – #AB - The current line number – saved for error messages.

#AC – #AD- Address of the start of the current instruction – 1.

#AE – #AF – Current DATA line number – used only when printing error messy ges. Altering this location does not change the READ sequence.

#BO – #B1 – The address of the next DATA item – 1. It is this address that one must modify in order to change the data accessed by the next READ command.

#B4 – #B5 – The identity of the last variable used.

#D0 – #D5 – The main floating-point accumulator.

#D8 – #DD – The second accumulator.

#E2 – #E7 – The get-character routine. This part increments the pointer at #E9, #EA and drops into address #E8.

#E8 – #F9 – The second part of the get-character routine. This section loads the next character, according to location #E9,#EA.

#FA – #FE – The current random number is stored here as a floating-point number.


5.3 Use of page 1

#100 –#10F – Used as a temporary area containing the ASCII string of characters whenever a floating-point number is converted. This is used for commands like PRINT and STR$.

#110 – #1FF – Used as a normal 6502 stack area (although it is occasionally pruned by non-standard methods).


Obviously the ROM makes extensive use of the stack for JSR commands, etc., but some BASIC commands can generate extra entries on the stack:

1. The ‘FOR’ command generates 18 bytes on the stack. From low address to high address these are:

  1 byte containing the ‘FOR’ token – #8D.

2 bytes pointing to the FOR variable.

5 bytes containing the STEP value (as a floating-point number).

1 byte indicating the sign of the step (either 1 or #FF).

5 bytes containing the upper limit in floating-point format. Note that the lower limit will have been stored in the variable being used, so this need not be saved.

2 bytes containing the line number of the FOR command.

2 bytes containir.g the address of the statement which follows the FOR instruction.

2. The ‘GOSUB’ command is somewhat more economical: it only needs 5 bytes. From low to high addresses these are:
  1 byte equal to #9B"’pthe token for ‘GOSUB’).

2 bytes giving the line number of the GOSUB command.

2 bytes giving the address of the character which follows the GOSUB command.

3. ‘REPEAT’ follows a similar format (again, these are listed from low address to high address):
  1 byte containing the token #8B – ‘REPEAT’.

2 bytes equal to the line number of the REPEAT.

2 bytes giving the address of the byte which follows the REPEAT command.

4. The formula evaluation subroutine keeps intermediate results on the stack. This is done because arithmetic operations have to be done in a strict order of priority. From most important to least

important, the operators are:

(a) Parenthesis – e.g., 4*(3+6).

(b) Exponentiation – e.g., 3^6+4.

(c) Negate – e.g., – B*4.

(d) Multiply and divide – e.g., 3*4/3+6.

(e) Add and subtract.

(f) NOT.

(g) AND.

(h) OR.

  From low address to high address, the following information is

stored on the stack:

2 bytes indicating the importance of the operation.

6 bytes containing the floating-point number.

2 bytes containing the address of the appropriate maths routine.

Because these commands use the stack you must ensure that the stack area is not filled. It is difficult to upset GOSUB and REPEAT, since you cannot specify which line RETURN and UNTIL apply to, but often a FOR ... NEXT loop can remain open.

For example, if you used the following lines in your program, you might leave the FOR information on the stack:

100 FORI=1 TO 10

110 IF X$(I) ="4" THEN 140

120 NEXT I

If this type of logic were repeated in other places you would soon be dealing with out-of-memory errors. Remember that a FOR... NEXT loop needs 18 bytes of stack!

If this is likely to be a problem, you will need to add a line in order to clear the unwanted FOR... NEXT information:

100 FOR I=1 TO 100

110 IF X$(I) ="4" THEN FOR I=1 TO 1:NEXT I:GOTO 140

120 NEXT I

Remember also that if you use up most of the stack for FOR and GOSUB commands, you may eventually hit an out-of-memory error when a complex formula is encountered.

5.4 Use of page 2

The difference between the use of #00 to #FF and #200 to #2FF is that the latter is mostly used by the newer Oric commands, while page 0 is almost fully utilised by the standard parts of Microsoft BASIC.

Only those locations which are of any interest (or are unused) are mentioned. There are often differences in the use of some locations by the two ROM versions.

#204 - Used when checking the range of values used in sound and graphics commands.

#208 - Contains details of the last ordinary key pressed (but not the ASCII code).

#209 - Contains details about the last shift or control key pressed.

#20c - Caps lock. This contains either #7F or #FF – no other value will work!

#212 - Contains the HIRES FB flag to indicate whether to draw, erase, or invert.

#213 - The pattern register is stored here. You can POKE values here instead of using the PATTERN command.

#215 - The graphics cursor mask.

#219 - The HIRES cursor X value.

#21A - The HIRES cursor Y value (do not forget to alter #10 and #11 as well)

#21F – A graphics flag; 0 is TEXT, 1 is graphics.

#220 – Memory size indicator; 0 means 48K, 1 means 16K.

#221 – #227 – Unused.

#228 – #22A – (version 1.0) Jump vector to the fast interrupt routine.

#22B – #22D – (version 1.0) Jump vector to the non-maskable interrupt routine.

#230 – #232 – (version 1.0) Jump vector to the slow interrupt routine.

#228 – #232 – (version 1.1) Unused.

#233 – #237 – Unused.

#238 – #260 – (version 1.0) Unused.

#238 – #23A – (version 1.1) Jump vector to VDU output routine.

#23B – #23D – (version 1.1) Jump vector to the KEY$ routine.

#23E – #240 – (version 1.1) Jump vector to the printer output subroutine.

#241 – #243 – (version 1.1) Jump vector to the routine that prints on the top line of the screen.

#244 – #246 – (version 1.1) Jump vector to the fast interrupt routine.

#247 – #249 – (version 1.1) Jump vector to the NMI routine.

#24A – #24C – (version 1.1) Jump vector to the slow interrupt routine.

#24D – #25D – (version 1.1) Various uses in cassette I/0 – see Chapter 4.

#268 -- Cursor position down the screen, relative to the start address of the screen.

#269 -- Cursor position across the screen.

#26A -- Oric status byte. Each bit relates to one aspect: from high bit to low bit – unused, double-height, protected-columns, ESC pressed, keyclick, unused, screen-on, cursor-off.

#26B – Text screen paper colour.

#26C – Text screen ink colour.

#26D – #26E – (version 1.0) Start of the TEXT screen – #28.

#26F – (version 1.0) Number of lines to scroll.

#272 – #273 – Timer 1 (used for reading the keyboard). W274 – t275 – Timer 2 (used by the flashing cursor).

#276 – #277 – Timer 3 (used by WAIT, HIRES, and TEXT). #278 – #2BF – (version 1.0) Unused.

#278 – #279 – (version 1.1) Start of TEXT screen + #28.

#27A – #27B – (version 1.1) Start of the text screen.

#27C – #27D – (version 1.1) Number of bytes to scroll – (#27E – 1) * #28

#27E – (version 1.1) Number of lines to scroll.

#27F – #2BF – (version 1.1) Used by the tape routines – (Chap. 4).

#2CO – Graphics enable: 0 means TEXT with GRAB, 1 means TEXT with RELEASE, and 3 means HIRES.

#2C1 – #2C2 – Highest address with graphics enabled + 1.

#2C4 – #2DE – Unused.

#2DF – The AS’CII code for the last key pressed (with top bit set).

#2E0 – #2EF – The parameter area for graphics and sound commands.

#2F1 – Print flag – set to 128 to make all print go to the printer, 0 for it to go to the screen.

#2F2 – A flag set by the EDIT command.

#2F4 – The trace flag.

#2F5 – Address of the ! extension command.

#2F7 – (version 1.0 only). The inverse flag. Try out different values!

#2F9 – #2FA – Unused.

#2FB – #2FD – A jump command to the & extension.

#2FE – #2FF – Unused.

5.5 Summary of ROM addresses

Version 1.0 ROM addresses are given first, followed by the equivalent version 1.1 address in parenthesis. All addresses are hexadecimal. Where there is no equivalent version 1.1 address, ‘ –’ has been specified.

C000 (C000)

C003 (C003)

C006 (C006)

Jump to cold start.

Jump to warm start.

Addresses of subroutines to handle each token (-1)


C0EA (C3C6)

C3F8 (C3F4)

C43B (C437)

C448 (C444)

C475 (C471)

C483 (C47C)

BASIC tokens. The last character of each has its top bit set.

Search the stack until a ‘FOR’ entry is found.

A block move.

Check stack for free space.

Check an address against the top of memory

Warm start entry (does not clear program).

Input and process a line.

C56F (C55F)

C59C (C58C)

C5F8 (C5E8)

C60A (C5FA)

C6E4 (C6B9)

C719 (C6EE)

C733 (C708)

C738 (C70D)

C751 (C726)

C773 (C748)

C824 (C7FD)

C832 (C809)

C841 (C855)

C8AD (C8C1)

C91F (C952)


CE8B (CF17)

D3ED (D499)

D4F0 (D5AB)

D539 (D5F4)

D595 (D650)

D7F1 (D8AC)

D871 (D92C)

DA79 (DB04)

DA80 (DB0B)

DA97 (DB22)



DD4D (DD51)





DE73 (DE77)




DF12 (DF21)

DF31 (DF49)


Recreate links between each line.

Input a line.

Wait for a keypress and return the ASCII code.

Translate a line into tokens.

Find the address of a given line.

The NEW command.

The RUN command.

The CLEAR command.

Reset the stack.

The LIST command.

The LLIST command.

The LPRINT command.

The FOR command.

Process a BASIC statement.

The RESTORE command.

Print ‘READY’.

The formula evaluation subroutine.

Integer to floating point.

Allocate string space.

Set up a new string.

Garbage collection subroutine.

Calculate the length of a string and clear temporary strings.

Floating point to integer.

Add 0.5 to accumulator.

Subtract accumulator from memory.

Add accumulator to memory.

Calculate LOG

Multiply the accumulator by memory.

Move memory to the second accumulator.

Multiply the accumulator by 10.

Divide the accumulator by 10.

Divide memory by the accumulator.

Divide the second accumulator by the main accumulator.

Move memory to the main accumulator.

Move the accumulator to memory.

Move the second accumulator to the main accumulator.

Move the main accumulator to the second accumulator.

Calculate SGN.

Calculate ABS.

Calculate INT.


E0D1 (E0D5)

E22A (E22E)

E231 (E235)

E26D (E271)

E34B (E34F)


E38E (E392)

E3D7 (E3DB)

E43B (E43F)

E4A8 (----)

E554 (E56C)

E563 (E5F5)

E576 (E5EA)

E57B (----)

E5C6 (E65E)

E630 (E6C9)

E696 (E735)

E6BA (E75A)

E6CA (E76A)

E6F0 (E790)

E70E (----)

E804 (E93D)

E905 (EB78)

E9A9 (EC21)


EC03 (EE22)


ED01 (EE1A)

ED09 (EE22)

ED1B (EE34)

ED70 (EE8C)

ED81 (EE9D)



F02D (FOC8)

F064 (FOFD)

F079 (F110)

F0A5 (F12D)

F141 (F1C8)

Input a floating-point number from a string of ASCII characters.

Output a floating-point number into a string of ASCII characters.

Calculate the square root.

Raise the second accumulator to the power of a number in memory.

Negate the main accumulator.

Calculate RND.

Calculate COS.

Calculate SIN.

Calculate TAN.

Calculate ATN.

Load a file from tape (see Chapter 4 for version 1.1).

Test for the end of a load from tape.

Clear the top line.

Print message at far left of top line.

Save a file on tape (for version 1.1, see Chapter 4).

Output one byte to tape.

Read byte from tape.

Latch onto tape header.

Output a tape header.

Change the 6522 ready for cassette I/0.

Compare filenames.

Print authors’ names.

Reset the 6522 after the completion of tape I/0.

Read a key without waiting.

Switch to text mode.

Switch to high-resolution mode.

Entry for interrupt handler.

Start clock.

Stop clock.

Poll timers.

Service timers.

Clear timers.

Read timer.

Set timer.

Wait for a given time.






F17F (F204)

F18B (F210)

F1E5 (F268)

F2E5 (F37F)

F412 (FA9F)

F415 (FAB5)

F418 (FACB)

F41B (FAE1)

F41E (FB40)

F421 (FBD0)

F424 (FC18)

F409 (F77C)

F430 (F8B2)

F436 (F865)

F4C8 (F523)

F535 (F590)

F57B (F5C1)

F89B (F8D0)

FA6C (FA86)


FB10 (FB2A)












Output character from X register to screen.

Entry point for non-maskable interrupt (NMI)

Output message to top line at position X.

Poll keyboard.

Write to the 8912 chip.

Output character in A to the printer.

Set up the ASCII character set.

Load up all the 8912 registers.

The high-pitched click.

The low-pitched click.


Additional note, August 1998

I'm not sure how applicable these addresses are to emulated Oric systems, and variants of the Oric that evolved after 1984.