@typecad/cuttlefish 0.1.0-alpha.1

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 (377) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +79 -0
  3. package/dist/api/board-types.d.ts +1 -0
  4. package/dist/api/board-types.js +4 -0
  5. package/dist/api/capabilities.d.ts +12 -0
  6. package/dist/api/capabilities.js +1 -0
  7. package/dist/api/config.d.ts +120 -0
  8. package/dist/api/config.js +7 -0
  9. package/dist/api/index.d.ts +5 -0
  10. package/dist/api/index.js +2 -0
  11. package/dist/api/schema/builder.d.ts +14 -0
  12. package/dist/api/schema/builder.js +15 -0
  13. package/dist/api/schema/index.d.ts +2 -0
  14. package/dist/api/schema/index.js +1 -0
  15. package/dist/api/schema/types.d.ts +257 -0
  16. package/dist/api/schema/types.js +4 -0
  17. package/dist/api/shared/async-runtime-static.d.ts +8 -0
  18. package/dist/api/shared/async-runtime-static.js +201 -0
  19. package/dist/api/shared/async-types.d.ts +42 -0
  20. package/dist/api/shared/async-types.js +8 -0
  21. package/dist/api/shared/board-resolver.d.ts +12 -0
  22. package/dist/api/shared/board-resolver.js +7 -0
  23. package/dist/api/shared/cpp-type-ir.d.ts +229 -0
  24. package/dist/api/shared/cpp-type-ir.js +672 -0
  25. package/dist/api/shared/display-adapter.d.ts +12 -0
  26. package/dist/api/shared/display-adapter.js +145 -0
  27. package/dist/api/shared/display-adapters/eink-mono.d.ts +2 -0
  28. package/dist/api/shared/display-adapters/eink-mono.js +53 -0
  29. package/dist/api/shared/display-adapters/sdl.d.ts +2 -0
  30. package/dist/api/shared/display-adapters/sdl.js +452 -0
  31. package/dist/api/shared/display-adapters/ssd1309.d.ts +2 -0
  32. package/dist/api/shared/display-adapters/ssd1309.js +136 -0
  33. package/dist/api/shared/display-adapters/st7796.d.ts +2 -0
  34. package/dist/api/shared/display-adapters/st7796.js +132 -0
  35. package/dist/api/shared/display-capabilities.d.ts +45 -0
  36. package/dist/api/shared/display-capabilities.js +54 -0
  37. package/dist/api/shared/display-op-ir.d.ts +62 -0
  38. package/dist/api/shared/display-op-ir.js +19 -0
  39. package/dist/api/shared/display-profile.d.ts +265 -0
  40. package/dist/api/shared/display-profile.js +338 -0
  41. package/dist/api/shared/graphics-strategy.d.ts +29 -0
  42. package/dist/api/shared/graphics-strategy.js +11 -0
  43. package/dist/api/shared/hal-op-ir.d.ts +393 -0
  44. package/dist/api/shared/hal-op-ir.js +18 -0
  45. package/dist/api/shared/index.d.ts +26 -0
  46. package/dist/api/shared/index.js +21 -0
  47. package/dist/api/shared/ir-core.d.ts +363 -0
  48. package/dist/api/shared/ir-core.js +8 -0
  49. package/dist/api/shared/ir-declarations.d.ts +201 -0
  50. package/dist/api/shared/ir-declarations.js +26 -0
  51. package/dist/api/shared/ir.d.ts +85 -0
  52. package/dist/api/shared/ir.js +13 -0
  53. package/dist/api/shared/platform-strategy.d.ts +402 -0
  54. package/dist/api/shared/platform-strategy.js +14 -0
  55. package/dist/api/shared/polyfill-helper-registry.d.ts +11 -0
  56. package/dist/api/shared/polyfill-helper-registry.js +86 -0
  57. package/dist/api/shared/polyfill-types.d.ts +33 -0
  58. package/dist/api/shared/polyfill-types.js +76 -0
  59. package/dist/api/shared/promise-runtime.d.ts +10 -0
  60. package/dist/api/shared/promise-runtime.js +244 -0
  61. package/dist/api/shared/snprintf-types.d.ts +29 -0
  62. package/dist/api/shared/snprintf-types.js +8 -0
  63. package/dist/api/shared/string-method-registry.d.ts +53 -0
  64. package/dist/api/shared/string-method-registry.js +168 -0
  65. package/dist/api/shared/toolchain-types.d.ts +63 -0
  66. package/dist/api/shared/toolchain-types.js +71 -0
  67. package/dist/api/shared/types.d.ts +50 -0
  68. package/dist/api/shared/types.js +6 -0
  69. package/dist/ast/parse.d.ts +2 -0
  70. package/dist/ast/parse.js +4 -0
  71. package/dist/cache.d.ts +26 -0
  72. package/dist/cache.js +95 -0
  73. package/dist/cli-utils.d.ts +37 -0
  74. package/dist/cli-utils.js +250 -0
  75. package/dist/cli.d.ts +2 -0
  76. package/dist/cli.js +635 -0
  77. package/dist/config-loader.d.ts +78 -0
  78. package/dist/config-loader.js +508 -0
  79. package/dist/config-schema.d.ts +233 -0
  80. package/dist/config-schema.js +83 -0
  81. package/dist/create/board-checklist.d.ts +2 -0
  82. package/dist/create/board-checklist.js +52 -0
  83. package/dist/create/board-codegen.d.ts +9 -0
  84. package/dist/create/board-codegen.js +238 -0
  85. package/dist/create/board-generators.d.ts +12 -0
  86. package/dist/create/board-generators.js +652 -0
  87. package/dist/create/board-spec.d.ts +640 -0
  88. package/dist/create/board-spec.js +215 -0
  89. package/dist/create/eslint-rules-template.d.ts +2 -0
  90. package/dist/create/eslint-rules-template.js +672 -0
  91. package/dist/create/index.d.ts +11 -0
  92. package/dist/create/index.js +8 -0
  93. package/dist/create/init-scaffold.d.ts +27 -0
  94. package/dist/create/init-scaffold.js +150 -0
  95. package/dist/create/init-templates.d.ts +24 -0
  96. package/dist/create/init-templates.js +379 -0
  97. package/dist/create/init-wizard.d.ts +8 -0
  98. package/dist/create/init-wizard.js +168 -0
  99. package/dist/debug/breakpoint-loader.d.ts +24 -0
  100. package/dist/debug/breakpoint-loader.js +137 -0
  101. package/dist/debug/index.d.ts +3 -0
  102. package/dist/debug/index.js +7 -0
  103. package/dist/debug/preprocessor.d.ts +9 -0
  104. package/dist/debug/preprocessor.js +214 -0
  105. package/dist/debug/types.d.ts +32 -0
  106. package/dist/debug/types.js +6 -0
  107. package/dist/diagnostics/diagnostics-report.d.ts +51 -0
  108. package/dist/diagnostics/diagnostics-report.js +333 -0
  109. package/dist/diagnostics/json-schema.d.ts +138 -0
  110. package/dist/diagnostics/json-schema.js +27 -0
  111. package/dist/diagnostics/md-writer.d.ts +10 -0
  112. package/dist/diagnostics/md-writer.js +336 -0
  113. package/dist/diagnostics/mermaid-builder.d.ts +65 -0
  114. package/dist/diagnostics/mermaid-builder.js +681 -0
  115. package/dist/emit/cpp-emitter.d.ts +6 -0
  116. package/dist/emit/cpp-emitter.js +48 -0
  117. package/dist/emit/emitters/class-emitter.d.ts +2 -0
  118. package/dist/emit/emitters/class-emitter.js +523 -0
  119. package/dist/emit/emitters/emitter-context.d.ts +174 -0
  120. package/dist/emit/emitters/emitter-context.js +1 -0
  121. package/dist/emit/emitters/entrypoint-synthesizer.d.ts +2 -0
  122. package/dist/emit/emitters/entrypoint-synthesizer.js +175 -0
  123. package/dist/emit/emitters/function-emitter-impl.d.ts +19 -0
  124. package/dist/emit/emitters/function-emitter-impl.js +428 -0
  125. package/dist/emit/emitters/line-appender.d.ts +15 -0
  126. package/dist/emit/emitters/line-appender.js +344 -0
  127. package/dist/emit/emitters/namespace-emitter.d.ts +2 -0
  128. package/dist/emit/emitters/namespace-emitter.js +324 -0
  129. package/dist/emit/emitters/output-finalizer.d.ts +4 -0
  130. package/dist/emit/emitters/output-finalizer.js +267 -0
  131. package/dist/emit/emitters/setup.d.ts +3 -0
  132. package/dist/emit/emitters/setup.js +851 -0
  133. package/dist/emit/emitters/top-level-prep.d.ts +2 -0
  134. package/dist/emit/emitters/top-level-prep.js +706 -0
  135. package/dist/emit/emitters/type-decl-emitter.d.ts +2 -0
  136. package/dist/emit/emitters/type-decl-emitter.js +251 -0
  137. package/dist/emit/emitters/ui-emitter.d.ts +21 -0
  138. package/dist/emit/emitters/ui-emitter.js +564 -0
  139. package/dist/emit/enum-emitter.d.ts +1 -0
  140. package/dist/emit/enum-emitter.js +1 -0
  141. package/dist/emit/expression-renderer.d.ts +283 -0
  142. package/dist/emit/expression-renderer.js +1477 -0
  143. package/dist/emit/native-helpers-emitter.d.ts +11 -0
  144. package/dist/emit/native-helpers-emitter.js +34 -0
  145. package/dist/emit/route-hal-op.d.ts +5 -0
  146. package/dist/emit/route-hal-op.js +13 -0
  147. package/dist/emit/snprintf-helpers.d.ts +17 -0
  148. package/dist/emit/snprintf-helpers.js +462 -0
  149. package/dist/emit/statement-renderer.d.ts +189 -0
  150. package/dist/emit/statement-renderer.js +948 -0
  151. package/dist/emit/utils/async-state-machine.d.ts +42 -0
  152. package/dist/emit/utils/async-state-machine.js +343 -0
  153. package/dist/emit/utils/comment-helpers.d.ts +20 -0
  154. package/dist/emit/utils/comment-helpers.js +31 -0
  155. package/dist/emit/utils/cpp-helpers.d.ts +47 -0
  156. package/dist/emit/utils/cpp-helpers.js +85 -0
  157. package/dist/emit/utils/include-resolver.d.ts +58 -0
  158. package/dist/emit/utils/include-resolver.js +155 -0
  159. package/dist/emit/utils/index.d.ts +8 -0
  160. package/dist/emit/utils/index.js +12 -0
  161. package/dist/emit/utils/type-inference.d.ts +159 -0
  162. package/dist/emit/utils/type-inference.js +559 -0
  163. package/dist/eslint-check.d.ts +10 -0
  164. package/dist/eslint-check.js +102 -0
  165. package/dist/framework-package.d.ts +10 -0
  166. package/dist/framework-package.js +58 -0
  167. package/dist/framework-registry.d.ts +39 -0
  168. package/dist/framework-registry.js +30 -0
  169. package/dist/incremental-cache.d.ts +116 -0
  170. package/dist/incremental-cache.js +335 -0
  171. package/dist/ir/adc-range-validation.d.ts +11 -0
  172. package/dist/ir/adc-range-validation.js +250 -0
  173. package/dist/ir/ast-node-utils.d.ts +8 -0
  174. package/dist/ir/ast-node-utils.js +32 -0
  175. package/dist/ir/board-pin-utils.d.ts +13 -0
  176. package/dist/ir/board-pin-utils.js +65 -0
  177. package/dist/ir/board-resolver.d.ts +36 -0
  178. package/dist/ir/board-resolver.js +437 -0
  179. package/dist/ir/build-ir-state.d.ts +167 -0
  180. package/dist/ir/build-ir-state.js +306 -0
  181. package/dist/ir/build-ir.d.ts +2 -0
  182. package/dist/ir/build-ir.js +808 -0
  183. package/dist/ir/call-graph.d.ts +35 -0
  184. package/dist/ir/call-graph.js +194 -0
  185. package/dist/ir/compile-time-only.d.ts +2 -0
  186. package/dist/ir/compile-time-only.js +16 -0
  187. package/dist/ir/declaration-builders.d.ts +9 -0
  188. package/dist/ir/declaration-builders.js +608 -0
  189. package/dist/ir/entry-points.d.ts +30 -0
  190. package/dist/ir/entry-points.js +191 -0
  191. package/dist/ir/expression-to-ir.d.ts +5 -0
  192. package/dist/ir/expression-to-ir.js +2249 -0
  193. package/dist/ir/extract-property-chain.d.ts +10 -0
  194. package/dist/ir/extract-property-chain.js +30 -0
  195. package/dist/ir/feature-prescan.d.ts +3 -0
  196. package/dist/ir/feature-prescan.js +43 -0
  197. package/dist/ir/feature-registry.d.ts +30 -0
  198. package/dist/ir/feature-registry.js +816 -0
  199. package/dist/ir/filter.d.ts +7 -0
  200. package/dist/ir/filter.js +85 -0
  201. package/dist/ir/function-builder.d.ts +19 -0
  202. package/dist/ir/function-builder.js +670 -0
  203. package/dist/ir/hal/hal-emitter.d.ts +62 -0
  204. package/dist/ir/hal/hal-emitter.js +735 -0
  205. package/dist/ir/hal/hal-parser.d.ts +61 -0
  206. package/dist/ir/hal/hal-parser.js +473 -0
  207. package/dist/ir/hal/hal-plugins.d.ts +34 -0
  208. package/dist/ir/hal/hal-plugins.js +706 -0
  209. package/dist/ir/hal-resolver.d.ts +5 -0
  210. package/dist/ir/hal-resolver.js +5 -0
  211. package/dist/ir/heap-analysis.d.ts +8 -0
  212. package/dist/ir/heap-analysis.js +350 -0
  213. package/dist/ir/heap-array-validation.d.ts +24 -0
  214. package/dist/ir/heap-array-validation.js +29 -0
  215. package/dist/ir/identifier-collector.d.ts +18 -0
  216. package/dist/ir/identifier-collector.js +439 -0
  217. package/dist/ir/interrupt-analysis.d.ts +39 -0
  218. package/dist/ir/interrupt-analysis.js +467 -0
  219. package/dist/ir/memory-budget-validation.d.ts +10 -0
  220. package/dist/ir/memory-budget-validation.js +86 -0
  221. package/dist/ir/namespace-builder.d.ts +7 -0
  222. package/dist/ir/namespace-builder.js +152 -0
  223. package/dist/ir/ownership-analysis.d.ts +9 -0
  224. package/dist/ir/ownership-analysis.js +1207 -0
  225. package/dist/ir/peripheral-ownership.d.ts +3 -0
  226. package/dist/ir/peripheral-ownership.js +152 -0
  227. package/dist/ir/peripheral-symbols.d.ts +7 -0
  228. package/dist/ir/peripheral-symbols.js +57 -0
  229. package/dist/ir/peripheral-usage.d.ts +54 -0
  230. package/dist/ir/peripheral-usage.js +691 -0
  231. package/dist/ir/peripheral-validation.d.ts +8 -0
  232. package/dist/ir/peripheral-validation.js +77 -0
  233. package/dist/ir/pin-alias-conflict.d.ts +4 -0
  234. package/dist/ir/pin-alias-conflict.js +34 -0
  235. package/dist/ir/pin-capability-validation.d.ts +6 -0
  236. package/dist/ir/pin-capability-validation.js +413 -0
  237. package/dist/ir/pin-mode-validation.d.ts +10 -0
  238. package/dist/ir/pin-mode-validation.js +301 -0
  239. package/dist/ir/pin-safety.d.ts +11 -0
  240. package/dist/ir/pin-safety.js +58 -0
  241. package/dist/ir/program-analysis.d.ts +44 -0
  242. package/dist/ir/program-analysis.js +589 -0
  243. package/dist/ir/pulldown-validation.d.ts +7 -0
  244. package/dist/ir/pulldown-validation.js +49 -0
  245. package/dist/ir/pwm-timer-sharing.d.ts +4 -0
  246. package/dist/ir/pwm-timer-sharing.js +93 -0
  247. package/dist/ir/reachability.d.ts +68 -0
  248. package/dist/ir/reachability.js +224 -0
  249. package/dist/ir/register-decorators.d.ts +6 -0
  250. package/dist/ir/register-decorators.js +49 -0
  251. package/dist/ir/render-expr.d.ts +4 -0
  252. package/dist/ir/render-expr.js +127 -0
  253. package/dist/ir/resource-analysis.d.ts +19 -0
  254. package/dist/ir/resource-analysis.js +153 -0
  255. package/dist/ir/statement-to-ir.d.ts +23 -0
  256. package/dist/ir/statement-to-ir.js +349 -0
  257. package/dist/ir/symbol-table.d.ts +68 -0
  258. package/dist/ir/symbol-table.js +179 -0
  259. package/dist/ir/symbol-types.d.ts +56 -0
  260. package/dist/ir/symbol-types.js +107 -0
  261. package/dist/ir/timer0-pwm-timing-conflict.d.ts +4 -0
  262. package/dist/ir/timer0-pwm-timing-conflict.js +71 -0
  263. package/dist/ir/timing-validation.d.ts +7 -0
  264. package/dist/ir/timing-validation.js +95 -0
  265. package/dist/ir/transformers/array-methods.d.ts +8 -0
  266. package/dist/ir/transformers/array-methods.js +493 -0
  267. package/dist/ir/transformers/call-statement.d.ts +5 -0
  268. package/dist/ir/transformers/call-statement.js +758 -0
  269. package/dist/ir/transformers/callback-context-registry.d.ts +20 -0
  270. package/dist/ir/transformers/callback-context-registry.js +55 -0
  271. package/dist/ir/transformers/canvas-lowering.d.ts +42 -0
  272. package/dist/ir/transformers/canvas-lowering.js +249 -0
  273. package/dist/ir/transformers/control-flow.d.ts +8 -0
  274. package/dist/ir/transformers/control-flow.js +508 -0
  275. package/dist/ir/transformers/expressions.d.ts +7 -0
  276. package/dist/ir/transformers/expressions.js +406 -0
  277. package/dist/ir/transformers/hal-call-resolver.d.ts +29 -0
  278. package/dist/ir/transformers/hal-call-resolver.js +274 -0
  279. package/dist/ir/transformers/hal-emit-helpers.d.ts +14 -0
  280. package/dist/ir/transformers/hal-emit-helpers.js +63 -0
  281. package/dist/ir/transformers/namespace-methods.d.ts +20 -0
  282. package/dist/ir/transformers/namespace-methods.js +110 -0
  283. package/dist/ir/transformers/register-assignment.d.ts +5 -0
  284. package/dist/ir/transformers/register-assignment.js +56 -0
  285. package/dist/ir/transformers/ui-call-resolver.d.ts +149 -0
  286. package/dist/ir/transformers/ui-call-resolver.js +1136 -0
  287. package/dist/ir/transformers/ui-callback-lowering.d.ts +62 -0
  288. package/dist/ir/transformers/ui-callback-lowering.js +623 -0
  289. package/dist/ir/transformers/ui-mount.d.ts +20 -0
  290. package/dist/ir/transformers/ui-mount.js +35 -0
  291. package/dist/ir/transformers/ui-reactive.d.ts +68 -0
  292. package/dist/ir/transformers/ui-reactive.js +129 -0
  293. package/dist/ir/transformers/variables.d.ts +14 -0
  294. package/dist/ir/transformers/variables.js +1045 -0
  295. package/dist/ir/try-catch-validation.d.ts +26 -0
  296. package/dist/ir/try-catch-validation.js +128 -0
  297. package/dist/ir/type-resolution.d.ts +31 -0
  298. package/dist/ir/type-resolution.js +977 -0
  299. package/dist/ir/ui-element-auto-wire.d.ts +50 -0
  300. package/dist/ir/ui-element-auto-wire.js +218 -0
  301. package/dist/ir/unit-suspicion-validation.d.ts +12 -0
  302. package/dist/ir/unit-suspicion-validation.js +296 -0
  303. package/dist/ir/utils/walk-ir.d.ts +6 -0
  304. package/dist/ir/utils/walk-ir.js +162 -0
  305. package/dist/ir/validation-orchestrator.d.ts +4 -0
  306. package/dist/ir/validation-orchestrator.js +45 -0
  307. package/dist/libdef/base-class-resolver.d.ts +23 -0
  308. package/dist/libdef/base-class-resolver.js +50 -0
  309. package/dist/libdef/cpp-to-decl.d.ts +34 -0
  310. package/dist/libdef/cpp-to-decl.js +584 -0
  311. package/dist/libdef/header-parser.d.ts +53 -0
  312. package/dist/libdef/header-parser.js +269 -0
  313. package/dist/libdef/registry.d.ts +10 -0
  314. package/dist/libdef/registry.js +142 -0
  315. package/dist/mapping/peripheral-names.d.ts +23 -0
  316. package/dist/mapping/peripheral-names.js +63 -0
  317. package/dist/mapping/source-map.d.ts +46 -0
  318. package/dist/mapping/source-map.js +207 -0
  319. package/dist/orchestrator/dts-generator.d.ts +17 -0
  320. package/dist/orchestrator/dts-generator.js +83 -0
  321. package/dist/orchestrator/graph-builder.d.ts +18 -0
  322. package/dist/orchestrator/graph-builder.js +218 -0
  323. package/dist/orchestrator/semantic-facts-verifier.d.ts +38 -0
  324. package/dist/orchestrator/semantic-facts-verifier.js +121 -0
  325. package/dist/orchestrator/semantic-facts.d.ts +141 -0
  326. package/dist/orchestrator/semantic-facts.js +652 -0
  327. package/dist/orchestrator/type-checker.d.ts +39 -0
  328. package/dist/orchestrator/type-checker.js +760 -0
  329. package/dist/platform/async-runtime.d.ts +8 -0
  330. package/dist/platform/async-runtime.js +26 -0
  331. package/dist/platform/generic-strategy.d.ts +101 -0
  332. package/dist/platform/generic-strategy.js +289 -0
  333. package/dist/platform/index.d.ts +4 -0
  334. package/dist/platform/index.js +9 -0
  335. package/dist/platform/registry.d.ts +21 -0
  336. package/dist/platform/registry.js +42 -0
  337. package/dist/platform/toolchain.d.ts +4 -0
  338. package/dist/platform/toolchain.js +43 -0
  339. package/dist/preview/client.d.ts +1 -0
  340. package/dist/preview/client.js +137 -0
  341. package/dist/preview/server.d.ts +5 -0
  342. package/dist/preview/server.js +199 -0
  343. package/dist/profiler/index.d.ts +28 -0
  344. package/dist/profiler/index.js +28 -0
  345. package/dist/profiler/profiler.d.ts +95 -0
  346. package/dist/profiler/profiler.js +338 -0
  347. package/dist/profiler/types.d.ts +87 -0
  348. package/dist/profiler/types.js +12 -0
  349. package/dist/stores/display-profile-store.d.ts +16 -0
  350. package/dist/stores/display-profile-store.js +48 -0
  351. package/dist/stores/theme-store.d.ts +13 -0
  352. package/dist/stores/theme-store.js +30 -0
  353. package/dist/testing.d.ts +45 -0
  354. package/dist/testing.js +47 -0
  355. package/dist/transpile/resolution.d.ts +29 -0
  356. package/dist/transpile/resolution.js +282 -0
  357. package/dist/transpile.d.ts +3 -0
  358. package/dist/transpile.js +722 -0
  359. package/dist/types.d.ts +217 -0
  360. package/dist/types.js +1 -0
  361. package/dist/ui/ui-bridge.d.ts +4 -0
  362. package/dist/ui/ui-bridge.js +34 -0
  363. package/dist/ui-hook.d.ts +84 -0
  364. package/dist/ui-hook.js +45 -0
  365. package/dist/utils/cli.d.ts +3 -0
  366. package/dist/utils/cli.js +463 -0
  367. package/dist/utils/fs.d.ts +4 -0
  368. package/dist/utils/fs.js +23 -0
  369. package/dist/utils/logger.d.ts +2 -0
  370. package/dist/utils/logger.js +8 -0
  371. package/dist/utils/strings.d.ts +35 -0
  372. package/dist/utils/strings.js +142 -0
  373. package/dist/utils/ui.d.ts +66 -0
  374. package/dist/utils/ui.js +149 -0
  375. package/dist/watch.d.ts +35 -0
  376. package/dist/watch.js +111 -0
  377. package/package.json +127 -0
@@ -0,0 +1,452 @@
1
+ // ---------------------------------------------------------------------------
2
+ // SDL2 display adapter — renders the UI to a native desktop window.
3
+ //
4
+ // Emits C++ implementing the display HAL contract (display_target*,
5
+ // display_canvas*, display_*) against SDL2. Color arrives as true RGB888
6
+ // (UI_COLOR_T == uint32_t under UI_COLOR_DEPTH 888) and is packed into an
7
+ // RGBA8888 framebuffer (0xFF000000 | color). Mirrors HostAdafruitGFX
8
+ // (preview/host-gfx.ts) — the C++ twin of that TS framebuffer renderer. The
9
+ // circle/line/round-rect algorithms are direct ports of host-gfx.ts.
10
+ //
11
+ // SDL2 is a host prerequisite (same posture as the g++/clang++ toolchain).
12
+ // On Windows/MSYS2 use the ucrt64 SDL2; on Linux/macOS install via the
13
+ // system package manager. Linked with -lSDL2.
14
+ // ---------------------------------------------------------------------------
15
+ import { escapeCppStringLiteral } from "../../../utils/strings.js";
16
+ export const sdlAdapter = (display) => {
17
+ // The SDL adapter renders to a 32-bit desktop framebuffer and is RGB888-only
18
+ // (uint32_t buf/fg/bg, drawChar args, present's 0xFF000000|color). UI_COLOR_T
19
+ // is emitted from the resolved profile's colorFormat — if a config forces
20
+ // rgb565/mono here, the emitter produces uint16_t while this adapter expects
21
+ // uint32_t (type mismatch / garbage colors). Fail loudly rather than emit
22
+ // broken code. The profile resolver defaults SDL to rgb888, so this only
23
+ // fires on explicit misconfiguration.
24
+ if (display.colorFormat !== "rgb888") {
25
+ throw new Error(`SDL display adapter requires colorFormat "rgb888" (a desktop window has a ` +
26
+ `32-bit framebuffer), but got "${display.colorFormat}". Remove the ` +
27
+ `colorFormat override from your SDL display config, or set it to "rgb888".`);
28
+ }
29
+ const w = display.width;
30
+ const h = display.height;
31
+ // Window title: default "cuttlefish", overridable via config (display.title)
32
+ // and at runtime (ui.window.setTitle → ui_window_set_title).
33
+ const title = `"${escapeCppStringLiteral(display.title ?? "cuttlefish")}"`;
34
+ // Window icon: optional BMP path from config (display.icon). Core SDL2 loads
35
+ // BMP only; .png/.ico would need SDL_image.
36
+ const icon = display.icon ? `"${escapeCppStringLiteral(display.icon)}"` : "";
37
+ return {
38
+ includes: [
39
+ `#define CuttlefishDisplayTarget SdlGfxCanvas`,
40
+ `#define CuttlefishCanvas16 SdlGfxCanvas`,
41
+ // Handle main() ourselves: SDL's default header renames main→SDL_main and
42
+ // expects an int(argc,argv) signature. The cuttlefish-generated main() is
43
+ // int main(void), so suppress the rename and call SDL_SetMainReady() in
44
+ // display_init() instead.
45
+ `#define SDL_MAIN_HANDLED`,
46
+ `#include <SDL2/SDL.h>`,
47
+ `#include <cstdint>`,
48
+ `#include <cstring>`,
49
+ ].join("\n"),
50
+ declaration: ``,
51
+ functions: [
52
+ `// --- Display adapter: SDL2 (RGB888 → RGBA8888 window) ---`,
53
+ ``,
54
+ `// Offscreen RGBA8888 framebuffer canvas. Mirrors HostAdafruitGFX`,
55
+ `// (preview/host-gfx.ts) — draw_* write 0xFF000000|color (opaque alpha).`,
56
+ `// Circle/line/round-rect math is a direct port of host-gfx.ts.`,
57
+ `class SdlGfxCanvas {`,
58
+ `public:`,
59
+ ` int16_t w_, h_;`,
60
+ ` uint32_t* buf;`,
61
+ ` int16_t cx = 0, cy = 0;`,
62
+ ` uint32_t fg = 0xFFFFFFu, bg = 0x000000u;`,
63
+ ` uint8_t textSize = 1;`,
64
+ ` bool wrap = true;`,
65
+ ` explicit SdlGfxCanvas(int16_t w, int16_t h) : w_(w), h_(h), buf(new uint32_t[(size_t)w * h]()) {}`,
66
+ ` virtual ~SdlGfxCanvas() { delete[] buf; }`,
67
+ ` int16_t width() const { return w_; }`,
68
+ ` int16_t height() const { return h_; }`,
69
+ ` inline void put(int16_t x, int16_t y, uint32_t rgba) {`,
70
+ ` if (x < 0 || y < 0 || x >= w_ || y >= h_) return;`,
71
+ ` buf[(size_t)y * w_ + x] = rgba;`,
72
+ ` }`,
73
+ ` inline uint32_t get(int16_t x, int16_t y) const {`,
74
+ ` if (x < 0 || y < 0 || x >= w_ || y >= h_) return 0;`,
75
+ ` return buf[(size_t)y * w_ + x];`,
76
+ ` }`,
77
+ ` void drawPixel(int16_t x, int16_t y, UI_COLOR_T color) { put(x, y, (uint32_t)color); }`,
78
+ ` void fillRect(int16_t x, int16_t y, int16_t rw, int16_t rh, UI_COLOR_T color) {`,
79
+ ` if (rw <= 0 || rh <= 0) return;`,
80
+ ` uint32_t rgba = (uint32_t)color;`,
81
+ ` int16_t x0 = x < 0 ? 0 : x;`,
82
+ ` int16_t y0 = y < 0 ? 0 : y;`,
83
+ ` int16_t x1 = x + rw; if (x1 > w_) x1 = w_;`,
84
+ ` int16_t y1 = y + rh; if (y1 > h_) y1 = h_;`,
85
+ ` if (x0 >= x1 || y0 >= y1) return;`,
86
+ ` for (int16_t j = y0; j < y1; j++)`,
87
+ ` for (int16_t i = x0; i < x1; i++) buf[(size_t)j * w_ + i] = rgba;`,
88
+ ` }`,
89
+ ` void fillScreen(UI_COLOR_T color) {`,
90
+ ` uint32_t rgba = (uint32_t)color;`,
91
+ ` for (size_t i = 0; i < (size_t)w_ * h_; i++) buf[i] = rgba;`,
92
+ ` }`,
93
+ ` void drawFastHLine(int16_t x, int16_t y, int16_t len, UI_COLOR_T c) { fillRect(x, y, len, 1, c); }`,
94
+ ` void drawFastVLine(int16_t x, int16_t y, int16_t len, UI_COLOR_T c) { fillRect(x, y, 1, len, c); }`,
95
+ ` void drawRect(int16_t x, int16_t y, int16_t rw, int16_t rh, UI_COLOR_T c) {`,
96
+ ` if (rw <= 0 || rh <= 0) return;`,
97
+ ` drawFastHLine(x, y, rw, c);`,
98
+ ` drawFastHLine(x, y + rh - 1, rw, c);`,
99
+ ` drawFastVLine(x, y, rh, c);`,
100
+ ` drawFastVLine(x + rw - 1, y, rh, c);`,
101
+ ` }`,
102
+ ` void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, UI_COLOR_T c) {`,
103
+ ` bool steep = (y1 - y0 < 0 ? -(y1 - y0) : (y1 - y0)) > (x1 - x0 < 0 ? -(x1 - x0) : (x1 - x0));`,
104
+ ` if (steep) { int16_t t; t = x0; x0 = y0; y0 = t; t = x1; x1 = y1; y1 = t; }`,
105
+ ` if (x0 > x1) { int16_t t; t = x0; x0 = x1; x1 = t; t = y0; y0 = y1; y1 = t; }`,
106
+ ` int16_t dx = x1 - x0;`,
107
+ ` int16_t dy = (y1 - y0 < 0) ? -(y1 - y0) : (y1 - y0);`,
108
+ ` int16_t err = dx / 2;`,
109
+ ` int16_t ystep = (y0 < y1) ? 1 : -1;`,
110
+ ` for (; x0 <= x1; x0++) {`,
111
+ ` if (steep) put(y0, x0, (uint32_t)c); else put(x0, y0, (uint32_t)c);`,
112
+ ` err -= dy; if (err < 0) { y0 += ystep; err += dx; }`,
113
+ ` }`,
114
+ ` }`,
115
+ ` void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cn, UI_COLOR_T c) {`,
116
+ ` int16_t f = 1 - r, ddFx = 1, ddFy = -2 * r, x = 0, y = r;`,
117
+ ` while (x < y) {`,
118
+ ` if (f >= 0) { y--; ddFy += 2; f += ddFy; }`,
119
+ ` x++; ddFx += 2; f += ddFx;`,
120
+ ` if (cn & 0x4) { put(x0 + x, y0 + y, (uint32_t)c); put(x0 + y, y0 + x, (uint32_t)c); }`,
121
+ ` if (cn & 0x2) { put(x0 + x, y0 - y, (uint32_t)c); put(x0 + y, y0 - x, (uint32_t)c); }`,
122
+ ` if (cn & 0x8) { put(x0 - y, y0 + x, (uint32_t)c); put(x0 - x, y0 + y, (uint32_t)c); }`,
123
+ ` if (cn & 0x1) { put(x0 - y, y0 - x, (uint32_t)c); put(x0 - x, y0 - y, (uint32_t)c); }`,
124
+ ` }`,
125
+ ` }`,
126
+ ` void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t corners, int16_t delta, UI_COLOR_T c) {`,
127
+ ` int16_t f = 1 - r, ddFx = 1, ddFy = -2 * r, x = 0, y = r, px = x, py = y;`,
128
+ ` delta++;`,
129
+ ` while (x < y) {`,
130
+ ` if (f >= 0) { y--; ddFy += 2; f += ddFy; }`,
131
+ ` x++; ddFx += 2; f += ddFx;`,
132
+ ` if (x < y + 1) {`,
133
+ ` if (corners & 1) drawFastVLine(x0 + x, y0 - y, 2 * y + delta, c);`,
134
+ ` if (corners & 2) drawFastVLine(x0 - x, y0 - y, 2 * y + delta, c);`,
135
+ ` }`,
136
+ ` if (y != py) {`,
137
+ ` if (corners & 1) drawFastVLine(x0 + py, y0 - px, 2 * px + delta, c);`,
138
+ ` if (corners & 2) drawFastVLine(x0 - py, y0 - px, 2 * px + delta, c);`,
139
+ ` py = y;`,
140
+ ` }`,
141
+ ` px = x;`,
142
+ ` }`,
143
+ ` }`,
144
+ ` void drawCircle(int16_t x0, int16_t y0, int16_t r, UI_COLOR_T c) {`,
145
+ ` int16_t f = 1 - r, ddFx = 1, ddFy = -2 * r, x = 0, y = r;`,
146
+ ` put(x0, y0 + r, (uint32_t)c); put(x0, y0 - r, (uint32_t)c);`,
147
+ ` put(x0 + r, y0, (uint32_t)c); put(x0 - r, y0, (uint32_t)c);`,
148
+ ` while (x < y) {`,
149
+ ` if (f >= 0) { y--; ddFy += 2; f += ddFy; }`,
150
+ ` x++; ddFx += 2; f += ddFx;`,
151
+ ` put(x0 + x, y0 + y, (uint32_t)c); put(x0 - x, y0 + y, (uint32_t)c);`,
152
+ ` put(x0 + x, y0 - y, (uint32_t)c); put(x0 - x, y0 - y, (uint32_t)c);`,
153
+ ` put(x0 + y, y0 + x, (uint32_t)c); put(x0 - y, y0 + x, (uint32_t)c);`,
154
+ ` put(x0 + y, y0 - x, (uint32_t)c); put(x0 - y, y0 - x, (uint32_t)c);`,
155
+ ` }`,
156
+ ` }`,
157
+ ` void fillCircle(int16_t x0, int16_t y0, int16_t r, UI_COLOR_T c) {`,
158
+ ` drawFastVLine(x0, y0 - r, 2 * r + 1, c);`,
159
+ ` fillCircleHelper(x0, y0, r, 3, 0, c);`,
160
+ ` }`,
161
+ ` void drawRoundRect(int16_t x, int16_t y, int16_t rw, int16_t rh, int16_t r, UI_COLOR_T c) {`,
162
+ ` if (rw <= 0 || rh <= 0) return;`,
163
+ ` if (r <= 0) { drawRect(x, y, rw, rh, c); return; }`,
164
+ ` int16_t mr = rw < rh ? rw : rh; mr /= 2; if (r > mr) r = mr;`,
165
+ ` drawFastHLine(x + r, y, rw - 2 * r, c);`,
166
+ ` drawFastHLine(x + r, y + rh - 1, rw - 2 * r, c);`,
167
+ ` drawFastVLine(x, y + r, rh - 2 * r, c);`,
168
+ ` drawFastVLine(x + rw - 1, y + r, rh - 2 * r, c);`,
169
+ ` drawCircleHelper(x + r, y + r, r, 1, c);`,
170
+ ` drawCircleHelper(x + rw - r - 1, y + r, r, 2, c);`,
171
+ ` drawCircleHelper(x + rw - r - 1, y + rh - r - 1, r, 4, c);`,
172
+ ` drawCircleHelper(x + r, y + rh - r - 1, r, 8, c);`,
173
+ ` }`,
174
+ ` void fillRoundRect(int16_t x, int16_t y, int16_t rw, int16_t rh, int16_t r, UI_COLOR_T c) {`,
175
+ ` if (rw <= 0 || rh <= 0) return;`,
176
+ ` if (r <= 0) { fillRect(x, y, rw, rh, c); return; }`,
177
+ ` int16_t mr = rw < rh ? rw : rh; mr /= 2; if (r > mr) r = mr;`,
178
+ ` fillRect(x + r, y, rw - 2 * r, rh, c);`,
179
+ ` int16_t delta = rh - 2 * r - 1; if (delta < 0) delta = 0;`,
180
+ ` fillCircleHelper(x + rw - r - 1, y + r, r, 1, delta, c);`,
181
+ ` fillCircleHelper(x + r, y + r, r, 2, delta, c);`,
182
+ ` }`,
183
+ ` void drawRGBBitmap(int16_t x, int16_t y, const UI_COLOR_T* b, int16_t bw, int16_t bh) {`,
184
+ ` for (int16_t j = 0; j < bh; j++)`,
185
+ ` for (int16_t i = 0; i < bw; i++) {`,
186
+ ` put(x + i, y + j, (uint32_t)b[(size_t)j * bw + i]);`,
187
+ ` }`,
188
+ ` }`,
189
+ ` void setCursor(int16_t x, int16_t y) { cx = x; cy = y; }`,
190
+ ` void setTextColor(UI_COLOR_T c) { fg = (uint32_t)c; bg = fg; }`,
191
+ ` void setTextColorBg(UI_COLOR_T c, UI_COLOR_T b) { fg = (uint32_t)c; bg = (uint32_t)b; }`,
192
+ ` void setTextSize(uint8_t s) { textSize = s; }`,
193
+ ` void setTextWrap(bool wp) { wrap = wp; }`,
194
+ ` // print() uses the 5x8 glcd font (same bytes as Adafruit_GFX / the`,
195
+ ` // preview's HostAdafruitGFX). __sdl_glcdfont is defined below.`,
196
+ ` void drawChar(int16_t x, int16_t y, unsigned char ch, uint32_t fgc, uint32_t bgc, uint8_t size);`,
197
+ ` void print(const char* s);`,
198
+ `};`,
199
+ ``,
200
+ `// 5x8 bitmap font. Public-domain Adafruit glcdfont.c bytes — identical`,
201
+ `// to what HostAdafruitGFX (preview/host-gfx.ts) uses.`,
202
+ `// Each glyph is 5 columns of 8 vertical bits (bit 0 = top row).`,
203
+ `static const uint8_t __sdl_glcdfont[1280] = {`,
204
+ ...glcdfontBytes(),
205
+ `};`,
206
+ ``,
207
+ `void SdlGfxCanvas::drawChar(int16_t x, int16_t y, unsigned char ch, uint32_t fgc, uint32_t bgc, uint8_t size) {`,
208
+ ` if (ch >= 176 && ch < 255) ch++;`,
209
+ ` const uint8_t* glyph = &__sdl_glcdfont[(size_t)ch * 5];`,
210
+ ` for (int8_t i = 0; i < 5; i++) {`,
211
+ ` uint8_t line = glyph[i];`,
212
+ ` for (int8_t j = 0; j < 8; j++, line >>= 1) {`,
213
+ ` if (line & 1) {`,
214
+ ` if (size == 1) put(x + i, y + j, fgc);`,
215
+ ` else fillRect(x + i * size, y + j * size, size, size, fgc);`,
216
+ ` } else if (bgc != fgc) {`,
217
+ ` if (size == 1) put(x + i, y + j, bgc);`,
218
+ ` else fillRect(x + i * size, y + j * size, size, size, bgc);`,
219
+ ` }`,
220
+ ` }`,
221
+ ` }`,
222
+ ` if (bgc != fgc) {`,
223
+ ` if (size == 1) fillRect(x + 5, y, 1, 8, bgc);`,
224
+ ` else fillRect(x + 5 * size, y, size, 8 * size, bgc);`,
225
+ ` }`,
226
+ `}`,
227
+ `void SdlGfxCanvas::print(const char* s) {`,
228
+ ` while (*s) {`,
229
+ ` if (*s == '\\n') { cx = 0; cy += 8 * textSize; s++; continue; }`,
230
+ ` if (*s == '\\r') { s++; continue; }`,
231
+ ` if (wrap && cx + 6 * textSize > w_) { cx = 0; cy += 8 * textSize; }`,
232
+ ` drawChar(cx, cy, (unsigned char)*s, fg, bg, textSize);`,
233
+ ` cx += 6 * textSize;`,
234
+ ` s++;`,
235
+ ` }`,
236
+ `}`,
237
+ ``,
238
+ `class SdlGfxTarget : public SdlGfxCanvas {`,
239
+ `public:`,
240
+ ` SDL_Window* win = nullptr;`,
241
+ ` SDL_Renderer* ren = nullptr;`,
242
+ ` SDL_Texture* tex = nullptr;`,
243
+ ` explicit SdlGfxTarget(int16_t w, int16_t h) : SdlGfxCanvas(w, h) {}`,
244
+ ` void present() {`,
245
+ ` if (!tex) return;`,
246
+ ` // The framebuffer stores raw RGB888 (no alpha). The texture is`,
247
+ ` // ARGB8888, so set opaque alpha (0xFF) per pixel at present time.`,
248
+ ` static uint32_t* _presentBuf = nullptr;`,
249
+ ` static size_t _presentBufLen = 0;`,
250
+ ` size_t n = (size_t)w_ * h_;`,
251
+ ` if (!_presentBuf || _presentBufLen < n) { delete[] _presentBuf; _presentBuf = new uint32_t[n]; _presentBufLen = n; }`,
252
+ ` for (size_t i = 0; i < n; i++) _presentBuf[i] = 0xFF000000u | buf[i];`,
253
+ ` SDL_UpdateTexture(tex, nullptr, _presentBuf, w_ * (int)sizeof(uint32_t));`,
254
+ ` SDL_RenderClear(ren);`,
255
+ ` SDL_RenderCopy(ren, tex, nullptr, nullptr);`,
256
+ ` SDL_RenderPresent(ren);`,
257
+ ` }`,
258
+ `};`,
259
+ ``,
260
+ `// Global display instance (declared after the class definitions above).`,
261
+ `SdlGfxTarget __tc_display(${w}, ${h});`,
262
+ ``,
263
+ `static inline void display_init() {`,
264
+ ` SDL_SetMainReady();`,
265
+ ` SDL_Init(SDL_INIT_VIDEO);`,
266
+ // FULLSCREEN_DESKTOP scales the fixed w_×h_ framebuffer to fill the
267
+ // monitor without changing the display mode (vs SDL_WINDOW_FULLSCREEN,
268
+ // which requires a matching mode and can fail). Mouse coords from
269
+ // SDL_GetMouseState stay in window/logical space, so the touch clamp
270
+ // (display_width()/height()) still maps clicks correctly.
271
+ ...(display.fullscreen
272
+ ? [` __tc_display.win = SDL_CreateWindow(${title},`,
273
+ ` SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,`,
274
+ ` __tc_display.w_, __tc_display.h_, SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN_DESKTOP);`]
275
+ : [` __tc_display.win = SDL_CreateWindow(${title},`,
276
+ ` SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,`,
277
+ ` __tc_display.w_, __tc_display.h_, SDL_WINDOW_SHOWN);`]),
278
+ ...(icon
279
+ ? [` { SDL_Surface* __icon = SDL_LoadBMP(${icon});`,
280
+ ` if (__icon) { SDL_SetWindowIcon(__tc_display.win, __icon); SDL_FreeSurface(__icon); } }`]
281
+ : []),
282
+ ` __tc_display.ren = SDL_CreateRenderer(__tc_display.win, -1,`,
283
+ ` SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);`,
284
+ ` __tc_display.tex = SDL_CreateTexture(__tc_display.ren,`,
285
+ ` SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING,`,
286
+ ` __tc_display.w_, __tc_display.h_);`,
287
+ ` __tc_display.fillScreen(0);`,
288
+ `}`,
289
+ // Runtime window-title setter (lowered from ui.window.setTitle). SDL-only;
290
+ // the transpiler emits no call on hardware targets.
291
+ `static inline void ui_window_set_title(const char* title) {`,
292
+ ` if (__tc_display.win && title) SDL_SetWindowTitle(__tc_display.win, title);`,
293
+ `}`,
294
+ `static inline void display_fillScreen(UI_COLOR_T color) { __tc_display.fillScreen(color); }`,
295
+ `static inline CuttlefishDisplayTarget* display_defaultTarget() { return &__tc_display; }`,
296
+ `static inline int16_t display_width() { return __tc_display.width(); }`,
297
+ `static inline int16_t display_height() { return __tc_display.height(); }`,
298
+ `static int16_t __sdl_addr_x = 0;`,
299
+ `static int16_t __sdl_addr_y = 0;`,
300
+ `static int16_t __sdl_addr_w = 0;`,
301
+ `static int16_t __sdl_addr_h = 0;`,
302
+ `static uint32_t __sdl_write_pos = 0;`,
303
+ // Event-driven mouse state: the host event loop (NativeStrategy.
304
+ // hostEventLoop) writes these from SDL_MOUSEBUTTONDOWN/MOTION/BUTTONUP,
305
+ // and the SDL touch shim (touch_isTouched/touch_readRaw in display-
306
+ // profile.ts) reads them instead of polling SDL_GetMouseState every
307
+ // frame. Declared here so both layers see one definition.
308
+ `static uint8_t __sdl_mouse_down = 0;`,
309
+ `static int16_t __sdl_mouse_x = 0;`,
310
+ `static int16_t __sdl_mouse_y = 0;`,
311
+ `static inline void display_startWrite() {}`,
312
+ `static inline void display_endWrite() {}`,
313
+ `static inline void display_setAddrWindow(int16_t x, int16_t y, int16_t w, int16_t h) {`,
314
+ ` __sdl_addr_x = x; __sdl_addr_y = y; __sdl_addr_w = w; __sdl_addr_h = h;`,
315
+ ` __sdl_write_pos = 0;`,
316
+ `}`,
317
+ `static inline void display_writePixels(uint32_t* pixels, uint32_t count) {`,
318
+ ` if (!pixels || __sdl_addr_w <= 0 || __sdl_addr_h <= 0) return;`,
319
+ ` uint32_t max = (uint32_t)__sdl_addr_w * (uint32_t)__sdl_addr_h;`,
320
+ ` for (uint32_t i = 0; i < count && __sdl_write_pos < max; i++, __sdl_write_pos++) {`,
321
+ ` int16_t dx = (int16_t)(__sdl_addr_x + (__sdl_write_pos % (uint32_t)__sdl_addr_w));`,
322
+ ` int16_t dy = (int16_t)(__sdl_addr_y + (__sdl_write_pos / (uint32_t)__sdl_addr_w));`,
323
+ ` __tc_display.put(dx, dy, pixels[i]);`,
324
+ ` }`,
325
+ `}`,
326
+ `static inline CuttlefishCanvas16* display_createCanvas(int16_t w, int16_t h) { return new SdlGfxCanvas(w, h); }`,
327
+ `static inline CuttlefishCanvas16* display_createCanvasPsram(int16_t, int16_t) { return nullptr; }`,
328
+ `static inline void display_deleteCanvas(CuttlefishCanvas16* c) { delete c; }`,
329
+ `static inline int16_t display_canvasWidth(CuttlefishCanvas16* c) { return c->width(); }`,
330
+ `static inline int16_t display_canvasHeight(CuttlefishCanvas16* c) { return c->height(); }`,
331
+ `static inline uint32_t* display_canvasBuffer(CuttlefishCanvas16* c) { return c->buf; }`,
332
+ `static inline UI_COLOR_T display_canvasGetPixel(CuttlefishCanvas16* c, int16_t x, int16_t y) { return c->get(x, y); }`,
333
+ `static inline void display_canvasFillScreen(CuttlefishCanvas16* c, UI_COLOR_T color) { c->fillScreen(color); }`,
334
+ `static inline void display_canvasFillRect(CuttlefishCanvas16* c, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) { c->fillRect(x, y, w, h, color); }`,
335
+ ``,
336
+ `static inline void display_targetDrawPixel(CuttlefishDisplayTarget* t, int16_t x, int16_t y, UI_COLOR_T color) { t->drawPixel(x, y, color); }`,
337
+ `static inline int16_t display_targetWidth(CuttlefishDisplayTarget* t) { return t->width(); }`,
338
+ `static inline int16_t display_targetHeight(CuttlefishDisplayTarget* t) { return t->height(); }`,
339
+ `static inline void display_targetDrawRGBBitmap(CuttlefishDisplayTarget* t, int16_t x, int16_t y, const UI_COLOR_T* b, int16_t w, int16_t h) { t->drawRGBBitmap(x, y, b, w, h); }`,
340
+ `static inline void display_targetFillRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) { t->fillRect(x, y, w, h, color); }`,
341
+ `static inline void display_targetDrawFastHLine(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, UI_COLOR_T color) { t->drawFastHLine(x, y, w, color); }`,
342
+ `static inline void display_targetDrawFastVLine(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t h, UI_COLOR_T color) { t->drawFastVLine(x, y, h, color); }`,
343
+ `static inline void display_targetFillRoundRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, UI_COLOR_T color) { t->fillRoundRect(x, y, w, h, r, color); }`,
344
+ `static inline void display_targetDrawRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) { t->drawRect(x, y, w, h, color); }`,
345
+ `static inline void display_targetDrawRoundRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, UI_COLOR_T color) { t->drawRoundRect(x, y, w, h, r, color); }`,
346
+ `static inline void display_targetDrawLine(CuttlefishDisplayTarget* t, int16_t x0, int16_t y0, int16_t x1, int16_t y1, UI_COLOR_T color) { t->drawLine(x0, y0, x1, y1, color); }`,
347
+ `static inline void display_targetFillCircle(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t r, UI_COLOR_T color) { t->fillCircle(x, y, r, color); }`,
348
+ `static inline void display_targetDrawCircle(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t r, UI_COLOR_T color) { t->drawCircle(x, y, r, color); }`,
349
+ `static inline void display_targetSetCursor(CuttlefishDisplayTarget* t, int16_t x, int16_t y) { t->setCursor(x, y); }`,
350
+ `static inline void display_targetSetTextColor(CuttlefishDisplayTarget* t, UI_COLOR_T fg) { t->setTextColor(fg); }`,
351
+ `static inline void display_targetSetTextColorBg(CuttlefishDisplayTarget* t, UI_COLOR_T fg, UI_COLOR_T bg) { t->setTextColorBg(fg, bg); }`,
352
+ `static inline void display_targetSetTextSize(CuttlefishDisplayTarget* t, uint8_t s) { t->setTextSize(s); }`,
353
+ `static inline void display_targetSetTextWrap(CuttlefishDisplayTarget* t, bool wp) { t->setTextWrap(wp); }`,
354
+ `static inline void display_targetPrint(CuttlefishDisplayTarget* t, const char* s) { t->print(s); }`,
355
+ `// Called by the SDL event loop after each ui_tick to push the framebuffer.`,
356
+ `static inline void display_present() { __tc_display.present(); }`,
357
+ ].join("\n"),
358
+ };
359
+ };
360
+ // Full Adafruit GFX 5x7 glcdfont table (256 glyphs × 5 bytes). Kept inline so
361
+ // the emitted C++ is self-contained and indexes glyphs exactly like preview.
362
+ function glcdfontBytes() {
363
+ const lines = [];
364
+ for (let i = 0; i < GLCDFONT_BYTES.length; i += 16) {
365
+ lines.push(` ${GLCDFONT_BYTES.slice(i, i + 16).map((b) => "0x" + b.toString(16).padStart(2, "0")).join(", ")},`);
366
+ }
367
+ return lines;
368
+ }
369
+ // Canonical Adafruit GFX 5x7 glcdfont. Public domain.
370
+ // Source: Adafruit_GFX library glcdfont.c.
371
+ const GLCDFONT_BYTES = [
372
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x5b, 0x4f, 0x5b, 0x3e, 0x3e, 0x6b, 0x4f, 0x6b, 0x3e, 0x1c,
373
+ 0x3e, 0x7c, 0x3e, 0x1c, 0x18, 0x3c, 0x7e, 0x3c, 0x18, 0x1c, 0x57, 0x7d, 0x57, 0x1c, 0x1c, 0x5e,
374
+ 0x7f, 0x5e, 0x1c, 0x00, 0x18, 0x3c, 0x18, 0x00, 0xff, 0xe7, 0xc3, 0xe7, 0xff, 0x00, 0x18, 0x24,
375
+ 0x18, 0x00, 0xff, 0xe7, 0xdb, 0xe7, 0xff, 0x30, 0x48, 0x3a, 0x06, 0x0e, 0x26, 0x29, 0x79, 0x29,
376
+ 0x26, 0x40, 0x7f, 0x05, 0x05, 0x07, 0x40, 0x7f, 0x05, 0x25, 0x3f, 0x5a, 0x3c, 0xe7, 0x3c, 0x5a,
377
+ 0x7f, 0x3e, 0x1c, 0x1c, 0x08, 0x08, 0x1c, 0x1c, 0x3e, 0x7f, 0x14, 0x22, 0x7f, 0x22, 0x14, 0x5f,
378
+ 0x5f, 0x00, 0x5f, 0x5f, 0x06, 0x09, 0x7f, 0x01, 0x7f, 0x00, 0x66, 0x89, 0x95, 0x6a, 0x60, 0x60,
379
+ 0x60, 0x60, 0x60, 0x94, 0xa2, 0xff, 0xa2, 0x94, 0x08, 0x04, 0x7e, 0x04, 0x08, 0x10, 0x20, 0x7e,
380
+ 0x20, 0x10, 0x08, 0x08, 0x2a, 0x1c, 0x08, 0x08, 0x1c, 0x2a, 0x08, 0x08, 0x1e, 0x10, 0x10, 0x10,
381
+ 0x10, 0x0c, 0x1e, 0x0c, 0x1e, 0x0c, 0x30, 0x38, 0x3e, 0x38, 0x30, 0x06, 0x0e, 0x3e, 0x0e, 0x06,
382
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x14,
383
+ 0x7f, 0x14, 0x7f, 0x14, 0x24, 0x2a, 0x7f, 0x2a, 0x12, 0x23, 0x13, 0x08, 0x64, 0x62, 0x36, 0x49,
384
+ 0x56, 0x20, 0x50, 0x00, 0x08, 0x07, 0x03, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, 0x00, 0x41, 0x22,
385
+ 0x1c, 0x00, 0x2a, 0x1c, 0x7f, 0x1c, 0x2a, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x80, 0x70, 0x30,
386
+ 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x60, 0x60, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02,
387
+ 0x3e, 0x51, 0x49, 0x45, 0x3e, 0x00, 0x42, 0x7f, 0x40, 0x00, 0x72, 0x49, 0x49, 0x49, 0x46, 0x21,
388
+ 0x41, 0x49, 0x4d, 0x33, 0x18, 0x14, 0x12, 0x7f, 0x10, 0x27, 0x45, 0x45, 0x45, 0x39, 0x3c, 0x4a,
389
+ 0x49, 0x49, 0x31, 0x41, 0x21, 0x11, 0x09, 0x07, 0x36, 0x49, 0x49, 0x49, 0x36, 0x46, 0x49, 0x49,
390
+ 0x29, 0x1e, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40, 0x34, 0x00, 0x00, 0x00, 0x08, 0x14, 0x22,
391
+ 0x41, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x59, 0x09, 0x06,
392
+ 0x3e, 0x41, 0x5d, 0x59, 0x4e, 0x7c, 0x12, 0x11, 0x12, 0x7c, 0x7f, 0x49, 0x49, 0x49, 0x36, 0x3e,
393
+ 0x41, 0x41, 0x41, 0x22, 0x7f, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x49, 0x49, 0x49, 0x41, 0x7f, 0x09,
394
+ 0x09, 0x09, 0x01, 0x3e, 0x41, 0x41, 0x51, 0x73, 0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00, 0x41, 0x7f,
395
+ 0x41, 0x00, 0x20, 0x40, 0x41, 0x3f, 0x01, 0x7f, 0x08, 0x14, 0x22, 0x41, 0x7f, 0x40, 0x40, 0x40,
396
+ 0x40, 0x7f, 0x02, 0x1c, 0x02, 0x7f, 0x7f, 0x04, 0x08, 0x10, 0x7f, 0x3e, 0x41, 0x41, 0x41, 0x3e,
397
+ 0x7f, 0x09, 0x09, 0x09, 0x06, 0x3e, 0x41, 0x51, 0x21, 0x5e, 0x7f, 0x09, 0x19, 0x29, 0x46, 0x26,
398
+ 0x49, 0x49, 0x49, 0x32, 0x03, 0x01, 0x7f, 0x01, 0x03, 0x3f, 0x40, 0x40, 0x40, 0x3f, 0x1f, 0x20,
399
+ 0x40, 0x20, 0x1f, 0x3f, 0x40, 0x38, 0x40, 0x3f, 0x63, 0x14, 0x08, 0x14, 0x63, 0x03, 0x04, 0x78,
400
+ 0x04, 0x03, 0x61, 0x59, 0x49, 0x4d, 0x43, 0x00, 0x7f, 0x41, 0x41, 0x41, 0x02, 0x04, 0x08, 0x10,
401
+ 0x20, 0x00, 0x41, 0x41, 0x41, 0x7f, 0x04, 0x02, 0x01, 0x02, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40,
402
+ 0x00, 0x03, 0x07, 0x08, 0x00, 0x20, 0x54, 0x54, 0x78, 0x40, 0x7f, 0x28, 0x44, 0x44, 0x38, 0x38,
403
+ 0x44, 0x44, 0x44, 0x28, 0x38, 0x44, 0x44, 0x28, 0x7f, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x08,
404
+ 0x7e, 0x09, 0x02, 0x18, 0xa4, 0xa4, 0x9c, 0x78, 0x7f, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7d,
405
+ 0x40, 0x00, 0x20, 0x40, 0x40, 0x3d, 0x00, 0x7f, 0x10, 0x28, 0x44, 0x00, 0x00, 0x41, 0x7f, 0x40,
406
+ 0x00, 0x7c, 0x04, 0x78, 0x04, 0x78, 0x7c, 0x08, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38,
407
+ 0xfc, 0x18, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x18, 0xfc, 0x7c, 0x08, 0x04, 0x04, 0x08, 0x48,
408
+ 0x54, 0x54, 0x54, 0x24, 0x04, 0x04, 0x3f, 0x44, 0x24, 0x3c, 0x40, 0x40, 0x20, 0x7c, 0x1c, 0x20,
409
+ 0x40, 0x20, 0x1c, 0x3c, 0x40, 0x30, 0x40, 0x3c, 0x44, 0x28, 0x10, 0x28, 0x44, 0x4c, 0x90, 0x90,
410
+ 0x90, 0x7c, 0x44, 0x64, 0x54, 0x4c, 0x44, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00,
411
+ 0x00, 0x00, 0x41, 0x36, 0x08, 0x00, 0x02, 0x01, 0x02, 0x04, 0x02, 0x3c, 0x26, 0x23, 0x26, 0x3c,
412
+ 0x1e, 0xa1, 0xa1, 0x61, 0x12, 0x3a, 0x40, 0x40, 0x20, 0x7a, 0x38, 0x54, 0x54, 0x55, 0x59, 0x21,
413
+ 0x55, 0x55, 0x79, 0x41, 0x22, 0x54, 0x54, 0x78, 0x42, 0x21, 0x55, 0x54, 0x78, 0x40, 0x20, 0x54,
414
+ 0x55, 0x79, 0x40, 0x0c, 0x1e, 0x52, 0x72, 0x12, 0x39, 0x55, 0x55, 0x55, 0x59, 0x39, 0x54, 0x54,
415
+ 0x54, 0x59, 0x39, 0x55, 0x54, 0x54, 0x58, 0x00, 0x00, 0x45, 0x7c, 0x41, 0x00, 0x02, 0x45, 0x7d,
416
+ 0x42, 0x00, 0x01, 0x45, 0x7c, 0x40, 0x7d, 0x12, 0x11, 0x12, 0x7d, 0xf0, 0x28, 0x25, 0x28, 0xf0,
417
+ 0x7c, 0x54, 0x55, 0x45, 0x00, 0x20, 0x54, 0x54, 0x7c, 0x54, 0x7c, 0x0a, 0x09, 0x7f, 0x49, 0x32,
418
+ 0x49, 0x49, 0x49, 0x32, 0x3a, 0x44, 0x44, 0x44, 0x3a, 0x32, 0x4a, 0x48, 0x48, 0x30, 0x3a, 0x41,
419
+ 0x41, 0x21, 0x7a, 0x3a, 0x42, 0x40, 0x20, 0x78, 0x00, 0x9d, 0xa0, 0xa0, 0x7d, 0x3d, 0x42, 0x42,
420
+ 0x42, 0x3d, 0x3d, 0x40, 0x40, 0x40, 0x3d, 0x3c, 0x24, 0xff, 0x24, 0x24, 0x48, 0x7e, 0x49, 0x43,
421
+ 0x66, 0x2b, 0x2f, 0xfc, 0x2f, 0x2b, 0xff, 0x09, 0x29, 0xf6, 0x20, 0xc0, 0x88, 0x7e, 0x09, 0x03,
422
+ 0x20, 0x54, 0x54, 0x79, 0x41, 0x00, 0x00, 0x44, 0x7d, 0x41, 0x30, 0x48, 0x48, 0x4a, 0x32, 0x38,
423
+ 0x40, 0x40, 0x22, 0x7a, 0x00, 0x7a, 0x0a, 0x0a, 0x72, 0x7d, 0x0d, 0x19, 0x31, 0x7d, 0x26, 0x29,
424
+ 0x29, 0x2f, 0x28, 0x26, 0x29, 0x29, 0x29, 0x26, 0x30, 0x48, 0x4d, 0x40, 0x20, 0x38, 0x08, 0x08,
425
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x2f, 0x10, 0xc8, 0xac, 0xba, 0x2f, 0x10, 0x28, 0x34,
426
+ 0xfa, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x08, 0x14, 0x2a, 0x14, 0x22, 0x22, 0x14, 0x2a, 0x14, 0x08,
427
+ 0x55, 0x00, 0x55, 0x00, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0xff, 0x55, 0xff, 0x55, 0xff, 0x00,
428
+ 0x00, 0x00, 0xff, 0x00, 0x10, 0x10, 0x10, 0xff, 0x00, 0x14, 0x14, 0x14, 0xff, 0x00, 0x10, 0x10,
429
+ 0xff, 0x00, 0xff, 0x10, 0x10, 0xf0, 0x10, 0xf0, 0x14, 0x14, 0x14, 0xfc, 0x00, 0x14, 0x14, 0xf7,
430
+ 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x14, 0x14, 0xf4, 0x04, 0xfc, 0x14, 0x14, 0x17, 0x10,
431
+ 0x1f, 0x10, 0x10, 0x1f, 0x10, 0x1f, 0x14, 0x14, 0x14, 0x1f, 0x00, 0x10, 0x10, 0x10, 0xf0, 0x00,
432
+ 0x00, 0x00, 0x00, 0x1f, 0x10, 0x10, 0x10, 0x10, 0x1f, 0x10, 0x10, 0x10, 0x10, 0xf0, 0x10, 0x00,
433
+ 0x00, 0x00, 0xff, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xff, 0x10, 0x00, 0x00,
434
+ 0x00, 0xff, 0x14, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x1f, 0x10, 0x17, 0x00, 0x00, 0xfc,
435
+ 0x04, 0xf4, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0xf4, 0x04, 0xf4, 0x00, 0x00, 0xff, 0x00,
436
+ 0xf7, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xf7, 0x00, 0xf7, 0x14, 0x14, 0x14, 0x17, 0x14,
437
+ 0x10, 0x10, 0x1f, 0x10, 0x1f, 0x14, 0x14, 0x14, 0xf4, 0x14, 0x10, 0x10, 0xf0, 0x10, 0xf0, 0x00,
438
+ 0x00, 0x1f, 0x10, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x14, 0x00, 0x00, 0x00, 0xfc, 0x14, 0x00, 0x00,
439
+ 0xf0, 0x10, 0xf0, 0x10, 0x10, 0xff, 0x10, 0xff, 0x14, 0x14, 0x14, 0xff, 0x14, 0x10, 0x10, 0x10,
440
+ 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
441
+ 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
442
+ 0x38, 0x44, 0x44, 0x38, 0x44, 0xfc, 0x4a, 0x4a, 0x4a, 0x34, 0x7e, 0x02, 0x02, 0x06, 0x06, 0x02,
443
+ 0x7e, 0x02, 0x7e, 0x02, 0x63, 0x55, 0x49, 0x41, 0x63, 0x38, 0x44, 0x44, 0x3c, 0x04, 0x40, 0x7e,
444
+ 0x20, 0x1e, 0x20, 0x06, 0x02, 0x7e, 0x02, 0x02, 0x99, 0xa5, 0xe7, 0xa5, 0x99, 0x1c, 0x2a, 0x49,
445
+ 0x2a, 0x1c, 0x4c, 0x72, 0x01, 0x72, 0x4c, 0x30, 0x4a, 0x4d, 0x4d, 0x30, 0x30, 0x48, 0x78, 0x48,
446
+ 0x30, 0xbc, 0x62, 0x5a, 0x46, 0x3d, 0x3e, 0x49, 0x49, 0x49, 0x00, 0x7e, 0x01, 0x01, 0x01, 0x7e,
447
+ 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x44, 0x44, 0x5f, 0x44, 0x44, 0x40, 0x51, 0x4a, 0x44, 0x40, 0x40,
448
+ 0x44, 0x4a, 0x51, 0x40, 0x00, 0x00, 0xff, 0x01, 0x03, 0xe0, 0x80, 0xff, 0x00, 0x00, 0x08, 0x08,
449
+ 0x6b, 0x6b, 0x08, 0x36, 0x12, 0x36, 0x24, 0x36, 0x06, 0x0f, 0x09, 0x0f, 0x06, 0x00, 0x00, 0x18,
450
+ 0x18, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x30, 0x40, 0xff, 0x01, 0x01, 0x00, 0x1f, 0x01, 0x01,
451
+ 0x1e, 0x00, 0x19, 0x1d, 0x17, 0x12, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
452
+ ];
@@ -0,0 +1,2 @@
1
+ import type { DisplayAdapterGenerator } from "../display-adapter.js";
2
+ export declare const ssd1309Adapter: DisplayAdapterGenerator;
@@ -0,0 +1,136 @@
1
+ // ---------------------------------------------------------------------------
2
+ // SSD1309 OLED display adapter — 1-bit monochrome OLED panels over I2C.
3
+ //
4
+ // Targets the Adafruit_SSD1306 library (which supports SSD1309 via the same
5
+ // API). The SSD1306 is a page-buffered Adafruit_GFX subclass: draw into its
6
+ // buffer via drawPixel/fillRect, then call display() to flush over I2C.
7
+ // Colors are 1-bit (SSD1306_WHITE / SSD1306_BLACK). The runtime's
8
+ // UI_NATIVE_MONO snap converts 565 → black/white at the draw choke points.
9
+ //
10
+ // The SSD1306 IS the backing store (its internal buffer), so this adapter
11
+ // follows the e-ink deferred-refresh pattern: the runtime draws dirty rects
12
+ // into the buffer, then display_partial_refresh() flushes. The SSD1306 has
13
+ // no true partial refresh — display() flushes the full page buffer — but
14
+ // the dirty-rect tracking still minimizes draw calls into the buffer.
15
+ //
16
+ // I2C wiring: SDA/SCL (Wire bus) + reset pin + I2C address (default 0x3C).
17
+ // ---------------------------------------------------------------------------
18
+ export const ssd1309Adapter = (display) => {
19
+ const w = display.width;
20
+ const h = display.height;
21
+ const reset = display._mountReset;
22
+ const address = display._mountAddress;
23
+ const rotation = display.rotation ?? 0;
24
+ return {
25
+ includes: [
26
+ `#define CuttlefishDisplayTarget Adafruit_GFX`,
27
+ `#define CuttlefishCanvas16 GFXcanvas16`,
28
+ `#define SSD1306_NO_SPLASH`,
29
+ `#include <Adafruit_GFX.h>`,
30
+ `#include <Adafruit_SSD1306.h>`,
31
+ `#include <Wire.h>`,
32
+ ].join("\n"),
33
+ // I2C constructor: Adafruit_SSD1306(width, height, &Wire, resetPin)
34
+ declaration: `Adafruit_SSD1306 __tc_display(${w}, ${h}, &Wire, ${reset});`,
35
+ functions: [
36
+ `// --- Display adapter: SSD1309 OLED (1-bit mono, I2C, page-buffered) ---`,
37
+ `static inline void display_init() {`,
38
+ ` // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally.`,
39
+ ` __tc_display.begin(SSD1306_SWITCHCAPVCC, 0x${address.toString(16)});`,
40
+ ` __tc_display.setRotation(${rotation});`,
41
+ ` __tc_display.clearDisplay();`,
42
+ ` __tc_display.display();`,
43
+ `}`,
44
+ ``,
45
+ `static inline void display_fillScreen(uint32_t color) {`,
46
+ ` __tc_display.fillScreen(color ? SSD1306_WHITE : SSD1306_BLACK);`,
47
+ `}`,
48
+ `static inline CuttlefishDisplayTarget* display_defaultTarget() { return &__tc_display; }`,
49
+ `static inline int16_t display_width() { return __tc_display.width(); }`,
50
+ `static inline int16_t display_height() { return __tc_display.height(); }`,
51
+ `static inline void display_startWrite() {}`,
52
+ `static inline void display_endWrite() {}`,
53
+ `static int16_t __ssd1309_addr_x = 0;`,
54
+ `static int16_t __ssd1309_addr_y = 0;`,
55
+ `static int16_t __ssd1309_addr_w = 0;`,
56
+ `static int16_t __ssd1309_addr_h = 0;`,
57
+ `static uint32_t __ssd1309_addr_cursor = 0;`,
58
+ `static inline void display_setAddrWindow(int16_t x, int16_t y, int16_t w, int16_t h) {`,
59
+ ` __ssd1309_addr_x = x;`,
60
+ ` __ssd1309_addr_y = y;`,
61
+ ` __ssd1309_addr_w = w;`,
62
+ ` __ssd1309_addr_h = h;`,
63
+ ` __ssd1309_addr_cursor = 0;`,
64
+ `}`,
65
+ `static inline void display_writePixels(UI_COLOR_T* pixels, uint32_t count) {`,
66
+ ` // SSD1306 is page-buffered — write into the GFX buffer via drawPixel.`,
67
+ ` if (__ssd1309_addr_w <= 0 || __ssd1309_addr_h <= 0) return;`,
68
+ ` uint32_t windowPixels = (uint32_t)__ssd1309_addr_w * (uint32_t)__ssd1309_addr_h;`,
69
+ ` for (uint32_t i = 0; i < count; i++) {`,
70
+ ` if (__ssd1309_addr_cursor >= windowPixels) break;`,
71
+ ` uint32_t pos = __ssd1309_addr_cursor++;`,
72
+ ` int16_t px = (int16_t)(__ssd1309_addr_x + (int16_t)(pos % (uint32_t)__ssd1309_addr_w));`,
73
+ ` int16_t py = (int16_t)(__ssd1309_addr_y + (int16_t)(pos / (uint32_t)__ssd1309_addr_w));`,
74
+ ` __tc_display.drawPixel(px, py, pixels[i] ? SSD1306_WHITE : SSD1306_BLACK);`,
75
+ ` }`,
76
+ `}`,
77
+ ``,
78
+ `// The SSD1306 has no true partial refresh — display() flushes the full`,
79
+ `// page buffer. The runtime's dirty-rect tracking still minimizes the draw`,
80
+ `// calls INTO the buffer (only dirty nodes are redrawn); this just publishes`,
81
+ `// the result. Called once per frame after the dirty-rect union is drawn.`,
82
+ `static inline void display_partial_refresh(int16_t x, int16_t y, int16_t w, int16_t h) {`,
83
+ ` (void)x; (void)y; (void)w; (void)h;`,
84
+ ` __tc_display.display();`,
85
+ `}`,
86
+ // ── Canvas (offscreen GFXcanvas16 for AA text / scroll compositing) ──
87
+ `static inline uint16_t ssd_mono(uint16_t c);`,
88
+ `static inline CuttlefishCanvas16* display_createCanvas(int16_t w, int16_t h) { return new GFXcanvas16(w, h); }`,
89
+ `static inline CuttlefishCanvas16* display_createCanvasPsram(int16_t w, int16_t h) {`,
90
+ `#if defined(ESP32) && defined(BOARD_HAS_PSRAM)`,
91
+ ` return new (ps_malloc(sizeof(GFXcanvas16))) GFXcanvas16(w, h);`,
92
+ `#else`,
93
+ ` (void)w; (void)h;`,
94
+ ` return nullptr;`,
95
+ `#endif`,
96
+ `}`,
97
+ `static inline void display_deleteCanvas(CuttlefishCanvas16* canvas) { delete canvas; }`,
98
+ `static inline int16_t display_canvasWidth(CuttlefishCanvas16* c) { return c->width(); }`,
99
+ `static inline int16_t display_canvasHeight(CuttlefishCanvas16* c) { return c->height(); }`,
100
+ `static inline uint16_t* display_canvasBuffer(CuttlefishCanvas16* c) { return c->getBuffer(); }`,
101
+ `static inline uint16_t display_canvasGetPixel(CuttlefishCanvas16* c, int16_t x, int16_t y) { return c->getPixel(x, y); }`,
102
+ `static inline void display_canvasFillScreen(CuttlefishCanvas16* c, UI_COLOR_T color) { c->fillScreen(ssd_mono((uint16_t)color)); }`,
103
+ `static inline void display_canvasFillRect(CuttlefishCanvas16* c, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) { c->fillRect(x, y, w, h, ssd_mono((uint16_t)color)); }`,
104
+ // ── Color conversion: runtime uses 0xffff/0x0000 (565 mono snap), but the
105
+ // SSD1306's drawPixel switch only accepts 0/1/2. Convert any nonzero to 1. ──
106
+ `static inline uint16_t ssd_mono(uint16_t c) { return c ? SSD1306_WHITE : SSD1306_BLACK; }`,
107
+ // ── Target-polymorphic draw (panel + canvas share CuttlefishDisplayTarget*) ──
108
+ `static inline void display_targetDrawPixel(CuttlefishDisplayTarget* t, int16_t x, int16_t y, UI_COLOR_T color) { t->drawPixel(x, y, ssd_mono((uint16_t)color)); }`,
109
+ `static inline int16_t display_targetWidth(CuttlefishDisplayTarget* t) { return t->width(); }`,
110
+ `static inline int16_t display_targetHeight(CuttlefishDisplayTarget* t) { return t->height(); }`,
111
+ `static inline void display_targetDrawRGBBitmap(CuttlefishDisplayTarget* t, int16_t x, int16_t y, const UI_COLOR_T* b, int16_t w, int16_t h) {`,
112
+ ` if (!b || w <= 0 || h <= 0) return;`,
113
+ ` for (int16_t yy = 0; yy < h; yy++) {`,
114
+ ` for (int16_t xx = 0; xx < w; xx++) {`,
115
+ ` t->drawPixel((int16_t)(x + xx), (int16_t)(y + yy), ssd_mono((uint16_t)b[(int32_t)yy * w + xx]));`,
116
+ ` }`,
117
+ ` }`,
118
+ `}`,
119
+ `static inline void display_targetFillRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) { t->fillRect(x, y, w, h, ssd_mono((uint16_t)color)); }`,
120
+ `static inline void display_targetDrawFastHLine(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, UI_COLOR_T color) { t->drawFastHLine(x, y, w, ssd_mono((uint16_t)color)); }`,
121
+ `static inline void display_targetDrawFastVLine(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t h, UI_COLOR_T color) { t->drawFastVLine(x, y, h, ssd_mono((uint16_t)color)); }`,
122
+ `static inline void display_targetFillRoundRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, UI_COLOR_T color) { t->fillRoundRect(x, y, w, h, r, ssd_mono((uint16_t)color)); }`,
123
+ `static inline void display_targetDrawRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) { t->drawRect(x, y, w, h, ssd_mono((uint16_t)color)); }`,
124
+ `static inline void display_targetDrawRoundRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, UI_COLOR_T color) { t->drawRoundRect(x, y, w, h, r, ssd_mono((uint16_t)color)); }`,
125
+ `static inline void display_targetDrawLine(CuttlefishDisplayTarget* t, int16_t x0, int16_t y0, int16_t x1, int16_t y1, UI_COLOR_T color) { t->drawLine(x0, y0, x1, y1, ssd_mono((uint16_t)color)); }`,
126
+ `static inline void display_targetFillCircle(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t r, UI_COLOR_T color) { t->fillCircle(x, y, r, ssd_mono((uint16_t)color)); }`,
127
+ `static inline void display_targetDrawCircle(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t r, UI_COLOR_T color) { t->drawCircle(x, y, r, ssd_mono((uint16_t)color)); }`,
128
+ `static inline void display_targetSetCursor(CuttlefishDisplayTarget* t, int16_t x, int16_t y) { t->setCursor(x, y); }`,
129
+ `static inline void display_targetSetTextColor(CuttlefishDisplayTarget* t, UI_COLOR_T fg) { t->setTextColor(ssd_mono((uint16_t)fg)); }`,
130
+ `static inline void display_targetSetTextColorBg(CuttlefishDisplayTarget* t, UI_COLOR_T fg, UI_COLOR_T bg) { t->setTextColor(ssd_mono((uint16_t)fg), ssd_mono((uint16_t)bg)); }`,
131
+ `static inline void display_targetSetTextSize(CuttlefishDisplayTarget* t, uint8_t s) { t->setTextSize(s); }`,
132
+ `static inline void display_targetSetTextWrap(CuttlefishDisplayTarget* t, bool w) { t->setTextWrap(w); }`,
133
+ `static inline void display_targetPrint(CuttlefishDisplayTarget* t, const char* s) { t->print(s); }`,
134
+ ].join("\n"),
135
+ };
136
+ };
@@ -0,0 +1,2 @@
1
+ import type { DisplayAdapterGenerator } from "../display-adapter.js";
2
+ export declare const st7796Adapter: DisplayAdapterGenerator;