@nataliapc/mcp-openmsx 1.1.15 → 1.2.3

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 (216) hide show
  1. package/README.md +84 -37
  2. package/dist/server.js +101 -40
  3. package/dist/utils.js +42 -2
  4. package/dist/vectordb.js +61 -0
  5. package/package.json +8 -3
  6. package/resources/audio/msx-midi.md +872 -0
  7. package/resources/audio/psg_registers.md +281 -0
  8. package/resources/audio/sound_cartridge_scc.md +123 -0
  9. package/resources/audio/sound_cartridge_scci.md +250 -0
  10. package/resources/audio/toc.json +8 -4
  11. package/resources/book--msx2-technical-handbook/toc.json +1 -1
  12. package/resources/msx-dos/MSX-DOS_2_Environment_Variables.md +1368 -0
  13. package/resources/msx-dos/MSX-DOS_File_extensions.md +154 -0
  14. package/resources/msx-dos/toc.json +13 -0
  15. package/resources/msx-unapi/toc.json +2 -2
  16. package/resources/others/keyboard_matrices.md +243 -0
  17. package/resources/others/toc.json +6 -0
  18. package/resources/programming/asm_callbios.md +79 -0
  19. package/resources/programming/asm_docopy.md +115 -0
  20. package/resources/programming/asm_fast_loops.md +200 -0
  21. package/resources/programming/asm_getslot.md +143 -0
  22. package/resources/programming/asm_interrupts.md +202 -0
  23. package/resources/programming/asm_load_screen.md +240 -0
  24. package/resources/programming/asm_mult_div_shifts.md +487 -0
  25. package/resources/programming/asm_raminpage1.md +56 -0
  26. package/resources/programming/asm_vdp_detection.md +78 -0
  27. package/resources/programming/asm_vdp_routines.md +343 -0
  28. package/resources/programming/asm_z80_routines_collection.md +810 -0
  29. package/resources/programming/basic_wiki/ABS().md +36 -0
  30. package/resources/programming/basic_wiki/AND.md +71 -0
  31. package/resources/programming/basic_wiki/ASC().md +38 -0
  32. package/resources/programming/basic_wiki/ATN().md +36 -0
  33. package/resources/programming/basic_wiki/AUTO.md +39 -0
  34. package/resources/programming/basic_wiki/BASE().md +147 -0
  35. package/resources/programming/basic_wiki/BEEP.md +27 -0
  36. package/resources/programming/basic_wiki/BIN$().md +36 -0
  37. package/resources/programming/basic_wiki/BLOAD.md +63 -0
  38. package/resources/programming/basic_wiki/BSAVE.md +61 -0
  39. package/resources/programming/basic_wiki/CALL.md +391 -0
  40. package/resources/programming/basic_wiki/CALL_ADJUST.md +40 -0
  41. package/resources/programming/basic_wiki/CALL_IMPOSE.md +28 -0
  42. package/resources/programming/basic_wiki/CALL_OPTIONS.md +26 -0
  43. package/resources/programming/basic_wiki/CALL_PAUSE.md +119 -0
  44. package/resources/programming/basic_wiki/CALL_PCMPLAY.md +60 -0
  45. package/resources/programming/basic_wiki/CALL_PCMREC.md +70 -0
  46. package/resources/programming/basic_wiki/CDBL().md +36 -0
  47. package/resources/programming/basic_wiki/CHR$().md +51 -0
  48. package/resources/programming/basic_wiki/CINT().md +36 -0
  49. package/resources/programming/basic_wiki/CIRCLE.md +51 -0
  50. package/resources/programming/basic_wiki/CLEAR.md +39 -0
  51. package/resources/programming/basic_wiki/CLOAD.md +27 -0
  52. package/resources/programming/basic_wiki/CLOAD?.md +31 -0
  53. package/resources/programming/basic_wiki/CLOSE.md +44 -0
  54. package/resources/programming/basic_wiki/CLS.md +51 -0
  55. package/resources/programming/basic_wiki/COLOR.md +143 -0
  56. package/resources/programming/basic_wiki/COLOR=.md +93 -0
  57. package/resources/programming/basic_wiki/COLOR_SPRITE$().md +83 -0
  58. package/resources/programming/basic_wiki/COLOR_SPRITE().md +85 -0
  59. package/resources/programming/basic_wiki/CONT.md +23 -0
  60. package/resources/programming/basic_wiki/COPY.md +215 -0
  61. package/resources/programming/basic_wiki/COPY_SCREEN.md +61 -0
  62. package/resources/programming/basic_wiki/COS().md +37 -0
  63. package/resources/programming/basic_wiki/CSAVE.md +35 -0
  64. package/resources/programming/basic_wiki/CSNG().md +36 -0
  65. package/resources/programming/basic_wiki/CSRLIN.md +33 -0
  66. package/resources/programming/basic_wiki/DATA.md +47 -0
  67. package/resources/programming/basic_wiki/DEFDBL.md +40 -0
  68. package/resources/programming/basic_wiki/DEFINT.md +40 -0
  69. package/resources/programming/basic_wiki/DEFSNG.md +40 -0
  70. package/resources/programming/basic_wiki/DEFSTR.md +40 -0
  71. package/resources/programming/basic_wiki/DEF_FN.md +49 -0
  72. package/resources/programming/basic_wiki/DEF_USR.md +33 -0
  73. package/resources/programming/basic_wiki/DELETE.md +49 -0
  74. package/resources/programming/basic_wiki/DIM.md +59 -0
  75. package/resources/programming/basic_wiki/DRAW.md +77 -0
  76. package/resources/programming/basic_wiki/ELSE.md +45 -0
  77. package/resources/programming/basic_wiki/END.md +32 -0
  78. package/resources/programming/basic_wiki/EOF().md +36 -0
  79. package/resources/programming/basic_wiki/EQV.md +76 -0
  80. package/resources/programming/basic_wiki/ERASE.md +35 -0
  81. package/resources/programming/basic_wiki/ERL.md +34 -0
  82. package/resources/programming/basic_wiki/ERR.md +143 -0
  83. package/resources/programming/basic_wiki/ERROR.md +145 -0
  84. package/resources/programming/basic_wiki/EXP().md +38 -0
  85. package/resources/programming/basic_wiki/FIELD.md +48 -0
  86. package/resources/programming/basic_wiki/FIX().md +44 -0
  87. package/resources/programming/basic_wiki/FN.md +61 -0
  88. package/resources/programming/basic_wiki/FOR...NEXT.md +80 -0
  89. package/resources/programming/basic_wiki/FRE().md +66 -0
  90. package/resources/programming/basic_wiki/GET_DATE.md +60 -0
  91. package/resources/programming/basic_wiki/GET_TIME.md +34 -0
  92. package/resources/programming/basic_wiki/GOSUB.md +41 -0
  93. package/resources/programming/basic_wiki/GOTO.md +41 -0
  94. package/resources/programming/basic_wiki/HEX$().md +36 -0
  95. package/resources/programming/basic_wiki/IF...GOTO...ELSE.md +55 -0
  96. package/resources/programming/basic_wiki/IF...THEN...ELSE.md +50 -0
  97. package/resources/programming/basic_wiki/IMP.md +83 -0
  98. package/resources/programming/basic_wiki/INKEY$.md +65 -0
  99. package/resources/programming/basic_wiki/INP().md +33 -0
  100. package/resources/programming/basic_wiki/INPUT$().md +51 -0
  101. package/resources/programming/basic_wiki/INPUT.md +93 -0
  102. package/resources/programming/basic_wiki/INSTR().md +44 -0
  103. package/resources/programming/basic_wiki/INT().md +44 -0
  104. package/resources/programming/basic_wiki/INTERVAL.md +57 -0
  105. package/resources/programming/basic_wiki/KEY().md +51 -0
  106. package/resources/programming/basic_wiki/KEY.md +254 -0
  107. package/resources/programming/basic_wiki/LEFT$().md +39 -0
  108. package/resources/programming/basic_wiki/LEN().md +36 -0
  109. package/resources/programming/basic_wiki/LET.md +68 -0
  110. package/resources/programming/basic_wiki/LINE.md +74 -0
  111. package/resources/programming/basic_wiki/LINE_INPUT.md +79 -0
  112. package/resources/programming/basic_wiki/LIST.md +58 -0
  113. package/resources/programming/basic_wiki/LLIST.md +43 -0
  114. package/resources/programming/basic_wiki/LOAD.md +56 -0
  115. package/resources/programming/basic_wiki/LOCATE.md +67 -0
  116. package/resources/programming/basic_wiki/LOG().md +36 -0
  117. package/resources/programming/basic_wiki/LPOS().md +31 -0
  118. package/resources/programming/basic_wiki/LPRINT.md +46 -0
  119. package/resources/programming/basic_wiki/MAXFILES.md +39 -0
  120. package/resources/programming/basic_wiki/MERGE.md +54 -0
  121. package/resources/programming/basic_wiki/MID$().md +72 -0
  122. package/resources/programming/basic_wiki/MOD.md +39 -0
  123. package/resources/programming/basic_wiki/MOTOR.md +46 -0
  124. package/resources/programming/basic_wiki/NEW.md +27 -0
  125. package/resources/programming/basic_wiki/NOT.md +61 -0
  126. package/resources/programming/basic_wiki/OCT$().md +36 -0
  127. package/resources/programming/basic_wiki/ON...GOSUB.md +45 -0
  128. package/resources/programming/basic_wiki/ON...GOTO.md +42 -0
  129. package/resources/programming/basic_wiki/ON_ERROR_GOTO.md +61 -0
  130. package/resources/programming/basic_wiki/ON_INTERVAL_GOSUB.md +54 -0
  131. package/resources/programming/basic_wiki/ON_KEY_GOSUB.md +56 -0
  132. package/resources/programming/basic_wiki/ON_SPRITE_GOSUB.md +41 -0
  133. package/resources/programming/basic_wiki/ON_STOP_GOSUB.md +56 -0
  134. package/resources/programming/basic_wiki/ON_STRIG_GOSUB.md +70 -0
  135. package/resources/programming/basic_wiki/OPEN.md +103 -0
  136. package/resources/programming/basic_wiki/OR.md +75 -0
  137. package/resources/programming/basic_wiki/OUT.md +35 -0
  138. package/resources/programming/basic_wiki/PAD().md +110 -0
  139. package/resources/programming/basic_wiki/PAINT.md +66 -0
  140. package/resources/programming/basic_wiki/PDL().md +53 -0
  141. package/resources/programming/basic_wiki/PEEK().md +44 -0
  142. package/resources/programming/basic_wiki/PLAY().md +58 -0
  143. package/resources/programming/basic_wiki/PLAY.md +196 -0
  144. package/resources/programming/basic_wiki/POINT.md +52 -0
  145. package/resources/programming/basic_wiki/POKE.md +51 -0
  146. package/resources/programming/basic_wiki/POS().md +36 -0
  147. package/resources/programming/basic_wiki/PRESET.md +61 -0
  148. package/resources/programming/basic_wiki/PRINT.md +179 -0
  149. package/resources/programming/basic_wiki/PSET.md +82 -0
  150. package/resources/programming/basic_wiki/PUT_KANJI.md +93 -0
  151. package/resources/programming/basic_wiki/PUT_SPRITE.md +143 -0
  152. package/resources/programming/basic_wiki/READ.md +45 -0
  153. package/resources/programming/basic_wiki/REM.md +42 -0
  154. package/resources/programming/basic_wiki/RENUM.md +78 -0
  155. package/resources/programming/basic_wiki/RESTORE.md +52 -0
  156. package/resources/programming/basic_wiki/RESUME.md +45 -0
  157. package/resources/programming/basic_wiki/RETURN.md +47 -0
  158. package/resources/programming/basic_wiki/RIGHT$().md +39 -0
  159. package/resources/programming/basic_wiki/RND().md +51 -0
  160. package/resources/programming/basic_wiki/RUN.md +56 -0
  161. package/resources/programming/basic_wiki/SAVE.md +65 -0
  162. package/resources/programming/basic_wiki/SCREEN.md +164 -0
  163. package/resources/programming/basic_wiki/SET_ADJUST.md +66 -0
  164. package/resources/programming/basic_wiki/SET_BEEP.md +76 -0
  165. package/resources/programming/basic_wiki/SET_DATE.md +103 -0
  166. package/resources/programming/basic_wiki/SET_PAGE.md +52 -0
  167. package/resources/programming/basic_wiki/SET_PASSWORD.md +75 -0
  168. package/resources/programming/basic_wiki/SET_PROMPT.md +61 -0
  169. package/resources/programming/basic_wiki/SET_SCREEN.md +100 -0
  170. package/resources/programming/basic_wiki/SET_SCROLL.md +55 -0
  171. package/resources/programming/basic_wiki/SET_TIME.md +83 -0
  172. package/resources/programming/basic_wiki/SET_TITLE.md +87 -0
  173. package/resources/programming/basic_wiki/SET_VIDEO.md +49 -0
  174. package/resources/programming/basic_wiki/SGN().md +38 -0
  175. package/resources/programming/basic_wiki/SIN().md +36 -0
  176. package/resources/programming/basic_wiki/SOUND.md +188 -0
  177. package/resources/programming/basic_wiki/SPACE$().md +38 -0
  178. package/resources/programming/basic_wiki/SPC().md +34 -0
  179. package/resources/programming/basic_wiki/SPRITE$().md +50 -0
  180. package/resources/programming/basic_wiki/SPRITE.md +31 -0
  181. package/resources/programming/basic_wiki/SQR().md +32 -0
  182. package/resources/programming/basic_wiki/STICK().md +70 -0
  183. package/resources/programming/basic_wiki/STOP.md +70 -0
  184. package/resources/programming/basic_wiki/STR$().md +37 -0
  185. package/resources/programming/basic_wiki/STRIG().md +82 -0
  186. package/resources/programming/basic_wiki/STRING$().md +42 -0
  187. package/resources/programming/basic_wiki/SWAP.md +62 -0
  188. package/resources/programming/basic_wiki/TAB().md +38 -0
  189. package/resources/programming/basic_wiki/TAN().md +36 -0
  190. package/resources/programming/basic_wiki/TIME.md +59 -0
  191. package/resources/programming/basic_wiki/TROFF.md +21 -0
  192. package/resources/programming/basic_wiki/TRON.md +39 -0
  193. package/resources/programming/basic_wiki/USR().md +66 -0
  194. package/resources/programming/basic_wiki/VAL().md +36 -0
  195. package/resources/programming/basic_wiki/VARPTR().md +50 -0
  196. package/resources/programming/basic_wiki/VDP().md +103 -0
  197. package/resources/programming/basic_wiki/VPEEK().md +46 -0
  198. package/resources/programming/basic_wiki/VPOKE.md +48 -0
  199. package/resources/programming/basic_wiki/WAIT.md +38 -0
  200. package/resources/programming/basic_wiki/WIDTH.md +76 -0
  201. package/resources/programming/basic_wiki/XOR.md +72 -0
  202. package/resources/programming/basic_wiki/_toc.json +871 -0
  203. package/resources/programming/dos_error_handling.md +85 -0
  204. package/resources/programming/toc.json +51 -36
  205. package/resources/programming/vdp_commands_speed.md +147 -0
  206. package/resources/programming/vdp_programming_faq.md +55 -0
  207. package/resources/programming/vdp_programming_tutorial.md +390 -0
  208. package/resources/programming/vdp_screensplit_programming_guide.md +166 -0
  209. package/resources/programming/vdp_scrolling_on_msx.md +124 -0
  210. package/resources/programming/vdp_the_yjk_screen_modes.md +227 -0
  211. package/resources/programming/vdp_v9938_vram_timings.md +539 -0
  212. package/resources/programming/vdp_v9938_vram_timings_part_2.md +281 -0
  213. package/resources/sdcc/toc.json +1 -1
  214. package/vector-db/index.json +1 -0
  215. /package/resources/msx-unapi/{Ethernet_UNAPI_specification_1.1.md → Ethernet_UNAPI_specification_1_1.md} +0 -0
  216. /package/resources/msx-unapi/{MSX_UNAPI_specification_1.1.md → MSX_UNAPI_specification_1_1.md} +0 -0
@@ -0,0 +1,85 @@
1
+ # Disk I/O error handling in MSX-DOS 1
2
+
3
+ by Ramon van der Winkel, 22/02/1992
4
+ by request of Matthijs Corpeleijn
5
+ translated by Laurens Holst
6
+
7
+ When an error occurs during floppy disk I/O, for example because there’s no disk in the disk drive, it’s not nice when a DOS error message appears right in the middle of the execution of the program. Especially when the program is Dutch and the error shown is English.
8
+
9
+ The error can be captured and redirected to a custom handler in the program. This handler can then use a more fitting way to ask the user how to deal with the error. Regardless of whether this is done with a single-line message or a graphical window.
10
+
11
+ In MSX-DOS 1 the program has to deal with everything manually. Two addresses need to be diverted and any possible stack problems also need to be taken care of by the program itself. Fortunately MSX-DOS 2 has a better way of handling things; a couple of ready-made routines do most of the work.
12
+
13
+ ## DOS 1
14
+
15
+ There are two relevant addresses for handling errors in MSX-DOS 1. First of all there’s the address which points to the error handling routine. Additionally there’s an address which is called when the “Abort” option is chosen.
16
+
17
+ For the error handling routine you need to use the address F323 in the system memory. The contents of this address point to another address which in turn contains the address of the routine. For example:
18
+
19
+ ```
20
+ F323 -> D000
21
+ D000 -> D002
22
+ D002 Start routine
23
+ ```
24
+
25
+ When the error handling routine chooses the Abort option, MSX-DOS jumps to a routine which ends with a jump instruction to return to the prompt. We can change this into a jump to our program by setting the address of our routine at address F1E6.
26
+
27
+ ```
28
+ F1E6 -> Abort handler
29
+ ```
30
+
31
+ The abort handler exists to intercept stack errors. When Ignore or Retry is chosen, a succesful attempt will return to the BDOS function’s call site, and when another error occurs the error handling routine is called again.
32
+
33
+ Next, the stack needs to be preserved. This can be done as follows, by introducing a universal wrapper routine for invoking the BDOS to the program:
34
+
35
+ ```assembler
36
+ bdos: ld (errStack),sp
37
+ call 5
38
+ ret
39
+ ```
40
+
41
+ At this point the error handling routines should already have been set up, and when an abort occurs it should jump to the following routine:
42
+
43
+ ```assembler
44
+ bdosAbort: ld sp,(errStack)
45
+ ret
46
+ ```
47
+
48
+ This will return to the routine that originally invoked the bdos. All that’s left is a mechanism that lets you check for errors. This can be done by setting a variable first before using the above method to return.
49
+
50
+ When the application diverts these two addresses, it’s important that the original values are preserved and restored when the program terminates.
51
+
52
+ All that remains is the description of the error codes that MSX-DOS 1 passes to the error handling routine. First of all the A register contains the drive number. This is the drive which produced the error. The C register will contain an indication of the error, see the following table:
53
+
54
+ ```
55
+ b7=1 : Bad FAT
56
+ b0=0 : Read action
57
+ b0=1 : Write action
58
+
59
+ b3 b2 b1
60
+ 0 0 0: Write Protected
61
+ 0 0 1: Not Read (disk offline)
62
+ 0 1 0: CRC error
63
+ 0 1 1: Seek error
64
+ 1 0 0: Record not found (sector not found)
65
+ 1 0 1: Write error
66
+ 1 1 0: Other
67
+ ```
68
+
69
+ When returning from the error handler, register C should specify the action to take:
70
+
71
+ ```
72
+ 0 = Ignore
73
+ 1 = Retry
74
+ 2 = Abort
75
+ ```
76
+
77
+ When option 2 (abort) is chosen, it will jump to the abort routine which we diverted earlier.
78
+
79
+ That’s all there is to it. One more thing: be careful where you put the error handling routine. This routine is called by the DiskROM and it may not be able to reach a routine in page 1 (4000..7FFF). However for the abort routine this is not an issue, as by this time the full TPA memory has been re-enabled.
80
+
81
+ For the MSX-DOS 2 error handling, please refer to the MSX-DOS application manual.
82
+
83
+ ## Source
84
+
85
+ https://map.grauw.nl/articles/dos-error-handling.php
@@ -4,97 +4,121 @@
4
4
  "toc": [
5
5
  {
6
6
  "title": "[ASM] Execute a VDP command",
7
- "uri": "https://map.grauw.nl/sources/docopy.php",
7
+ "uri": "msxdocs://programming/asm_docopy",
8
+ "external_url": "https://map.grauw.nl/sources/docopy.php",
8
9
  "description": "This page provides a detailed explanation of how to execute a VDP command in MSX assembly language, including the necessary registers and instructions."
9
10
  },
10
11
  {
11
12
  "title": "[ASM] Detecting VDP version",
12
- "uri": "https://map.grauw.nl/sources/vdp_detection.php",
13
+ "uri": "msxdocs://programming/asm_vdp_detection",
14
+ "external_url": "https://map.grauw.nl/sources/vdp_detection.php",
13
15
  "description": "A guide on how to detect the version of the VDP (Video Display Processor) in MSX systems using assembly language. It includes code examples and explanations of the relevant registers."
14
16
  },
15
17
  {
16
18
  "title": "[ASM] A whole shitload of VDP routines",
17
- "uri": "https://map.grauw.nl/sources/vdp_rout.php",
19
+ "uri": "msxdocs://programming/asm_vdp_routines",
20
+ "external_url": "https://map.grauw.nl/sources/vdp_rout.php",
18
21
  "description": "A comprehensive collection of MSX VDP (Video Display Processor) assembly routines including fast DoCopy, VDP register management, screen mode selection, sprite control, palette setting, and VRAM access functions. These optimized routines are designed for DOS environment and provide essential building blocks for MSX graphics programming."
19
22
  },
20
23
  {
21
24
  "title": "[ASM] Load graphic data into the VRAM",
22
- "uri": "https://map.grauw.nl/sources/load_screen.php",
25
+ "uri": "msxdocs://programming/asm_load_screen",
26
+ "external_url": "https://map.grauw.nl/sources/load_screen.php",
23
27
  "description": "Assembly routines for loading graphic data files directly into MSX VRAM memory. Includes optimized file loading, palette handling, and VRAM writing functions designed for MSX-DOS 2 environment. Features efficient buffer management and fast loops for screen data transfer."
24
28
  },
25
29
  {
26
30
  "title": "[ASM] Multiplications, divisions and shifts",
27
- "uri": "https://map.grauw.nl/articles/mult_div_shifts.php",
31
+ "uri": "msxdocs://programming/asm_mult_div_shifts",
32
+ "external_url": "https://map.grauw.nl/articles/mult_div_shifts.php",
28
33
  "description": "Comprehensive guide to optimized mathematical operations in Z80 assembly for MSX. Covers fast multiplication and division techniques using bit shifts, generic multiplication routines, division algorithms, and square root calculations. Essential for performance-critical MSX programming where the Z80 lacks built-in multiplication instructions."
29
34
  },
30
35
  {
31
36
  "title": "[ASM] Get slot ID of any page",
32
- "uri": "https://map.grauw.nl/sources/getslot.php",
37
+ "uri": "msxdocs://programming/asm_getslot",
38
+ "external_url": "https://map.grauw.nl/sources/getslot.php",
33
39
  "description": "Assembly routine to determine the slot ID of any memory page in MSX systems. Essential for ROM cartridges and programs that need to identify which slot/subslot is currently selected in a specific memory page. Includes detailed explanation of MSX slot selection system and BIOS slot ID format."
34
40
  },
35
41
  {
36
42
  "title": "[ASM] How to switch RAM/ROM in page 1",
37
- "uri": "https://map.grauw.nl/sources/raminpage1.php",
43
+ "uri": "msxdocs://programming/asm_raminpage1",
44
+ "external_url": "https://map.grauw.nl/sources/raminpage1.php",
38
45
  "description": "Techniques for switching between RAM and ROM in memory page 1 (4000H-7FFFH) to gain additional 16KB of RAM space in MSX BASIC environment. Includes methods using RAMAD1 system variable and alternative approaches for systems without DiskROM."
39
46
  },
40
47
  {
41
48
  "title": "[ASM] Calling the BIOS from MSX-DOS",
42
- "uri": "https://map.grauw.nl/sources/callbios.php",
49
+ "uri": "msxdocs://programming/asm_callbios",
50
+ "external_url": "https://map.grauw.nl/sources/callbios.php",
43
51
  "description": "Methods for calling MSX BIOS routines from MSX-DOS environment using interslot calls. Includes special procedures for calling SUBROM routines and the official ASCII-provided routine for safe SUBROM access from MSX-DOS."
44
52
  },
45
53
  {
46
54
  "title": "[ASM] Z80 routines collection",
47
- "uri": "https://map.grauw.nl/sources/external/z80bits.html",
55
+ "uri": "msxdocs://programming/asm_z80_routines_collection",
56
+ "external_url": "https://map.grauw.nl/sources/external/z80bits.html",
48
57
  "description": "Comprehensive collection of optimized Z80 assembly routines including integer multiplication/division algorithms, square roots, random number generators, number-to-string conversions, and CRC calculations. Features highly optimized code for performance-critical applications."
49
58
  },
50
59
  {
51
60
  "title": "[ASM] Fast loops",
52
- "uri": "https://map.grauw.nl/articles/fast_loops.php",
61
+ "uri": "msxdocs://programming/asm_fast_loops",
62
+ "external_url": "https://map.grauw.nl/articles/fast_loops.php",
53
63
  "description": "Advanced Z80 assembly techniques for optimizing loop performance. Covers fast 16-bit loops using DJNZ that can achieve the same speed as 8-bit loops, and loop unrolling methods like making LDIR 21% faster. Essential for performance-critical MSX programming where every clock cycle counts."
54
64
  },
55
65
  {
56
- "title": "[ASM] VDP programming tutorial",
57
- "uri": "https://map.grauw.nl/articles/vdp_tut.php",
58
- "description": "Comprehensive tutorial for beginning assembly programmers on MSX VDP programming. Covers VDP basics (VRAM, registers, command unit), register access methods, VRAM operations, VDP commands execution, palette settings, and includes practical programming examples. Essential guide for MSX graphics programming."
66
+ "title": "[ASM] Z80 Advanced Maths",
67
+ "uri": "http://z80-heaven.wikidot.com/advanced-math",
68
+ "description": "Comprehensive guide covering advanced mathematical routines for Z80 processors including integer arithmetic, BCD arithmetic, fixed point arithmetic, and floating point arithmetic. Features algorithms for multiplication (schoolbook, Karatsuba, Toom-Cook), division methods, square root calculations, exponential functions, and trigonometric operations optimized for Z80 assembly programming."
59
69
  },
60
70
  {
61
- "title": "[ASM] VDP programming FAQ",
62
- "uri": "https://map.grauw.nl/articles/vdp_guide.php",
63
- "description": "Collection of VDP programming tips and solutions to common problems. Addresses issues like r#18 register corruption with VDP commands, screensplit problems, interrupt handling, missing screen modes (screen 9), register gaps (r#24), and screen 8 color composition. Essential troubleshooting guide for VDP development."
71
+ "title": "Interrupts",
72
+ "uri": "msxdocs://programming/asm_interrupts",
73
+ "external_url": "https://map.grauw.nl/articles/interrupts.php",
74
+ "description": "Detailed explanation of MSX interrupt programming covering H.KEYI and H.TIMI interrupt hooks, interrupt routine setup requirements, register preservation, slot register management, and memory mapper considerations. Explains differences between hooks called every interrupt versus regular intervals (50/60 Hz), with practical examples for background music and device communication interrupt handlers."
64
75
  },
65
76
  {
66
- "title": "[ASM] Z80 Advanced Maths",
67
- "uri": "http://z80-heaven.wikidot.com/advanced-math",
68
- "description": "Comprehensive guide covering advanced mathematical routines for Z80 processors including integer arithmetic, BCD arithmetic, fixed point arithmetic, and floating point arithmetic. Features algorithms for multiplication (schoolbook, Karatsuba, Toom-Cook), division methods, square root calculations, exponential functions, and trigonometric operations optimized for Z80 assembly programming."
77
+ "title": "[VDP] VDP programming tutorial",
78
+ "uri": "msxdocs://programming/vdp_programming_tutorial",
79
+ "external_url": "https://map.grauw.nl/articles/vdp_tut.php",
80
+ "description": "Comprehensive tutorial for beginning assembly programmers on MSX VDP programming. Covers VDP basics (VRAM, registers, command unit), register access methods, VRAM operations, VDP commands execution, palette settings, and includes practical programming examples. Essential guide for MSX graphics programming."
81
+ },
82
+ {
83
+ "title": "[VDP] VDP programming FAQ",
84
+ "uri": "msxdocs://programming/vdp_programming_faq",
85
+ "external_url": "https://map.grauw.nl/articles/vdp_guide.php",
86
+ "description": "Collection of VDP programming tips and solutions to common problems. Addresses issues like r#18 register corruption with VDP commands, screensplit problems, interrupt handling, missing screen modes (screen 9), register gaps (r#24), and screen 8 color composition. Essential troubleshooting guide for VDP development."
69
87
  },
70
88
  {
71
89
  "title": "[VDP] Screensplit programming guide",
72
- "uri": "https://map.grauw.nl/articles/split_guide.php",
90
+ "uri": "msxdocs://programming/vdp_screensplit_programming_guide",
91
+ "external_url": "https://map.grauw.nl/articles/split_guide.php",
73
92
  "description": "Detailed guide for programming screensplits on MSX systems covering timing accuracy, HBLANK/VBLANK concepts, VDP line interrupts, seamless splits, and compatibility across different MSX computer types and CPU speeds. Includes Q&A sections on split timing, MSX1 screensplits, spritesplits, and scrollsplits using register 23."
74
93
  },
75
94
  {
76
95
  "title": "[VDP] VDP commands & speed measurements",
77
- "uri": "https://map.grauw.nl/articles/vdp_commands_speed.php",
96
+ "uri": "msxdocs://programming/vdp_commands_speed",
97
+ "external_url": "https://map.grauw.nl/articles/vdp_commands_speed.php",
78
98
  "description": "Comprehensive analysis of VDP command execution speed with detailed measurement tables showing bytes processed per interrupt under different circumstances. Covers speedup methods, performance differences between copy and fill operations, 50/60 Hz timing variations, and programming optimization tips for VDP command efficiency."
79
99
  },
80
100
  {
81
101
  "title": "[VDP] A guide to scrolling game engines on MSX",
82
- "uri": "https://map.grauw.nl/articles/scrolling.php",
102
+ "uri": "msxdocs://programming/vdp_scrolling_on_msx",
103
+ "external_url": "https://map.grauw.nl/articles/scrolling.php",
83
104
  "description": "Comprehensive guide to implementing scrolling in MSX games covering hardware limitations and solutions for different VDP versions (TMS9918, v9938, v9958, v9990). Explains tile-based systems, hardware scrolling capabilities, software scrolling optimization, and combining hardware/software approaches for efficient scrolling game engines."
84
105
  },
85
106
  {
86
107
  "title": "[VDP] V9938 VRAM timings",
87
- "uri": "https://map.grauw.nl/articles/vdp-vram-timing/vdp-timing.html",
108
+ "uri": "msxdocs://programming/vdp_v9938_vram_timings",
109
+ "external_url": "https://map.grauw.nl/articles/vdp-vram-timing/vdp-timing.html",
88
110
  "description": "Detailed technical analysis of V9938 VRAM access timings in bitmap screen modes (screen 5-8) covering VRAM access for bitmap rendering, sprite rendering, VDP command execution, and CPU VRAM operations. Includes measurement data and analysis to improve MSX emulator accuracy for VDP command engine timing and LINE command speed variations."
89
111
  },
90
112
  {
91
113
  "title": "[VDP] V9938 VRAM timings, part II",
92
- "uri": "https://map.grauw.nl/articles/vdp-vram-timing/vdp-timing-2.html",
114
+ "uri": "msxdocs://programming/vdp_v9938_vram_timings_part_2",
115
+ "external_url": "https://map.grauw.nl/articles/vdp-vram-timing/vdp-timing-2.html",
93
116
  "description": "Follow-up document to V9938 VRAM timings covering logic analyzer measurements of V9938-VRAM communication. Details CPU (Z80) VRAM access timing constraints, what constitutes 'too fast' access, and accurate VDP command engine timing implementation. Focuses on bitmap screen modes with measurement data for improved MSX emulation accuracy."
94
117
  },
95
118
  {
96
119
  "title": "[VDP] The YJK screen modes",
97
- "uri": "https://map.grauw.nl/articles/yjk/",
120
+ "uri": "msxdocs://programming/vdp_the_yjk_screen_modes",
121
+ "external_url": "https://map.grauw.nl/articles/yjk/",
98
122
  "description": "Comprehensive guide to the YJK high-color screen modes of the MSX2+ and turbo R (V9958 VDP). Covers YJK encoding, conversion between YJK and RGB color spaces, SCREEN 10/11/12 modes supporting up to 19268 colors, color attribute clash in 4x1 pixel groups, and drawing techniques for photographic images and games with enhanced sprite palette capabilities."
99
123
  },
100
124
  {
@@ -104,18 +128,9 @@
104
128
  },
105
129
  {
106
130
  "title": "[DOS] Disk I/O error handling in MSX-DOS 1",
107
- "uri": "https://map.grauw.nl/articles/dos-error-handling.php",
131
+ "uri": "msxdocs://programming/dos_error_handling",
132
+ "external_url": "https://map.grauw.nl/articles/dos-error-handling.php",
108
133
  "description": "Guide to implementing custom disk I/O error handling in MSX-DOS 1 programs. Covers redirecting error handlers to prevent default DOS error messages, setting up custom error handling routines using addresses F323 and F1E6, managing abort handlers, and dealing with stack problems. Includes comparison with improved MSX-DOS 2 error handling methods."
109
- },
110
- {
111
- "title": "Keyboard matrices",
112
- "uri": "https://map.grauw.nl/articles/keymatrix.php",
113
- "description": "Comprehensive guide to MSX keyboard matrix layouts covering the 11x8 bit key matrix structure, keyboard version detection from BIOS address #002C, differences between Japanese, International, French, German, and Spanish keyboard layouts. Discusses keyboard matrix reading techniques and compatibility issues across different MSX computer models, with special focus on rows 6-10 standardization."
114
- },
115
- {
116
- "title": "Interrupts",
117
- "uri": "https://map.grauw.nl/articles/interrupts.php",
118
- "description": "Detailed explanation of MSX interrupt programming covering H.KEYI and H.TIMI interrupt hooks, interrupt routine setup requirements, register preservation, slot register management, and memory mapper considerations. Explains differences between hooks called every interrupt versus regular intervals (50/60 Hz), with practical examples for background music and device communication interrupt handlers."
119
134
  }
120
135
  ]
121
136
  }
@@ -0,0 +1,147 @@
1
+ # VDP commands ~ speed measurements
2
+
3
+ This article explains in some detail how fast the VDP’s command execution is, and how you can speed it up. It has some rather accurate tables with measurement data on how much bytes the VDP can approximately process within the timeframe of one interrupt under different circumstances. By using these tables, you can calculate on beforehand whether for example a cool effect can be done or not. Also, near the end of this article there are a couple of programming tips.
4
+
5
+ This article was originally written for the Track diskmagazine I and the rest of the Datax crew produced back then. It was also published in XSW-Magazine later on. Since I think this is a quite valuable resource, I now put it online at the MAP. For this purpose I translated the original article to English, and while I was at it I re-edited it and also added some additional notes.
6
+
7
+ You can download a [speed test tool here](https://map.grauw.nl/downloads/articles/testcopy.lzh) with which you can make measurements yourself.
8
+
9
+ - [Introduction](#introduction)
10
+ - [The well-known methods](#the-well-known-methods)
11
+ - [The unknown (?) speedup method](#the-unknown--speedup-method)
12
+ - [Smaller copies are slower](#smaller-copies-are-slower)
13
+ - [The difference between 50/60 Hertz](#the-difference-between-5060-hertz)
14
+ - [The speed tests](#the-speed-tests)
15
+ - [The tables for the copies](#the-tables-for-the-copies)
16
+ - [The tables for the fills](#the-tables-for-the-fills)
17
+ - [Applications of the tables](#applications-of-the-tables)
18
+ - [Some additional notes](#some-additional-notes)
19
+ - [The tests](#the-tests)
20
+
21
+ ## Introduction
22
+
23
+ In this edition of ‘ML with LH’ I will discuss the videoprocessor’s speed when executing its commands, and how to boost it. This might result in monitor problems in case it is monochrome (SCART-connections don’t always work flawless either, but you can fix that by smudging some peanutbutter into the input).
24
+
25
+ The videoprocessor loses a lot of time with the construction of the image, and while it is at that job it’s only got very little spare time to execute commands with. That’s why the best way to speed up the VDP is to decrease the amount of time the VDP uses to do that.
26
+
27
+ ## The well-known methods
28
+
29
+ The VDP’s two ‘official’ speedup methods are probably already known to you, these are:
30
+
31
+ Disabling the screen by resetting bit 6 of register 1
32
+ Disabling the display of the sprites by setting bit 1 of register 8 (vdp(9) in Basic).
33
+ However, there are also a couple of other methods, which all come down to decreasing the amount of time the VDP has to put in its other tasks.
34
+
35
+ ## The unknown (?) speedup method
36
+
37
+ One of the other ways to speed the VDP up a little is a variant of the abovementioned ‘official’ method nr. 1, disabling the screen. To be more specific, I’m talking about partially disabling the screen here. It’s easiest to simply reset bit 7 of register 9 (vdp(10) in Basic), which will make the screen 192 lines higher instead of 212. That way the VDP has to put 20 lines less on screen, and has therefor more time left for executing commands like a fill or a copy. The screen remains fairly large (like on MSX1) and it’s a very low-maintenance solution, you only need to change one single bit and after that won’t have to look at it again. Another additional result of this is that - in case of a game - the area where the action takes place becomes smaller, so the copies themselves will also be smaller, resulting in some additional speed.
38
+
39
+ However, you can also ‘shorten’ the screen from (and to) every possible horizontal line by using a screensplit and disabling the screen on certain lines.
40
+
41
+ If you for example have a game which uses the larger part of the screen for the field, where a statusbar is located at the bottom (like SD-Snatcher or Pumpkin Adventure), and if you usually would disable the screen in its entirety when flipping to the next field to speedup the screen buildup, you could also use the abovementioned method and only disable the top part of the screen, being the field, but leave the bottom part, the status bar, visible. That’ll probably look better while it will still provide additional speed.
42
+
43
+ ## Smaller copies are slower
44
+
45
+ One thing you should really keep in mind is that smaller copies are a lot slower than large copies. I’ll give you a couple of figures, you can verify them with my test program, and do some more detailed measurements. If you are using a tilemap for something, you are usually using tiles of 8x8 pixels, or 16x16 ones. Well, take the case that you are running at 60Hz, with sprites disabled, and using HMMM copies. With a single copy, you can relocate 3616 bytes in the timeframe of 1 interrupt. With 8x8 copies however, you can only copy 2080 bytes, and with 16x16 copies you can do 2944 bytes. These are quite astonashing numbers, 8x8 copies are 42% slower than 1 large copy, and 16x16 copies are 19% slower!
46
+
47
+ Some more tests made apparant that the ‘loss’ in speed is mainly dependant on the X size and in a lesser degree on the Y size. So if you have the choice, a 32x8 copy should for example be preferred over a 8x32 one. But the key factor in gaining speed is the size, so just try to make the copies as large as possible. When designing a game this might be a reason to favor 16x16 tiles over 8x8 tiles.
48
+
49
+ So how could tilebased games like Ys and Akin/Coredump be so damn fast then when they’re using 8x8 tiles? Well, in order to do that you must combine a number of speedup tactics. First off, only copy the necessary tiles. If there’s a patch of grass on the ground, and next to it there’s more grass, then you won’t have to redraw all of the grass, only the tiles which change need to be redrawn. Secondly, when you have to draw a ‘clear’ tile (in 1 single color), use an HMMV instead of an HMMM. You’d be surprised how often clear tiles are used, especially if the graphics designer keeps it in mind. And finally, try to apply some form of caching to your tiles. Store commonly used groups of tiles on an alternate page, or copy them from elsewhere on the visible field if they are on it. That way you’ll be able to use larger copies. One final note on this subject; when applying these techniques, try to preprocess the data to the largest extent possible, because if you do it all in realtime valuable time gets lost. And some stuff can simply not be done in realtime, like pattern matching, you probably even need a PC to do the preprocessing.
50
+
51
+ ## The difference between 50/60 Hertz
52
+
53
+ Often games seem to work faster when running on 60 Hz. The sprites move faster, the music is played faster aswell. However, when executing VDP-commands on 60 Hz it seems as if they are significantly slower. In the worst-case scenario of LMMM the speed even drops to below 1000 bytes/interrupt. Now this can very easily be explained. These measurements were taken in number of bytes per interrupt. Since there are a 20% more interrupts (60 per minute instead of 50 per minute) it’s also logical the number of bytes per interrupt drops with 20%.
54
+
55
+ However, aside from that, there also is some real slowdown when using 60 Hz. At 50Hertz, the number of bytes per minute is not 20% more than at 60 Hertz, as one would expect, but roughly 26% more! Also, as more and more display features are disabled, with ultimately a blank screen, the difference drops back to the expected 20%... This can not simply be explained by measurement errors, because the difference of 6% is a couple of times larger than the accuracy. So, the conclusion is that when running at 60 Hz the VDP has got more work to do per displayed line, and has therefore less spare time for the execution of commands, which means they become slower.
56
+
57
+ ## The speed tests
58
+
59
+ I did a couple of tests about the speed of two types of VDP commands, being the copy and the fill (both in aswell low as highspeed versions). I tested the speed of these commands with the sprites on and off, and with 212, 192 or 0 displayed lines. All data has been tested on aswell 50 as 60 Hertz, so you can easily decide which table to look at, depending on which frequency you want your game or demo to run on. I have also added the YMMM test results which weren’t present in the original article.
60
+
61
+ First off, a short legenda:
62
+
63
+ First of all the official name of the tested command is mentioned, and next to it is the term ‘accuracy’, which (wonder wonder) indicates the accuracy of the measurements. To be more specific, it indicates on what boundary the value is rounded down. An accuracy of 32 means for example that the real value, for example 107 (in an imaginary case) will be rounded down to 96, which is a multiple of 32. The other way around, a given value of 96 means that the real value can be up to 31 bytes higher.
64
+
65
+ Next: Spr means sprites, which can be either enabled or disabled (on/off), Lin indicates the number of lines displayed, either 212 or 192, and --Blank-- indicates the screen is entirely blanked out. This is effectively the same as Lin being set to 0 and Spr being set to off.
66
+
67
+ Further, there’s Speed. This number indicates how many bytes the VDP’s command can process per interrupt. So in case of LMMM and HMMM this is the number of bytes it can copy, and in LMMV/HMMV’s case this is the number of bytes it can fill. These values are valid for ALL screens from 5 to 12 (and on v9958, I guess aswell for the MSX1 screen modes).
68
+
69
+ Finally, 50/60 Hertz, this is related to Speed and shows the difference in number of bytes between both interrupt modes.
70
+
71
+ ## The tables for the copies
72
+
73
+ Speed is indicated in bytes per interrupt.
74
+
75
+ ```
76
+ LMMM accuracy: 16 HMMM accuracy: 32 YMMM accuracy: 32
77
+
78
+ Spr / Lin - Speed 50/60Hz Spr / Lin - Speed 50/60Hz Spr / Lin - Speed 50/60Hz
79
+
80
+ on / 212 - 1232 / 976 on / 212 - 3552 / 2784 on / 212 - 4192 / 3168
81
+ on / 192 - 1264 / 1008 on / 192 - 3616 / 2880 on / 192 - 4384 / 3360
82
+ off / 212 - 1584 / 1312 off / 212 - 4384 / 3616 off / 212 - 5856 / 4832
83
+ off / 192 - 1584 / 1312 off / 192 - 4384 / 3684 off / 192 - 5856 / 4864
84
+ --Blank-- - 1600 / 1344 --Blank-- - 4512 / 3776 --Blank-- - 6112 / 5120
85
+ ```
86
+
87
+ When we analyze these tables a bit, several conclusions can be drawn:
88
+ - First of all, a highspeed copy (HMMM) is a little more than 2.8, meaning almost 3 times as fast as a lowspeed copy! An YMMM copy is even faster, it’s 3.4 times as fast.
89
+ - Secondly, did you notice that disabling the sprites during a copy-command matters a huge lot? Say disabling the screen gives a speedup of 100%. Compared to that, disabling the sprites gives you a speedup 87%!!! So, by simply disabling the sprites you can already gain almost as much VDP-processor power as by disabling the entire screen!!!
90
+ - From the previous you MIGHT conclude that the sprites use up 87% of the display process and that the building of the screen itself only uses 13% of the time. I don’t know if that’s a 100% correct though.
91
+ - In case of a copy it matters very little whether you’ve got the screen set to either 212 or 192 lines. With the sprites enabled, the difference it a bit more, 64 bytes in case of a HMMV, which is a half line in screen 5.
92
+
93
+ ## The tables for the fills
94
+
95
+ ```
96
+ LMMV accuracy: 16 HMMV accuracy: 64
97
+
98
+ Spr / Lin - Speed 50/60Hz Spr / Lin - Speed 50/60Hz
99
+
100
+ on / 212 - 1696 / 1344 on / 212 - 7040 / 5632
101
+ on / 192 - 1728 / 1392 on / 192 - 7168 / 5760
102
+ off / 212 - 1840 / 1488 off / 212 - 7232 / 5888
103
+ off / 192 - 1856 / 1504 off / 192 - 7360 / 5952
104
+ --Blank-- - 2128 / 1776 --Blank-- - 8448 / 7040
105
+ ```
106
+
107
+ Some conclusions we can draw by analyzing the fill-command tables a little:
108
+ - First of all we’ll ofcourse compare the speed divisions here aswell, and what do we see? A highspeed fill is FOUR TIMES AS FAST as a lowspeed fill!!! (w00t ;p) Also, a highspeed fill is twice as fast as a highspeed copy, so ‘copying’ blank (single-colored) areas with a fill instead of a copy is definately worth the effort.
109
+ - In case of HMMV the maximum byterate at 60 Hz is equal to the minimum at 50 Hz. Once more you can see there’s a huge difference in byterate if you want to keep synchronized with the interrupts. This is also the reason why the Japanese Takeru-release of Unknow Reality by NOP was called off - it didn’t work on 60 Hz. So if possible, program for the worst case, being 60Hz.
110
+ - Here, switching the screen height from 212 to 192 lines definately does matter - relatively spoken. This in contrary to the copy’s case. If you state that disabling the sprites results in a speedup of 100%, disabling the bottom 20 lines only already gives you a gain percentage of 66% in comparison! The fun part about this (well, ofcourse as far as you consider this fun ;)) is that you can ‘add’ those tweaks, so that you get an even higher speed (say, 166% compared to disabling the sprites only). Anyways, from this we can conclude that in case of the LMMV and HMMV commands - in contrary to both copy’s - the screen buildup slows down the command more than the sprites do.
111
+ - However, actually the gain in speed isn’t that much, speed increases on the copy front were much more dramatic. Compared to the total amount of bytes the largest speedup you can get with HMMV while still displaying the screen is with 320 bytes, while the total amount of bytes is then 7040; percentage-wise, it’s only a 4,5% speed increase. Although this will barely give you those two additional lines in screen 5 you might just need, it’s hardly worth the trouble - and the disadvantages.
112
+ - Another thing, screen 5 has 54272 pixels, which is 27136 bytes, and the fastest operation is HMMV during 50 Hz blank with its 8448 bytes/interrupt, so even with the fastest command possible (clearing the screen) it still takes 3.2 interrupts (64 ms) to process the entire screen.
113
+
114
+ ## Applications of the tables
115
+
116
+ Now that we’re finished, what can you use the value Speed for? Well, I’ll give a few examples. Say, you want to know the maximum height of a horizontal scrolltext at 60 Hz by means of a copy, with sprites disabled. In that case, look at the speed of a highspeed copy, which is 3616 bytes per interrupt. The screen is 256 pixels wide, which translates to 128 bytes per line. Well then, a little division shows us that 3616/128 = 28.25, so in screen 5 a scroll’s height will be max. 28 pixels.
117
+
118
+ Please note though that these are very strict calculations. In order for this to happen, you will need to issue a new copy right at line 212, *before* the interrupt handler starts, since the handler will take up prescious time. Also, you need to start the new copy at line 212 (or right after whatever line the bottom of your copy is located at in case it’s not at the bottom of the screen), because if you don’t the screen buildup will catch up with the copy before it’s finished and you’ll notice a relocation to the left halfway your scroll. Also, the overhead of DoCopy’s polling and issueing of the next command needs to be very small. See my DoCopy source example for the as far as I know fastest way of doing that.
119
+
120
+ ## Some additional notes
121
+
122
+ There are a few other things which weren’t in the original article but which I would like to mention. First of all, I haven’t verified this yet, but I would advise you to execute VDP commands as much as possible during the VBLANK period (right after the interrupt, which should be kept as short as possible or be executed at a later time by using a line interrupt). They should execute a little faster then.
123
+
124
+ Secondly, until now I always assumed a framerate of 50 or 60 fps. However, what about using a lower framerate? It doesn’t look all that bad, and nowadays it’s even quite common in games on for example the PSX or the PC to have a framerate of about 30 fps. So it might just be a good idea to half your framerate to 25 or 30 fps, which might perhaps look a little less smooth (though your eye’s sampling frequency is only 24 fps, and that’s also what every movie runs at), but in exchange for that you might just be able to pull out some extra dazzling effects, or super-large sprites. However, you will need to flip pages in order to do that, because otherwise the screen display will catch up with your copy’s, and your screen buildup will show. There is a way to circumvent the usage of an additional page though, under the conditions that a. your framerate doesn’t get any lower than half the interrupt frequency, and b. your screen is being built up from the top to the bottom. If those are the case, then the tip is: as soon as the VDP starts out displaying at line 0, you start out doing your copy’s. The VDP won’t catch up with you then until after 2 interrupts. Mind you though, that this way you actually only get Display Cycle 1 + VBLANK period 1 + Display Cycle 2, which is not two full display cycles. Also, if my previous statement (about the VBLANK period being the fastest) is true, the gained speed might be not as much as expected. Page flipping will always be easier, and leave you more time for the copies.
125
+
126
+ I might put some more research into this and get more measurements about the latter two unknowns, being whether VBLANK is faster and how much can be done in the timeframe of the trick I just described.
127
+
128
+ ## The tests
129
+
130
+ Now all that’s left is a small remark on how the tests were done. This is the procedure I basically used:
131
+ 1. Disable the interrupts first<br>(we don’t want nasty interrupt-handlers to mess up our measurements).
132
+ 2. Wait for the VBLANK period to start (by means of polling).
133
+ 3. Issue the command.
134
+ 4. Wait for the next VBLANK period to start.
135
+ 5. Check if the command was executed within the timeframe of 1 interrupt<br>(by checking whether the VDP is ready for the next command already).
136
+ 6. If not, decrease the command’s size and repeat from step 2.
137
+ 7. If so, the vdp’s speed is found, the end.
138
+
139
+ I gradually increased the command’s size by changing the height of the copy/fill, and the accuracy was determined by its width. You can try it for yourself with the test tool linked to at the top of this article.
140
+
141
+ Well, that’s it.
142
+
143
+ ~Grauw
144
+
145
+ ## Source
146
+
147
+ https://map.grauw.nl/articles/vdp_commands_speed.php
@@ -0,0 +1,55 @@
1
+ # VDP programming guide
2
+
3
+ This article aims to document most VDP programming loopholes you may encounter. Below is a list of tips and answers to questions, which may be useful either before programming a certain VDP-related routine, or afterwards to hunt down bugs (should've read it beforehand after all, eh ;)). The screensplit related tips are located in a separate article. If you have any suggestions, please submit them to us!
4
+
5
+ ## r#18 in combination with VDP commands corrupts VRAM?
6
+
7
+ Yes. If you use the screen position adjust register while executing a copy command, it will corrupt the byte the VDP command is currently processing. This occurs regardless of whether you have the sprites or screen enabled. So, if that is the case, you should wait with setting r#18 until the VDP's CE bit indicates the current command is finished.
8
+
9
+ See [this test program](https://map.grauw.nl/downloads/articles/vdpreg18test.zip).
10
+
11
+ ## What about screensplits with the help of r#18?
12
+
13
+ Once again, this register behaves a bit strangely. During the display cycle, if you move the screen horizontally using r#18, the entire current line can be blanked. This only happens when the sprites are disabled. So if you're creating a screensplit with r#18, watch out for this.
14
+
15
+ See [this test program](https://map.grauw.nl/downloads/articles/vdpreg18test.zip).
16
+
17
+ ## VDP does lots of random strange things, how come?
18
+
19
+ Do you DI during the register OUTs? Is there a poll loop during which the ints are continuously disabled, hence messing up your screensplits? It has probably something to do with the interrupts.
20
+
21
+ ## Where did screen 9 go?
22
+
23
+ On this topic, ASCII's official MSX Magazine says: SCREEN9は、韓国のMSX2にのみ搭載されたハングル表示専用モードで、国内のMSXと同様にMSXPLAYerでは搭載していません。
24
+
25
+ It translates to: "SCREEN9 is a dedicated mode for displaying Hangul (Korean characters), which was only available on the Korean MSX2, and is not available on the MSXPLAYer as well as the domestic (Japanese) MSX." Under the hood this Hangul mode actually uses the SCREEN 6 bitmap mode, similar to the Japanese Kanji modes. The MSX2+ screen mode numbering continued with SCREEN 10-12.
26
+
27
+ ## Where did r#24 go?
28
+
29
+ It is unknown. Maybe Yamaha had a V9948 prototype in development which used this register, so they kept it reserved, and the V9958 continued with registers 25-27. But no evidence of the existence of this chip has been found other than a rather obvious blank in the Yamaha's numbering of the chip name (V9938 vs V9958) and the ID in status register s#1 (0 vs 2).
30
+
31
+ ## What is there to say about screen 8's colours?
32
+
33
+ Screen 8's colours are composed of Red and Green, with ranges of 0-7, and Blue, with a range of 0-3. Red and Green's colours are divided over a gliding scale. So, if you were to map these 3-bit colours to 8-bit colour information, you would get steps of (255/7), or in other words: 0, 36, 73, 109, 146, 182, 219, 255. In Assembly, this can by the way easiest be calculated by shifting and OR-ing bits 0-2 as follows: xxxxx210 --> 21021021 (although a table may be faster :)). Anyways, the real subject of this Q&A is the colour Blue. This one does NOT operate on a gliding scale from 0-3 (so no 255/3 stuff), but, just like the other two colours, also from 0-7. It then maps its four colours as follows to that range: 0->0, 1->2, 2->4, 3->7. There is a small test program below for you to experiment with, if you want. Anyways, because of this, gray colours can be really gray and not blue-ish or yellow-ish teints.
34
+
35
+ Another issue is that although the voltages the VDP outputs increase linearly, the actual intensity of the colours displayed has an exponential curve (thanks to Maarten ter Huurne, btw). To cope for this, you have to apply gamma correction to the colours. A television or an MSX monitor generally has a gamma of 2.5, while on a PC the usual colourspace is sRGB nowadays, with a gamma of 2.2. So, in order to get the correct colors displayed on your PC, you'll have to apply a gamma correction of 2.2 / 2.5 = 0.88 to the palette. Paint Shop Pro can do this fairly easily.
36
+
37
+ Many who designed or converted graphics on the PC have probably not considered these two 'complications', and instead used a gliding blue scale and no gamma correction, which would yield somewhat inaccurate results. I have however put a [proper palette](https://map.grauw.nl/articles/downloads/articles/sc8_palette_srgb.zip) online for your convenience. It used to be a 'wrong' one too, so if you downloaded it before, do it again.
38
+
39
+ ```basic
40
+ 10 SCREEN 8:SETPAGE 1,1:LINE (0,0)-(255,211),&B11111111,BF
41
+ 20 SCREEN 1:KEY OFF:COLOR 15,4,0:COLOR=(4,5,5,5) 'change to (4,4,4,4), etc
42
+ 30 VDP(0)=0:VDP(2)=6
43
+ 40 IF INKEY$="" GOTO 40
44
+ 50 VDP(0)=14:VDP(2)=63
45
+ 60 IF INKEY$="" GOTO 60
46
+ 70 GOTO 30
47
+ ```
48
+
49
+ As you can see, this article is still being worked on. If you have any ideas for good Q&A's, please let us know and we will add them.
50
+
51
+ ~Grauw
52
+
53
+ ## Source
54
+
55
+ https://map.grauw.nl/articles/vdp_guide.php