@nataliapc/mcp-openmsx 1.2.10 → 1.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +20 -2
  2. package/dist/chunker.js +187 -0
  3. package/dist/embedder.js +250 -0
  4. package/dist/server.js +6 -1
  5. package/dist/server_tools.js +6 -5
  6. package/dist/vectordb.js +94 -35
  7. package/package.json +4 -8
  8. package/resources/audio/chipsfmpacpr1_en.md +209 -0
  9. package/resources/audio/chipsfmpacpr2_en.md +170 -0
  10. package/resources/audio/toc.json +12 -0
  11. package/resources/book--msx-top-secret-3/MTS3-Appendix-English-Upd2.pdf +0 -0
  12. package/resources/book--msx-top-secret-3/MTS3-Complete-English.pdf +0 -0
  13. package/resources/book--msx-top-secret-3/mts3-appendix-english-upd2.md +25863 -0
  14. package/resources/book--msx-top-secret-3/mts3-complete-english.md +44895 -0
  15. package/resources/book--msx2-technical-handbook/toc.json +1 -1
  16. package/resources/book--the-msx-red-book/Chapter1_Programmable_Peripheral_Interface.md +112 -0
  17. package/resources/book--the-msx-red-book/Chapter2_Video_Display_Processor.md +308 -0
  18. package/resources/book--the-msx-red-book/Chapter3_Programmable_Sound_Generator.md +168 -0
  19. package/resources/book--the-msx-red-book/Chapter4_ROM_BIOS.md +2528 -0
  20. package/resources/book--the-msx-red-book/Chapter5_ROM_BASIC_Interpreter.md +3975 -0
  21. package/resources/book--the-msx-red-book/Chapter6_Memory_Map.md +1963 -0
  22. package/resources/book--the-msx-red-book/Chapter7_Machine_Code_Programs.md +1238 -0
  23. package/resources/book--the-msx-red-book/Introduction.md +104 -0
  24. package/resources/book--the-msx-red-book/toc.json +38 -3
  25. package/resources/processors/toc.json +3 -3
  26. package/resources/processors/z80-undocumented.md +141 -0
  27. package/resources/programming/asm_develop_a_program_in_cartridge_rom.md +1881 -0
  28. package/resources/programming/toc.json +6 -0
  29. package/resources/sdcc/1_Introduction.md +199 -0
  30. package/resources/sdcc/2_Installing_SDCC.md +533 -0
  31. package/resources/sdcc/3_Using_SDCC.md +1758 -0
  32. package/resources/sdcc/4_Notes_on_supported_Processors.md +1638 -0
  33. package/resources/sdcc/5_Debugging.md +210 -0
  34. package/resources/sdcc/6_Tips_and_Support.md +258 -0
  35. package/resources/sdcc/7_SDCC_Technical_Data.md +489 -0
  36. package/resources/sdcc/8_Compiler_internals.md +477 -0
  37. package/resources/sdcc/toc.json +44 -2
  38. package/resources/system/how_to_detect_ram.md +14 -0
  39. package/resources/system/mrc_wiki_megarom_mappers.md +533 -0
  40. package/resources/system/the_memory.md +118 -0
  41. package/resources/system/toc.json +18 -0
  42. package/vector-db/__manifest/_transactions/0-675ee228-bffb-4636-80e5-cdfde25cc4fe.txn +2 -0
  43. package/vector-db/__manifest/_versions/18446744073709551614.manifest +0 -0
  44. package/vector-db/__manifest/_versions/latest_version_hint.json +1 -0
  45. package/vector-db/msxdocs.lance/_indices/37194b01-2a25-40d1-ac38-7fbe254df5ea/metadata.lance +0 -0
  46. package/vector-db/msxdocs.lance/_indices/37194b01-2a25-40d1-ac38-7fbe254df5ea/part_2_docs.lance +0 -0
  47. package/vector-db/msxdocs.lance/_indices/37194b01-2a25-40d1-ac38-7fbe254df5ea/part_2_invert.lance +0 -0
  48. package/vector-db/msxdocs.lance/_indices/37194b01-2a25-40d1-ac38-7fbe254df5ea/part_2_tokens.lance +0 -0
  49. package/vector-db/msxdocs.lance/_transactions/0-dd155672-40e6-4c6a-942f-7fcbe8c3dbd0.txn +0 -0
  50. package/vector-db/msxdocs.lance/_transactions/1-e7230cbd-ce8e-465c-9b85-b91443862427.txn +0 -0
  51. package/vector-db/msxdocs.lance/_versions/18446744073709551613.manifest +0 -0
  52. package/vector-db/msxdocs.lance/_versions/18446744073709551614.manifest +0 -0
  53. package/vector-db/msxdocs.lance/_versions/latest_version_hint.json +1 -0
  54. package/vector-db/msxdocs.lance/data/000100110110001011110001fc578141d296825d0bea11c95d.lance +0 -0
  55. package/resources/book--the-msx-red-book/the_msx_red_book.md +0 -10349
  56. package/resources/processors/z80-undocumented.tex +0 -5617
  57. package/resources/sdcc/lyx2md.py +0 -745
  58. package/resources/sdcc/sdccman.lyx +0 -81574
  59. package/resources/sdcc/sdccman.md +0 -5557
  60. package/vector-db/index.json +0 -1
@@ -0,0 +1,2528 @@
1
+ # 4. ROM BIOS
2
+
3
+ The design of the MSX ROM is of importance if machine code programs are to be developed efficiently and Operate reliably. Almost every program, including the BASIC Interpreter itself, will require a certain set of primitive functions to operate. These include screen and printer drivers, a keyboard decoder and other hardware related functions. By separating these routines from the BASIC Interpreter they can be made available to any application program. The section of ROM from 0000H to 268BH is largely devoted to such routines and is called the ROM BIOS (Basic Input Output System).
4
+
5
+ This chapter gives a functional description of every recognizably separate routine in the ROM BIOS. Special attention is given to the "standard" routines. These are documented by Microsoft and guaranteed to remain consistent through possible hardware and software changes. The first few hundred bytes of the ROM consists of Z80 JP instructions which provide fixed position entry points to these routines. For maximum compatibility with future software an application program should restrict its dependence on the ROM to these locations only. The description of the ROM begins with this list of entry points to the standard routines. A brief comment is placed with each entry point, the full description is given with the routine itself.
6
+
7
+ <a name="data_areas"></a>
8
+ ## Data Areas
9
+
10
+ It is expected that most users will wish to disassemble the ROM to some extent (the full listing runs to nearly four hundred pages). In order to ease this process the data areas, which do not contain executable Z80 code, are shown below:
11
+
12
+ ```
13
+ 0004H-0007H 185DH-1863H 4B3AH-4B4CH 73E4H-73E4H
14
+ 002BH-002FH 1B97H-1BAAH 4C2FH-4C3FH 752EH-7585H
15
+ 0508H-050DH 1BBFH-23BEH 555AH-5569H 7754H-7757H
16
+ 092FH-097FH 2439H-2459H 5D83H-5DB0H 7BA3H-7BCAH
17
+ 0DA5H-0EC4H 2CF1H-2E70H 6F76H-6F8EH 7ED8H-7F26H
18
+ 1033H-105AH 3030H-3039H 70FFH-710CH 7F41H-7FB6H
19
+ 1061H-10C1H 3710H-3719H 7182H-7195H 7FBEH-7FFFH
20
+ 1233H-1252H 392EH-3FE1H 71A2H-71B5H
21
+ 13A9H-1448H 43B5H-43C3H 71C7H-71DAH
22
+ 160BH-1612H 46E6H-46E7H 72A6H-72B9H
23
+ ```
24
+
25
+ Note that these data areas are for the UK ROM, there are slight differences in the Japanese ROM relating to the keyboard decoder and the video character set. Disparities between the ROMs are restricted to these regions with the bulk of the code being identical in both cases.
26
+
27
+ <a name="terminology"></a>
28
+ ## Terminology
29
+
30
+ Reference is frequently made in this chapter to the standard routines and to Workspace Area variables. Whenever this is done the Microsoft-recommended name is used in upper case letters, for example "the [FILVRM](#filvrm) standard routine" and "[SCRMOD](#scrmod) is set". Subroutines which are not named are referred to by a parenthesized address, "the screen is cleared ([0777H](#0777h))" for example. When reference is made to the Z80 status flags assembly language conventions are used, for example "Flag C" would mean that the carry flag is set while "Flag NZ" means that the zero flag is reset. The terms "EI" and "DI" mean enabled interrupts and disabled interrupts respectively.
31
+
32
+ |ADDRESS |NAME |TO |FUNCTION
33
+ |:---------:|:-----------------:|:-----------------:|--------------------------------------
34
+ |0000H |[CHKRAM](#chkram) |[02D7H](#02d7h) |Power-up, check RAM
35
+ |0004H |...... |..... |Two bytes, address of ROM character set
36
+ |0006H |...... |..... |One byte, VDP [Data Port](#data_port) number
37
+ |0007H |...... |..... |One byte, VDP [Data Port](#data_port) number
38
+ |0008H |[SYNCHR](#synchr) |[2683H](#2683h) |Check BASIC program character
39
+ |000BH |...... |..... |NOP
40
+ |000CH |[RDSLT](#rdslt) |[01B6H](#01b6h) |Read RAM in any slot
41
+ |000FH |...... |..... |NOP
42
+ |0010H |[CHRGTR](#chrgtr) |[2686H](#2686h) |Get next BASIC program character
43
+ |0013H |...... |..... |NOP
44
+ |0014H |[WRSLT](#wrslt) |[01D1H](#01d1h) |Write to RAM in any slot
45
+ |0017H |...... |..... |NOP
46
+ |0018H |[OUTDO](#outdo) |[1B45H](#1b45h) |Output to current device
47
+ |001BH |...... |..... |NOP
48
+ |001CH |[CALSLT](#calslt) |[0217H](#0217h) |Call routine in any slot
49
+ |001FH |...... |..... |NOP
50
+ |0020H |[DCOMPR](#dcompr) |[146AH](#146ah) |Compare register pairs HL and DE
51
+ |0023H |...... |..... |NOP
52
+ |0024H |[ENASLT](#enaslt) |[025EH](#025eh) |Enable any slot permanently
53
+ |0027H |...... |..... |NOP
54
+ |0028H |[GETYPR](#getypr) |[2689H](#2689h) |Get BASIC operand type
55
+ |002BH |...... |..... |Five bytes Version Number
56
+ |0030H |[CALLF](#callf) |[0205H](#0205h) |Call routine in any slot
57
+ |0033H |...... |..... |Five NOPs
58
+ |0038H |[KEYINT](#keyint) |[0C3CH](#0c3ch) |Interrupt handler, keyboard scan
59
+ |003BH |[INITIO](#initio) |[049DH](#049dh) |Initialize I/O devices
60
+ |003EH |[INIFNK](#inifnk) |[139DH](#139dh) |Initialize function key strings
61
+ |0041H |[DISSCR](#disscr) |[0577H](#0577h) |Disable screen
62
+ |0044H |[ENASCR](#enascr) |[0570H](#0570h) |Enable screen
63
+ |0047H |[WRTVDP](#wrtvdp) |[057FH](#057fh) |Write to any VDP register
64
+ |004AH |[RDVRM](#rdvrm) |[07D7H](#07d7h) |Read byte from VRAM
65
+ |004DH |[WRTVRM](#wrtvrm) |[07CDH](#07cdh) |Write byte to VRAM
66
+ |0050H |[SETRD](#setrd) |[07ECH](#07ech) |Set up VDP for read
67
+ |0053H |[SETWRT](#setwrt) |[07DFH](#07dfh) |Set up VDP for write
68
+ |0056H |[FILVRM](#filvrm) |[0815H](#0815h) |Fill block of VRAM with data byte
69
+ |0059H |[LDIRMV](#ldirmv) |[070FH](#070fh) |Copy block to memory from VRAM
70
+ |005CH |[LDIRVM](#ldirvm) |[0744H](#0744h) |Copy block to VRAM, from memory
71
+ |005FH |[CHGMOD](#chgmod) |[084FH](#084fh) |Change VDP mode
72
+ |0062H |[CHGCLR](#chgclr) |[07F7H](#07f7h) |Change VDP colours
73
+ |0065H |...... |..... |NOP
74
+ |0066H |[NMI](#nmi) |[1398H](#1398h) |Non Maskable Interrupt handler
75
+ |0069H |[CLRSPR](#clrspr) |[06A8H](#06a8h) |Clear all sprites
76
+ |006CH |[INITXT](#initxt) |[050EH](#050eh) |Initialize VDP to [40x24 Text Mode](#40x24_text_mode)
77
+ |006FH |[INIT32](#init32) |[0538H](#0538h) |Initialize VDP to [32x24 Text Mode](#32x24_text_mode)
78
+ |0072H |[INIGRP](#inigrp) |[05D2H](#05d2h) |Initialize VDP to [Graphics Mode](#graphics_mode)
79
+ |0075H |[INIMLT](#inimlt) |[061FH](#061fh) |Initialize VDP to [Multicolour Mode](#multicolor_mode)
80
+ |0078H |[SETTXT](#settxt) |[0594H](#0594h) |Set VDP to [40x24 Text Mode](#40x24_text_mode)
81
+ |007BH |[SETT32](#sett32) |[05B4H](#05b4h) |Set VDP to [32x24 Text Mode](#32x24_text_mode)
82
+ |007EH |[SETGRP](#setgrp) |[0602H](#0602h) |Set VDP to [Graphics Mode](#graphics_mode)
83
+ |0081H |[SETMLT](#setmlt) |[0659H](#0659h) |Set VDP to [Multicolour Mode](#multicolour_mode)
84
+ |0084H |[CALPAT](#calpat) |[06E4H](#06e4h) |Calculate address of sprite pattern
85
+ |0087H |[CALATR](#calatr) |[06F9H](#06f9h) |Calculate address of sprite attribute
86
+ |008AH |[GSPSIZ](#gspsiz) |[0704H](#0704h) |Get sprite size
87
+ |008DH |[GRPPRT](#grpprt) |[1510H](#1510h) |Print character on graphic screen
88
+ |0090H |[GICINI](#gicini) |[04BDH](#04bdh) |Initialize PSG (GI Chip)
89
+ |0093H |[WRTPSG](#wrtpsg) |[1102H](#1102h) |Write to any PSG register
90
+ |0096H |[RDPSG](#rdpsg) |[110EH](#110eh) |Read from any PSG register
91
+ |0099H |[STRTMS](#strtms) |[11C4H](#11c4h) |Start music dequeueing
92
+ |009CH |[CHSNS](#chsns) |[0D6AH](#0d6ah) |Sense keyboard buffer for character
93
+ |009FH |[CHGET](#chget) |[10CBH](#10cbh) |Get character from keyboard buffer (wait)
94
+ |00A2H |[CHPUT](#chput) |[08BCH](#08bch) |Screen character output
95
+ |00A5H |[LPTOUT](#lptout) |[085DH](#085dh) |Line printer character output
96
+ |00A8H |[LPTSTT](#lptstt) |[0884H](#0884h) |Line printer status test
97
+ |00ABH |[CNVCHR](#cnvchr) |[089DH](#089dh) |Convert character with graphic header
98
+ |00AEH |[PINLIN](#pinlin) |[23BFH](#23bfh) |Get line from console (editor)
99
+ |00B1H |[INLIN](#inlin) |[23D5H](#23d5h) |Get line from console (editor)
100
+ |00B4H |[QINLIN](#qinlin) |[23CCH](#23cch) |Display "`?`", get line from console (editor)
101
+ |00B7H |[BREAKX](#breakx) |[046FH](#046fh) |Check CTRL-STOP key directly
102
+ |00BAH |[ISCNTC](#iscntc) |[03FBH](#03fbh) |Check CRTL-STOP key
103
+ |00BDH |[CKCNTC](#ckcntc) |[10F9H](#10f9h) |Check CTRL-STOP key
104
+ |00C0H |[BEEP](#beep) |[1113H](#1113h) |Go beep
105
+ |00C3H |[CLS](#cls) |[0848H](#0848h) |Clear screen
106
+ |00C6H |[POSIT](#posit) |[088EH](#088eh) |Set cursor position
107
+ |00C9H |[FNKSB](#fnksb) |[0B26H](#0b26h) |Check if function key display on
108
+ |00CCH |[ERAFNK](#erafnk) |[0B15H](#0b15h) |Erase function key display
109
+ |00CFH |[DSPFNK](#dspfnk) |[0B2BH](#0b2bh) |Display function keys
110
+ |00D2H |[TOTEXT](#totext) |[083BH](#083bh) |Return VDP to text mode
111
+ |00D5H |[GTSTCK](#gtstck) |[11EEH](#11eeh) |Get joystick status
112
+ |00D8H |[GTTRIG](#gttrig) |[1253H](#1253h) |Get trigger status
113
+ |00DBH |[GTPAD](#gtpad) |[12ACH](#12ach) |Get touch pad status
114
+ |00DEH |[GTPDL](#gtpdl) |[1273H](#1273h) |Get paddle status
115
+ |00E1H |[TAPION](#tapion) |[1A63H](#1a63h) |Tape input ON
116
+ |00E4H |[TAPIN](#tapin) |[1ABCH](#1abch) |Tape input
117
+ |00E7H |[TAPIOF](#tapiof) |[19E9H](#19e9h) |Tape input OFF
118
+ |00EAH |[TAPOON](#tapoon) |[19F1H](#19f1h) |Tape output ON
119
+ |00EDH |[TAPOUT](#tapout) |[1A19H](#1a19h) |Tape output
120
+ |00F0H |[TAPOOF](#tapoof) |[19DDH](#19ddh) |Tape output OFF
121
+ |00F3H |[STMOTR](#stmotr) |[1384H](#1384h) |Turn motor ON/OFF
122
+ |00F6H |[LFTQ](#lftq) |[14EBH](#14ebh) |Space left in music queue
123
+ |00F9H |[PUTQ](#putq) |[1492H](#1492h) |Put byte in music queue
124
+ |00FCH |[RIGHTC](#rightc) |[16C5H](#16c5h) |Move current pixel physical address right
125
+ |00FFH |[LEFTC](#leftc) |[16EEH](#16eeh) |Move current pixel physical address left
126
+ |0102H |[UPC](#upc) |[175DH](#175dh) |Move current pixel physical address up
127
+ |0105H |[TUPC](#tupc) |[173CH](#173ch) |Test then [UPC](#upc) if legal
128
+ |0108H |[DOWNC](#downc) |[172AH](#172ah) |Move current pixel physical address down
129
+ |010BH |[TDOWNC](#tdownc) |[170AH](#170ah) |Test then [DOWNC](#downc) if legal
130
+ |010EH |[SCALXY](#scalxy) |[1599H](#1599h) |Scale graphics coordinates
131
+ |0111H |[MAPXYC](#mapxyc) |[15DFH](#15dfh) |Map graphic coordinates to physical address
132
+ |0114H |[FETCHC](#fetchc) |[1639H](#1639h) |Fetch current pixel physical address
133
+ |0117H |[STOREC](#storec) |[1640H](#1640h) |Store current pixel physical address
134
+ |011AH |[SETATR](#setatr) |[1676H](#1676h) |Set attribute byte
135
+ |011DH |[READC](#readc) |[1647H](#1647h) |Read attribute of current pixel
136
+ |0120H |[SETC](#setc) |[167EH](#167eh) |Set attribute of current pixel
137
+ |0123H |[NSETCX](#nsetcx) |[1809H](#1809h) |Set attribute of number of pixels
138
+ |0126H |[GTASPC](#gtaspc) |[18C7H](#18c7h) |Get aspect ratio
139
+ |0129H |[PNTINI](#pntini) |[18CFH](#18cfh) |Paint initialize
140
+ |012CH |[SCANR](#scanr) |[18E4H](#18e4h) |Scan pixels to right
141
+ |012FH |[SCANL](#scanl) |[197AH](#197ah) |Scan pixels to left
142
+ |0132H |[CHGCAP](#chgcap) |[0F3DH](#0f3dh) |Change Caps Lock LED
143
+ |0135H |[CHGSND](#chgsnd) |[0F7AH](#0f7ah) |Change Key Click sound output
144
+ |0138H |[RSLREG](#rslreg) |[144CH](#144ch) |Read Primary Slot Register
145
+ |013BH |[WSLREG](#wslreg) |[144FH](#144fh) |Write to Primary Slot Register
146
+ |013EH |[RDVDP](#rdvdp) |[1449H](#1449h) |Read VDP Status Register
147
+ |0141H |[SNSMAT](#snsmat) |[1452H](#1452h) |Read row of keyboard matrix
148
+ |0144H |[PHYDIO](#phydio) |[148AH](#148ah) |Disk, no action
149
+ |0147H |[FORMAT](#format) |[148EH](#148eh) |Disk, no action
150
+ |014AH |[ISFLIO](#isflio) |[145FH](#145fh) |Check for file I/O
151
+ |014DH |[OUTDLP](#outdlp) |[1B63H](#1b63h) |Formatted output to line printer
152
+ |0150H |[GETVCP](#getvcp) |[1470H](#1470h) |Get music voice pointer
153
+ |0153H |[GETVC2](#getvc2) |[1474H](#1474h) |Get music voice pointer
154
+ |0156H |[KILBUF](#kilbuf) |[0468H](#0468h) |Clear keyboard buffer
155
+ |0159H |[CALBAS](#calbas) |[01FFH](#01ffh) |Call to BASIC from any slot
156
+ |015CH |...... |..... |NOPs to 01B5H for expansion
157
+
158
+ <a name="01b6h"></a><a name="rdslt"></a>
159
+
160
+ ```
161
+ Address... 01B6H
162
+ Name...... RDSLT
163
+ Entry..... A=Slot ID, HL=Address
164
+ Exit...... A=Byte read
165
+ Modifies.. AF, BC, DE, DI
166
+ ```
167
+
168
+ Standard routine to read a single byte from memory in any slot. The Slot Identifier is composed of a Primary Slot number a Secondary Slot number and a flag:
169
+
170
+ <a name="figure34"></a>![][CH04F34]
171
+
172
+ **Figure 34:** Slot ID
173
+
174
+ The flag is normally 0 but must be 1 if a Secondary Slot number is included in the Slot ID. The memory address and Slot ID are first processed ([027EH](#027eh)) to yield a set of bit masks to apply to the relevant slot register. If a Secondary Slot number is specified then the Secondary Slot Register is first modified to select the relevant page from that Secondary Slot ([02A3H](#02a3h)). The Primary Slot is then switched in to the Z80 address space, the byte read and the Primary Slot restored to its original setting via the [RDPRIM](#rdprim) routine in the Workspace Area. Finally, if a Secondary Slot number is included in the Slot ID, the original Secondary Slot Register setting is restored (01ECH).
175
+
176
+ Note that, unless it is the slot containing the Workspace Area, any attempt to access page 3 (C000H to FFFFH) will cause the system to crash as [RDPRIM](#rdprim) will switch itself out. Note also that interrupts are left disabled by all the memory switching routines.
177
+
178
+ <a name="01d1h"></a><a name="wrslt"></a>
179
+
180
+ ```
181
+ Address... 01D1H
182
+ Name...... WRSLT
183
+ Entry..... A=Slot ID, HL=Address, E=Byte to write
184
+ Exit...... None
185
+ Modifies.. AF, BC, D, DI
186
+ ```
187
+
188
+ Standard routine to write a single byte to memory in any slot. Its operation is fundamentally the same as that of the [RDSLT](#rdslt) standard routine except that the Workspace Area routine [WRPRIM](#wrprim) is used rather than [RDPRIM](#rdprim).
189
+
190
+ <a name="01ffh"></a><a name="calbas"></a>
191
+
192
+ ```
193
+ Address... 01FFH
194
+ Name...... CALBAS
195
+ Entry..... IX=Address
196
+ Exit...... None
197
+ Modifies.. AF', BC', DE', HL', IY, DI
198
+ ```
199
+
200
+ Standard routine to call an address in the BASIC Interpreter from any slot. Usually this will be from a machine code program running in an extension ROM in page 1 (4000H to 7FFFH). The high byte of register pair IY is loaded with the MSX ROM Slot ID (00H) and control transfers to the [CALSLT](#calslt) standard routine.
201
+
202
+ <a name="0205h"></a><a name="callf"></a>
203
+
204
+ ```
205
+ Address... 0205H
206
+ Name...... CALLF
207
+ Entry..... None
208
+ Exit...... None
209
+ Modifies.. AF', BC', DE', HL', IX, IY, DI
210
+ ```
211
+
212
+ Standard routine to call an address in any slot. The Slot ID and address are supplied as inline parameters rather than in registers to fit inside a hook ([Chapter 6](chapter_6)), for example:
213
+
214
+ ```
215
+ RST 30H
216
+ DEFB Slot ID
217
+ DEFW Address
218
+ RET
219
+ ```
220
+
221
+ The Slot ID is first collected and placed in the high byte of register pair IY. The address is then placed in register pair IX and control drops into the [CALSLT](#calslt) standard routine.
222
+
223
+ <a name="0217h"></a><a name="calslt"></a>
224
+
225
+ ```
226
+ Address... 0217H
227
+ Name...... CALSLT
228
+ Entry..... IY(High byte)=Slot ID, IX=Address
229
+ Exit...... None
230
+ Modifies.. AF', BC', DE', HL', DI
231
+ ```
232
+
233
+ Standard routine to call an address in any slot. Its operation is fundamentally the same as that of the [RDSLT](#rdslt) standard routine except that the Workspace Area routine [CLPRIM](#clprim) is used rather than [RDPRIM](#rdprim). Note that [CALBAS](#calbas) and [CALLF](#callf) are just specialized entry points to this standard routine which offer a reduction in the amount of code required.
234
+
235
+ <a name="025eh"></a><a name="enaslt"></a>
236
+
237
+ ```
238
+ Address... 025EH
239
+ Name...... ENASLT
240
+ Entry..... A=Slot ID, HL=Address
241
+ Exit...... None
242
+ Modifies.. AF, BC, DE, DI
243
+ ```
244
+
245
+ Standard routine to switch in a page permanently from any slot. Unlike the [RDSLT](#rdslt), [WRSLT](#wrslt) and [CALSLT](#calslt) standard routines the Primary Slot switching is performed directly and not by a Workspace Area routine. Consequently addresses in page 0 (0000H to 3FFFH) will cause an immediate system crash.
246
+
247
+ <a name="027eh"></a>
248
+
249
+ Address... 027EH
250
+
251
+ This routine is used by the memory switching standard routines to turn an address, in register pair HL, and a Slot ID, in register A, into a set of bit masks. As an example a Slot ID of FxxxSSPP and an address in Page 1 (4000H to 7FFFH) would return the following:
252
+
253
+ ```
254
+ Register B=00 00 PP 00 (OR mask)
255
+ Register C=11 11 00 11 (AND mask)
256
+ Register D=PP PP PP PP (Replicated)
257
+ Register E=00 00 11 00 (Page mask)
258
+ ```
259
+
260
+ Registers B and C are derived from the Primary Slot number and the page mask. They are later used to mix the new Primary Slot number into the existing contents of the Primary Slot Register. Register D contains the Primary Slot number replicated four times and register E the page mask. This is produced by examining the two most significant bits of the address, to determine the page number, and then shifting the mask along to the relevant position. These registers are later used during Secondary Slot switching.
261
+
262
+ As the routine terminates bit 7 of the Slot ID is tested, to determine whether a Secondary Slot has been specified, and Flag M returned if this is so.
263
+
264
+ <a name="02a3h"></a>
265
+
266
+ Address... 02A3H
267
+
268
+ This routine is used by the memory switching standard routines to modify a Secondary Slot Register. The Slot ID is supplied in register A while registers D and E contain the bit masks shown in the previous routine.
269
+
270
+ Bits 6 and 7 of register D are first copied into the Primary Slot register. This switches in page 3 from the Primary Slot specified by the Slot ID and makes the required Secondary Slot Register available. This is then read from memory location FFFFH and the page mask, inverted, used to clear the required two bits. The Secondary Slot number is shifted to the relevant position and mixed in. Finally the new setting is placed in the Secondary Slot Register and the Primary Slot Register restored to its original setting.
271
+
272
+ <a name="02d7h"></a><a name="chkram"></a>
273
+
274
+ ```
275
+ Address... 02D7H
276
+ Name...... CHKRAM
277
+ Entry..... None
278
+ Exit...... None
279
+ Modifies.. AF, BC, DE, HL, SP
280
+ ```
281
+
282
+ Standard routine to perform memory initialization at power- up. It non-destructively tests for RAM in pages 2 and 3 in all sixteen possible slots then sets the Primary and Secondary Slot registers to switch in the largest area found. The entire Workspace Area (F380H to FFC9H) is zeroed and [EXPTBL](#exptbl) and [SLTTBL](#slttbl) filled in to map any expansion interfaces in existence Interrupt Mode 1 is set and control transfers to the remainder of the power-up initialization routine ([7C76H](#7c76h)).
283
+
284
+ <a name="03fbh"></a><a name="iscntc"></a>
285
+
286
+ ```
287
+ Address... 03FBH
288
+ Name...... ISCNTC
289
+ Entry..... None
290
+ Exit...... None
291
+ Modifies.. AF, EI
292
+ ```
293
+
294
+ Standard routine to check whether the CTRL-STOP or STOP keys have been pressed. It is used by the BASIC Interpreter at the end of each statement to check for program termination. [BASROM](#basrom) is first examined to see if it contains a non-zero value, if so the routine terminates immediately. This is to prevent users breaking into any extension ROM containing a BASIC program.
295
+
296
+ [INTFLG](#intflg) is then checked to determine whether the interrupt handler has placed the CTRL-STOP or STOP key codes (03H or 04H) there. If STOP has been detected then the cursor is turned on ([09DAH](#09dah)) and [INTFLG](#intflg) continually checked until one of the two key codes reappears. The cursor is then turned off ([0A27H](#0a27h)) and, if the key is STOP, the routine terminates.
297
+
298
+ If CTRL-STOP has been detected then the keyboard buffer is first cleared via the [KILBUF](#kilbuf) standard routine and [TRPTBL](#trptbl) is checked to see whether an "`ON STOP GOSUB`" statement is active. If so the relevant entry in [TRPTBL](#trptbl) is updated ([0EF1H](#0ef1h)) and the routine terminates as the event will be handled by the Interpreter Runloop. Otherwise the [ENASLT](#enaslt) standard routine is used to switch in page 1 from the MSX ROM, in case an extension ROM is using the routine, and control transfers to the "`STOP`" statement handler (63E6H).
299
+
300
+ <a name="0468h"></a><a name="kilbuf"></a>
301
+
302
+ ```
303
+ Address... 0468H
304
+ Name...... KILBUF
305
+ Entry..... None
306
+ Exit...... None
307
+ Modifies.. HL
308
+ ```
309
+
310
+ Standard Routine to clear the forty character type-ahead keyboard buffer [KEYBUF](#keybuf). There are two pointers into this buffer, [PUTPNT](#putpnt) where the interrupt handler places characters, and [GETPNT](#getpnt) where application programs fetch them from. As the number of characters in the buffer is indicated by the difference between these two pointers [KEYBUF](#keybuf) is emptied simply by making them both equal.
311
+
312
+ <a name="046fh"></a><a name="breakx"></a>
313
+
314
+ ```
315
+ Address... 046FH
316
+ Name...... BREAKX
317
+ Entry..... None
318
+ Exit...... Flag C if CTRL-STOP key pressed
319
+ Modifies.. AF
320
+ ```
321
+
322
+ Standard routine which directly tests rows 6 and 7 of the keyboard to determine whether the CTRL and STOP keys are both pressed. If they are then [KEYBUF](#keybuf) is cleared and row 7 of [OLDKEY](#oldkey) modified to prevent the interrupt handler picking the keys up as well. This routine may often be more suitable for use by an application program, in preference to [ISCNTC](#iscntc), as it will work when interrupts are disabled, during cassette I/O for example, and does not exit to the Interpreter.
323
+
324
+ <a name="049dh"></a><a name="initio"></a>
325
+
326
+ ```
327
+ Address... 049DH
328
+ Name...... INITIO
329
+ Entry..... None
330
+ Exit...... None
331
+ Modifies.. AF, E, EI
332
+ ```
333
+
334
+ Standard routine to initialize the PSG and the Centronics Status Port. [PSG Register 7](#register_7) is first set to 80H making PSG Port B=Output and PSG Port A=Input. [PSG Register 15](#register_15) is set to CFH to initialize the Joystick connector control hardware. [PSG Register 14](#register_14) is then read and the Keyboard Mode bit placed in [KANAMD](#kanamd), this has no relevance for UK machines.
335
+
336
+ Finally a value of FFH is output to the Centronics Status Port (I/O port 90H) to set the [STROBE](#strobe) signal high. Control then drops into the [GICINI](#gicini) standard routine to complete initialization.
337
+
338
+ <a name="04bdh"></a><a name="gicini"></a>
339
+
340
+ ```
341
+ Address... 04BDH
342
+ Name...... GICINI
343
+ Entry..... None
344
+ Exit...... None
345
+ Modifies.. EI
346
+ ```
347
+
348
+ Standard routine to initialize the PSG and the Workspace Area variables associated with the "`PLAY`" statement. [QUETAB](#quetab), [VCBA](#vcba), [VCBB](#vcbb) and [VCBC](#vcbc) are first initialized with the values shown in Chapter 6. PSG Registers [8](#register_8), [9](#register_9) and [10](#register_10) are then set to zero amplitude and [PSG Register 7](#register_7) to B8H. This enables the Tone Generator and disables the Noise Generator on each channel.
349
+
350
+ <a name="0508h"></a>
351
+
352
+ Address... 0508H
353
+
354
+ This six byte table contains the "`PLAY`" statement parameters initially placed in [VCBA](#vcba), [VCBB](#vcbb) and [VCBC](#vcbc) by the [GICINI](#gicini) standard routine: Octave=4, Length=4, Tempo=120, Volume=88H, Envelope=00FFH.
355
+
356
+ <a name="050eh"></a><a name="initxt"></a>
357
+
358
+ ```
359
+ Address... 050EH
360
+ Name...... INITXT
361
+ Entry..... None
362
+ Exit...... None
363
+ Modifies.. AF, BC, DE, HL, EI
364
+ ```
365
+
366
+ Standard routine to initialize the VDP to [40x24 Text Mode](#40x24_text_mode). The screen is temporarily disabled via the [DISSCR](#disscr) standard routine and [SCRMOD](#scrmod) and [OLDSCR](#oldscr) set to 00H. The parameters required by the [CHPUT](#chput) standard routine are set up by copying [LINL40](#linl40) to [LINLEN](#linlen), [TXTNAM](#txtnam) to [NAMBAS](#nambas) and [TXTCGP](#txtcgp) to [CGPBAS](#cgpbas). The VDP colours are then set by the [CHGCLR](#chgclr) standard routine and the screen is cleared (077EH). The current character set is copied into the VRAM Character Pattern Table ([071EH](#071eh)). Finally the VDP mode and base addresses are set via the [SETTXT](#settxt) standard routine and the screen is enabled.
367
+
368
+ <a name="0538h"></a><a name="init32"></a>
369
+
370
+ ```
371
+ Address... 0538H
372
+ Name...... INIT32
373
+ Entry..... None
374
+ Exit...... None
375
+ Modifies.. AF, BC, DE, HL, EI
376
+ ```
377
+
378
+ Standard routine to initialize the VDP to [32x24 Text Mode](#32x24_text_mode). The screen is temporarily disabled via the [DISSCR](#disscr) standard routine and [SCRMOD](#scrmod) and [OLDSCR](#oldscr) set to 01H. The parameters required by the [CHPUT](#chput) standard routine are set up by copying [LINL32](#linl32) to [LINLEN](#linlen), [T32NAM](#t32nam) to [NAMBAS](#nambas), [T32CGP](#t32cgp) to [CGPBAS](#cgpbas), [T32PAT](#t32pat) to [PATBAS](#patbas) and [T32ATR](#t32atr) to [ATRBAS](#atrbas). The VDP colours are then set via the [CHGCLR](#chgclr) standard routine and the screen is cleared (077EH). The current character set is copied into the VRAM Character Pattern Table ([071EH](#071eh)) and all sprites cleared (06BBH). Finally the VDP mode and base addresses are set via the [SETT32](#sett32) standard routine and the screen is enabled.
379
+
380
+ <a name="0570h"></a><a name="enascr"></a>
381
+
382
+ ```
383
+ Address... 0570H
384
+ Name...... ENASCR
385
+ Entry..... None
386
+ Exit...... None
387
+ Modifies.. AF, BC, EI
388
+ ```
389
+
390
+ Standard routine to enable the screen. This simply involves setting bit 6 of VDP [Mode Register 1](#mode_register_1).
391
+
392
+ <a name="0577h"></a><a name="disscr"></a>
393
+
394
+ ```
395
+ Address... 0577H
396
+ Name...... DISSCR
397
+ Entry..... None
398
+ Exit...... None
399
+ Modifies.. AF, BC, EI
400
+ ```
401
+
402
+ Standard routine to disable the screen. This simply involves resetting bit 6 of VDP [Mode Register 1](#mode_register_1).
403
+
404
+ <a name="057fh"></a><a name="wrtvdp"></a>
405
+
406
+ ```
407
+ Address... 057FH
408
+ Name...... WRTVDP
409
+ Entry..... B=Data byte, C=VDP Mode Register number
410
+ Exit...... None
411
+ Modifies.. AF, B, EI
412
+ ```
413
+
414
+ Standard routine to write a data byte to any VDP [Mode Register](#vdp_mode_registers). The register selection byte is first written to the VDP [Command Port](#commandpport), followed by the data byte. This is then copied to the relevant register image, [RG0SAV](#rg0sav) to [RG7SAV](#rg7sav), in the Workspace Area
415
+
416
+ <a name="0594h"></a><a name="settxt"></a>
417
+
418
+ ```
419
+ Address... 0594H
420
+ Name...... SETTXT
421
+ Entry..... None
422
+ Exit...... None
423
+ Modifies.. AF, BC, DE, HL, EI
424
+ ```
425
+
426
+ Standard routine to partially set the VDP to [40x24 Text Mode](#40x24_text_mode). The mode bits M1, M2 and M3 are first set in VDP Mode Registers [0](#mode_register_0) and [1](#mode_register_1). The five VRAM table base addresses, beginning with [TXTNAM](#txtnam), are then copied from the Workspace Area into VDP Mode Registers [2](#mode_register_2), [3](#mode_register_3), [4](#mode_register_4), [5](#mode_register_5) and [6](#mode_register_6) ([0677H](#0677h)).
427
+
428
+ <a name="05b4h"></a><a name="sett32"></a>
429
+
430
+ ```
431
+ Address... 05B4H
432
+ Name...... SETT32
433
+ Entry..... None
434
+ Exit...... None
435
+ Modifies.. AF, BC, DE, HL, EI
436
+ ```
437
+
438
+ Standard routine to partially set the VDP to [32x24 Text Mode](#32x24_text_mode). The mode bits M1, M2 and M3 are first set in VDP Mode Registers [0](#mode_register_0) and [1](#mode_register_1). The five VRAM table base addresses, beginning with [T32NAM](#t32nam), are then copied from the Workspace Area into VDP Mode Registers [2](#mode_register_2), [3](#mode_register_3), [4](#mode_register_4), [5](#mode_register_5) and [6](#mode_register_6) ([0677H](#0677h)).
439
+
440
+ <a name="05d2h"></a><a name="inigrp"></a>
441
+
442
+ ```
443
+ Address... 05D2H
444
+ Name...... INIGRP
445
+ Entry..... None
446
+ Exit...... None
447
+ Modifies.. AF, BC, DE, HL, EI
448
+ ```
449
+
450
+ Standard routine to initialize the VDP to [Graphics Mode](#graphics_mode). The screen is temporarily disabled via the [DISSCR](#disscr) standard routine and [SCRMOD](#scrmod) set to 02H. The parameters required by the [GRPPRT](#grpprt) standard routine are set up by copying [GRPPAT](#grppat) to [PATBAS](#patbas) and [GRPATR](#grpatr) to [ATRBAS](#atrbas). The character code driver pattern is then copied into the VDP Name Table, the screen cleared (07A1H) and all sprites cleared (06BBH). Finally the VDP mode and base addresses are set via the [SETGRP](#setgrp) standard routine and the screen is enabled.
451
+
452
+ <a name="0602h"></a><a name="setgrp"></a>
453
+
454
+ ```
455
+ Address... 0602H
456
+ Name...... SETGRP
457
+ Entry..... None
458
+ Exit...... None
459
+ Modifies.. AF, BC, DE, HL, EI
460
+ ```
461
+
462
+ Standard routine to partially set the VDP to [Graphics Mode](#graphics_mode). The mode bits M1, M2 and M3 are first set in VDP Mode Registers [0](#mode_register_0) and [1](#mode_register_1). The five VRAM table base addresses, beginning with [GRPNAM](#grpnam), are then copied from the Workspace Area into VDP Mode Registers [2](#mode_register_2), [3](#mode_register_3), [4](#mode_register_4), [5](#mode_register_5) and [6](#mode_register_6) ([0677H](#0677h)).
463
+
464
+ <a name="061fh"></a><a name="inimlt"></a>
465
+
466
+ ```
467
+ Address... 061FH
468
+ Name...... INIMLT
469
+ Entry..... None
470
+ Exit...... None
471
+ Modifies.. AF, BC, DE, HL, EI
472
+ ```
473
+
474
+ Standard routine to initialize the VDP to [Multicolour Mode](#multicolour_mode). The screen is temporarily disabled via the [DISSCR](#disscr) standard routine and [SCRMOD](#scrmod) set to 03H. The parameters required by the [GRPPRT](#grpprt) standard routine are set up by copying [MLTPAT](#mltpat) to [PATBAS](#patbas) and [MLTATR](#mltatr) to [ATRBAS](#atrbas). The character code driver pattern is then copied into the VDP Name Table, the screen cleared (07B9H) and all sprites cleared (06BBH). Finally the VDP mode and base addresses are set via the [SETMLT](#setmlt) standard routine and the screen is enabled.
475
+
476
+ <a name="0659h"></a><a name="setmlt"></a>
477
+
478
+ ```
479
+ Address... 0659H
480
+ Name...... SETMLT
481
+ Entry..... None
482
+ Exit...... None
483
+ Modifies.. AF, BC, DE, HL, EI
484
+ ```
485
+
486
+ Standard routine to partially set the VDP to [Multicolour Mode](#multicolour_mode). The mode bits M1, M2 and M3 are first set in VDP Mode Registers [0](#mode_register_0) and [1](#mode_register_1). The five VRAM table base addresses, beginning with [MLTNAM](#mltnam), are then copied from the Workspace Area to VDP Mode Registers [2](#mode_register_2), [3](#mode_register_3), [4](#mode_register_4), [5](#mode_register_5) and [6](#mode_register_6).
487
+
488
+ <a name="0677h"></a>
489
+
490
+ Address... 0677H
491
+
492
+ This routine is used by the [SETTXT](#settxt), [SETT32](#sett32), [SETGRP](#setgrp) and [SETMLT](#setmlt) standard routines to copy a block of five table base addresses from the Workspace Area into VDP Mode Registers [2](#mode_register_2), [3](#mode_register_3), [4](#mode_register_4), [5](#mode_register_5) and [6](#mode_register_6). On entry register pair HL points to the relevant group of addresses. Each base address is collected in turn shifted the required number of places and then written to the relevant Mode Register via the [WRTVDP](#wrtvdp) standard routine.
493
+
494
+ <a name="06a8h"></a><a name="clrspr"></a>
495
+
496
+ ```
497
+ Address... 06A8H
498
+ Name...... CLRSPR
499
+ Entry..... None
500
+ Exit...... None
501
+ Modifies.. AF, BC, DE, HL, EI
502
+ ```
503
+
504
+ Standard routine to clear all sprites. The entire 2 KB Sprite Pattern Table is first filled with zeros via the [FILVRM](#filvrm) standard routine. The vertical coordinate of each of the thirty-two sprite attribute blocks is then set to -47 (D1H) to place the sprite above the top of the screen, the horizontal coordinate is left unchanged.
505
+
506
+ The pattern numbers in the Sprite Attribute Table are initialized with the series 0, 1, 2, 3, 4,... 31 for 8x8 sprites or the series 0, 4, 8, 12, 16,... 124 for 16x16 sprites. The series to be generated is determined by the Size bit in VDP [Mode Register 1](#mode_register_1). Finally the colour byte of each sprite attribute block is filled in with the colour code contained in [FORCLR](#forclr), this is initially white.
507
+
508
+ Note that the Size and Mag bits in VDP [Mode Register 1](#mode_register_1) are not affected by this routine. Note also that the [INIT32](#init32), [INIGRP](#inigrp) and [INIMLT](#inimlt) standard routines use this routine with an entry point at 06BBH, leaving the Sprite Pattern Table undisturbed.
509
+
510
+ <a name="06e4h"></a><a name="calpat"></a>
511
+
512
+ ```
513
+ Address... 06E4H
514
+ Name...... CALPAT
515
+ Entry..... A=Sprite pattern number
516
+ Exit...... HL=Sprite pattern address
517
+ Modifies.. AF, DE, HL
518
+ ```
519
+
520
+ Standard routine to calculate the address of a sprite pattern. The pattern number is first multiplied by eight then, if 16x16 sprites are selected, multiplied by a further factor of four. This is then added to the Sprite Pattern Table base address, taken from [PATBAS](#patbas), to produce the final address.
521
+
522
+ This numbering system is in line with the BASIC Interpreter's usage of pattern numbers rather than the VDP's when 16x16 sprites are selected. As an example while the Interpreter calls the second pattern number one, it is actually VDP pattern number four. This usage means that the maximum pattern number this routine should allow, when 16x16 sprites are selected, is sixty-three. There is no actual check on this limit so large pattern numbers will produce addresses greater than 3FFFH. Such addresses, when passed to the other VDP routines, will wrap around past zero and corrupt the Character Pattern Table in VRAM.
523
+
524
+ <a name="06f9h"></a><a name="calatr"></a>
525
+
526
+ ```
527
+ Address... 06F9H
528
+ Name...... CALATR
529
+ Entry..... A=Sprite number
530
+ Exit...... HL=Sprite attribute address
531
+ Modifies.. AF, DE, HL
532
+ ```
533
+
534
+ Standard routine to calculate the address of a sprite attribute block. The sprite number, from zero to thirty-one, is multiplied by four and added to the Sprite Attribute Table base address taken from [ATRBAS](#atrbas).
535
+
536
+ <a name="0704h"></a><a name="gspsiz"></a>
537
+
538
+ ```
539
+ Address... 0704H
540
+ Name...... GSPSIZ
541
+ Entry..... None
542
+ Exit...... A=Bytes in sprite pattern (8 or 32)
543
+ Modifies.. AF
544
+ ```
545
+
546
+ Standard routine to return the number of bytes occupied by each sprite pattern in the Sprite Pattern Table. The result is determined simply by examining the Size bit in VDP [Mode Register 1](#mode_register_1).
547
+
548
+ <a name="070fh"></a><a name="ldirmv"></a>
549
+
550
+ ```
551
+ Address... 070FH
552
+ Name...... LDIRMV
553
+ Entry..... BC=Length, DE=RAM address, HL=VRAM address
554
+ Exit...... None
555
+ Modifies.. AF, BC, DE, EI
556
+ ```
557
+
558
+ Standard routine to copy a block into main memory from the VDP VRAM. The VRAM starting address is set via the [SETRD](#setrd) standard routine and then sequential bytes read from the VDP [Data Port](#data_port) and placed in main memory.
559
+
560
+ <a name="071eh"></a>
561
+
562
+ Address... 071EH
563
+
564
+ This routine is used to copy a 2 KB character set into the VDP Character Pattern Table in any mode. The base address of the Character Pattern Table in VRAM is taken from [CGPBAS](#cgpbas). The starting address of the character set is taken from [CGPNT](#cgpnt). The [RDSLT](#rdslt) standard routine is used to read the character data so this may be situated in an extension ROM.
565
+
566
+ At power-up [CGPNT](#cgpnt) is initialized with the address contained at ROM location 0004H, which is [1BBFH](#1bbfh). [CGPNT](#cgpnt) is easily altered to produce some interesting results, `POKE &HF920,&HC7:SCREEN 0` provides a thoroughly confusing example.
567
+
568
+ <a name="0744h"></a><a name="ldirvm"></a>
569
+
570
+ ```
571
+ Address... 0744H
572
+ Name...... LDIRVM
573
+ Entry..... BC=Length, DE=VRAM address, HL=RAM address
574
+ Exit...... None
575
+ Modifies.. AF, BC, DE, HL, EI
576
+ ```
577
+
578
+ Standard routine to copy a block to VRAM from main memory. The VRAM starting address is set via the [SETWRT](#setwrt) standard routine and then sequential bytes taken from main memory and written to the VDP [Data Port](#data_port).
579
+
580
+ <a name="0777h"></a>
581
+
582
+ Address... 0777H
583
+
584
+ This routine will clear the screen in any VDP mode. In [40x24 Text Mode](#40x24_text_mode) and [32x24 Text Mode](#32x24_text_mode) the Name Table, whose base address is taken from [NAMBAS](#nambas), is first filled with ASCII spaces. The cursor is then set to the home position ([0A7FH](#0a7fh)) and [LINTTB](#linttb), the line termination table, re-initialized. Finally the function key display is restored, if it is enabled, via the [FNKSB](#fnksb) standard routine.
585
+
586
+ In [Graphics Mode](#graphics_mode) the border colour is first set via VDP [Mode Register 7](#mode_register_7) (0832H). The Colour Table is then filled with the background colour code, taken from [BAKCLR](#bakclr), for both 0 and 1 pixels. Finally the Character Pattern Table is filled with zeroes.
587
+
588
+ In [Multicolour Mode](#multicolour_mode) the border colour is first set via VDP [Mode Register 7](#mode_register_7) (0832H). The Character Pattern Table is then filled with the background colour taken from [BAKCLR](#bakclr).
589
+
590
+ <a name="07cdh"></a><a name="wrtvrm"></a>
591
+
592
+ ```
593
+ Address... 07CDH
594
+ Name...... WRTVRM
595
+ Entry..... A=Data byte, HL=VRAM address
596
+ Exit...... None
597
+ Modifies.. EI
598
+ ```
599
+
600
+ Standard routine to write a single byte to the VDP VRAM. The VRAM address is first set up via the [SETWRT](#setwrt) standard routine and then the data byte written to the VDP [Data Port](#data_port). Note that the two seemingly spurious `EX(SP),HL` instructions in this routine, and several others, are required to meet the VDP's timing constraints.
601
+
602
+ <a name="07d7h"></a><a name="rdvrm"></a>
603
+
604
+ ```
605
+ Address... 07D7H
606
+ Name...... RDVRM
607
+ Entry..... HL=VRAM address
608
+ Exit...... A=Byte read
609
+ Modifies.. AF, EI
610
+ ```
611
+
612
+ Standard routine to read a single byte from the VDP VRAM. The VRAM address is first set up via the [SETRD](#setrd) standard routine and then the byte read from the VDP [Data Port](#data_port).
613
+
614
+ <a name="07dfh"></a><a name="setwrt"></a>
615
+
616
+ ```
617
+ Address... 07DFH
618
+ Name...... SETWRT
619
+ Entry..... HL=VRAM address
620
+ Exit...... None
621
+ Modifies.. AF, EI
622
+ ```
623
+
624
+ Standard routine to set up the VDP for subsequent writes to VRAM via the [Data Port](#data_port). The address contained in register pair HL is written to the VDP [Command Port](#command_port) LSB first, MSB second as shown in [Figure 7](#figure7). Addresses greater than 3FFFH will wrap around past zero as the two most significant bits of the address are ignored.
625
+
626
+ <a name="07ech"></a><a name="setrd"></a>
627
+
628
+ ```
629
+ Address... 07ECH
630
+ Name...... SETRD
631
+ Entry..... HL=VRAM address
632
+ Exit...... None
633
+ Modifies.. AF, EI
634
+ ```
635
+
636
+ Standard routine to set up the VDP for subsequent reads from VRAM via the [Data Port](#data_port). The address contained in register pair HL is written to the VDP [Command Port](#command_port) LSB first, MSB second as shown in [Figure 7](#figure7). Addresses greater than 3FFFH will wrap around past zero as the two most significant bits of the address are ignored.
637
+
638
+ <a name="07f7h"></a><a name="chgclr"></a>
639
+
640
+ ```
641
+ Address... 07F7H
642
+ Name...... CHGCLR
643
+ Entry..... None
644
+ Exit...... None
645
+ Modifies.. AF, BC, HL, EI
646
+ ```
647
+
648
+ Standard routine to set the VDP colours. [SCRMOD](#scrmod) is first examined to determine the appropriate course of action. In [40x24 Text Mode](#40x24_text_mode) the contents of [BAKCLR](#bakclr) and [FORCLR](#forclr) are written to VDP [Mode Register 7](#mode_register_7) to set the colour of the 0 and 1 pixels, these are initially blue and white. Note that in this mode there is no way of specifying the border colour, this will be the same as the 0 pixel colour. In [32x24 Text Mode](#32x24_text_mode), [Graphics Mode](#graphics_mode) or [Multicolour Mode](#multicolour_mode) the contents of [BDRCLR](#bdrclr) are written to VDP [Mode Register 7](#mode_register_7) to set the colour of the border, this is initially blue. Also in [32x24 Text Mode](#32x24_text_mode) the contents of [BAKCLR](#bakclr) and [FORCLR](#forclr) are copied to the whole of the Colour Table to determine the 0 and 1 pixel colours.
649
+
650
+ <a name="0815h"></a><a name="filvrm"></a>
651
+
652
+ ```
653
+ Address... 0815H
654
+ Name...... FILVRM
655
+ Entry..... A=Data byte, BC=Length, HL=VRAM address
656
+ Exit...... None
657
+ Modifies.. AF, BC, EI
658
+ ```
659
+
660
+ Standard routine to fill a block of the VDP VRAM with a single data byte. The VRAM starting address, contained in register pair HL, is first set up via the [SETWRT](#setwrt) standard routine. The data byte is then repeatedly written to the VDP [Data Port](#data_port) to fill successive VRAM locations.
661
+
662
+ <a name="083bh"></a><a name="totext"></a>
663
+
664
+ ```
665
+ Address... 083BH
666
+ Name...... TOTEXT
667
+ Entry..... None
668
+ Exit...... None
669
+ Modifies.. AF, BC, DE, HL, EI
670
+ ```
671
+
672
+ Standard routine to return the VDP to either [40x24 Text Mode](#40x24_text_mode) or [32x24 Text Mode](#32x24_text_mode) if it is currently in [Graphics Mode](#graphics_mode) or [Multicolour Mode](#multicolour_mode). It is used by the BASIC Interpreter Mainloop and by the "[INPUT](#input)" statement handler. Whenever the [INITXT](#initxt) or [INIT32](#init32) standard routines are used the mode byte, 00H or 01H, is copied into [OLDSCR](#oldscr). If the mode is subsequently changed to [Graphics Mode](#graphics_mode) or [Multicolour Mode](#multicolour_mode), and then has to be returned to one of the two text modes for keyboard input, this routine ensures that it returns to the same one.
673
+
674
+ [SCRMOD](#scrmod) is first examined and, if the screen is already in either text mode, the routine simply terminates with no action. Otherwise the previous text mode is taken from [OLDSCR](#oldscr) and passed to the [CHGMOD](#chgmod) standard routine.
675
+
676
+ <a name="0848h"></a><a name="cls"></a>
677
+
678
+ ```
679
+ Address... 0848H
680
+ Name...... CLS
681
+ Entry..... Flag Z
682
+ Exit...... None
683
+ Modifies.. AF, BC, DE, EI
684
+ ```
685
+
686
+ Standard routine to clear the screen in any mode, it does nothing but call the routine at 0777H. This is actually the "`CLS`" statement handler and, because this indicates that there is illegal text after the statement, it will simply return if entered with Flag NZ.
687
+
688
+ <a name="084fh"></a><a name="chgmod"></a>
689
+
690
+ ```
691
+ Address... 084FH
692
+ Name...... CHGMOD
693
+ Entry..... A=Screen mode required (0, 1, 2, 3)
694
+ Exit...... None
695
+ Modifies.. AF, BC, DE, HL, EI
696
+ ```
697
+
698
+ Standard routine to set a new screen mode. Register A, containing the required screen mode, is tested and control transferred to [INITXT](#initxt), [INIT32](#init32), [INIGRP](#inigrp) or [INIMLT](#inimlt).
699
+
700
+ <a name="085dh"></a><a name="lptout"></a>
701
+
702
+ ```
703
+ Address... 085DH
704
+ Name...... LPTOUT
705
+ Entry..... A=Character to print
706
+ Exit...... Flag C if CTRL-STOP termination
707
+ Modifies.. AF
708
+ ```
709
+
710
+ Standard routine to output a character to the line printer via the Centronics Port. The printer status is continually tested, via the [LPTSTT](#lptstt) standard routine, until the printer becomes free. The character is then written to the Centronics Data Port (I/O port 91H) and the [STROBE](#strobe) signal of the Centronics Status Port (I/O port 90H) briefly pulsed low. Note that the [BREAKX](#breakx) standard routine is used to test for the CTRL-STOP key if the printer is busy. If CTRL-STOP is detected a CR code is written to the Centronics Data Port, to flush the printer's line buffer, and the routine terminates with Flag C.
711
+
712
+ <a name="0884h"></a><a name="lptstt"></a>
713
+
714
+ ```
715
+ Address... 0884H
716
+ Name...... LPTSTT
717
+ Entry..... None
718
+ Exit...... A=0 and Flag Z if printer busy
719
+ Modifies.. AF
720
+ ```
721
+
722
+ Standard routine to test the Centronics Status Port BUSY signal. This just involves reading I/O port 90H and examining the state of bit 1: 0=Ready, 1=Busy.
723
+
724
+ <a name="088eh"></a><a name="posit"></a>
725
+
726
+ ```
727
+ Address... 088EH
728
+ Name...... POSIT
729
+ Entry..... H=Column, L=Row
730
+ Exit...... None
731
+ Modifies.. AF, EI
732
+ ```
733
+
734
+ Standard routine to set the cursor coordinates. The row and column coordinates are sent to the [OUTDO](#outdo) standard routine as the parameters in an ESC,"Y",Row+1FH, Column+1FH sequence. Note that the BIOS home position has coordinates of 1,1 rather than the 0,0 used by the BASIC Interpreter.
735
+
736
+ <a name="089dh"></a><a name="cnvchr"></a>
737
+
738
+ ```
739
+ Address... 089DH
740
+ Name...... CNVCHR
741
+ Entry..... A=Character
742
+ Exit...... Flag Z,NC=Header; Flag NZ,C=Graphic; Flag Z,C=Normal
743
+ Modifies.. AF
744
+ ```
745
+
746
+ Standard routine to test for, and convert if necessary, characters with graphic headers. Characters less than 20H are normally interpreted by the output device drivers as control characters. A character code in this range can be treated as a displayable character by preceding it with a graphic header control code (01H) and adding 40H to its value. For example to directly display character code 0DH, rather than have it interpreted as a carriage return, it is necessary to output the two bytes 01H,4DH. This routine is used by the output device drivers, such as the [CHPUT](#chput) standard routine, to check for such sequences.
747
+
748
+ If the character is a graphic header [GRPHED](#grphed) is set to 01H and the routine terminates, otherwise [GRPHED](#grphed) is zeroed. If the character is outside the range 40H to 5FH it is left unchanged. If it is inside this range, and [GRPHED](#grphed) contains 01H indicating a previous graphic header, it is converted by subtracting 40H.
749
+
750
+ <a name="08bch"></a><a name="chput"></a>
751
+
752
+ ```
753
+ Address... 08BCH
754
+ Name...... CHPUT
755
+ Entry..... A=Character
756
+ Exit...... None
757
+ Modifies.. EI
758
+ ```
759
+
760
+ Standard routine to output a character to the screen in [40x24 Text Mode](#40x24_text_mode) or [32x24 Text Mode](#32x24_text_mode). [SCRMOD](#scrmod) is first checked and, if the VDP is in either [Graphics Mode](#graphics_mode) or [Multicolour Mode](#multicolour_mode), the routine terminates with no action. Otherwise the cursor is removed ([0A2EH](#0a2eh)), the character decoded ([08DFH](#08dfh)) and then the cursor replaced ([09E1H](#09e1h)). Finally the cursor column position is placed in [TTYPOS](#ttypos), for use by the "`PRINT`" statement, and the routine terminates.
761
+
762
+ <a name="08dfh"></a>
763
+
764
+ Address... 08DFH
765
+
766
+ This routine is used by the [CHPUT](#chput) standard routine to decode a character and take the appropriate action. The [CNVCHR](#cnvchr) standard routine is first used to check for a graphic character, if the character is a header code (01H) then the routine terminates with no action. If the character is a converted graphic one then the control code decoding section is skipped. Otherwise [ESCCNT](#esccnt) is checked to see if a previous ESC character (1BH) has been received, if so control transfers to the ESC sequence processor ([098FH](#098fh)). Otherwise the character is checked to see if it is smaller than 20H, if so control transfers to the control code processor ([0914H](#0914h)). The character is then checked to see if it is DEL (7FH), if so control transfers to the delete routine (0AE3H).
767
+
768
+ Assuming the character is displayable the cursor coordinates are taken from [CSRY](#csry) and [CSRX](#csrx) and placed in register pair HL, H=Column, L=Row. These are then converted to a physical address in the VDP Name Table and the character placed there ([0BE6H](#0be6h)). The cursor column position is then incremented ([0A44H](#0a44h)) and, assuming the rightmost column has not been exceeded, the routine terminates. Otherwise the row's entry in [LINTTB](#linttb), the line termination table, is zeroed to indicate an extended logical line, the column number is set to 01H and a LF is performed.
769
+
770
+ <a name="0908h"></a>
771
+
772
+ Address... 0908H
773
+
774
+ This routine performs the LF operation for the [CHPUT](#chput) standard routine control code processor. The cursor row is incremented ([0A61H](#0a61h)) and, assuming the lowest row has not been exceeded, the routine terminates. Otherwise the screen is scrolled upwards and the lowest row erased (0A88H).
775
+
776
+ <a name="0914h"></a>
777
+
778
+ Address... 0914H
779
+
780
+ This is the control code processor for the [CHPUT](#chput) standard routine. The table at [092FH](#092fh) is searched for a match with the code and control transferred to the associated address.
781
+
782
+ <a name="092fh"></a>
783
+
784
+ Address... 092FH
785
+
786
+ This table contains the control codes, each with an associated address, recognized by the [CHPUT](#chput) standard routine:
787
+
788
+ |CODE |TO |FUNCTION
789
+ |:---:|:-----:|--------------------------------
790
+ |07H |1113H |BELL, go beep
791
+ |08H |0A4CH |BS, cursor left
792
+ |09H |0A71H |TAB, cursor to next tab position
793
+ |0AH |0908H |LF, cursor down a row
794
+ |0BH |0A7FH |HOME, cursor to home
795
+ |0CH |077EH |FORMFEED, clear screen and home
796
+ |0DH |0A81H |CR, cursor to leftmost column
797
+ |1BH |0989H |ESC, enter escape sequence
798
+ |1CH |0A5BH |RIGHT, cursor right
799
+ |1DH |0A4CH |LEFT, cursor left
800
+ |1EH |0A57H |UP, cursor up
801
+ |1FH |0A61H |DOWN, cursor down.
802
+
803
+ </a>
804
+
805
+ <a name="0953h"></a>
806
+
807
+ Address... 0953H
808
+
809
+ This table contains the ESC control codes, each with an associated address, recognized by the [CHPUT](#chput) standard routine:
810
+
811
+ |CODE |TO |FUNCTION
812
+ |:---:|:-----:|-------------------------------
813
+ |6AH |077EH |ESC,"j", clear screen and home
814
+ |45H |077EH |ESC,"E", clear screen and home
815
+ |4BH |0AEEH |ESC,"K", clear to end of line
816
+ |4AH |0B05H |ESC,"J", clear to end of screen
817
+ |6CH |0AECH |ESC,"l", clear line
818
+ |4CH |0AB4H |ESC,"L", insert line
819
+ |4DH |0A85H |ESC,"M", delete line
820
+ |59H |0986H |ESC,"Y", set cursor coordinates
821
+ |41H |0A57H |ESC,"A", cursor up
822
+ |42H |0A61H |ESC,"B", cursor down
823
+ |43H |0A44H |ESC,"C", cursor right
824
+ |44H |0A55H |ESC,"D", cursor left
825
+ |48H |0A7FH |ESC,"H", cursor home
826
+ |78H |0980H |ESC,"x", change cursor
827
+ |79H |0983H |ESC,"y", change cursor
828
+
829
+ </a>
830
+
831
+ <a name="0980h"></a>
832
+
833
+ Address... 0980H
834
+
835
+ This routine performs the ESC,"x" operation for the [CHPUT](#chput) standard routine control code processor. [ESCCNT](#esccnt) is set to 01H to indicate that the next character received is a parameter.
836
+
837
+ <a name="0983h"></a>
838
+
839
+ Address... 0983H
840
+
841
+ This routine performs the ESC,"y" operation for the [CHPUT](#chput) standard routine control code decoder. [ESCCNT](#esccnt) is set to 02H to indicate that the next character received is a parameter.
842
+
843
+ <a name="0986h"></a>
844
+
845
+ Address... 0986H
846
+
847
+ This routine performs the ESC",Y" operation for the [CHPUT](#chput) standard routine control code processor. [ESCCNT](#esccnt) is set to 04H to indicate that the next character received is a parameter.
848
+
849
+ <a name="0989h"></a>
850
+
851
+ Address... 0989H
852
+
853
+ This routine performs the ESC operation for the [CHPUT](#chput) standard routine control code processor. [ESCCNT](#esccnt) is set to FFH to indicate that the next character received is the second control character.
854
+
855
+ <a name="098fh"></a>
856
+
857
+ Address... 098FH
858
+
859
+ This is the [CHPUT](#chput) standard routine ESC sequence processor. If [ESCCNT](#esccnt) contains FFH then the character is the second control character and control transfers to the control code processor (0919H) to search the ESC code table at [0953H](#0953h).
860
+
861
+ If [ESCCNT](#esccnt) contains 01H then the character is the single parameter of the ESC,"x" sequence. If the parameter is "4" (34H) then [CSTYLE](#cstyle) is set to 00H resulting in a block cursor. If the parameter is "5" (35H) then [CSRSW](#csrsw) is set to 00H making the cursor normally disabled.
862
+
863
+ If [ESCCNT](#esccnt) contains 02H then the character is the single parameter in the ESC,"y" sequence. If the parameter is "4" (34H) then [CSTYLE](#cstyle) is set to 01H resulting in an underline cursor. If the parameter is "5" (35H) then [CSRSW](#csrsw) is set to 01H making the cursor normally enabled.
864
+
865
+ If [ESCCNT](#esccnt) contains 04H then the character is the first parameter of the ESC,"Y" sequence and is the row coordinate. The parameter has 1FH subtracted and is placed in [CSRY](#csry), [ESCCNT](#esccnt) is then decremented to 03H.
866
+
867
+ If [ESCCNT](#esccnt) contains 03H then the character is the second parameter of the ESC,"Y" sequence and is the column coordinate. The parameter has 1FH subtracted and is placed in [CSRX](#csrx).
868
+
869
+ <a name="09dah"></a>
870
+
871
+ Address... 09DAH
872
+
873
+ This routine is used, by the [CHGET](#chget) standard routine for example, to display the cursor character when it is normally disabled. If [CSRSW](#csrsw) is non-zero the routine simply terminates with no action, otherwise the cursor is displayed (09E6H).
874
+
875
+ <a name="09e1h"></a>
876
+
877
+ Address... 09E1H
878
+
879
+ This routine is used, by the [CHPUT](#chput) standard routine for example, to display the cursor character when it is normally enabled. If [CSRSW](#csrsw) is zero the routine simply terminates with no action. [SCRMOD](#scrmod) is checked and, if the screen is in [Graphics Mode](#graphics_mode) or [Multicolour Mode](#multicolour_mode), the routine terminates with no action. Otherwise the cursor coordinates are converted to a physical address in the VDP Name Table and the character read from that location ([0BD8H](#0bd8h)) and saved in [CURSAV](#cursav).
880
+
881
+ The character's eight byte pixel pattern is read from the VDP Character Pattern Table into the [LINWRK](#linwrk) buffer ([0BA5H](#0ba5h)). The pixel pattern is then inverted, all eight bytes if [CSTYLE](#cstyle) indicates a block cursor, only the bottom three if [CSTYLE](#cstyle) indicates an underline cursor. The pixel pattern is copied back to the position for character code 255 in the VDP Character Pattern Table ([0BBEH](#0bbeh)). The character code 255 is then placed at the current cursor location in the VDP Name Table ([0BE6H](#0be6h)) and the routine terminates.
882
+
883
+ This method of generating the cursor character, by using character code 255, can produce curious effects under certain conditions. These can be demonstrated by executing the BASIC statement `FOR N=1 TO 100: PRINT CHR$(255);:NEXT` and then pressing the cursor up key.
884
+
885
+ <a name="0a27h"></a>
886
+
887
+ Address... 0A27H
888
+
889
+ This routine is used, by the [CHGET](#chget) standard routine for example, to remove the cursor character when it is normally disabled. If [CSRSW](#csrsw) is non-zero the routine simply terminates with no action, otherwise the cursor is removed (0A33H).
890
+
891
+ <a name="0a2eh"></a>
892
+
893
+ Address... 0A2EH
894
+
895
+ This routine is used, by the [CHPUT](#chput) standard routine for example, .to remove the cursor character when it is normally enabled. If [CSRSW](#csrsw) is zero the routine simply terminates with no action. [SCRMOD](#scrmod) is checked and, if the screen is in [Graphics Mode](#graphics_mode) or [Multicolour Mode](#multicolour_mode), the routine terminates with no action. Otherwise the cursor coordinates are converted to a physical address in the VDP Name Table and the character held in [CURSAV](#cursav) written to that location ([0BE6H](#0be6h)).
896
+
897
+ <a name="0a44h"></a>
898
+
899
+ Address... 0A44H
900
+
901
+ This routine performs the ESC,"C" operation for the [CHPUT](#chput) standard routine control code processor. If the cursor column coordinate is already at the rightmost column, determined by [LINLEN](#linlen), then the routine terminates with no action. Otherwise the column coordinate is incremented and [CSRX](#csrx) updated.
902
+
903
+ <a name="0a4ch"></a>
904
+
905
+ Address... 0A4CH
906
+
907
+ This routine performs the BS/LEFT operation for the [CHPUT](#chput) standard routine control code processor. The cursor column coordinate is decremented and [CSRX](#csrx) updated. If the column coordinate has moved beyond the leftmost position it is set to the rightmost position, from [LINLEN](#linlen), and an UP operation performed.
908
+
909
+ <a name="0a55h"></a>
910
+
911
+ Address... 0A55H
912
+
913
+ This routine performs the ESC,"D" operation for the [CHPUT](#chput) standard routine control code processor. If the cursor column coordinate is already at the leftmost position then the routine terminates with no action. Otherwise the column coordinate is decremented and [CSRX](#csrx) updated.
914
+
915
+ <a name="0a57h"></a>
916
+
917
+ Address... 0A57H
918
+
919
+ This routine performs the ESC,"A" (UP) operation for the [CHPUT](#chput) standard routine control code processor. If the cursor row coordinate is already at the topmost position the routine terminates with no action. Otherwise the row coordinate is decremented and [CSRY](#csry) updated.
920
+
921
+ <a name="0a5bh"></a>
922
+
923
+ Address... 0A5BH
924
+
925
+ This routine performs the RIGHT operation for the [CHPUT](#chput) standard routine control code processor. The cursor column coordinate is incremented and [CSRX](#csrx) updated. If the column coordinate has moved beyond the rightmost position, determined by [LINLEN](#linlen), it is set to the leftmost position (01H) and a DOWN operation performed.
926
+
927
+ <a name="0a61h"></a>
928
+
929
+ Address... 0A61H
930
+
931
+ This routine performs the ESC,"B" (DOWN) operation for the [CHPUT](#chput) standard routine control code processor. If the cursor row coordinate is already at the lowest position, determined by [CRTCNT](#crtcnt) and [CNSDFG](#cnsdfg) ([0C32H](#0c32h)), then the routine terminates with no action. Otherwise the row coordinate is incremented and [CSRY](#csry) updated.
932
+
933
+ <a name="0a71h"></a>
934
+
935
+ Address... 0A71H
936
+
937
+ This routine performs the TAB operation for the [CHPUT](#chput) standard routine control code processor. ASCII spaces are output ([08DFH](#08dfh)) until [CSRX](#csrx) is a multiple of eight plus one (BIOS columns 1, 9, 17, 25, 33).
938
+
939
+ <a name="0a7fh"></a>
940
+
941
+ Address... 0A7FH
942
+
943
+ This routine performs the ESC,"H" (HOME) operation for the [CHPUT](#chput) standard routine control code processor, [CSRX](#csrx) and [CSRY](#csry) are simply set to 1,1. The ROM BIOS cursor coordinate system, while functionally identical to that used by the BASIC Interpreter, numbers the screen rows from 1 to 24 and the columns from 1 to 32/40.
944
+
945
+ <a name="0a81h"></a>
946
+
947
+ Address... 0A81H
948
+
949
+ This routine performs the CR operation for the [CHPUT](#chput) standard routine control code processor, [CSRX](#csrx) is simply set to 01H .
950
+
951
+ <a name="0a85h"></a>
952
+
953
+ Address... 0A85H
954
+
955
+ This routine performs the ESC,"M" function for the [CHPUT](#chput) standard routine control code processor. A CR operation is first performed to set the cursor column coordinate to the leftmost position. The number of rows from the current row to the bottom of the screen is then determined, if this is zero the current row is simply erased ([0AECH](#0aech)). The row count is first used to scroll up the relevant section of [LINTTB](#linttb), the line termination table, by one byte. It is then used to scroll up the relevant section of the screen a row at a time. Starting at the row below the current row, each line is copied from the VDP Name Table into the [LINWRK](#linwrk) buffer ([0BAAH](#0baah)) then copied back to the Name Table one row higher ([0BC3H](#0bc3h)). Finally the lowest row on the screen is erased ([0AECH](#0aech)).
956
+
957
+ <a name="0ab4h"></a>
958
+
959
+ Address... 0AB4H
960
+
961
+ This routine performs the ESC,"L" operation for the [CHPUT](#chput) standard routine control code processor. A CR operation is first performed to set the cursor column coordinate to the leftmost position. The number of rows from the current row to the bottom of the screen is then determined, if this is zero the current row is simply erased ([0AECH](#0aech)). The row count is first used to scroll down the relevant section of [LINTTB](#linttb), the line termination table, by one byte. It is then used to scroll down the relevant section of the screen a row at a time. Starting at the next to last row of the screen, each line is copied from the VDP Name Table into the [LINWRK](#linwrk) buffer ([0BAAH](#0baah)), then copied back to the Name Table one row lower ([0BC3H](#0bc3h)). Finally the current row is erased ([0AECH](#0aech)).
962
+
963
+ Address... 0AE3H
964
+
965
+ This routine is used to perform the DEL operation for the [CHPUT](#chput) standard routine control code processor. A LEFT operation is first performed. If this cannot be completed, because the cursor is already at the home position, then the routine terminates with no action. Otherwise a space is written to the VDP Name Table at the cursor's physical location ([0BE6H](#0be6h)).
966
+
967
+ <a name="0aech"></a>
968
+
969
+ Address... 0AECH
970
+
971
+ This routine performs the ESC,"l" operation for the [CHPUT](#chput) standard routine control code processor. The cursor column coordinate is set to 01H and control drops into the ESC,"K" routine.
972
+
973
+ <a name="0aeeh"></a>
974
+
975
+ Address... 0AEEH
976
+
977
+ This routine performs the ESC,"K" operation for the [CHPUT](#chput) standard routine control code processor. The row's entry in [LINTTB](#linttb), the line termination table, is first made non-zero to indicate that the logical line is not extended ([0C29H](#0c29h)). The cursor coordinates are converted to a physical address (0BF2H) in the VDP Name Table and the VDP set up for writes via the [SETWRT](#setwrt) standard routine. Spaces are then written directly to the VDP [Data Port](#data_port) until the rightmost column, determined by [LINLEN](#linlen), is reached.
978
+
979
+ Address... 0B05H
980
+
981
+ This routine performs the ESC,"J" operation for the [CHPUT](#chput) standard routine control code processor. An ESC,"K" operation is performed on successive rows, starting with the current one, until the bottom of the screen is reached.
982
+
983
+ <a name="0b15h"></a><a name="erafnk"></a>
984
+
985
+ ```
986
+ Address... 0B15H
987
+ Name...... ERAFNK
988
+ Entry..... None
989
+ Exit...... None
990
+ Modifies.. AF, DE, EI
991
+ ```
992
+
993
+ Standard routine to turn the function key display off. [CNSDFG](#cnsdfg) is first zeroed and, if the VDP is in [Graphics Mode](#graphics_mode) or [Multicolour Mode](#multicolour_mode), the routine terminates with no further action. If the VDP is in [40x24 Text Mode](#40x24_text_mode) or [32x24 Text Mode](#32x24_text_mode) the last row on the screen is then erased ([0AECH](#0aech)).
994
+
995
+ <a name="0b26h"></a><a name="fnksb"></a>
996
+
997
+ ```
998
+ Address... 0B26H
999
+ Name...... FNKSB
1000
+ Entry..... None
1001
+ Exit...... None
1002
+ Modifies.. AF, BC, DE, EI
1003
+ ```
1004
+
1005
+ Standard routine to show the function key display if it is enabled. If [CNSDFG](#cnsdfg) is zero the routine terminates with no action, otherwise control drops into the [DSPFNK](#dspfnk) standard routine..
1006
+
1007
+ <a name="0b2bh"></a><a name="dspfnk"></a>
1008
+
1009
+ ```
1010
+ Address... 0B2BH
1011
+ Name...... DSPFNK
1012
+ Entry..... None
1013
+ Exit...... None
1014
+ Modifies.. AF, BC, DE, EI
1015
+ ```
1016
+
1017
+ Standard routine to turn the function key display on. [CNSDFG](#cnsdfg) is set to FFH and, if the VDP is in [Graphics Mode](#graphics_mode) or [Multicolour Mode](#multicolour_mode), the routine terminates with no further action. Otherwise the cursor row coordinate is checked and, if the cursor is on the last row of the screen, a LF code (0AH) issued to the [OUTDO](#outdo) standard routine to scroll the screen up.
1018
+
1019
+ Register pair HL is then set to point to either the unshifted or shifted function strings in the Workspace Area depending upon whether the SHIFT key is pressed. [LINLEN](#linlen) has four subtracted, to allow a minimum of one space between fields, and is divided by five to determine the field size for each string. Successive characters are then taken from each function string, checked for graphic headers via the [CNVCHR](#cnvchr) standard routine and placed in the [LINWRK](#linwrk) buffer until the string is exhausted or the zone is filled. When all five strings are completed the [LINWRK](#linwrk) buffer is written to the last row in the VDP Name Table ([0BC3H](#0bc3h)).
1020
+
1021
+ <a name="0b9ch"></a>
1022
+
1023
+ Address... 0B9CH
1024
+
1025
+ This routine is used by the function key display related standard routines. The contents of register A are placed in [CNSDFG](#cnsdfg) then [SCRMOD](#scrmod) tested and Flag NC returned if the screen is in [Graphics Mode](#graphics_mode) or [Multicolour Mode](#multicolour_mode).
1026
+
1027
+ <a name="0ba5h"></a>
1028
+
1029
+ Address... 0BA5H
1030
+
1031
+ This routine copies eight bytes from the VDP VRAM into the [LINWRK](#linwrk) buffer, the VRAM physical address is supplied in register pair HL.
1032
+
1033
+ <a name="0baah"></a>
1034
+
1035
+ Address... 0BAAH
1036
+
1037
+ This routine copies a complete row of characters, with the length determined by [LINLEN](#linlen), from the VDP VRAM into the [LINWRK](#linwrk) buffer. The cursor row coordinate is supplied in register L.
1038
+
1039
+ <a name="0bbeh"></a>
1040
+
1041
+ Address... 0BBEH
1042
+
1043
+ This routine copies eight bytes from the [LINWRK](#linwrk) buffer into the VDP VRAM, the VRAM physical address is supplied in register pair HL.
1044
+
1045
+ <a name="0bc3h"></a>
1046
+
1047
+ Address... 0BC3H
1048
+
1049
+ This routine copies a complete row of characters, with the length determined by [LINLEN](#linlen), from the [LINWRK](#linwrk) buffer into the VDP VRAM. The cursor row coordinate is supplied in register L.
1050
+
1051
+ <a name="0bd8h"></a>
1052
+
1053
+ Address... 0BD8H
1054
+
1055
+ This routine reads a single byte from the VDP VRAM into register C. The column coordinate is supplied in register H, the row coordinate in register L.
1056
+
1057
+ <a name="0be6h"></a>
1058
+
1059
+ Address... 0BE6H
1060
+
1061
+ This routine converts a pair of screen coordinates, the column in register H and the row in register L, into a physical address in the VDP Name Table. This address is returned in register pair HL.
1062
+
1063
+ The row coordinate is first multiplied by thirty-two or forty, depending upon the screen mode, and added to the column coordinate. This is then added to the Name Table base address, taken from [NAMBAS](#nambas), to produce an initial address.
1064
+
1065
+ Because of the variable screen width, as contained in [LINLEN](#linlen), an additional offset has to be added to the initial address to keep the active region roughly centered within the screen. The difference between the "true" number of characters per row, thirty-two or forty, and the current width is halved and then rounded up to produce the left hand offset. For a UK machine, with a thirty-seven character width in [40x24 Text Mode](#40x24_text_mode), this will result in two unused characters on the left hand side and one on the right. The statement `PRINT (41-WID)\2`, where `WID` is any screen width, will display the left hand column offset in [40x24 Text Mode](#40x24_text_mode).
1066
+
1067
+ A complete BASIC program which emulates this routine is given below:
1068
+
1069
+ ```
1070
+ 10 CPR=40:NAM=BASE(0):WID=PEEK(&HF3AE)
1071
+ 20 SCRMD=PEEK(&HFCAF):IF SCRMD=0 THEN 40
1072
+ 30 CPR=32:NAM=BASE(5):WID=PEEK(&HF3AF)
1073
+ 40 LH=(CPR+1-WID)\2
1074
+ 50 ADDR=NAM+(ROW-1)*CPR+(COL-1)+LH
1075
+ ```
1076
+
1077
+ This program is designed for the `ROW` and `COL` coordinate system used by the ROM BIOS where home is 1,1. Line 50 may be simplified, by removing the "-1" factors, if the BASIC Interpreter's coordinate system is to be used.
1078
+
1079
+ <a name="0c1dh"></a>
1080
+
1081
+ Address... 0C1DH
1082
+
1083
+ This routine calculates the address of a row's entry in [LINTTB](#linttb), the line termination table. The row coordinate is supplied in register L and the address returned in register pair DE.
1084
+
1085
+ <a name="0c29h"></a>
1086
+
1087
+ Address... 0C29H
1088
+
1089
+ This routine makes a row's entry in [LINTTB](#linttb) non-zero when entered at [0C29H](#0c29h) and zero when entered at 0C2AH. The row coordinate is supplied in register L.
1090
+
1091
+ <a name="0c32h"></a>
1092
+
1093
+ Address... 0C32H
1094
+
1095
+ This routine returns the number of rows on the screen in register A. It will normally return twenty-four if the function key display is disabled and twenty-three if it is enabled. Note that the screen size is determined by [CRTCNT](#crtcnt) and may be modified with a BASIC statement, `POKE &HF3B1H,14:SCREEN 0` for example.
1096
+
1097
+ <a name="0c3ch"></a><a name="keyint"></a>
1098
+
1099
+ ```
1100
+ Address... 0C3CH
1101
+ Name...... KEYINT
1102
+ Entry..... None
1103
+ Exit...... None
1104
+ Modifies.. EI
1105
+ ```
1106
+
1107
+ Standard routine to process Z80 interrupts, these are generated by the VDP once every 20 ms on a UK machine. The [VDP Status Register](#vdp_status_register) is first read and bit 7 checked to ensure that this is a frame rate interrupt, if not the routine terminates with no action. The contents of the [Status Register](#vdp_status_register) are saved in [STATFL](#statfl) and bit 5 checked for sprite coincidence. If the Coincidence Flag is active then the relevant entry in [TRPTBL](#trptbl) is updated ([0EF1H](#0ef1h)).
1108
+
1109
+ [INTCNT](#intcnt), the "`INTERVAL`" counter, is then decremented. If this has reached zero the relevant entry in [TRPTBL](#trptbl) is updated ([0EF1H](#0ef1h)) and the counter reset with the contents of [INTVAL](#intval).
1110
+
1111
+ [JIFFY](#jiffy), the "`TIME`" counter, is then incremented. This counter just wraps around to zero when it overflows.
1112
+
1113
+ [MUSICF](#musicf) is examined to determine whether any of the three music queues generated by the "`PLAY`" statement are active. For each active queue the dequeueing routine ([113BH](#113bh)) is called to fetch the next music packet and write it to the PSG.
1114
+
1115
+ [SCNCNT](#scncnt) is then decremented to determine if a joystick and keyboard scan is required, if not the interrupt handler terminates with no further action. This counter is used to increase throughput and to minimize keybounce problems by ensuring that a scan is only carried out every three interrupts. Assuming a scan is required joystick connector 1 is selected and the two Trigger bits read ([120CH](#120ch)), followed by the two Trigger bits from joystick connector 2 ([120CH](#120ch)) and the SPACE key from row 8 of the keyboard ([1226H](#1226h)). These five inputs, which are all related to the "`STRIG`" statement, are combined into a single byte where 0=Pressed, 1=Not pressed:
1116
+
1117
+ <a name="figure35"></a>![][CH04F35]
1118
+
1119
+ **Figure 35:** "`STRIG`" Inputs
1120
+
1121
+ This reading is compared with the previous one, held in [TRGFLG](#trgflg), to produce an active transition byte and [TRGFLG](#trgflg) is updated with the new reading. The active transition byte is normally zero but contains a 1 in each position where a transition from unpressed to pressed has occurred. This active transition byte is shifted out bit by bit and the relevant entry in [TRPTBL](#trptbl) updated ([0EF1H](#0ef1h)) for each active device.
1122
+
1123
+ A complete scan of the keyboard matrix is then performed to identify new key depressions, any found are translated into key codes and placed in [KEYBUF](#keybuf) ([0D12H](#0d12h)). If [KEYBUF](#keybuf) is found to be empty at the end of this process [REPCNT](#repcnt) is decremented to see whether the auto-repeat delay has expired, if not the routine terminates. If the delay period has expired [REPCNT](#repcnt) is reset with the fast repeat value (60 ms), the [OLDKEY](#oldkey) keyboard map is reinitialized and the keyboard scanned again (0D4EH). Any keys which are continuously pressed will show up as new transitions during this scan. Note that keys will only auto-repeat while an application program keeps [KEYBUF](#keybuf) empty by reading characters. The interrupt handler then terminates.
1124
+
1125
+ <a name="0d12h"></a>
1126
+
1127
+ Address... 0D12H
1128
+
1129
+ This routine performs a complete scan of all eleven rows of the keyboard matrix for the interrupt handler. Each of the eleven rows is read in via the PPI and placed in ascending order in [NEWKEY](#newkey). [ENSTOP](#enstop) is then checked to see if warm starts are enabled. If its contents are non-zero and the keys CODE, GRAPH, CTRL and SHIFT are pressed control transfers to the BASIC Interpreter (409BH) via the [CALBAS](#calbas) standard routine. This facility is useful as even a machine code program can be terminated as long as the interrupt handler is running. The contents of [NEWKEY](#newkey) are compared with the previous scan contained in [OLDKEY](#oldkey). If any change at all has occurred [REPCNT](#repcnt) is loaded with the initial auto-repeat delay (780 ms). Each row 1, reading from [NEWKEY](#newkey) is then compared with the previous one, held in [OLDKEY](#oldkey), to produce an active transition byte and [OLDKEY](#oldkey) is updated with the new reading. The active transition byte is normally zero but contains a 1 in each position where a transition from unpressed to pressed has occurred. If the row contains any transitions these are decoded and placed in [KEYBUF](#keybuf) as key codes ([0D89H](#0d89h)). When all eleven rows have been completed the routine checks whether there are any characters in [KEYBUF](#keybuf), by subtracting [GETPNT](#getpnt) from [PUTPNT](#putpnt), and terminates.
1130
+
1131
+ <a name="0d6ah"></a><a name="chsns"></a>
1132
+
1133
+ ```
1134
+ Address... 0D6AH
1135
+ Name...... CHSNS
1136
+ Entry..... None
1137
+ Exit...... Flag NZ if characters in KEYBUF
1138
+ Modifies.. AF, EI
1139
+ ```
1140
+
1141
+ Standard routine to check if any keyboard characters are ready. If the screen is in [Graphics Mode](#graphincsmode) or [Multicolour Mode](#multicolour_mode) then [GETPNT](#getpnt) is subtracted from [PUTPNT](#putpnt) (0D62H) and the routine terminates. If the screen is in [40x24 Text Mode](#40x24_text_mode) or [32x24 Text Mode](#32x24_text_mode) the state of the SHIFT key is also examined and the function key display updated, via the [DSPFNK](#dspfnk) standard routine, if it has changed.
1142
+
1143
+ <a name="0d89h"></a>
1144
+
1145
+ Address... 0D89H
1146
+
1147
+ This routine converts each active bit in a keyboard row transition byte into a key code. A bit is first converted into a key number determined by its position in the keyboard matrix:
1148
+
1149
+ <a name="figure36"></a>![][CH04F36]
1150
+
1151
+ **Figure 36:** Key Numbers
1152
+
1153
+ The key number is then converted into a key code and placed in [KEYBUF](#keybuf) ([1021H](#1021h)). When all eight possible bits have been processed the routine terminates.
1154
+
1155
+ <a name="0da5h"></a>
1156
+
1157
+ Address... 0DA5H
1158
+
1159
+ This table contains the key codes of key numbers 00H to 2FH for various combinations of the control keys. A zero entry in the table means that no key code will be produced when that key is pressed:
1160
+
1161
+ ```
1162
+ 37H 36H 35H 34H 33H 32H 31H 30H Row 0
1163
+ 3BH 5DH 5BH 5CH 3DH 2DH 39H 38H Row 1
1164
+ NORMAL 62H 61H 9CH 2FH 2EH 2CH 60H 27H Row 2
1165
+ 6AH 69H 68H 67H 66H 65H 64H 63H Row 3
1166
+ 72H 71H 70H 6FH 6EH 6DH 6CH 6BH Row 4
1167
+ 7AH 79H 78H 77H 76H 75H 74H 73H Row 5
1168
+
1169
+ 26H 5EH 25H 24H 23H 40H 21H 29H Row 0
1170
+ 3AH 7DH 7BH 7CH 2BH 5FH 28H 2AH Row 1
1171
+ SHIFT 42H 41H 9CH 3FH 3EH 3CH 7EH 22H Row 2
1172
+ 4AH 49H 48H 47H 46H 45H 44H 43H Row 3
1173
+ 52H 51H 50H 4FH 4EH 4DH 4CH 4BH Row 4
1174
+ 5AH 59H 58H 57H 56H 55H 54H 53H Row 5
1175
+
1176
+ FBH F4H BDH EFH BAH ABH ACH 09H Row 0
1177
+ 06H 0DH 01H 1EH F1H 17H 07H ECH Row 1
1178
+ GRAPH 11H C4H 9CH 1DH F2H F3H BBH 05H Row 2
1179
+ C6H DCH 13H 15H 14H CDH C7H BCH Row 3
1180
+ 18H CCH DBH C2H 1BH 0BH C8H DDH Row 4
1181
+ 0FH 19H 1CH CFH 1AH C0H 12H D2H Row 5
1182
+
1183
+ 00H F5H 00H 00H FCH FDH 00H 0AH Row 0
1184
+ 04H 0EH 02H 16H F0H 1FH 08H 00H Row 1
1185
+ SHIFT 00H FEH 9CH F6H AFH AEH F7H 03H Row 2
1186
+ GRAPH CAH DFH D6H 10H D4H CEH C1H FAH Row 3
1187
+ A9H CBH D7H C3H D3H 0CH C9H DEH Row 4
1188
+ F8H AAH F9H D0H D5H C5H 00H D1H Row 5
1189
+
1190
+ E1H E0H 98H 9BH BFH D9H 9FH EBH Row 0
1191
+ B7H DAH EDH 9CH E9H EEH 87H E7H Row 1
1192
+ CODE 97H 84H 9CH A7H A6H 86H E5H B9H Row 2
1193
+ 91H A1H B1H 81H 94H 8CH 8BH 8DH Row 3
1194
+ 93H 83H A3H A2H A4H E6H B5H B3H Row 4
1195
+ 85H A0H 8AH 88H 95H 82H 96H 89H Row 5
1196
+
1197
+ 00H 00H 9DH 9CH BEH 9EH ADH D8H Row 0
1198
+ B6H EAH E8H 00H 00H 00H 80H E2H Row 1
1199
+ SHIFT 00H 8EH 9CH A8H 00H 8FH E4H B8H Row 2
1200
+ CODE 92H 00H B0H 9AH 99H 00H 00H 00H Row 3
1201
+ 00H 00H E3H 00H A5H 00H B4H B2H Row 4
1202
+ 00H 00H 00H 00H 00H 90H 00H 00H Row 5
1203
+
1204
+ 7 6 5 4 3 2 1 0 Column
1205
+ ```
1206
+
1207
+ </a>
1208
+
1209
+ <a name="0ec5h"></a>
1210
+
1211
+ Address... 0EC5H
1212
+
1213
+ Control transfers to this routine, from [0FC3H](#0fc3h), to complete decoding of the five function keys. The relevant entry in [FNKFLG](#fnkflg) is first checked to determine whether the key is associated with an "`ON KEY GOSUB`" statement. If so, and provided that [CURLIN](#curlin) shows the BASIC Interpreter to be in program mode, the relevant entry in [TRPTBL](#trptbl) is updated ([0EF1H](#0ef1h)) and the routine terminates. If the key is not tied to an "`ON KEY GOSUB`" statement, or if the Interpreter is in direct mode, the string of characters associated with the function key is returned instead. The key number is multiplied by sixteen, as each string is sixteen characters long, and added to the starting address of the function key strings in the Workspace Area. Sequential characters are then taken from the string and placed in [KEYBUF](#keybuf) ([0F55H](#0f55h)) until the zero byte terminator is reached.
1214
+
1215
+ <a name="0ef1h"></a>
1216
+
1217
+ Address... 0EF1H
1218
+
1219
+ This routine is used to update a device's entry in [TRPTBL](#trptbl) when it has produced a BASIC program interrupt. On entry register pair HL points to the device's status byte in the table. Bit 0 of the status byte is checked first, if the device is not "`ON`" then the routine terminates with no action. Bit 2, the event flag, is then checked. If this is already set then the routine terminates, otherwise it is set to indicate that an event has occurred. Bit 1, the "`STOP`" flag, is then checked. If the device is stopped then the routine terminates with no further action. Otherwise [ONGSBF](#ongsbf) is incremented to signal to the Interpreter Runloop that the event should now be processed.
1220
+
1221
+ <a name="0f06h"></a>
1222
+
1223
+ Address... 0F06H
1224
+
1225
+ This section of the key decoder processes the HOME key only. The state of the SHIFT key is determined via row 6 of [NEWKEY](#newkey) and the key code for HOME (0BH) or CLS (0CH) placed in [KEYBUF](#keybuf) ([0F55H](#0f55h)) accordingly.
1226
+
1227
+ <a name="0f10h"></a>
1228
+
1229
+ Address... 0F10H
1230
+
1231
+ This section of the keyboard decoder processes key numbers 30H to 57H apart from the CAP, F1 to F5, STOP and HOME keys. The key number is simply used to look up the key code in the table at [1033H](#1033h) and this is then placed in [KEYBUF](#keybuf) ([0F55H](#0f55h)).
1232
+
1233
+ <a name="0f1fh"></a>
1234
+
1235
+ Address... 0F1FH
1236
+
1237
+ This section of the keyboard decoder processes the DEAD key found on European MSX machines. On UK machines the key in row 2, column 5 always generates the pound key code (9CH) shown in the table at 0DA5H. On European machines this table will have the key code FFH in the same locations. This key code only serves as a flag to indicate that the next key pressed, if it is a vowel, should be modified to produce an accented graphics character.
1238
+
1239
+ The state of the SHIFT and CODE keys is determined via row 6 of [NEWKEY](#newkey) and one of the following placed in [KANAST](#kanast): 01H=DEAD, 02H=DEAD+SHIFT, 03H=DEAD+CODE, 04H=DEAD+SHIFT+CODE.
1240
+
1241
+ <a name="0f36h"></a>
1242
+
1243
+ Address... 0F36H
1244
+
1245
+ This section of the keyboard decoder processes the CAP key. The current state of [CAPST](#capst) is inverted and control drops into the [CHGCAP](#chgcap) standard routine.
1246
+
1247
+ <a name="0f3dh"></a><a name="chgcap"></a>
1248
+
1249
+ ```
1250
+ Address... 0F3DH
1251
+ Name...... CHGCAP
1252
+ Entry..... A=ON/OFF Switch
1253
+ Exit...... None
1254
+ Modifies.. AF
1255
+ ```
1256
+
1257
+ Standard routine to turn the Caps Lock LED on or off as determined by the contents of register A: 00H=On, NZ=Off. The LED is modified using the bit set/reset facility of the PPI Mode Port. As [CAPST](#capst) is not changed this routine does not affect the characters produced by the keyboard.
1258
+
1259
+ <a name="0f46h"></a>
1260
+
1261
+ Address... 0F46H
1262
+
1263
+ This section of the keyboard decoder processes the STOP key. The state of the CTRL key is determined via row 6 of [NEWKEY](#newkey) and the key code for STOP (04H) or CTRL/STOP (03H) produced as appropriate. If the CTRL/STOP code is produced it is copied to [INTFLG](#intflg), for use by the [ISCNTC](#iscntc) standard routine, and then placed in [KEYBUF](#keybuf) ([0F55H](#0f55h)). If the STOP code is produced it is also copied to [INTFLG](#intflg) but is not placed in [KEYBUF](#keybuf), instead only a click is generated (0F64H). This means that an application program cannot read the STOP key code via the ROM BIOS standard routines.
1264
+
1265
+ <a name="0f55h"></a>
1266
+
1267
+ Address... 0F55H
1268
+
1269
+ This section of the keyboard decoder places a key code in [KEYBUF](#keybuf) and generates an audible click. The correct address in the keyboard buffer is first taken from [PUTPNT](#putpnt) and the code placed there. The address is then incremented ([105BH](#105bh)). If it has wrapped round and caught up with [GETPNT](#getpnt) then the routine terminates with no further action as the keyboard buffer is full. Otherwise [PUTPNT](#putpnt) is updated with the new address.
1270
+
1271
+ [CLIKSW](#cliksw) and [CLIKFL](#clikfl) are then both checked to determine whether a click is required. [CLIKSW](#cliksw) is a general enable/disable switch while [CLIKFL](#clikfl) is used to prevent multiple clicks when the function keys are pressed. Assuming a click is required the Key Click output is set via the [PPI Mode Port](#ppi_mode_port) and, after a delay of 50 µs, control drops into the [CHGSND](#chgsnd) standard routine.
1272
+
1273
+ <a name="0f7ah"></a><a name="chgsnd"></a>
1274
+
1275
+ ```
1276
+ Address... 0F7AH
1277
+ Name...... CHGSND
1278
+ Entry..... A=ON/OFF Switch
1279
+ Exit...... None
1280
+ Modifies.. AF
1281
+ ```
1282
+
1283
+ Standard routine to set or reset the Key Click output via the [PPI Mode Port](#ppi_mode_port): 00H=Reset, NZ=Set. This audio output is AC coupled so absolute polarities should not be taken too seriously.
1284
+
1285
+ <a name="0f83h"></a>
1286
+
1287
+ Address... 0F83H
1288
+
1289
+ This section of the keyboard decoder processes key numbers 00H to 2FH. The state of the SHIFT, GRAPH and CODE keys is determined via row 6 of [NEWKEY](#newkey) and combined with the key number to form a look-up address into the table at [0DA5H](#0da5h). The key code is then taken from the table. If it is zero the routine terminates with no further action, if it is FFH control transfers to the DEAD key processor ([0F1FH](#0f1fh)). If the code is in the range 40H to 5FH or 60H to 7FH and the CTRL key is pressed then the corresponding control code is placed in [KEYBUF](#keybuf) ([0F55H](#0f55h)). If the code is in the range 01H to 1FH then a graphic header code (01H) is first placed in [KEYBUF](#keybuf) ([0F55H](#0f55h)) followed by the code with 40H added. If the code is in the range 61H to 7BH and [CAPST](#capst) indicates that caps lock is on then it is converted to upper case by subtracting 20H. Assuming that [KANAST](#kanast) contains zero, as it always will on UK machines, then the key code is placed in [KEYBUF](#keybuf) ([0F55H](#0f55h)) and the routine terminates. On European MSX machines, with a DEAD key instead of a pound key, then the key codes corresponding to the vowels a, e, i, o, u may be further modified into graphics codes.
1290
+
1291
+ <a name="0fc3h"></a>
1292
+
1293
+ Address... 0FC3H
1294
+
1295
+ This section of the keyboard decoder processes the five function keys. The state of the SHIFT key is examined via row 6 of [NEWKEY](#newkey) and five added to the key number if it is pressed. Control then transfers to [0EC5H](#0ec5h) to complete processing.
1296
+
1297
+ <a name="1021h"></a>
1298
+
1299
+ Address... 1021H
1300
+
1301
+ This routine searches the table at [1B97H](#1b97h) to determine which group of keys the key number supplied in register C belongs to. The associated address is then taken from the table and control transferred to that section of the keyboard decoder. Note that the table itself is actually patched into the middle of the [OUTDO](#outdo) standard routine as a result of the modifications made to the Japanese ROM.
1302
+
1303
+ <a name="1033h"></a>
1304
+
1305
+ Address... 1033H
1306
+
1307
+ This table contains the key codes of key numbers 30H to 57H other than the special keys CAP, F1 to F5, STOP and HOME. A zero entry in the table means that no key code will be produced when that key is pressed:
1308
+
1309
+ ```
1310
+ 00H 00H 00H 00H 00H 00H 00H 00H Row 6
1311
+ 0DH 18H 08H 00H 09H 1BH 00H 00H Row 7
1312
+ 1CH 1FH 1EH 1DH 7FH 12H 0CH 20H Row 8
1313
+ 34H 33H 32H 31H 30H 00H 00H 00H Row 9
1314
+ 2EH 2CH 2DH 39H 38H 37H 36H 35H Row 10
1315
+
1316
+ 7 6 5 4 3 2 1 0 Column
1317
+ ```
1318
+
1319
+ </a>
1320
+
1321
+ <a name="105bh"></a>
1322
+
1323
+ Address... 105BH
1324
+
1325
+ This routine simply zeroes [KANAST](#kanast) and then transfers control to [10C2H](#10c2h).
1326
+
1327
+ <a name="1061h"></a>
1328
+
1329
+ Address... 1061H
1330
+
1331
+ This table contains the graphics characters which replace the vowels a, e, i, o, u on European machines.
1332
+
1333
+ <a name="10c2h"></a>
1334
+
1335
+ Address... 10C2H
1336
+
1337
+ This routine increments the keyboard buffer pointer, either [PUTPNT](#putpnt) or [GETPNT](#getpnt), supplied in register pair HL. If the pointer then exceeds the end of the keyboard buffer it is wrapped back to the beginning.
1338
+
1339
+ <a name="10cbh"></a><a name="chget"></a>
1340
+
1341
+ ```
1342
+ Address... 10CBH
1343
+ Name...... CHGET
1344
+ Entry..... None
1345
+ Exit...... A=Character from keyboard
1346
+ Modifies.. AF, EI
1347
+ ```
1348
+
1349
+ Standard routine to fetch a character from the keyboard buffer. The buffer is first checked to see if already contains a character ([0D6AH](#0d6ah)). If not the cursor is turned on ([09DAH](#09dah)), the buffer checked repeatedly until a character appears ([0D6AH](#0d6ah)) and then the cursor turned off ([0A27H](#0a27h)). The character is taken from the buffer using [GETPNT](#getpnt) which is then incremented ([10C2H](#10c2h)).
1350
+
1351
+ <a name="10f9h"></a><a name="ckcntc"></a>
1352
+
1353
+ ```
1354
+ Address... 10F9H
1355
+ Name...... CKCNTC
1356
+ Entry..... None
1357
+ Exit...... None
1358
+ Modifies.. AF, EI
1359
+ ```
1360
+
1361
+ Standard routine to check whether the CTRL-STOP or STOP keys have been pressed. It is used by the BASIC Interpreter inside processor-intensive statements, such as "`WAIT`" and "`CIRCLE`", to check for program termination. Register pair HL is first zeroed and then control transferred to the [ISCNTC](#iscntc) standard routine. When the Interpreter is running register pair HL normally contains the address of the current character in the BASIC program text. If [ISCNTC](#iscntc) is CTRL-STOP terminated this address will be placed in [OLDTXT](#oldtxt) by the "`STOP`" statement handler (63E6H) for use by a later "`CONT`" statement. Zeroing register pair HL beforehand signals to the "`CONT`" handler that termination occurred inside a statement and it will issue a "`Can't CONTINUE`" error if continuation is attempted.
1362
+
1363
+ <a name="1102h"></a><a name="wrtpsg"></a>
1364
+
1365
+ ```
1366
+ Address... 1102H
1367
+ Name...... WRTPSG
1368
+ Entry..... A=Register number, E=Data byte
1369
+ Exit...... None
1370
+ Modifies.. EI
1371
+ ```
1372
+
1373
+ Standard routine to write a data byte to any of the sixteen [PSG registers](#registers_0_and_1). The register selection number is written to the PSG [Address Port](#address_port) and the data byte written to the PSG [Data Write Port](#data_write_port).
1374
+
1375
+ <a name="110eh"></a><a name="rdpsg"></a>
1376
+
1377
+ ```
1378
+ Address... 110EH
1379
+ Name...... RDPSG
1380
+ Entry..... A=Register number
1381
+ Exit...... A=Data byte read from PSG
1382
+ Modifies.. A
1383
+ ```
1384
+
1385
+ Standard routine to read a data byte from any of the sixteen [PSG registers](#registers_0_and_1). The register selection number is written to the PSG [Address Port](#address_port) and the data byte read from the PSG [Data Read Port](#data_read_port).
1386
+
1387
+ <a name="1113h"></a><a name="beep"></a>
1388
+
1389
+ ```
1390
+ Address... 1113H
1391
+ Name...... BEEP
1392
+ Entry..... None
1393
+ Exit...... None
1394
+ Modifies.. AF, BC, E, EI
1395
+ ```
1396
+
1397
+ Standard routine to produce a beep via the PSG. Channel A is set to produce a tone of 1316Hz then enabled with an amplitude of seven. After a delay of 40 ms control transfers to the [GICINI](#gicini) standard routine to reinitialize the PSG.
1398
+
1399
+ <a name="113bh"></a>
1400
+
1401
+ Address... 113BH
1402
+
1403
+ This routine is used by the interrupt handler to service a music queue. As there are three of these, each feeding a PSG channel, the queue to be serviced is specified by supplying its number in register A: 0=[VOICAQ](#voicaq), 1=[VOICBQ](#voicbq) and 2=[VOICCQ](#voiccq).
1404
+
1405
+ Each string in a "`PLAY`" statement is translated into a series of data packets by the BASIC Interpreter. These are placed in the appropriate queue followed by an end of data byte (FFH). The task of dequeueing the packets, decoding them and setting the PSG is left to the interrupt handler. The Interpreter is thus free to proceed immediately to the next statement without having to wait for notes to finish.
1406
+
1407
+ The first two bytes of any packet specify its byte count and duration. The three most significant bits of the first byte specify the number of bytes following the header in the packet. The remainder of the header specifies the event duration in 20 ms units. This duration count determines how long it will be before the next packet is read from the queue.
1408
+
1409
+ <a name="figure37"></a>![][CH04F37]
1410
+
1411
+ **Figure 37:** Packet Header
1412
+
1413
+ The packet header may be followed by zero or more blocks, in any order, containing frequency or amplitude information:
1414
+
1415
+ <a name="figure38"></a>![][CH04F38]
1416
+
1417
+ **Figure 38:** Packet Block Types
1418
+
1419
+ The routine first locates the current duration counter in the relevant voice buffer ([VCBA](#vcba), [VCBB](#vcbb) or [VCBC](#vcbc)) via the [GETVCP](#getvcp) standard routine and decrements it. If the counter has reached zero then the next packet must be read from the queue, otherwise the routine terminates.
1420
+
1421
+ The queue number is placed in [QUEUEN](#queuen) and a byte read from the queue ([11E2H](#11e2h)). This is then checked to see if it is the end of data mark (FFH), if so the queue terminates ([11B0H](#11b0h)). Otherwise the byte count is placed in register C and the duration MSB in the relevant voice buffer. The second byte is read ([11E2H](#11e2h)) and the duration LSB placed in the relevant voice buffer. The byte count is then examined, if there are no bytes to follow the packet header the routine terminates. Otherwise successive bytes are read from the queue, and the appropriate action taken, until the byte count is exhausted.
1422
+
1423
+ If a frequency block is found then a second byte is read and both bytes written to PSG Registers [0](#registers_0_and_1) and [1](#registers_0_and_1), [2](#registers_2_and_3) and [3](#registers_2_and_3) or [4](#registers_4_and_5) and [5](#registers_4_and_5) depending on the queue number.
1424
+
1425
+ If an amplitude block is found the Amplitude and Mode bits are written to PSG Registers [8](#register_8), [9](#register_9) or [10](#register_10) depending on the queue number. If the Mode bit is 1, selecting modulated rather than fixed amplitude, then the byte is also written to PSG [Register 13](#register_13) to set the envelope shape.
1426
+
1427
+ If an envelope block is found, or if bit 6 of an amplitude block is set, then a further two bytes are read from the queue and written to PSG Registers [11](#registers_11_and_12) and [12](#registers_11_and_12).
1428
+
1429
+ <a name="11b0h"></a>
1430
+
1431
+ Address... 11B0H
1432
+
1433
+ This routine is used when an end of data mark (FFH) is found in one of the three music queues. An amplitude value of zero is written to PSG Register [8](#register_8) [9](#register_9) or [10](#register_10), depending on the queue number, to shut the channel down. The channel's bit in [MUSICF](#musicf) is then reset and control drops into the [STRTMS](#strtms) standard routine.
1434
+
1435
+ <a name="11c4h"></a><a name="strtms"></a>
1436
+
1437
+ ```
1438
+ Address... 11C4H
1439
+ Name...... STRTMS
1440
+ Entry..... None
1441
+ Exit...... None
1442
+ Modifies.. AF, HL
1443
+ ```
1444
+
1445
+ Standard routine used by the "`PLAY`" statement handler to initiate music dequeueing by the interrupt handler. [MUSICF](#musicf) is first examined, if any channels are already running the routine terminates with no action. [PLYCNT](#plycnt) is then decremented, if there are no more "`PLAY`" strings queued up the routine terminates. Otherwise the three duration counters, in [VCBA](#vcba), [VCBB](#vcbb) and [VCBC](#vcbc), are set to 0001H, so that the first packet of the new group will be dequeued at the next interrupt, and [MUSICF](#musicf) is set to 07H to enable all three channels.
1446
+
1447
+ <a name="11e2h"></a>
1448
+
1449
+ Address... 11E2H
1450
+
1451
+ This routine loads register A with the current queue number, from [QUEUEN](#queuen), and then reads a byte from that queue ([14ADH](#14adh)).
1452
+
1453
+ <a name="11eeh"></a><a name="gtstck"></a>
1454
+
1455
+ ```
1456
+ Address... 11EEH
1457
+ Name...... GTSTCK
1458
+ Entry..... A=Joystick ID (0, 1 or 2)
1459
+ Exit...... A=Joystick position code
1460
+ Modifies.. AF, B, DE, HL, EI
1461
+ ```
1462
+
1463
+ Standard routine to read the position of a joystick or the four cursor keys. If the supplied ID is zero the state of the cursor keys is read via [PPI Port B](ppi_port_b) ([1226H](#1226h)) and converted to a position code using the look-up table at 1243H. Otherwise joystick connector 1 or 2 is read ([120CH](#120ch)) and the four direction bits converted to a position code using the look-up table at 1233H. The returned position codes are:
1464
+
1465
+ <a name="figure39a"></a>![][CH04F39a]
1466
+
1467
+ <a name="120ch"></a>
1468
+
1469
+ Address... 120CH
1470
+
1471
+ This routine reads the joystick connector specified by the contents of register A: 0=Connector 1, 1=Connector 2. The current contents of PSG [Register 15](#register_15) are read in then written back with the Joystick Select bit appropriately set. PSG [Register 14](#register_14) is then read into register A (110CH) and the routine terminates.
1472
+
1473
+ <a name="1226h"></a>
1474
+
1475
+ Address... 1226H
1476
+
1477
+ This routine reads row 8 of the keyboard matrix. The current contents of [PPI Port C](ppi_port_c) are read in then written back with the four Keyboard Row Select bits set for row 8. The column inputs are then read into register A from [PPI Port B](ppi_port_b).
1478
+
1479
+ <a name="1253h"></a><a name="gttrig"></a>
1480
+
1481
+ ```
1482
+ Address... 1253H
1483
+ Name...... GTTRIG
1484
+ Entry..... A=Trigger ID (0, 1, 2, 3 or 4)
1485
+ Exit...... A=Status code
1486
+ Modifies.. AF, BC, EI
1487
+ ```
1488
+
1489
+ Standard routine to check the joystick trigger or space key status. If the supplied ID is zero row 8 of the keyboard matrix is read ([1226H](#1226h)) and converted to a status code. Otherwise joystick connector 1 or 2 is read ([120CH](#120ch)) and converted to a status code. The selection IDs are:
1490
+
1491
+ ```
1492
+ 0=SPACE KEY
1493
+ 1=JOY 1, TRIGGER A
1494
+ 2=JOY 2, TRIGGER A
1495
+ 3=JOY 1, TRIGGER B
1496
+ 4=JOY 2, TRIGGER B
1497
+ ```
1498
+
1499
+ The value returned is FFH if the relevant trigger is pressed and zero otherwise.
1500
+
1501
+ <a name="1273h"></a><a name="gtpdl"></a>
1502
+
1503
+ ```
1504
+ Address... 1273H
1505
+ Name...... GTPDL
1506
+ Entry..... A=Paddle ID (1 to 12)
1507
+ Exit...... A=Paddle value (0 to 255)
1508
+ Modifies.. AF, BC, DE, EI
1509
+ ```
1510
+
1511
+ Standard routine to read the value of any paddle attached to a joystick connector. Each of the six input lines (four direction plus two triggers) per connector can support a paddle so twelve are possible altogether. The paddles attached to joystick connector 1 have entry identifiers 1, 3, 5, 7, 9 and 11. Those attached to joystick connector 2 have entry identifiers 2, 4, 6, 8, 10 and 12. Each paddle is basically a one-shot pulse generator, the length of the pulse being controlled by a variable resistor. A start pulse is issued to the specified joystick connector via PSG [Register 15](#register_15). A count is then kept of how many times PSG [Register 14](#register_14) has to be read until the relevant input times out. Each unit increment represents an approximate period of 12 µs on an MSX machine with one wait state.
1512
+
1513
+ <a name="12ach"></a><a name="gtpad"></a>
1514
+
1515
+ ```
1516
+ Address... 12ACH
1517
+ Name...... GTPAD
1518
+ Entry..... A=Function code (0 to 7)
1519
+ Exit...... A=Status or value
1520
+ Modifies.. AF, BC, DE, HL, EI
1521
+ ```
1522
+
1523
+ Standard routine to access a touchpad attached to either of the joystick connectors. Available functions codes for joystick connector 1 are:
1524
+
1525
+ ```
1526
+ 0=Return Activity Status
1527
+ 1=Return "X" coordinate
1528
+ 2=Return "Y" coordinate
1529
+ 3=Return Switch Status
1530
+ ```
1531
+
1532
+ Function codes 4 to 7 have the same effect with respect to joystick connector 2. The Activity Status function returns FFH if the Touchpad is being touched and zero otherwise. The Switch Status function returns FFH if the switch is being pressed and zero otherwise. The two coordinate request functions return the coordinates of the last location touched. These coordinates are actually stored in the Workspace Area variables [PADX](#padx) and [PADY](#pady) when a call with function code 0 or 4 detects activity. Note that these variables are shared by both joystick connectors.
1533
+
1534
+ <a name="1384h"></a><a name="stmotr"></a>
1535
+
1536
+ ```
1537
+ Address... 1384H
1538
+ Name...... STMOTR
1539
+ Entry..... A=Motor ON/OFF code
1540
+ Exit...... None
1541
+ Modifies.. AF
1542
+ ```
1543
+
1544
+ Standard routine to turn the cassette motor relay on or off via [PPI Port C](ppi_port_c): 00H=Off, 01H=On, FFH=Reverse current state.
1545
+
1546
+ <a name="1398h"></a><a name="nmi"></a>
1547
+
1548
+ ```
1549
+ Address... 1398H
1550
+ Name...... NMI
1551
+ Entry..... None
1552
+ Exit...... None
1553
+ Modifies.. None
1554
+ ```
1555
+
1556
+ Standard routine to process a Z80 Non Maskable Interrupt, simply returns on a standard MSX machine.
1557
+
1558
+ <a name="139dh"></a><a name="inifnk"></a>
1559
+
1560
+ ```
1561
+ Address... 139DH
1562
+ Name...... INIFNK
1563
+ Entry..... None
1564
+ Exit...... None
1565
+ Modifies.. BC, DE, HL
1566
+ ```
1567
+
1568
+ Standard routine to initialize the ten function key strings to their power-up values. The one hundred and sixty bytes of data commencing at [13A9H](#13a9h) are copied to the [FNKSTR](#fnkstr) buffer in the Workspace Area.
1569
+
1570
+ <a name="13a9h"></a>
1571
+
1572
+ Address... 13A9H
1573
+
1574
+ This area contains the power-up strings for the ten function keys. Each string is sixteen characters long, unused positions contain zeroes:
1575
+
1576
+ ```
1577
+ F1 to F5 F6 to F10
1578
+ color color 15,4,4 CR
1579
+ auto cload"
1580
+ goto cont CR
1581
+ list list. CR UP UP
1582
+ run CR run CLS CR
1583
+ ```
1584
+
1585
+ <a name="1449h"></a><a name="rdvdp"></a>
1586
+
1587
+ ```
1588
+ Address... 1449H
1589
+ Name...... RDVDP
1590
+ Entry..... None
1591
+ Exit...... A=VDP Status Register contents
1592
+ Modifies.. A
1593
+ ```
1594
+
1595
+ Standard routine to input the contents of the [VDP Status Register](#vdp_status_register) by reading the [Command Port](#command_port). Note that reading the [VDP Status Register](#vdp_status_register) will clear the associated flags and may affect the interrupt handler.
1596
+
1597
+ <a name="144ch"></a><a name="rslreg"></a>
1598
+
1599
+ ```
1600
+ Address... 144CH
1601
+ Name...... RSLREG
1602
+ Entry..... None
1603
+ Exit...... A=Primary Slot Register contents
1604
+ Modifies.. A
1605
+ ```
1606
+
1607
+ Standard routine to input the contents of the Primary slot Register by reading [PPI Port A](ppi_port_a).
1608
+
1609
+ <a name="144fh"></a><a name="wslreg"></a>
1610
+
1611
+ ```
1612
+ Address... 144FH
1613
+ Name...... WSLREG
1614
+ Entry..... A=Value to write
1615
+ Exit...... None
1616
+ Modifies.. None
1617
+ ```
1618
+
1619
+ Standard routine to set the Primary Slot Register by writing to [PPI Port A](ppi_port_a).
1620
+
1621
+ <a name="1452h"></a><a name="snsmat"></a>
1622
+
1623
+ ```
1624
+ Address... 1452H
1625
+ Name...... SNSMAT
1626
+ Entry..... A=Keyboard row number
1627
+ Exit...... A=Column data of keyboard row
1628
+ Modifies.. AF, C, EI
1629
+ ```
1630
+
1631
+ Standard routine to read a complete row of the keyboard matrix. [PPI Port C](ppi_port_c) is read in then written back with the row number occupying the four Keyboard Row Select bits. [PPI Port B](ppi_port_b) is then read into register A to return the eight column inputs. The four miscellaneous control outputs of [PPI Port C](ppi_port_c) are unaffected by this routine.
1632
+
1633
+ <a name="145fh"></a><a name="isflio"></a>
1634
+
1635
+ ```
1636
+ Address... 145FH
1637
+ Name...... ISFLIO
1638
+ Entry..... None
1639
+ Exit...... Flag NZ if file I/O active
1640
+ Modifies.. AF
1641
+ ```
1642
+
1643
+ Standard routine to check whether the BASIC Interpreter is currently directing its input or output via an I/O buffer. This is determined by examining [PTRFIL](#ptrfil). It is normally zero but will contain a buffer FCB (File Control Block) address while statements such as "`PRINT#1`", "`INPUT#1`", etc. are being executed by the Interpreter.
1644
+
1645
+ <a name="146ah"></a><a name="dcompr"></a>
1646
+
1647
+ ```
1648
+ Address... 146AH
1649
+ Name...... DCOMPR
1650
+ Entry..... HL, DE
1651
+ Exit...... Flag NC if HL>DE, Flag Z if HL=DE, Flag C if HL<DE
1652
+ Modifies.. AF
1653
+ ```
1654
+
1655
+ Standard routine used by the BASIC Interpreter to check the relative values of register pairs HL and DE.
1656
+
1657
+ <a name="1470h"></a><a name="getvcp"></a>
1658
+
1659
+ ```
1660
+ Address... 1470H
1661
+ Name...... GETVCP
1662
+ Entry..... A=Voice number (0, 1, 2)
1663
+ Exit...... HL=Address in voice buffer
1664
+ Modifies.. AF, HL
1665
+ ```
1666
+
1667
+ Standard routine to return the address of byte 2 in the specified voice buffer ([VCBA](#vcba), [VCBB](#vcbb) or [VCBC](#vcbc)).
1668
+
1669
+ <a name="1474h"></a><a name="getvc2"></a>
1670
+
1671
+ ```
1672
+ Address... 1474H
1673
+ Name...... GETVC2
1674
+ Entry..... L=Byte number (0 to 36)
1675
+ Exit...... HL=Address in voice buffer
1676
+ Modifies.. AF, HL
1677
+ ```
1678
+
1679
+ Standard routine to return the address of any byte in the voice buffer ([VCBA](#vcba), [VCBB](#vcbb) or [VCBC](#vcbc)) specified by the voice number in [VOICEN](#voicen).
1680
+
1681
+ <a name="148ah"></a><a name="phydio"></a>
1682
+
1683
+ ```
1684
+ Address... 148AH
1685
+ Name...... PHYDIO
1686
+ Entry..... None
1687
+ Exit...... None
1688
+ Modifies.. None
1689
+ ```
1690
+
1691
+ Standard routine for use by Disk BASIC, simply returns on standard MSX machines.
1692
+
1693
+ <a name="148eh"></a><a name="format"></a>
1694
+
1695
+ ```
1696
+ Address... 148EH
1697
+ Name...... FORMAT
1698
+ Entry..... None
1699
+ Exit...... None
1700
+ Modifies.. None
1701
+ ```
1702
+
1703
+ Standard routine for use by Disk BASIC, simply returns on standard MSX machines.
1704
+
1705
+ <a name="1492h"></a><a name="putq"></a>
1706
+
1707
+ ```
1708
+ Address... 1492H
1709
+ Name...... PUTQ
1710
+ Entry..... A=Queue number, E=Data byte
1711
+ Exit...... Flag Z if queue full
1712
+ Modifies.. AF, BC, HL
1713
+ ```
1714
+
1715
+ Standard routine to place a data byte in one of the three music queues. The queue's get and put positions are first taken from [QUETAB](#quetab) ([14FAH](#14fah)). The put position is temporarily incremented and compared with the get position, if they are equal the routine terminates as the queue is full. Otherwise the queue's address is taken from [QUETAB](#quetab) and the put position added to it. The data byte is placed at this location in the queue, the put position is incremented and the routine terminates. Note that the music queues are circular, if the get or put pointers reach the last position in the queue they wrap around back to the start.
1716
+
1717
+ <a name="14adh"></a>
1718
+
1719
+ Address... 14ADH
1720
+
1721
+ This routine is used by the interrupt handler to read a byte from one of the three music queues. The queue number is supplied in register A, the data byte is returned in register A and the routine returns Flag Z if the queue is empty. The queue's get and put positions are first taken from [QUETAB](#quetab) ([14FAH](#14fah)). If the putback flag is active then the data byte is taken from [QUEBAK](#quebak) and the routine terminates (14D1H), this facility is unused in the current versions of the MSX ROM. The put position is then compared with the get position, if they are equal the routine terminates as the queue is empty. Otherwise the queue's address is taken from [QUETAB](#quetab) and the get position added to it. The data byte is read from this location in the queue, the get position is incremented and the routine terminates.
1722
+
1723
+ Address... 14DAH
1724
+
1725
+ This routine is used by the [GICINI](#gicini) standard routine to initialize a queue's control block in [QUETAB](#quetab). The control block is first located in [QUETAB](#quetab) ([1504H](#1504h)) and the put, get and putback bytes zeroed. The size byte is set from register B and the queue address from register pair DE.
1726
+
1727
+ <a name="14ebh"></a><a name="lftq"></a>
1728
+
1729
+ ```
1730
+ Address... 14EBH
1731
+ Name...... LFTQ
1732
+ Entry..... A=Queue number
1733
+ Exit...... HL=Free space left in queue
1734
+ Modifies.. AF, BC, HL
1735
+ ```
1736
+
1737
+ Standard routine to return the number of free bytes left in a music queue. The queue's get and put positions are taken from [QUETAB](#quetab) ([14FAH](#14fah)) and the free space determined by subtracting put from get.
1738
+
1739
+ <a name="14fah"></a>
1740
+
1741
+ Address... 14FAH
1742
+
1743
+ This routine returns a queue's control parameters from [QUETAB](#quetab), the queue number is supplied in register A. The control block is first located in [QUETAB](#quetab) ([1504H](#1504h)), the put position is then placed in register B, the get position in register C and the putback flag in register A.
1744
+
1745
+ <a name="1504h"></a>
1746
+
1747
+ Address... 1504H
1748
+
1749
+ This routine locates a queue's control block in [QUETAB](#quetab). The queue number is supplied in register A and the control block address returned in register pair HL. The queue number is simply multiplied by six, as there are six bytes per block, and added to the address of [QUETAB](#quetab) as held in [QUEUES](#queues).
1750
+
1751
+ <a name="1510h"></a><a name="grpprt"></a>
1752
+
1753
+ ```
1754
+ Address... 1510H
1755
+ Name...... GRPPRT
1756
+ Entry..... A=Character
1757
+ Exit...... None
1758
+ Modifies.. EI
1759
+ ```
1760
+
1761
+ Standard routine to display a character on the screen in either [Graphics Mode](#graphics_mode) or [Multicolour Mode](#multicolour_mode), it is functionally equivalent to the [CHPUT](#chput) standard routine.
1762
+
1763
+ The [CNVCHR](#cnvchr) standard routine is first used to check for a graphic character, if the character is a header code (01H) then the routine terminates with no action. If the character is a converted graphic one then the control code decoding section is skipped. Otherwise the character is checked to see if it is a control code. Only the CR code (0DH) is recognized ([157EH](#157eh)), all other characters smaller than 20H are ignored.
1764
+
1765
+ Assuming the character is displayable its eight byte pixel pattern is copied from the ROM character set into the [PATWRK](#patwrk) buffer (0752H) and [FORCLR](#forclr) copied to [ATRBYT](#atrbyt) to set its colour. The current graphics coordinates are then taken from [GRPACX](#grpacx) and [GRPACY](#grpacy) and used to set the current pixel physical address via the [SCALXY](#scalxy) and [MAPXYC](#mapxyc) standard routines.
1766
+
1767
+ The eight byte pattern in [PATWRK](#patwrk) is processed a byte at a time. At the start of each byte the current pixel physical address is obtained via the [FETCHC](#fetchc) standard routine and saved. The eight bits are then examined in turn. If the bit is a 1 the associated pixel is set by the [SETC](#setc) standard routine, if it is a 0 no action is taken. After each bit the current pixel physical address is moved right ([16ACH](#16ach)). When the byte is finished, or the right hand edge of the screen is reached, the initial current pixel physical address is restored and moved down one position by the [TDOWNC](#tdownc) standard routine.
1768
+
1769
+ When the pattern is complete, or the bottom of the screen has been reached, [GRPACX](#grpacx) is updated. In [Graphics Mode](#graphics_mode) its value is increased by eight, in [Multicolour Mode](#multicolour_mode) by thirty-two. If [GRPACX](#grpacx) then exceeds 255, the right hand edge of the screen, a CR operation is performed ([157EH](#157eh)).
1770
+
1771
+ <a name="157eh"></a>
1772
+
1773
+ Address... 157EH
1774
+
1775
+ This routine performs the CR operation for the [GRPPRT](#grpprt) standard routine, this code functions as a combined CR,LF. [GRPACX](#grpacx) is zeroed and eight or thirty-two, depending on the screen mode, added to [GRPACY](#grpacy). If [GRPACY](#grpacy) then exceeds 191, the bottom of the screen, it is set to zero.
1776
+
1777
+ [GRPACX](#grpacx) and [GRPACY](#grpacy) may be manipulated directly by an application program to compensate for the limited number of control functions available.
1778
+
1779
+ <a name="1599h"></a><a name="scalxy"></a>
1780
+
1781
+ ```
1782
+ Address... 1599H
1783
+ Name...... SCALXY
1784
+ Entry..... BC=X coordinate, DE=Y coordinate
1785
+ Exit...... Flag NC if clipped
1786
+ Modifies.. AF
1787
+ ```
1788
+
1789
+ Standard routine to clip a pair of graphics coordinates if necessary. The BASIC Interpreter can produce coordinates in the range -32768 to +32767 even though this far exceeds the actual screen size. This routine modifies excessive coordinate values to fit within the physically realizable range. If the X coordinate is greater than 255 it is set to 255, if the Y coordinate is greater than 191 it is set to 191. If either coordinate is negative (greater than 7FFFH) it is set to zero. Finally if the screen is in [Multicolour Mode](#multicolour_mode) both coordinates are divided by four as required by the [MAPXYC](#mapxyc) standard routine.
1790
+
1791
+ Address... 15D9H
1792
+
1793
+ This routine is used to check the current screen mode, it returns Flag Z if the screen is in [Graphics Mode](#graphics_mode).
1794
+
1795
+ <a name="15dfh"></a><a name="mapxyc"></a>
1796
+
1797
+ ```
1798
+ Address... 15DFH
1799
+ Name...... MAPXYC
1800
+ Entry..... BC=X coordinate, DE=Y coordinate
1801
+ Exit...... None
1802
+ Modifies.. AF, D, HL
1803
+ ```
1804
+
1805
+ Standard routine to convert a graphics coordinate pair into the current pixel physical address. The location in the Character Pattern Table of the byte containing the pixel is placed in [CLOC](#cloc). The bit mask identifying the pixel within that byte is placed in [CMASK](#cmask). Slightly different conversion methods are used for [Graphics Mode](#graphics_mode) and [Multicolour Mode](#multicolour_mode), equivalent programs in BASIC are:
1806
+
1807
+ ```
1808
+ Graphics Mode
1809
+
1810
+ 10 INPUT"X,Y Coordinates";X,Y
1811
+ 20 A=(Y\8)*256+(Y AND 7)+(X AND &HF8)
1812
+ 30 PRINT"ADDR=";HEX$(Base(12)+A);"H ";
1813
+ 40 RESTORE 100
1814
+ 50 FOR N=0 TO (X AND 7):READ M$: NEXT N
1815
+ 60 PRINT"MASK=";M$
1816
+ 70 GOTO 10
1817
+ 100 DATA 10000000
1818
+ 110 DATA 01000000
1819
+ 120 DATA 00100000
1820
+ 130 DATA 00010000
1821
+ 140 DATA 00001000
1822
+ 150 DATA 00000100
1823
+ 160 DATA 00000010
1824
+ 170 DATA 00000001
1825
+ ```
1826
+
1827
+ </a>
1828
+
1829
+ ```
1830
+ Multicolour Mode
1831
+
1832
+ 10 INPUT"X,Y Coordinates";X,Y
1833
+ 20 X=X\4:Y-Y\4
1834
+ 30 A=(Y\8)*256+(Y AND 7)+(X*4 AND &HF8)
1835
+ 40 PRINT"ADDR=";HEX$(BASE(17)+A);"H ";
1836
+ 50 IF X MOD 2=0 THEN MS="11110000" ELSE MS="00001111"
1837
+ 60 PRINT"MASK=";M$
1838
+ 70 GOTO 10
1839
+ ```
1840
+
1841
+ The allowable input range for both programs is X=0 to 255 and Y=0 to 191. The data statements in the [Graphics Mode](#graphics_mode) program correspond to the eight byte mask table commencing at 160BH in the MSX ROM. Line 20 in the [Multicolour Mode](#multicolour_mode) program actually corresponds to the division by four in the [SCALXY](#scalxy) standard routine. It is included to make the coordinate system consistent for both programs.
1842
+
1843
+ <a name="1639h"></a><a name="fetchc"></a>
1844
+
1845
+ ```
1846
+ Address... 1639H
1847
+ Name...... FETCHC
1848
+ Entry..... None
1849
+ Exit...... A=CMASK, HL=CLOC
1850
+ Modifies.. A, HL
1851
+ ```
1852
+
1853
+ Standard routine to return the current pixel physical address, register pair HL is loaded from [CLOC](#cloc) and register A from [CMASK](#cmask).
1854
+
1855
+ <a name="1640h"></a><a name="storec"></a>
1856
+
1857
+ ```
1858
+ Address... 1640H
1859
+ Name...... STOREC
1860
+ Entry..... A=CMASK, HL=CLOC
1861
+ Exit...... None
1862
+ Modifies.. None
1863
+ ```
1864
+
1865
+ Standard routine to set the current pixel physical address, register pair HL is copied to [CLOC](#cloc) and register A is copied to [CMASK](#cmask).
1866
+
1867
+ <a name="1647h"></a><a name="readc"></a>
1868
+
1869
+ ```
1870
+ Address... 1647H
1871
+ Name...... READC
1872
+ Entry..... None
1873
+ Exit...... A=Colour code of current pixel
1874
+ Modifies.. AF, EI
1875
+ ```
1876
+
1877
+ Standard routine to return the colour of the current pixel. The VRAM physical address is first obtained via the [FETCHC](#fetchc) standard routine. If the screen is in [Graphics Mode](#graphics_mode) the byte pointed to by [CLOC](#cloc) is read from the Character Pattern Table via the [RDVRM](#rdvrm) standard routine. The required bit is then isolated by [CMASK](#cmask) and used to select either the upper or lower four bits of the corresponding entry in the Colour Table.
1878
+
1879
+ If the screen is in [Multicolour Mode](#multicolour_mode) the byte pointed to by [CLOC](#cloc) is read from the Character Pattern Table via the [RDVRM](#rdvrm) standard routine. [CMASK](#cmask) is then used to select either the upper or lower four bits of this byte. The value returned in either case will be a normal VDP colour code from zero to fifteen.
1880
+
1881
+ <a name="1676h"></a><a name="setatr"></a>
1882
+
1883
+ ```
1884
+ Address... 1676H
1885
+ Name...... SETATR
1886
+ Entry..... A=Colour code
1887
+ Exit...... Flag C if illegal code
1888
+ Modifies.. Flags
1889
+ ```
1890
+
1891
+ Standard routine to set the graphics ink colour used by the [SETC](#setc) and [NSETCX](#nsetcx) standard routines. The colour code, from zero to fifteen, is simply placed in [ATRBYT](#atrbyt).
1892
+
1893
+ <a name="167eh"></a><a name="setc"></a>
1894
+
1895
+ ```
1896
+ Address... 167EH
1897
+ Name...... SETC
1898
+ Entry..... None
1899
+ Exit...... None
1900
+ Modifies.. AF, EI
1901
+ ```
1902
+
1903
+ Standard routine to set the current pixel to any colour, the colour code is taken from [ATRBYT](#atrbyt). The pixel's VRAM physical address is first obtained via the [FETCHC](#fetchc) standard routine. In [Graphics Mode](#graphics_mode) both the Character Pattern Table and Colour Table are then modified ([186CH](#186ch)).
1904
+
1905
+ In [Multicolour Mode](#multicolour_mode) the byte pointed to by [CLOC](#cloc) is read from the Character Pattern Table by the [RDVRM](#rdvrm) standard routine. The contents of [ATRBYT](#atrbyt) are then placed in the upper or lower four bits, as determined by [CMASK](#cmask), and the byte written back via the [WRTVRM](#wrtvrm) standard routine
1906
+
1907
+ <a name="16ach"></a>
1908
+
1909
+ Address... 16ACH
1910
+
1911
+ This routine moves the current pixel physical address one position right. If the right hand edge of the screen is exceeded it returns with Flag C and the physical address is unchanged. In [Graphics Mode](#graphics_mode) [CMASK](#cmask) is first shifted one bit right, if the pixel still remains within the byte the routine terminates. If [CLOC](#cloc) is at the rightmost character cell (LSB=F8H to FFH) then the routine terminates with Flag C (175AH). Otherwise [CMASK](#cmask) is set to 80H, the leftmost pixel, and 0008H added to [CLOC](#cloc).
1912
+
1913
+ In [Multicolour Mode](#multicolour_mode) control transfers to a separate routine ([1779H](#1779h)).
1914
+
1915
+ <a name="16c5h"></a><a name="rightc"></a>
1916
+
1917
+ ```
1918
+ Address... 16C5H
1919
+ Name...... RIGHTC
1920
+ Entry..... None
1921
+ Exit...... None
1922
+ Modifies.. AF
1923
+ ```
1924
+
1925
+ Standard routine to move the current pixel physical address one position right. In [Graphics Mode](#graphics_mode) [CMASK](#cmask) is first shifted one bit right, if the pixel still remains within the byte the routine terminates. Otherwise [CMASK](#cmask) is set to 80H, the leftmost pixel, and 0008H added to [CLOC](#cloc). Note that incorrect addresses will be produced if the right hand edge of the screen is exceeded.
1926
+
1927
+ In [Multicolour Mode](#multicolour_mode) control transfers to a separate routine ([178BH](#178bh)).
1928
+
1929
+ <a name="16d8h"></a>
1930
+
1931
+ Address... 16D8H
1932
+
1933
+ This routine moves the current pixel physical address one position left. If the left hand edge of the screen is exceeded it returns Flag C and the physical address is unchanged. In [Graphics Mode](#graphics_mode) [CMASK](#cmask) is first shifted one bit left, if the pixel still remains within the byte the routine terminates. If [CLOC](#cloc) is at the leftmost character cell (LSB=00H to 07H) then the routine terminates with Flag C (175AH). Otherwise [CMASK](#cmask) is set to 01H, the rightmost pixel, and 0008H subtracted from [CLOC](#cloc).
1934
+
1935
+ In [Multicolour Mode](#multicolour_mode) control transfers to a separate routine ([179CH](#179ch)).
1936
+
1937
+ <a name="16eeh"></a><a name="leftc"></a>
1938
+
1939
+ ```
1940
+ Address... 16EEH
1941
+ Name...... LEFTC
1942
+ Entry..... None
1943
+ Exit...... None
1944
+ Modifies.. AF
1945
+ ```
1946
+
1947
+ Standard routine to move the current pixel physical address one position left. In [Graphics Mode](#graphics_mode) [CMASK](#cmask) is first shifted one bit left, if the pixel still remains within the byte the routine terminates. Otherwise [CMASK](#cmask) is set to 01H, the leftmost pixel, and 0008H subtracted from [CLOC](#cloc). Note that incorrect addresses will be produced if the left hand edge of the screen is exceeded.
1948
+
1949
+ In [Multicolour Mode](#multicolour_mode) control transfers to a separate routine ([17ACH](#17ach)).
1950
+
1951
+ <a name="170ah"></a><a name="tdownc"></a>
1952
+
1953
+ ```
1954
+ Address... 170AH
1955
+ Name...... TDOWNC
1956
+ Entry..... None
1957
+ Exit...... Flag C if off screen
1958
+ Modifies.. AF
1959
+ ```
1960
+
1961
+ Standard routine to move the current pixel physical address one position down. If the bottom edge of the screen is exceeded it returns Flag C and the physical address is unchanged. In [Graphics Mode](#graphics_mode) [CLOC](#cloc) is first incremented, if it still remains within an eight byte boundary the routine terminates. If [CLOC](#cloc) was in the bottom character row ([CLOC](#cloc)>=1700H) then the routine terminates with Flag C (1759H). Otherwise 00F8H is added to [CLOC](#cloc).
1962
+
1963
+ In [Multicolour Mode](#multicolour_mode) control transfers to a separate routine ([17C6H](#17c6h)).
1964
+
1965
+ <a name="172ah"></a><a name="downc"></a>
1966
+
1967
+ ```
1968
+ Address... 172AH
1969
+ Name...... DOWNC
1970
+ Entry..... None
1971
+ Exit...... None
1972
+ Modifies.. AF
1973
+ ```
1974
+
1975
+ Standard routine to move the current pixel physical address one position down. In [Graphics Mode](#graphics_mode) [CLOC](#cloc) is first incremented, if it still remains within an eight byte boundary the routine terminates. Otherwise 00F8H is added to [CLOC](#cloc). Note that incorrect addresses will be produced if the bottom edge of the screen is exceeded.
1976
+
1977
+ In [Multicolour Mode](#multicolour_mode) control transfers to a separate routine ([17DCH](#17dch)).
1978
+
1979
+ <a name="173ch"></a><a name="tupc"></a>
1980
+
1981
+ ```
1982
+ Address... 173CH
1983
+ Name...... TUPC
1984
+ Entry..... None
1985
+ Exit...... Flag C if off screen
1986
+ Modifies.. AF
1987
+ ```
1988
+
1989
+ Standard routine to move the current pixel physical address one position up. If the top edge of the screen is exceeded it returns with Flag C and the physical address is unchanged. In [Graphics Mode](#graphics_mode) [CLOC](#cloc) is first decremented, if it still remains within an eight byte boundary the routine terminates. If [CLOC](#cloc) was in the top character row ([CLOC](#cloc)<0100H) then the routine terminates with Flag C. Otherwise 00F8H is subtracted from [CLOC](#cloc).
1990
+
1991
+ In [Multicolour Mode](#multicolour_mode) control transfers to a separate routine ([17E3H](#17e3h)).
1992
+
1993
+ <a name="175dh"></a><a name="upc"></a>
1994
+
1995
+ ```
1996
+ Address... 175DH
1997
+ Name...... UPC
1998
+ Entry..... None
1999
+ Exit...... None
2000
+ Modifies.. AF
2001
+ ```
2002
+
2003
+ Standard routine to move the current pixel physical address one position up. In [Graphics Mode](#graphics_mode) [CLOC](#cloc) is first decremented, if it still remains within an eight byte boundary the routine terminates. Otherwise 00F8H is subtracted from [CLOC](#cloc). Note that incorrect addresses will be produced if the top edge of the screen is exceeded.
2004
+
2005
+ In [Multicolour Mode](#multicolour_mode) control transfers to a separate routine ([17F8H](#17f8h)).
2006
+
2007
+ <a name="1779h"></a>
2008
+
2009
+ Address... 1779H
2010
+
2011
+ This is the [Multicolour Mode](#multicolour_mode) version of the routine at [16ACH](#16ach). It is identical to the [Graphics Mode](#graphics_mode) version except that [CMASK](#cmask) is shifted four bit positions right and becomes F0H if a cell boundary is crossed.
2012
+
2013
+ <a name="178bh"></a>
2014
+
2015
+ Address... 178BH
2016
+
2017
+ This is the [Multicolour Mode](#multicolour_mode) version of the [RIGHTC](#rightc) standard routine. It is identical to the [Graphics Mode](#graphics_mode) version except that [CMASK](#cmask) is shifted four bit positions right and becomes F0H if a cell boundary is crossed.
2018
+
2019
+ <a name="179ch"></a>
2020
+
2021
+ Address... 179CH
2022
+
2023
+ This is the [Multicolour Mode](#multicolour_mode) version of the routine at [16D8H](#16d8h). It is identical to the [Graphics Mode](#graphics_mode) version except that [CMASK](#cmask) is shifted four bit positions left and becomes 0FH if a cell boundary is crossed.
2024
+
2025
+ <a name="17ach"></a>
2026
+
2027
+ Address... 17ACH
2028
+
2029
+ This is the [Multicolour Mode](#multicolour_mode) version of the [LEFTC](#leftc) standard routine. It is identical to the [Graphics Mode](#graphics_mode) version except that [CMASK](#cmask) is shifted four bit positions left and becomes 0FH if a cell boundary is crossed.
2030
+
2031
+ <a name="17c6h"></a>
2032
+
2033
+ Address... 17C6H
2034
+
2035
+ This is the [Multicolour Mode](#multicolour_mode) version of the [TDOWNC](#tdownc) standard routine. It is identical to the [Graphics Mode](#graphics_mode) version except that the bottom boundary address is 0500H instead of 1700H. There is a bug in this routine which will cause it to behave unpredictably if [MLTCGP](#mltcgp), the Character Pattern Table base address, is changed from its normal value of zero. There should be an `EX DE,HL` instruction inserted at address 17CEH.
2036
+
2037
+ If the Character Pattern Table base is increased the routine will think it has reached the bottom of the screen when it actually has not. This routine is used by the "`PAINT`" statement so the following demonstrates the fault:
2038
+
2039
+ ```
2040
+ 10 BASE(17)=&H1000
2041
+ 20 SCREEN 3
2042
+ 30 PSET(200,0)
2043
+ 40 DRAW"D180L100U180R100"
2044
+ 50 PAINT(150,90)
2045
+ 60 GOTO 60
2046
+ ```
2047
+
2048
+ </a>
2049
+
2050
+ <a name="17dch"></a>
2051
+
2052
+ Address... 17DCH
2053
+
2054
+ This is the [Multicolour Mode](#multicolour_mode) version of the [DOWNC](#downc) standard routine, it is identical to the [Graphics Mode](#graphics_mode) version.
2055
+
2056
+ <a name="17e3h"></a>
2057
+
2058
+ Address... 17E3H
2059
+
2060
+ This is the [Multicolour Mode](#multicolour_mode) version of the [TUPC](#tupc) standard routine. It is identical to the [Graphics Mode](#graphics_mode) version except that is has a bug as above, this time there should be an `EX DE,HL` instruction at address 17EBH.
2061
+
2062
+ If the Character Pattern Table base address is increased the routine will think it is within the table when it has actually exceeded the top edge of the screen. This may be demonstrated by removing the "`R100`" part of Line 40 in the previous program.
2063
+
2064
+ <a name="17f8h"></a>
2065
+
2066
+ Address... 17F8H
2067
+
2068
+ This is the [Multicolour Mode](#multicolour_mode) version of the [UPC](#upc) standard routine, it is identical to the [Graphics Mode](#graphics_mode) version.
2069
+
2070
+ <a name="1809h"></a><a name="nsetcx"></a>
2071
+
2072
+ ```
2073
+ Address... 1809H
2074
+ Name...... NSETCX
2075
+ Entry..... HL=Pixel fill count
2076
+ Exit...... None
2077
+ Modifies.. AF, BC, DE, HL, EI
2078
+ ```
2079
+
2080
+ Standard routine to set the colour of multiple pixels horizontally rightwards from the current pixel physical address. Although its function can be duplicated by the [SETC](#setc) and [RIGHTC](#rightc) standard routines this would result in significantly slower operation. The supplied pixel count should be chosen so that the right-hand edge of the screen is not passed as this will produce anomalous behaviour. The current pixel physical address is unchanged by this routine.
2081
+
2082
+ In [Graphics Mode](#graphics_mode) [CMASK](#cmask) is first examined to determine the number of pixels to the right within the current character cell. Assuming the fill count is large enough these are then set ([186CH](#186ch)). The remaining fill count is divided by eight to determine the number of whole character cells. Successive bytes in the Character Pattern Table are then zeroed and the corresponding bytes in the Colour Table set from [ATRBYT](#atrbyt) to fill these whole cells. The remaining fill count is then converted to a bit mask, using the seven byte table at 185DH, and these pixels are set ([186CH](#186ch)).
2083
+
2084
+ In [Multicolour Mode](#multicolour_mode) control transfers to a separate routine ([18BBH](#18bbh)).
2085
+
2086
+ <a name="186ch"></a>
2087
+
2088
+ Address... 186CH
2089
+
2090
+ This routine sets up to eight pixels within a cell to a specified colour in [Graphics Mode](#graphicsmod). [ATRBYT](#atrbyt) contains the colour code, register pair HL the address of the relevant byte in the Character Pattern Table and register A a bit mask, 11100000 for example, where every 1 specifies a bit to be set.
2091
+
2092
+ If [ATRBYT](#atrbyt) matches the existing 1 pixel colour in the corresponding Colour Table byte then each specified bit is set to 1 in the Character Pattern Table byte. If [ATRBYT](#atrbyt) matches the existing 0 pixel colour in the corresponding Colour Table byte then each specified bit is set to 0 in the Character Pattern Table byte.
2093
+
2094
+ If [ATRBYT](#atrbyt) does not match either of the existing colours in the Colour Table Byte then normally each specified bit is set to 1 in the Character Pattern Table byte and the 1 pixel colour changed in the Colour Table byte. However if this would result in all bits being set to 1 in the Character Pattern Table byte then each specified bit is set to 0 and the 0 pixel colour changed in the Colour Table byte.
2095
+
2096
+ <a name="18bbh"></a>
2097
+
2098
+ Address... 18BBH
2099
+
2100
+ This is the [Multicolour Mode](#multicolour_mode) version of the [NSETCX](#nsetcx) standard routine. The [SETC](#setc) and [RIGHTC](#rightc) standard routines are called until the fill count is exhausted. Speed of operation is not so important in [Multicolour Mode](#multicolour_mode) because of the lower screen resolution and the consequent reduction in the number of operations required.
2101
+
2102
+ <a name="18c7h"></a><a name="gtaspc"></a>
2103
+
2104
+ ```
2105
+ Address... 18C7H
2106
+ Name...... GTASPC
2107
+ Entry..... None
2108
+ Exit...... DE=ASPCT1, HL=ASPCT2
2109
+ Modifies.. DE, HL
2110
+ ```
2111
+
2112
+ Standard routine to return the "`CIRCLE`" statement default aspect ratios.
2113
+
2114
+ <a name="18cfh"></a><a name="pntini"></a>
2115
+
2116
+ ```
2117
+ Address... 18CFH
2118
+ Name...... PNTINI
2119
+ Entry..... A=Boundary colour (0 to 15)
2120
+ Exit...... Flag C if illegal colour
2121
+ Modifies.. AF
2122
+ ```
2123
+
2124
+ Standard routine to set the boundary colour for the "`PAINT`" statement. In [Multicolour Mode](#multicolour_mode) the supplied colour code is placed in [BDRATR](#bdratr). In [Graphics Mode](#graphics_mode) [BDRATR](#bdratr) is copied from [ATRBYT](#atrbyt) as it is not possible to have separate paint and boundary colours.
2125
+
2126
+ <a name="18e4h"></a><a name="scanr"></a>
2127
+
2128
+ ```
2129
+ Address... 18E4H
2130
+ Name...... SCANR
2131
+ Entry..... B=Fill switch, DE=Skip count
2132
+ Exit...... DE=Skip remainder, HL=Pixel count
2133
+ Modifies.. AF, BC, DE, HL, EI
2134
+ ```
2135
+
2136
+ Standard routine used by the "`PAINT`" statement handler to search rightwards from the current pixel physical address until a colour code equal to [BDRATR](#bdratr) is found or the edge of the screen is reached. The terminating position becomes the current pixel physical address and the initial position is returned in [CSAVEA](#csavea) and [CSAVEM](#csavem). The size of the traversed region is returned in register pair HL and [FILNAM](#filnam)+1. The traversed region is normally filled in but this can be inhibited, in [Graphics Mode](#graphics_mode) only, by using an entry parameter of zero in register B. The skip count in register pair DE determines the maximum number of pixels of the required colour that may be ignored from the initial starting position. This facility is used by the "`PAINT`" statement handler to search for gaps in a horizontal boundary blocking its upward progress.
2137
+
2138
+ <a name="197ah"></a><a name="scanl"></a>
2139
+
2140
+ ```
2141
+ Address... 197AH
2142
+ Name...... SCANL
2143
+ Entry..... None
2144
+ Exit...... HL=Pixel count
2145
+ Modifies.. AF, BC, DE, HL, EI
2146
+ ```
2147
+
2148
+ Standard routine to search leftwards from the current pixel physical address until a colour code equal to [BDRATR](#bdratr) is found or the edge of the screen is reached. The terminating position becomes the current pixel physical address and the size of the traversed region is returned in register pair HL. The traversed region is always filled in.
2149
+
2150
+ <a name="19c7h"></a>
2151
+
2152
+ Address... 19C7H
2153
+
2154
+ This routine is used by the [SCANL](#scanl) and [SCANR](#scanr) standard routines to check the current pixel's colour against the boundary colour in [BDRATR](#bdratr).
2155
+
2156
+ <a name="19ddh"></a><a name="tapoof"></a>
2157
+
2158
+ ```
2159
+ Address... 19DDH
2160
+ Name...... TAPOOF
2161
+ Entry..... None
2162
+ Exit...... None
2163
+ Modifies.. EI
2164
+ ```
2165
+
2166
+ Standard routine to stop the cassette motor after data has been written to the cassette. After a delay of 550 ms, on MSX machines with one wait state, control drops into the [TAPIOF](#tapiof) standard routine.
2167
+
2168
+ <a name="19e9h"></a><a name="tapiof"></a>
2169
+
2170
+ ```
2171
+ Address... 19E9H
2172
+ Name...... TAPIOF
2173
+ Entry..... None
2174
+ Exit...... None
2175
+ Modifies.. EI
2176
+ ```
2177
+
2178
+ Standard routine to stop the cassette motor after data has been read from the cassette. The motor relay is opened via the [PPI Mode Port](#ppi_mode_port). Note that interrupts, which must be disabled during cassette data transfers for timing reasons, are enabled as this routine terminates.
2179
+
2180
+ <a name="19f1h"></a><a name="tapoon"></a>
2181
+
2182
+ ```
2183
+ Address... 19F1H
2184
+ Name...... TAPOON
2185
+ Entry..... A=Header length switch
2186
+ Exit...... Flag C if CTRL-STOP termination
2187
+ Modifies.. AF, BC, HL, DI
2188
+ ```
2189
+
2190
+ Standard routine to turn the cassette motor on, wait 550 ms for the tape to come up to speed and then write a header to the cassette. A header is a burst of HI cycles written in front of every data block so the baud rate can be determined when the data is read back.
2191
+
2192
+ The length of the header is determined by the contents of register A: 00H=Short header, NZ=Long header. The BASIC cassette statements "`SAVE`", "`CSAVE`" and "`BSAVE`" all generate a long header at the start of the file, in front of the identification block, and thereafter use short headers between data blocks. The number of cycles in the header is also modified by the current baud rate so as to keep its duration constant:
2193
+
2194
+ ```
2195
+ 1200 Baud SHORT ... 3840 Cycles ... 1.5 Seconds
2196
+ 1200 Baud LONG ... 15360 Cycles ... 6.1 Seconds
2197
+ 2400 Baud SHORT ... 7936 Cycles ... 1.6 Seconds
2198
+ 2400 Baud LONG ... 31744 Cycles ... 6.3 Seconds
2199
+ ```
2200
+
2201
+ After the motor has been turned on and the delay has expired the contents of [HEADER](#header) are multiplied by two hundred and fifty-six and, if register A is non-zero, by a further factor of four to produce the cycle count. HI cycles are then generated ([1A4DH](#1a4dh)) until the count is exhausted whereupon control transfers to the [BREAKX](#breakx) standard routine. Because the CTRL-STOP key is only examined at termination it is impossible to break out part way through this routine.
2202
+
2203
+ <a name="1a19h"></a><a name="tapout"></a>
2204
+
2205
+ ```
2206
+ Address... 1A19H
2207
+ Name...... TAPOUT
2208
+ Entry..... A=Data byte
2209
+ Exit...... Flag C if CTRL-STOP termination
2210
+ Modifies.. AF, B, HL
2211
+ ```
2212
+
2213
+ Standard routine to write a single byte of data to the cassette. The MSX ROM uses a software driven FSK (Frequency Shift Keyed) method for storing information on the cassette. At the 1200 baud rate this is identical to the Kansas City Standard used by the BBC for the distribution of BASICODE programs.
2214
+
2215
+ At 1200 baud each 0 bit is written as one complete 1200 Hz LO cycle and each 1 bit as two complete 2400 Hz HI cycles. The data rate is thus constant as 0 and 1 bits have the same duration. When the 2400 baud rate is selected the two frequencies change to 2400 Hz and 4800 Hz but the format is otherwise unchanged.
2216
+
2217
+ A byte of data is written with a 0 start bit ([1A50H](#1a50h)), eight data bits with the least significant bit first, and two 1 stop bits ([1A40H](#1a40h)). At the 1200 baud rate a single byte will have a nominal duration of 11 x 833 µs = 9.2 ms. After the stop bits have been written control transfers to the [BREAKX](#breakx) standard routine to check the CTRL-STOP key. The byte 43H is shown below as it would be written to cassette:
2218
+
2219
+ <a name="figure39b"></a>![][CH04F39b]
2220
+
2221
+ **Figure 39:** Cassette Data Byte
2222
+
2223
+ It is important not to leave too long an interval between bytes when writing data as this will increase the error rate. An inter-byte gap of 80 µs, for example, produces a read failure rate of approximately twelve percent. If a substantial amount of processing is required between each byte then buffering should be used to lump data into headered blocks. The BASIC "`SAVE`" format is of this type.
2224
+
2225
+ <a name="1a39h"></a>
2226
+
2227
+ Address... 1A39H
2228
+
2229
+ This routine writes a single LO cycle with a length of approximately 816 µs to the cassette. The length of each half of the cycle is taken from [LOW](#low) and control transfers to the general cycle generator ([1A50H](#1a50h)).
2230
+
2231
+ <a name="1a40h"></a>
2232
+
2233
+ Address... 1A40H
2234
+
2235
+ This routine writes two HI cycles to the cassette. The first cycle is generated ([1A4DH](#1a4dh)) followed by a 17 µs delay and then the second cycle ([1A4DH](#1a4dh)).
2236
+
2237
+ <a name="1a4dh"></a>
2238
+
2239
+ Address... 1A4DH
2240
+
2241
+ This routine writes a single HI cycle with a length of approximately 396 µs to the cassette. The length of each half of the cycle is taken from [HIGH](#high) and control drops into the general cycle generator.
2242
+
2243
+ <a name="1a50h"></a>
2244
+
2245
+ Address... 1A50H
2246
+
2247
+ This routine writes a single cycle to the cassette. The length of the cycle's first half is supplied in register L and its second half in register H. The first length is counted down and then the Cas Out bit set via the [PPI Mode Port](#ppi_mode_port). The second length is counted down and the Cas Out bit reset.
2248
+
2249
+ On all MSX machines the Z80 runs at a clock frequency of 3.579545 MHz (280 ns) with one wait state during the M1 cycle. As this routine counts every 16T states each unit increment in the length count represents a period of 4.47 µs. There is also a fixed overhead of 20.7 µs associated with the routine whatever the length count.
2250
+
2251
+ <a name="1a63h"></a><a name="tapion"></a>
2252
+
2253
+ ```
2254
+ Address... 1A63H
2255
+ Name...... TAPION
2256
+ Entry..... None
2257
+ Exit...... Flag C if CTRL-STOP termination
2258
+ Modifies.. AF, BC, DE, HL, DI
2259
+ ```
2260
+
2261
+ Standard routine to turn the cassette motor on, read the cassette until a header is found and then determine the baud rate. Successive cycles are read from the cassette and the length of each one measured ([1B34H](#1b34h)). When 1,111 cycles have been found with less than 35 µs variation in their lengths a header has been located.
2262
+
2263
+ The next 256 cycles are then read ([1B34H](#1b34h)) and averaged to determine the cassette HI cycle length. This figure is multiplied by 1.5 and placed in [LOWLIM](#lowlim) where it defines the minimum acceptable length of a 0 start bit. The HI cycle length is placed in [WINWID](#winwid) and will be used to discriminate between LO and HI cycles.
2264
+
2265
+ <a name="1abch"></a><a name="tapin"></a>
2266
+
2267
+ ```
2268
+ Address... 1ABCH
2269
+ Name...... TAPIN
2270
+ Entry..... None
2271
+ Exit...... A=Byte read, Flag C if CTRL-STOP or I/O error
2272
+ Modifies.. AF, BC, DE, L
2273
+ ```
2274
+
2275
+ Standard routine to read a byte of data from the cassette. The cassette is first read continuously until a start bit is found. This is done by locating a negative transition, measuring the following cycle length ([1B1FH](#1b1fh)) and comparing this to see if it is greater than [LOWLIM](#lowlim).
2276
+
2277
+ Each of the eight data bits is then read by counting the number of transitions within a fixed period of time ([1B03H](#1b03h)). If zero or one transitions are found it is a 0 bit, if two or three are found it is a 1 bit. If more than three transitions are found the routine terminates with Flag C as this is presumed to be a hardware error of some sort. After the value of each bit has been determined a further one or two transitions are read (1B23H) to retain synchronization. With an odd transition count one more will be read, with an even transition count two more.
2278
+
2279
+ <a name="1b03h"></a>
2280
+
2281
+ Address... 1B03H
2282
+
2283
+ This routine is used by the [TAPIN](#tapin) standard routine to count the number of cassette transitions within a fixed period of time. The window duration is contained in [WINWID](#winwid) and is approximately 1.5 times the length of a HI cycle as shown below:
2284
+
2285
+ <a name="figure40"></a>![][CH04F40]
2286
+
2287
+ **Figure 40:** Cassette Window
2288
+
2289
+ The Cas Input bit is continuously sampled via PSG [Register 14](#register_14) and compared with the previous reading held in register E. Each time a change of state is found register C is incremented. The sampling rate is once every 17.3 µs so the value in [WINWID](#winwid), which was determined by the [TAPION](#tapion) standard routine with a count rate of 11.45 µs, is effectively multiplied one and a half times.
2290
+
2291
+ <a name="1b1fh"></a>
2292
+
2293
+ Address... 1B1FH
2294
+
2295
+ This routine measures the time to the next cassette input transition. The Cassette Input bit is continuously sampled via PSG [Register 14](#register_14) until it changes from the state supplied in register E. The state flag is then inverted and the duration count returned in register C, each unit increment represents a period of 11.45 µs.
2296
+
2297
+ <a name="1b34h"></a>
2298
+
2299
+ Address... 1B34H
2300
+
2301
+ This routine measures the length of a complete cassette cycle from negative transition to negative transition. The Cassette Input bit is sampled via PSG [Register 14](#register_14) until it goes to zero. The transition flag in register E is set to zero and the time to the positive transition measured (1B23H). The time to the negative transition is then measured (1B25H) and the total returned in register C.
2302
+
2303
+ <a name="1b45h"></a><a name="outdo"></a>
2304
+
2305
+ ```
2306
+ Address... 1B45H
2307
+ Name...... OUTDO
2308
+ Entry..... A=Character to output
2309
+ Exit...... None
2310
+ Modifies.. EI
2311
+ ```
2312
+
2313
+ Standard routine used by the BASIC Interpreter to output a character to the current device. The [ISFLIO](#isflio) standard routine is first used to check whether output is currently directed to an I/O buffer, if so control transfers to the sequential output driver ([6C48H](#6c48h)) via the [CALBAS](#calbas) standard routine. If [PRTFLG](#prtflg) is zero control transfers to the [CHPUT](#chput) standard routine to output the character to the screen. Assuming the printer is active [RAWPRT](#rawprt) is checked. If this is non-zero the character is passed directly to the printer ([1BABH](#1babh)), otherwise control drops into the [OUTDLP](#outdlp) standard routine.
2314
+
2315
+ <a name="1b63h"></a><a name="outdlp"></a>
2316
+
2317
+ ```
2318
+ Address... 1B63H
2319
+ Name...... OUTDLP
2320
+ Entry..... A=Character to output
2321
+ Exit...... None
2322
+ Modifies.. EI
2323
+ ```
2324
+
2325
+ Standard routine to output a character to the printer. If the character is a TAB code (09H) spaces are issued to the [OUTDLP](#outdlp) standard routine until [LPTPOS](#lptpos) is a multiple of eight (0, 8, 16 etc.). If the character is a CR code (0DH) [LPTPOS](#lptpos) is zeroed if it is any other control code [LPTPOS](#lptpos) is unaffected, if it is a displayable character [LPTPOS](#lptpos) is incremented.
2326
+
2327
+ If [NTMSXP](#ntmsxp) is zero, meaning an MSX-specific printer is connected, the character is passed directly to the printer ([1BABH](#1babh)). Assuming a normal printer is connected the [CNVCHR](#cnvchr) standard routine is used to check for graphic characters. If the character is a header code (01H) the routine terminates with no action. If it is a converted graphic character it is replaced by a space, all other characters are passed to the printer (1BACH).
2328
+
2329
+ <a name="1b97h"></a>
2330
+
2331
+ Address... 1B97H
2332
+
2333
+ This twenty byte table is used by the keyboard decoder to find the correct routine for a given key number:
2334
+
2335
+ |KEY NUMBER |TO |FUNCTION
2336
+ |------------|:-----:|------------------
2337
+ |00H to 2FH |0F83H |Rows 0 to 5
2338
+ |30H to 32H |0F10H |SHIFT, CTRL, GRAPH
2339
+ |33H |0F36H |CAP
2340
+ |34H |0F10H |CODE
2341
+ |35H to 39H |0FC3H |F1 to F5
2342
+ |3AH to 3BH |0F10H |ESC, TAB
2343
+ |3CH |0F46H |STOP
2344
+ |3DH to 40H |0F10H |BS, CR, SEL, SPACE
2345
+ |41H |0F06H |HOME
2346
+ |42H to 57H |0F10H |INS, DEL, CURSOR
2347
+
2348
+ </a>
2349
+
2350
+ <a name="1babh"></a>
2351
+
2352
+ Address... 1BABH
2353
+
2354
+ This routine is used by the [OUTDLP](#outdlp) standard routine to pass a character to the printer. It is sent via the [LPTOUT](#lptout) standard routine, if this returns Flag C control transfers to the "`Device I/O error`" generator ([73B2H](#73b2h)) via the [CALBAS](#calbas) standard routine.
2355
+
2356
+ <a name="1bbfh"></a>
2357
+
2358
+ Address... 1BBFH
2359
+
2360
+ The following 2 KB contains the power-up character set. The first eight bytes contain the pattern for character code 00H, the second eight bytes the pattern for character code 01H and so on to character code FFH.
2361
+
2362
+ <a name="23bfh"></a><a name="pinlin"></a>
2363
+
2364
+ ```
2365
+ Address... 23BFH
2366
+ Name...... PINLIN
2367
+ Entry..... None
2368
+ Exit...... HL=Start of text, Flag C if CTRL-STOP termination
2369
+ Modifies.. AF, BC, DE, HL, EI
2370
+ ```
2371
+
2372
+ Standard routine used by the BASIC Interpreter Mainloop to collect a logical line of text from the console. Control transfers to the [INLIN](#inlin) standard routine just after the point where the previous line has been cut (23E0H).
2373
+
2374
+ <a name="23cch"></a><a name="qinlin"></a>
2375
+
2376
+ ```
2377
+ Address... 23CCH
2378
+ Name...... QINLIN
2379
+ Entry..... None
2380
+ Exit...... HL=Start of text, Flag C if CTRL-STOP termination
2381
+ Modifies.. AF, BC, DE, HL, EI
2382
+ ```
2383
+
2384
+ Standard routine used by the "`INPUT`" statement handler to collect a logical line of text from the console. The characters "`? `" are displayed via the [OUTDO](#outdo) standard routine and control drops into the [INLIN](#inlin) standard routine.
2385
+
2386
+ <a name="23d5h"></a><a name="inlin"></a>
2387
+
2388
+ ```
2389
+ Address... 23D5H
2390
+ Name...... INLIN
2391
+ Entry..... None
2392
+ Exit...... HL=Start of text, Flag C if CTRL-STOP termination
2393
+ Modifies.. AF, BC, DE, HL, EI
2394
+ ```
2395
+
2396
+ Standard routine used by the "`LINE INPUT`" statement handler to collect a logical line of text from the console. Characters are read from the keyboard until either the CR or CTRL-STOP keys are pressed. The logical line is then read from the screen character by character and placed in the Workspace Area text buffer [BUF](#buf).
2397
+
2398
+ The current screen coordinates are first taken from [CSRX](#csrx) and [CSRY](#csry) and placed in [FSTPOS](#fstpos). The screen row immediately above the current one then has its entry in [LINTTB](#linttb) made non-zero ([0C29H](#0c29h)) to stop it extending logically into the current row.
2399
+
2400
+ Each keyboard character read via the [CHGET](#chget) standard routine is checked (0919H) against the editing key table at [2439H](#2439h). Control then transfers to one of the editing routines or to the default key handler ([23FFH](#23ffh)) as appropriate. This process continues until Flag C is returned by the CTRL-STOP or CR routines. Register pair HL is then set to point to the start of [BUF](#buf) and the routine terminates. Note that the carry, flag is cleared when Flag NZ is also returned to distinguish between a CR or protected CTRL-STOP termination and a normal CTRL-STOP termination.
2401
+
2402
+ <a name="23ffh"></a>
2403
+
2404
+ Address... 23FFH
2405
+
2406
+ This routine processes all characters for the [INLIN](#inlin) standard routine except the special editing keys. If the character is a TAB code (09H) spaces are issued ([23FFH](#23ffh)) until [CSRX](#csrx) is a multiple of eight plus one (columns 1, 9, 17, 25, 33). If the character is a graphic header code (01H) it is simply echoed to the [OUTDO](#outdo) standard routine. All other control codes smaller than 20H are echoed to the [OUTDO](#outdo) standard routine after which [INSFLG](#insflg) and [CSTYLE](#cstyle) are zeroed. For the displayable characters [INSFLG](#insflg) is first checked and a space inserted ([24F2H](#24f2h)) if applicable before the character is echoed to the [OUTDO](#outdo) standard routine.
2407
+
2408
+ <a name="2439h"></a>
2409
+
2410
+ Address... 2439H
2411
+
2412
+ This table contains the special editing keys recognized by the [INLIN](#inlin) standard routine together with the relevant addresses:
2413
+
2414
+ |CODE |TO |FUNCTION
2415
+ |:---:|:----:|----------------------------
2416
+ |08H |2561H |BS, backspace
2417
+ |12H |24E5H |INS, toggle insert mode
2418
+ |1BH |23FEH |ESC, no action
2419
+ |02H |260EH |CTRL-B, previous word
2420
+ |06H |25F8H |CTRL-F, next word
2421
+ |0EH |25D7H |CTRL-N, end of logical line
2422
+ |05H |25B9H |CTRL-E, clear to end of line
2423
+ |03H |24C5H |CTRL-STOP, terminate
2424
+ |0DH |245AH |CR, terminate
2425
+ |15H |25AEH |CTRL-U, clear line
2426
+ |7FH |2550H |DEL, delete character
2427
+
2428
+ </a>
2429
+
2430
+ <a name="245ah"></a>
2431
+
2432
+ Address... 245AH
2433
+
2434
+ This routine performs the CR operation for the [INLIN](#inlin) standard routine. The starting coordinates of the logical line are found ([266CH](#266ch)) and the cursor removed from the screen ([0A2EH](#0a2eh)). Up to 254 characters are then read from the VDP VRAM ([0BD8H](#0bd8h)) and placed in [BUF](#buf). Any null codes (00H) are ignored, any characters smaller than 20H are replaced by a graphic header code (01H) and the character itself with 40H added. As the end of each physical row is reached [LINTTB](#linttb) is checked ([0C1DH](#0c1dh)) to see whether the logical line extends to the next physical row. Trailing spaces are then stripped from [BUF](#buf) and a zero byte added as an end of text marker. The cursor is restored to the screen ([09E1H](#09e1h)) and its coordinates set to the last physical row of the logical line via the [POSIT](#posit) standard routine. A LF code is issued to the [OUTDO](#outdo) standard routine, [INSFLG](#insflg) is zeroed and the routine terminates with a CR code (0DH) in register A and Flag NZ,C. This CR code will be echoed to the screen by the [INLIN](#inlin) standard routine mainloop just before it terminates.
2435
+
2436
+ <a name="24c5h"></a>
2437
+
2438
+ Address... 24C5H
2439
+
2440
+ This routine performs the CTRL-STOP operation for the [INLIN](#inlin) standard routine. The last physical row of the logical line is found by examining [LINTTB](#linttb) ([0C1DH](#0c1dh)), [CSTYLE](#cstyle) is zeroed, a zero byte is placed at the start of [BUF](#buf) and all music variables are cleared via the [GICINI](#gicini) standard routine. [TRPTBL](#trptbl) is then examined (0454H) to see if an "`ON STOP`" statement is active, if so the cursor is reset (24AFH) and the routine terminates with Flag NZ,C. [BASROM](#basrom) is then checked to see whether a protected ROM is running, if so the cursor is reset (24AFH) and the routine terminates with Flag NZ,C. Otherwise the cursor is reset (24B2H) and the routine terminates with Flag Z,C.
2441
+
2442
+ <a name="24e5h"></a>
2443
+
2444
+ Address... 24E5H
2445
+
2446
+ This routine performs the INS operation for the [INLIN](#inlin) standard routine. The current state of [INSFLG](#insflg) is inverted and control terminates via the [CSTYLE](#cstyle) setting routine (242CH).
2447
+
2448
+ <a name="24f2h"></a>
2449
+
2450
+ Address... 24F2H
2451
+
2452
+ This routine inserts a space character for the default key section of the [INLIN](#inlin) standard routine. The cursor is removed ([0A2EH](#0a2eh)) and the current cursor coordinates taken from [CSRX](#csrx) and [CSRY](#csry). The character at this position is read from the VDP VRAM ([0BD8H](#0bd8h)) and replaced with a space ([0BE6H](#0be6h)). Successive characters are then copied one column position to the right until the end of the physical row is reached.
2453
+
2454
+ At this point [LINTTB](#linttb) is examined ([0C1DH](#0c1dh)) to determine whether the logical line is extended, if so the process continues on the next physical row. Otherwise the character taken from the last column position is examined, if this is a space the routine terminates by replacing the cursor ([09E1H](#09e1h)). Otherwise the physical row's entry in [LINTTB](#linttb) is zeroed to indicate an extended logical line. The number of the next physical row is compared with the number of rows on the screen ([0C32H](#0c32h)). If the next row is the last one the screen is scrolled up (0A88H), otherwise a blank row is inserted (0AB7H) and the copying process continues.
2455
+
2456
+ <a name="2550h"></a>
2457
+
2458
+ Address... 2550H
2459
+
2460
+ This routine performs the DEL operation for the [INLIN](#inlin) standard routine. If the current cursor position is at the rightmost column and the logical line is not extended no action is taken other than to write a space to the VDP VRAM (2595H). Otherwise a RIGHT code (1CH) is issued to the [OUTDO](#outdo) standard routine and control drops into the BS routine.
2461
+
2462
+ <a name="2561h"></a>
2463
+
2464
+ Address... 2561H
2465
+
2466
+ This routine performs the BS operation for the [INLIN](#inlin) standard routine. The cursor is first removed ([0A2EH](#0a2eh)) and the cursor column coordinate decremented unless it is at the leftmost position and the previous row is not extended. Characters are then read from the VDP VRAM ([0BD8H](#0bd8h)) and written back one position to the left ([0BE6H](#0be6h)) until the end of the logical line is reached. At this point a space is written to the VDP VRAM ([0BE6H](#0be6h)) and the cursor character is restored ([09E1H](#09e1h)).
2467
+
2468
+ <a name="25aeh"></a>
2469
+
2470
+ Address... 25AEH
2471
+
2472
+ This routine performs the CTRL-U operation for the [INLIN](#inlin) standard routine. The cursor is removed ([0A2EH](#0a2eh)) and the start of the logical line located ([266CH](#266ch)) and placed in [CSRX](#csrx) and [CSRY](#csry). The entire logical line is then cleared (25BEH).
2473
+
2474
+ <a name="25b9h"></a>
2475
+
2476
+ Address... 25B9H
2477
+
2478
+ This routine performs the CTRL-E operation for the [INLIN](#inlin) standard routine. The cursor is removed ([0A2EH](#0a2eh)) and the remainder of the physical row cleared ([0AEEH](#0aeeh)). This process is repeated for successive physical rows until the end of the logical line is found in [LINTBB](#lintbb) ([0C1DH](#0c1dh)). The cursor is then restored ([09E1H](#09e1h)), [INSFLG](#insflg) zeroed and [CSTLYE](#cstlye) reset to a block cursor (242DH).
2479
+
2480
+ <a name="25d7h"></a>
2481
+
2482
+ Address... 25D7H
2483
+
2484
+ This routine performs the CTRL-N operation for the [INLIN](#inlin) standard routine. The cursor is removed ([0A2EH](#0a2eh)) and the last physical row of the logical line found by examination of [LINTTB](#linttb) ([0C1DH](#0c1dh)). Starting at the rightmost column of this physical row characters are read from the VDP VRAM ([0BD8H](#0bd8h)) until a non-space character is found. The cursor coordinates are then set one column to the right of this position ([0A5BH](#0a5bh)) and the routine terminates by restoring the cursor (25CDH).
2485
+
2486
+ <a name="25f8h"></a>
2487
+
2488
+ Address... 25F8H
2489
+
2490
+ This routine performs the CTRL-F operation for the [INLIN](#inlin) standard routine. The cursor is removed ([0A2EH](#0a2eh)) and moved successively right ([2624H](#2624h)) until a non-alphanumeric character is found. The cursor is then moved successively right ([2624H](#2624h)) until an alphanumeric character is found. The routine terminates by restoring the cursor (25CDH).
2491
+
2492
+ <a name="260eh"></a>
2493
+
2494
+ Address... 260EH
2495
+
2496
+ This routine performs the CTRL-B operation for the [INLIN](#inlin) standard routine. The cursor is removed ([0A2EH](#0a2eh)) and moved successively left ([2634H](#2634h)) until an alphanumeric character is found. The cursor is then moved successively left ([2634H](#2634h)) until a non-alphanumeric character is found and then moved one position right ([0A5BH](#0a5bh)). The routine terminates by restoring the cursor (25CDH).
2497
+
2498
+ <a name="2624h"></a>
2499
+
2500
+ Address... 2624H
2501
+
2502
+ This routine moves the cursor one position right ([0A5BH](#0a5bh)), loads register D with the rightmost column number, register E with the bottom row number and then tests for an alphanumeric character at the cursor position (263DH).
2503
+
2504
+ <a name="2634h"></a>
2505
+
2506
+ Address... 2634H
2507
+
2508
+ This routine moves the cursor one position left ([0A4CH](#0a4ch)), loads register D with the leftmost column number and register E with the top row number. The current cursor coordinates are compared with these values and the routine terminates Flag Z if the cursor is at this position. Otherwise the character at this position is read from the VDP VRAM ([0BD8H](#0bd8h)) and checked to see if it is alphanumeric. If so the routine terminates Flag NZ,C otherwise it terminates Flag NZ,NC.
2509
+
2510
+ The alphanumeric characters are the digits "0" to "9" and the letters "A" to "Z" and "a" to "z". Also included are the graphics characters 86H to 9FH and A6H to FFH, these were originally Japanese letters and should have been excluded during the conversion to the UK ROM.
2511
+
2512
+ <a name="266ch"></a>
2513
+
2514
+ Address... 266CH
2515
+
2516
+ This routine finds the start of a logical line and returns its screen coordinates in register pair HL. Each physical row above the current one is checked via the [LINTTB](#linttb) table ([0C1DH](#0c1dh)) until a non-extended row is found. The row immediately below this on the screen is the start of the logical line and its row number is placed in register L. This is then compared with [FSTPOS](#fstpos), which contains the row number when the [INLIN](#inlin) standard routine was first entered, to see if the cursor is still on the same line. If so the column coordinate in register H is set to its initial position from [FSTPOS](#fstpos). Otherwise register H is set to the leftmost position to return the whole line.
2517
+
2518
+ <a name="2680h"></a>
2519
+ <a name="2683h"></a>
2520
+ <a name="2686h"></a>
2521
+ <a name="2689h"></a>
2522
+
2523
+ ```
2524
+ Address...2680H, JP to power-up initialize routine (7C76H).
2525
+ Address...2683H, JP to the SYNCHR standard routine (558CH).
2526
+ Address...2686H, JP to the CHRGTR standard routine (4666H).
2527
+ Address...2689H, JP to the GETYPR standard routine (5597H).
2528
+ ```