diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..eb80c63b --- /dev/null +++ b/404.html @@ -0,0 +1,474 @@ + + + + + + + + + + + + + + + + + + Amstrad RUST cpcdemotools + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 00000000..1cf13b9f Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/javascripts/bundle.51d95adb.min.js b/assets/javascripts/bundle.51d95adb.min.js new file mode 100644 index 00000000..b20ec683 --- /dev/null +++ b/assets/javascripts/bundle.51d95adb.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Hi=Object.create;var xr=Object.defineProperty;var Pi=Object.getOwnPropertyDescriptor;var $i=Object.getOwnPropertyNames,kt=Object.getOwnPropertySymbols,Ii=Object.getPrototypeOf,Er=Object.prototype.hasOwnProperty,an=Object.prototype.propertyIsEnumerable;var on=(e,t,r)=>t in e?xr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))Er.call(t,r)&&on(e,r,t[r]);if(kt)for(var r of kt(t))an.call(t,r)&&on(e,r,t[r]);return e};var sn=(e,t)=>{var r={};for(var n in e)Er.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&kt)for(var n of kt(e))t.indexOf(n)<0&&an.call(e,n)&&(r[n]=e[n]);return r};var Ht=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Fi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $i(t))!Er.call(e,o)&&o!==r&&xr(e,o,{get:()=>t[o],enumerable:!(n=Pi(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Hi(Ii(e)):{},Fi(t||!e||!e.__esModule?xr(r,"default",{value:e,enumerable:!0}):r,e));var fn=Ht((wr,cn)=>{(function(e,t){typeof wr=="object"&&typeof cn!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(wr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(T){return!!(T&&T!==document&&T.nodeName!=="HTML"&&T.nodeName!=="BODY"&&"classList"in T&&"contains"in T.classList)}function f(T){var Ke=T.type,We=T.tagName;return!!(We==="INPUT"&&a[Ke]&&!T.readOnly||We==="TEXTAREA"&&!T.readOnly||T.isContentEditable)}function c(T){T.classList.contains("focus-visible")||(T.classList.add("focus-visible"),T.setAttribute("data-focus-visible-added",""))}function u(T){T.hasAttribute("data-focus-visible-added")&&(T.classList.remove("focus-visible"),T.removeAttribute("data-focus-visible-added"))}function p(T){T.metaKey||T.altKey||T.ctrlKey||(s(r.activeElement)&&c(r.activeElement),n=!0)}function m(T){n=!1}function d(T){s(T.target)&&(n||f(T.target))&&c(T.target)}function h(T){s(T.target)&&(T.target.classList.contains("focus-visible")||T.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(T.target))}function v(T){document.visibilityState==="hidden"&&(o&&(n=!0),B())}function B(){document.addEventListener("mousemove",z),document.addEventListener("mousedown",z),document.addEventListener("mouseup",z),document.addEventListener("pointermove",z),document.addEventListener("pointerdown",z),document.addEventListener("pointerup",z),document.addEventListener("touchmove",z),document.addEventListener("touchstart",z),document.addEventListener("touchend",z)}function re(){document.removeEventListener("mousemove",z),document.removeEventListener("mousedown",z),document.removeEventListener("mouseup",z),document.removeEventListener("pointermove",z),document.removeEventListener("pointerdown",z),document.removeEventListener("pointerup",z),document.removeEventListener("touchmove",z),document.removeEventListener("touchstart",z),document.removeEventListener("touchend",z)}function z(T){T.target.nodeName&&T.target.nodeName.toLowerCase()==="html"||(n=!1,re())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),B(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var un=Ht(Sr=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var u={next:function(){var p=c.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},a=function(){var c=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof c){var d=this;p.forEach(function(re,z){d.append(z,re)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(f,c){typeof f!="string"&&(f=String(f)),c&&typeof c!="string"&&(c=String(c));var u=document,p;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=c,u.head.appendChild(p);try{if(p.href.indexOf(c)!==0)throw new Error(p.href)}catch(T){throw new Error("URL unable to set base "+c+" due to "+T)}}var m=u.createElement("a");m.href=f,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=f,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,B=!0,re=this;["append","delete","set"].forEach(function(T){var Ke=h[T];h[T]=function(){Ke.apply(h,arguments),v&&(B=!1,re.search=h.toString(),B=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var z=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==z&&(z=this.search,B&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},a=i.prototype,s=function(f){Object.defineProperty(a,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){s(f)}),Object.defineProperty(a,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(a,{toString:{get:function(){var f=this;return function(){return f.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(f){this._anchorElement.href=f,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(f){this._anchorElement.pathname=f},enumerable:!0},origin:{get:function(){var f={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=f&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(f){},enumerable:!0},username:{get:function(){return""},set:function(f){},enumerable:!0}}),i.createObjectURL=function(f){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(f){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr)});var Qr=Ht((Lt,Kr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Lt=="object"&&typeof Kr=="object"?Kr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Lt=="object"?Lt.ClipboardJS=r():t.ClipboardJS=r()})(Lt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return ki}});var a=i(279),s=i.n(a),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(O){return!1}}var d=function(O){var w=p()(O);return m("cut"),w},h=d;function v(j){var O=document.documentElement.getAttribute("dir")==="rtl",w=document.createElement("textarea");w.style.fontSize="12pt",w.style.border="0",w.style.padding="0",w.style.margin="0",w.style.position="absolute",w.style[O?"right":"left"]="-9999px";var k=window.pageYOffset||document.documentElement.scrollTop;return w.style.top="".concat(k,"px"),w.setAttribute("readonly",""),w.value=j,w}var B=function(O,w){var k=v(O);w.container.appendChild(k);var F=p()(k);return m("copy"),k.remove(),F},re=function(O){var w=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},k="";return typeof O=="string"?k=B(O,w):O instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(O==null?void 0:O.type)?k=B(O.value,w):(k=p()(O),m("copy")),k},z=re;function T(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?T=function(w){return typeof w}:T=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},T(j)}var Ke=function(){var O=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},w=O.action,k=w===void 0?"copy":w,F=O.container,q=O.target,Le=O.text;if(k!=="copy"&&k!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&T(q)==="object"&&q.nodeType===1){if(k==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(k==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Le)return z(Le,{container:F});if(q)return k==="cut"?h(q):z(q,{container:F})},We=Ke;function Ie(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ie=function(w){return typeof w}:Ie=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},Ie(j)}function Ti(j,O){if(!(j instanceof O))throw new TypeError("Cannot call a class as a function")}function nn(j,O){for(var w=0;w0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof F.action=="function"?F.action:this.defaultAction,this.target=typeof F.target=="function"?F.target:this.defaultTarget,this.text=typeof F.text=="function"?F.text:this.defaultText,this.container=Ie(F.container)==="object"?F.container:document.body}},{key:"listenClick",value:function(F){var q=this;this.listener=c()(F,"click",function(Le){return q.onClick(Le)})}},{key:"onClick",value:function(F){var q=F.delegateTarget||F.currentTarget,Le=this.action(q)||"copy",Rt=We({action:Le,container:this.container,target:this.target(q),text:this.text(q)});this.emit(Rt?"success":"error",{action:Le,text:Rt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(F){return yr("action",F)}},{key:"defaultTarget",value:function(F){var q=yr("target",F);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(F){return yr("text",F)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(F){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return z(F,q)}},{key:"cut",value:function(F){return h(F)}},{key:"isSupported",value:function(){var F=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof F=="string"?[F]:F,Le=!!document.queryCommandSupported;return q.forEach(function(Rt){Le=Le&&!!document.queryCommandSupported(Rt)}),Le}}]),w}(s()),ki=Ri},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,f){for(;s&&s.nodeType!==o;){if(typeof s.matches=="function"&&s.matches(f))return s;s=s.parentNode}}n.exports=a},438:function(n,o,i){var a=i(828);function s(u,p,m,d,h){var v=c.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function f(u,p,m,d,h){return typeof u.addEventListener=="function"?s.apply(null,arguments):typeof m=="function"?s.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return s(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=a(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=f},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(n,o,i){var a=i(879),s=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(h))throw new TypeError("Third argument must be a Function");if(a.node(m))return c(m,d,h);if(a.nodeList(m))return u(m,d,h);if(a.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return s(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),a=f.toString()}return a}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,a,s){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var f=this;function c(){f.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=s.length;for(f;f{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var is=/["'&<>]/;Jo.exports=as;function as(e){var t=""+e,r=is.exec(t);if(!r)return t;var n,o="",i=0,a=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],a;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(s){a={error:s}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(a)throw a.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||s(m,d)})})}function s(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof Xe?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){s("next",m)}function u(m){s("throw",m)}function p(m,d){m(d),i.shift(),i.length&&s(i[0][0],i[0][1])}}function mn(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof xe=="function"?xe(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(a){return new Promise(function(s,f){a=e[i](a),o(s,f,a.done,a.value)})}}function o(i,a,s,f){Promise.resolve(f).then(function(c){i({value:c,done:s})},a)}}function A(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var $t=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function De(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Fe=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=xe(a),f=s.next();!f.done;f=s.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var u=this.initialTeardown;if(A(u))try{u()}catch(v){i=v instanceof $t?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=xe(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{dn(h)}catch(v){i=i!=null?i:[],v instanceof $t?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new $t(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)dn(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&De(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&De(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Or=Fe.EMPTY;function It(e){return e instanceof Fe||e&&"closed"in e&&A(e.remove)&&A(e.add)&&A(e.unsubscribe)}function dn(e){A(e)?e():e.unsubscribe()}var Ae={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,a=o.isStopped,s=o.observers;return i||a?Or:(this.currentObservers=null,s.push(r),new Fe(function(){n.currentObservers=null,De(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,a=n.isStopped;o?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new U;return r.source=this,r},t.create=function(r,n){return new wn(r,n)},t}(U);var wn=function(e){ne(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Or},t}(E);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ne(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,a=n._infiniteTimeWindow,s=n._timestampProvider,f=n._windowTime;o||(i.push(r),!a&&i.push(s.now()+f)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,a=o._buffer,s=a.slice(),f=0;f0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var a=r.actions;n!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Ut);var On=function(e){ne(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Wt);var we=new On(Tn);var R=new U(function(e){return e.complete()});function Dt(e){return e&&A(e.schedule)}function kr(e){return e[e.length-1]}function Qe(e){return A(kr(e))?e.pop():void 0}function Se(e){return Dt(kr(e))?e.pop():void 0}function Vt(e,t){return typeof kr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function zt(e){return A(e==null?void 0:e.then)}function Nt(e){return A(e[ft])}function qt(e){return Symbol.asyncIterator&&A(e==null?void 0:e[Symbol.asyncIterator])}function Kt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Ki(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Qt=Ki();function Yt(e){return A(e==null?void 0:e[Qt])}function Gt(e){return ln(this,arguments,function(){var r,n,o,i;return Pt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,Xe(r.read())];case 3:return n=a.sent(),o=n.value,i=n.done,i?[4,Xe(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,Xe(o)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Bt(e){return A(e==null?void 0:e.getReader)}function $(e){if(e instanceof U)return e;if(e!=null){if(Nt(e))return Qi(e);if(pt(e))return Yi(e);if(zt(e))return Gi(e);if(qt(e))return _n(e);if(Yt(e))return Bi(e);if(Bt(e))return Ji(e)}throw Kt(e)}function Qi(e){return new U(function(t){var r=e[ft]();if(A(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Yi(e){return new U(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?_(function(o,i){return e(o,i,n)}):me,Oe(1),r?He(t):zn(function(){return new Xt}))}}function Nn(){for(var e=[],t=0;t=2,!0))}function fe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new E}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,f=s===void 0?!0:s;return function(c){var u,p,m,d=0,h=!1,v=!1,B=function(){p==null||p.unsubscribe(),p=void 0},re=function(){B(),u=m=void 0,h=v=!1},z=function(){var T=u;re(),T==null||T.unsubscribe()};return g(function(T,Ke){d++,!v&&!h&&B();var We=m=m!=null?m:r();Ke.add(function(){d--,d===0&&!v&&!h&&(p=jr(z,f))}),We.subscribe(Ke),!u&&d>0&&(u=new et({next:function(Ie){return We.next(Ie)},error:function(Ie){v=!0,B(),p=jr(re,o,Ie),We.error(Ie)},complete:function(){h=!0,B(),p=jr(re,a),We.complete()}}),$(T).subscribe(u))})(c)}}function jr(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function V(e,t=document){let r=se(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function se(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),N(e===_e()),Y())}function Be(e){return{x:e.offsetLeft,y:e.offsetTop}}function Yn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,we),l(()=>Be(e)),N(Be(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,we),l(()=>rr(e)),N(rr(e)))}var Bn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!zr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),xa?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!zr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=ya.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Jn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Zn=typeof WeakMap!="undefined"?new WeakMap:new Bn,eo=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=Ea.getInstance(),n=new Ra(t,r,this);Zn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){eo.prototype[e]=function(){var t;return(t=Zn.get(this))[e].apply(t,arguments)}});var ka=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:eo}(),to=ka;var ro=new E,Ha=I(()=>H(new to(e=>{for(let t of e)ro.next(t)}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function de(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){return Ha.pipe(S(t=>t.observe(e)),x(t=>ro.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(()=>de(e)))),N(de(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var no=new E,Pa=I(()=>H(new IntersectionObserver(e=>{for(let t of e)no.next(t)},{threshold:0}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function sr(e){return Pa.pipe(S(t=>t.observe(e)),x(t=>no.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function oo(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=de(e),o=bt(e);return r>=o.height-n.height-t}),Y())}var cr={drawer:V("[data-md-toggle=drawer]"),search:V("[data-md-toggle=search]")};function io(e){return cr[e].checked}function qe(e,t){cr[e].checked!==t&&cr[e].click()}function je(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),N(t.checked))}function $a(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ia(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(N(!1))}function ao(){let e=b(window,"keydown").pipe(_(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:io("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),_(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!$a(n,r)}return!0}),fe());return Ia().pipe(x(t=>t?R:e))}function Me(){return new URL(location.href)}function ot(e){location.href=e.href}function so(){return new E}function co(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)co(e,r)}function M(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)co(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function fo(){return location.hash.substring(1)}function uo(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Fa(){return b(window,"hashchange").pipe(l(fo),N(fo()),_(e=>e.length>0),J(1))}function po(){return Fa().pipe(l(e=>se(`[id="${e}"]`)),_(e=>typeof e!="undefined"))}function Nr(e){let t=matchMedia(e);return Zt(r=>t.addListener(()=>r(t.matches))).pipe(N(t.matches))}function lo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(N(e.matches))}function qr(e,t){return e.pipe(x(r=>r?t():R))}function ur(e,t={credentials:"same-origin"}){return ve(fetch(`${e}`,t)).pipe(ce(()=>R),x(r=>r.status!==200?Tt(()=>new Error(r.statusText)):H(r)))}function Ue(e,t){return ur(e,t).pipe(x(r=>r.json()),J(1))}function mo(e,t){let r=new DOMParser;return ur(e,t).pipe(x(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),J(1))}function pr(e){let t=M("script",{src:e});return I(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(x(()=>Tt(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),C(()=>document.head.removeChild(t)),Oe(1))))}function ho(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function bo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(ho),N(ho()))}function vo(){return{width:innerWidth,height:innerHeight}}function go(){return b(window,"resize",{passive:!0}).pipe(l(vo),N(vo()))}function yo(){return Q([bo(),go()]).pipe(l(([e,t])=>({offset:e,size:t})),J(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(X("size")),o=Q([n,r]).pipe(l(()=>Be(e)));return Q([r,t,o]).pipe(l(([{height:i},{offset:a,size:s},{x:f,y:c}])=>({offset:{x:a.x-f,y:a.y-c+i},size:s})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(a=>{let s=document.createElement("script");s.src=i,s.onload=a,document.body.appendChild(s)})),Promise.resolve())}var r=class{constructor(n){this.url=n,this.onerror=null,this.onmessage=null,this.onmessageerror=null,this.m=a=>{a.source===this.w&&(a.stopImmediatePropagation(),this.dispatchEvent(new MessageEvent("message",{data:a.data})),this.onmessage&&this.onmessage(a))},this.e=(a,s,f,c,u)=>{if(s===this.url.toString()){let p=new ErrorEvent("error",{message:a,filename:s,lineno:f,colno:c,error:u});this.dispatchEvent(p),this.onerror&&this.onerror(p)}};let o=new EventTarget;this.addEventListener=o.addEventListener.bind(o),this.removeEventListener=o.removeEventListener.bind(o),this.dispatchEvent=o.dispatchEvent.bind(o);let i=document.createElement("iframe");i.width=i.height=i.frameBorder="0",document.body.appendChild(this.iframe=i),this.w.document.open(),this.w.document.write(` + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Command line arguments

+

Here is the help provided by basm.

+
Profile debug compiled: Sun, 20 Aug 2023 20:55:05 +0000
+
+Benediction ASM -- z80 assembler that mainly targets Amstrad CPC
+
+Usage: basm.exe [OPTIONS] [INPUT]
+
+Arguments:
+  [INPUT]  Input file to read.
+
+Options:
+      --inline <INLINE>                Z80 code is provided inline
+  -o, --output <OUTPUT>                Filename of the output.
+      --db                             Write a db list on screen (usefull to get the value of an opcode)
+      --lst <LISTING_OUTPUT>           Filename of the listing output.
+      --sym <SYMBOLS_OUTPUT>           Filename of the output symbols file.
+      --sym_kind <SYMBOLS_KIND>        Format of the output symbols file [default: basm] [possible values: winape, basm]
+      --basic                          Request a Basic header (the very first instruction has to be the LOCOMOTIVE directive).
+      --binary                         Request a binary header
+      --snapshot                       Generate a snapshot
+  -i, --case-insensitive               Configure the assembler to be case insensitive.
+  -d, --directives-prefixed-by-dot     Expect directives to by prefixed with a dot
+  -I, --include <INCLUDE_DIRECTORIES>  Provide additional directories used to search files
+  -D, --define <DEFINE_SYMBOL>         Provide a symbol with its value (default set to 1)
+      --m4 <TO_M4>                     Provide the IP address of the M4
+  -l <LOAD_SYMBOLS>                    Load symbols from the given file
+      --Werror                         Warning are considered to be errors
+      --progress                       Show a progress bar.
+      --list-embedded                  List the embedded files
+      --view-embedded <VIEW_EMBEDDED>  Display one specific embedded file [possible values: inner://crtc.asm, inner://deexo.asm, inner://dzx0_fast.asm, inner://dzx0_standard.asm, inner://firmware/amsdos.asm, inner://firmware/casmng.asm, inner://firmware/gfxvdu.asm, inner://firmware/highkern.asm, inner://firmware/indirect.asm, inner://firmware/kernel.asm, inner://firmware/keymng.asm, inner://firmware/lowkern.asm, inner://firmware/machine.asm, inner://firmware/math6128.asm, inner://firmware/mathnot464.asm, inner://firmware/mathnot6xx.asm, inner://firmware/not464.asm, inner://firmware/scrpack.asm, inner://firmware/sound.asm, inner://firmware/txtvdu.asm, inner://ga.asm, inner://lz48decrunch.asm, inner://lz49decrunch.asm, inner://lz4_docent.asm, inner://opcodes_first_byte.asm, inner://pixels-routs.asm, inner://unaplib.asm, inner://unaplib_fast.asm]
+  -h, --help                           Print help
+  -V, --version                        Print version
+
+Still a Work In Progress assembler
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/basm/directives/index.html b/basm/directives/index.html new file mode 100644 index 00000000..1787c703 --- /dev/null +++ b/basm/directives/index.html @@ -0,0 +1,2581 @@ + + + + + + + + + + + + + + + + + + + + + + Directives - Amstrad RUST cpcdemotools + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Directives

+
+

Failure

+

Not all directives have their synopsis, explanation, and examples

+
+ +

LIST, NOLIST

+

Example:

+
    org 0
+    LIST
+
+    ld a, 0
+    ; visible in the listing output
+
+    NOLIST
+
+    ld a, 1
+    ; Not visible in the listing ouput
+
+ +

ALIGN

+

Example:

+
    org 0x1234
+
+        align 256
+        assert $ == 0x1300
+
+        align 256
+        assert $ == 0x1300
+
+        nop
+
+        align 128, 3
+        assert $ == 0x1300 + 128
+
+

CONFINED

+

Confine a memory area of 256 bytes maximum in such a way that it is always possible to navigate in the data by only modifying the low byte address (i.e INC L always works).

+
CONFINED
+  LISTING
+ENDCONFINED
+
+
;;
+; Confined directive is inspired by confine from rasm.
+; I guess confined is more  ergonomic has it does not requires to manually specify the size of the confined area
+
+    org 0x0000
+
+    CONFINED
+        assert $ == 0
+        defs 128, 0xff
+    ENDCONFINED
+
+    CONFINED
+        assert $ == 256
+        defs 200, 0xff
+    ENDCONFINED
+
+    CONFINED
+        assert $ == 256 + 200
+        defs 20, 0xff
+    ENDCONFINED
+
+

ORG

+

LIMIT

+

On the code space ($), not physical space ($$)

+

Example of code that assembles: +

    org 0x100
+
+    limit 102
+

+

Example of code that fails: +


+

+

PHASE, DEPHASE

+
; https://k1.spdns.de/Develop/Projects/zasm/Documentation/z71.htm
+    org 0x100
+
+label_100
+    nop
+label_101
+
+    assert $$ == 0x101
+    assert $ == 0x101
+
+    phase 0x200
+
+    assert $$ == 0x101
+    assert $ == 0x200
+
+label_200
+    nop
+label_201
+
+    dephase
+label_102
+
+    assert label_100 == 0x100
+    assert label_101 == 0x101
+    assert label_102 == 0x102
+    assert label_200 == 0x200
+    assert label_201 == 0x201
+
+

PROTECT

+

Synopsis: +

PROTECT START, STOP
+
+Description: +Mark the memory between START and STOP as protected against write. Assembler fails when writting there.

+

On the code space ($), not physical space ($$)

+

Example: +

    org 0x4000
+
+    protect 0x8000, 0xbfff
+
+    defb "No memory issue"
+

+

RANGE, SECTION

+

Description: +RANGE allows to define named portion of the memory, while SECTION allows to chose the portion of interest.

+

Example: +

; sarcasm inspiration https://www.ecstaticlyrics.com/electronics/Z80/sarcasm/
+
+range $0080, $3FFF, code
+range $4000, $7FFF, data
+
+section code
+  ld hl, message_1
+  call print_message
+
+section data
+message_1: db "This is message #1.", $00
+
+section code
+  ld hl, message_2
+  call print_message
+
+section data
+message_2: db "This is message #2.", $00
+
+section code
+  print_message: 
+    ld a, (hl)
+    or a
+    ret z
+    call 0xbb5a
+    inc hl
+    jr print_message
+
+    assert section_start("data") ==  0x4000
+    assert section_length("data") == 0x4000
+    assert section_used("data") == 40
+

+

BANK

+

Description:

+

When used with no argument, a bank corresponds to a memory area outside of the snapshot. All things read&write in memory are thus uncorrelated to the snapshot. +Sections do not apply in a bank.

+

BANK page is similar to WRITE DIRECT -1 -1 page

+

Synopsis:

+
BANK [EXPRESSION]
+
+

Example: +

    ; Set up a unique value in various banks
+    BANK 0xc0
+    org 0x4000 + 0
+    db 0xc0
+
+    BANK 0xc4
+    org 0x4000 + 1
+    db 0xc4
+
+
+    BANK 0xc5
+    org 0x4000 + 2
+    db 0xc5
+
+    BANK 0xc6
+    org 0x4000 + 3
+    db 0xc6
+
+
+    BANK 0xc7
+    org 0x4000 + 4
+    db 0xc7
+
+
+    BANKSET 0
+    assert memory(0x4000 + 0) == 0xC0 
+
+    BANKSET 1
+    assert memory(0x4000 + 2) == 0xC5
+    assert memory(0x8000 + 3) == 0xC6
+    assert memory(0xC000 + 4) == 0xC7
+

+

BANKSET

+

Synopsis:

+
BANKSET EXPRESSION
+
+

Example: +

    BANKSET 0
+
+    org 0x0000
+    db 1,2,3,4
+
+    org 0x4000
+    db 5,6,7,8
+
+    org 0x8000
+    db 9,10,11,12
+
+    org 0xc000
+    db 13, 14, 15, 16
+
+
+    BANKSET 1
+    org 0x0000
+    db 10,20,30,40
+
+    org 0x4000
+    db 50,60,70,80
+
+    org 0x8000
+    db 90,100,110,120
+
+    org 0xc000
+    db 130, 140, 150, 160
+
+
+    BANKSET 0
+    assert memory(0x0000) == 1
+    assert memory(0x4000) == 5
+    assert memory(0x8000) == 9
+    assert memory(0xc000) == 13
+
+    save "good_bankset_0_0.o", 0x0000, 4
+    save "good_bankset_0_1.o", 0x4000, 4
+    save "good_bankset_0_2.o", 0x8000, 4
+    save "good_bankset_0_3.o", 0xc000, 4
+
+    BANKSET 1
+    assert memory(0x0000) == 10
+    assert memory(0x4000) == 50
+    assert memory(0x8000) == 90
+    assert memory(0xc000) == 130
+
+    save "good_bankset_1_0.o", 0x0000, 4
+    save "good_bankset_1_1.o", 0x4000, 4
+    save "good_bankset_1_2.o", 0x8000, 4
+    save "good_bankset_1_3.o", 0xc000, 4
+

+

WRITE DIRECT

+

Description: +WRITE DIRECT is a directive from Winape that we have not fully reproduced. It's two first arguments need to be -1.

+

Example: +

    WRITE DIRECT -1, -1, 0xc0
+    org 0x4000+0
+    db 0xc0
+
+    WRITE DIRECT -1, -1,  0xc4
+    org 0x4000+1
+    db 0xc4
+
+
+    WRITE DIRECT -1, -1,  0xc5
+    org 0x4000+2
+    db 0xc5
+
+    WRITE DIRECT -1, -1,  0xc6
+    org 0x4000+3
+    db 0xc6
+
+
+    WRITE DIRECT -1, -1,  0xc7
+    org 0x4000+4
+    db 0xc7
+
+
+    BANKSET 0
+    assert memory(0x4000 + 0) == 0xC0 
+
+    BANKSET 1
+    assert memory(0x4000 + 2) == 0xC5
+    assert memory(0x8000 + 3) == 0xC6
+    assert memory(0xC000 + 4) == 0xC7
+

+ +

=, SET

+

Description:

+

Assign an expression to a label. Assignement can be repeated several times.

+

Synopsis: +

LABEL = EXPRESSION
+

+

Example: +

label = 1
+label =3
+.label=2
+
+    assert label == 3
+
+
+label = 5
+    assert label == 5
+
+label <<= 1
+    assert label == 10
+

+

EQU

+

Description: +Assign an expression to a label. Assignement cannot be repeated several times.

+

Synopsis: +

LABEL = EXPRESSION
+

+

Example: +

label = 1
+label =3
+.label=2
+
+    assert label == 3
+
+
+label = 5
+    assert label == 5
+
+label <<= 1
+    assert label == 10
+

+

MAP

+

MAP VALUE define a map counter to the required value.#` is used to assign the value to a given label and increment it of the appropriate amount.

+

Example: +

    ; extract stolen here https://github.com/GuillianSeed/MetalGear/blob/master/Variables.asm#L10
+            map #c000
+
+GameStatus:     # 1
+GameSubstatus:      # 1
+ControlConfig:      # 1
+                                ; Bit6: 1=Enable music/Player control
+TickCounter:        # 1
+WaitCounter:        # 1
+TickInProgress:     # 1
+ControlsTrigger:    # 1
+                                ; 5 = Fire2 / M,  4 = Fire / Space, 3 = Right, 2 = Left, 1 = Down, 0 = Up
+ControlsHold:       # 1
+                                ; 5 = Fire2 / M,  4 = Fire / Space, 3 = Right, 2 = Left, 1 = Down, 0 = Up
+Pause_1_F5_2:       # 1
+TutorialStatus:     # 1
+DemolHoldTime:      # 1
+UnusedVar1:     # 1
+DemoPlayId:     # 1
+DemoDataPointer:    # 2
+                                ; Pointer to presaved demo controls
+SprShuffleOffset:   # 1
+
+
+    assert GameStatus = 0xc000
+    assert GameSubstatus = (0xc000 + 1)
+    assert ControlConfig = (0xc000 + 1 + 1)
+    assert TickCounter = (0xc000 + 1 + 1+1)
+    assert DemolHoldTime = (0xc000 + 10)
+    assert SprShuffleOffset = (0xc000 + 15)
+

+

SETN, NEXT

+

MAP directive is probably easier to use

+

Example: +

 ; http://www.aspisys.com/asm11man.htm
+
+ org 0x100
+
+
+data set $
+    assert data == 0x100
+
+data1 setn  data ; data1 could be modified
+data2 next data, 2 ; data2 cannot be modified
+data3 next data
+
+    assert data1 == 0x100
+    assert data2 == 0x101
+    assert data3 == 0x103
+    assert data == 0x104
+

+

UNDEF

+

Example: +

my_label = 1
+
+    ifndef my_label
+        fail "my_label must exist"
+    endif
+
+    undef my_label
+
+    ifdef my_label
+        fail "my_label must not exist"
+    endif
+

+ +

BYTE, TEXT, DB, DEFB, DM, DEFM

+

Example: +

    ; defb tests
+    org 0x200
+
+    defb 1, 2, 3, 4
+    defb "hello", ' ', "world"
+    defb $, $ ; should generate 2 different values
+    db "Hello world", 0
+

+

WORD, DW, DEFW

+

DEFS

+

Example: +

    org 0x100
+
+
+    defs 5
+    defs 5, 8, 4
+    defs 5, 8, 4, 1
+

+

STR

+

Description: +STR encodes string in AMSDOS format (i.e., adds 0x80 to the last char) and stores its bytes in memory.

+

Example: +

    org 0x1000
+    defb "hell"
+    defb 'o' + 0x80
+
+    org 0x2000
+    str "hello"
+
+    org 0x3000
+    db "Next one will be more complex"
+    db "   \" et voila"
+    db " \" et voila"
+    db "\" et voila"
+
+    assert memory(0x1000) == memory(0x2000)
+    assert memory(0x1001) == memory(0x2001)
+    assert memory(0x1002) == memory(0x2002)
+    assert memory(0x1003) == memory(0x2003)
+

+

CHARSET

+

Example: +

 org 0x100
+
+ charset "abcdefghijklmnopqrstuvwxyz", 0
+ charset "AB", 100
+ db "aA"
+ ASSERT memory(0x100) == 0x00
+ ASSERT memory(0x101) == 100
+
+ org 0x200
+ charset
+ db "aA"
+ ASSERT memory(0x200) == 'a'
+ ASSERT memory(0x201) == 'A' 
+

+

Conditional directives

+

IF, IFNOT

+

IFDEF, IFNDEF

+

Example: +

    org 0x1000
+
+    ifndef toto
+    assert toto == $
+toto
+        assert pouet == 0x1002
+        dw pouet
+    endif
+pouet
+

+

IFUSED

+

Example: +

    org 0x1000
+; 3 passes are needed there
+
+    ifused toto
+toto
+        ret
+    endif
+
+    call toto
+
+; test
+

+

Nested conditions

+

Conditions can be nested.

+

Example: +

    org 0x100
+
+    if 0 == 1
+        fail "not reachable"
+    else ifdef toto
+        fail "not reachable"
+    else ifndef toto
+        print "reached"
+        db 1
+    else
+        fail "not reachable"
+    endif
+

+

SWITCH, ENDSWITCH

+

Example: +

    org 0x100
+
+    switch 3
+    ; one comment
+    case 1
+        db 1
+        break
+    case 3
+        db 3
+    ; another comment
+    case 4
+        db 4
+        break
+    case 5
+        db 5
+    default
+        db 6
+    endswitch
+
+
+
+        switch 5
+    case 1
+        db 1
+        break
+    case 3
+        db 3
+    case 4
+        db 4
+        break
+    case 5
+        db 5
+    default
+        db 6
+    endswitch
+

+

Code duplication directives

+

FOR

+
FOR <variable> [, EXPRESSION]+
+  LISTING
+ENDFOR|FEND
+
+

Example: +

    ; Takes inspiration from BRASS assembler
+
+    for count, 0, 10, 3
+        db {count}
+    endfor
+
+    for x, 0, 3
+        for y, 0, 3
+            db {x}*4 + {y}
+        fend
+    endfor
+
+Corresponds to +
        db 0
+        db 3
+        db 6
+        db 9
+
+        db 0*4 + 0
+        db 0*4 + 1
+        db 0*4 + 2
+        db 0*4 + 3
+
+        db 1*4 + 0
+        db 1*4 + 1
+        db 1*4 + 2
+        db 1*4 + 3
+
+        db 2*4 + 0
+        db 2*4 + 1
+        db 2*4 + 2
+        db 2*4 + 3
+
+        db 3*4 + 0
+        db 3*4 + 1
+        db 3*4 + 2
+        db 3*4 + 3
+

+

WHILE

+
CPT=3
+
+    while CPT > 0
+        db CPT
+CPT=CPT-1
+    wend
+
+

REPEAT

+

REPEAT AMOUNT [, COUNTER [, START]] + INNER LISTING +REND

+
start
+    repeat 3, count
+        incbin 'AZERTY{{count}}.TXT'
+    rend
+
+
+    assert char(memory(start+0)) == 'A'
+    assert char(memory(start+1)) == 'Z'
+    assert char(memory(start+2)) == 'E'
+    assert char(memory(start+3)) == 'R'
+    assert char(memory(start+4)) == 'T'
+    assert char(memory(start+5)) == 'Y'
+    assert char(memory(start+6)) == 'U'
+    assert char(memory(start+7)) == 'I'
+    assert char(memory(start+8)) == 'O'
+    assert char(memory(start+9)) == 'P'
+
+    assert char(memory(start+10)) == 'Q'
+    assert char(memory(start+11)) == 'S'
+    assert char(memory(start+12)) == 'D'
+    assert char(memory(start+13)) == 'F'
+    assert char(memory(start+14)) == 'G'
+    assert char(memory(start+15)) == 'H'
+    assert char(memory(start+16)) == 'J'
+    assert char(memory(start+17)) == 'K'
+    assert char(memory(start+18)) == 'L'
+    assert char(memory(start+19)) == 'M'
+
+
+    assert char(memory(start+20)) == 'W'
+    assert char(memory(start+21)) == 'X'
+    assert char(memory(start+22)) == 'C'
+    assert char(memory(start+23)) == 'V'
+    assert char(memory(start+24)) == 'B'
+    assert char(memory(start+25)) == 'N'
+
+

ITERATE

+
ITERATE COUNTER, EXPR...
+    INNER LISTING
+IEND
+
+

The expression $i$ is evaluated after having generated the code of expression $i-1$. Take that into account if expressions use $.

+

Example: +

; Glass inspiration http://www.grauw.nl/projects/glass/
+
+    iterate value, 1, 2, 10
+        add {value}
+        jr nz, @no_inc
+            inc c
+@no_inc
+        call do_stuff
+    iend
+
+
+    iterate value in [11, 12, 110]
+        add {value}
+        jr nz, @no_inc
+            inc c
+@no_inc
+        call do_stuff
+    iend
+
+do_stuff
+    ret
+
+Corresponds to: +
        add 1
+        jr nz, no_inc1
+            inc c
+no_inc1
+        call do_stuff
+
+        add 2
+        jr nz, no_inc2
+            inc c
+no_inc2
+        call do_stuff
+
+        add 10
+        jr nz, no_inc3
+            inc c
+no_inc3
+        call do_stuff
+
+
+        add 11
+        jr nz, no_inc4
+            inc c
+no_inc4
+        call do_stuff
+
+        add 12
+        jr nz, no_inc5
+            inc c
+no_inc5
+        call do_stuff
+
+        add 110
+        jr nz, no_inc6
+            inc c
+no_inc6
+        call do_stuff
+
+do_stuff
+    ret
+

+

Code and data generation directives

+

MACRO

+

Example of standard macro: +

    ; rasm inspired
+    macro LDIXREG register,dep
+        if {dep}<-128 || {dep}>127
+            push BC
+            ld BC,{dep}
+            add IX,BC
+            ld (IX+0),{register}
+            pop BC
+        else
+            ld (IX+{dep}),{register}
+        endif
+    mend
+
+    LDIXREG H,200
+    LDIXREG L,32
+

+

Example of macro using raw arguments: +

    macro BUILD_LABEL r#label
+{label}_first
+    endm
+
+
+    BUILD_LABEL "HERE"
+    BUILD_LABEL "THERE"
+
+    ifndef HERE_first
+        fail "macro error"
+    endif
+    ifndef THERE_first
+        fail "macro error"
+    endif
+
+    macro BUILD_CODE r#code
+        {code}
+    endm
+
+START_CODE1
+    BUILD_CODE "xor a"
+    BUILD_CODE "ld hl, 0xc9fb : ld (0x38), hl"
+END_CODE1
+
+START_CODE2
+    xor a
+    ld hl, 0xc9fb : ld (0x38), hl
+END_CODE2
+
+    assert END_CODE2 - START_CODE2 == END_CODE1 - START_CODE1
+    assert END_CODE2 - START_CODE2 == 7
+
+    assert memory(START_CODE1) == memory(START_CODE2)
+    assert memory(START_CODE1+1) == memory(START_CODE2+1)
+    assert memory(START_CODE1+2) == memory(START_CODE2+2)
+    assert memory(START_CODE1+3) == memory(START_CODE2+3)
+    assert memory(START_CODE1+4) == memory(START_CODE2+4)
+    assert memory(START_CODE1+5) == memory(START_CODE2+5)
+    assert memory(START_CODE1+6) == memory(START_CODE2+6)
+

+

STRUCT

+

Description: +Structures allow to defined data blocs with semantic. +In practice, they replace bunches of DEFB, DEFW directives and enforce checks at assembling (you cannot add more data than expected or forget some). +If a label is used before the use of a struct, it is necessary to postfix it by :. +Otherwise the assembler thinks the label is a macro or structure call.

+

Synopsis

+
STRUCT <name>
+<filed1> DB|DW|STR|<other struct> [<value>]
+...
+<filedn> DB|DW|<other struct> [<value>]
+ENDSTRUCT
+
+
+
+[<label>:] <name> <arg1>, ... , <argn>
+
+

Standard example: +

    struct color
+r db 1
+g db 2
+b db 3
+    endstruct
+
+    struct point
+x db 4
+y db 5
+    endstruct
+
+col0:   color (void)
+pt0:    point (void)
+
+col1:   color 'a', 'b', 'c'
+pt1:    point 'd', 'e'
+
+    struct colored_point
+col     color 10, 20, 30
+pt      point 10, 20
+    endstruct
+
+
+    colored_point (void)
+

+

Example using default values: +

  ;; Define a 3 fields structure
+  struct point
+xx    db 4
+yy    db 5
+zz    db 6
+  endstruct
+
+  assert point == 3
+  assert point.xx == 0
+  assert point.yy == 1
+  assert point.zz == 2
+
+ point 1, 2 , 3
+ point ,,8
+ point 9
+
+
+; force values
+; : after label name allows to disambiguate parser that does not try to check if label is a macro (less errors/faster)
+my_point1: point 1, 2, 3
+
+; use all default values
+my_point2: point (void)
+
+; use default at the end
+my_point3: point 1
+
+; use default at the beginning
+my_point4: point ,,1
+
+
+p1: point 1, 2 , 3
+p2: point ,,8
+p3: point 9
+
+
+
+
+    struct triangle
+p1 point 1, 2 , 3
+p2 point ,,8
+p3 point 9 ; third point
+    endstruct
+
+    assert triangle == 9
+    assert triangle.p1 == 0
+    assert triangle.p2 == 3
+    assert triangle.p3 == 6
+
+
+my_triangle2: triangle [1, 2, 3], [4, 5, 6], [7, 8 , 9]
+
+
+ if 0
+
+
+my_triangle1: triangle
+
+my_triangle2: triangle [1, 2, 3], , [7, 8 , 9]
+ endif
+

+

Data loading and transformation directives

+

Filenames are stored in a string. +These string can do expansion of formulas embedded in {}.

+

basm embeds some files in its executable, they are access under the name "inner://" :

+

LZAPU, LZ48, LZ49

+

Example: +

    org 0x100
+
+
+    ld hl, CS_START
+    ld de, 0xc000
+    call aplib.depack
+    jp $
+
+CS_START
+    LZAPU
+INNER_START
+        defs 100
+INNER_STOP
+    LZCLOSE
+CS_STOP
+
+    assert INNER_STOP - INNER_START == 100
+    assert CS_STOP - CS_START < 100
+
+    include "inner://unaplib.asm" namespace "aplib"
+

+

INCBIN, BINCLUDE

+

INCBIN|BINCLUDE "fname" [[, SKIP], AMOUNT]

+

Fname can be build with variables.

+

Limitations:

+
    +
  • File is loaded fully in memory before being sliced depending on arguments.
  • +
+

Example: +

here
+    incbin "AZERTY.TXT", 2, 3
+there
+
+    assert peek(here) == 'E'
+    assert peek(here+1) == 'R'
+
+    assert there-here == 3
+
+with AZERTY.TXT containing the text AZERTYUIOPQSDFGHJKLMWXCVBN.

+

INCLUDE, READ

+

INCLUDE|READ [ONCE] "<fname>" [AS|MODULE|NAMESPACE "<module>"]

+

Fname can be build with variables.

+

Example with once: +

    org 0x4000
+
+SIZE1_start
+    include once "include_once.asm"
+SIZE1_stop
+
+SIZE2_start
+    include once "include_once.asm"
+SIZE2_stop
+
+    assert (SIZE2_stop - SIZE2_start) == 0
+

+

Example with namespace: +

    include "good_labels.asm" namespace "good"
+
+    ifndef good.outer1
+        fail "good.outer1 is undefined"
+    endif
+
+    ifdef outer1
+        fail "outer1 is defined"
+    endif
+
+    ifndef good.outer2.inner1
+        fail "good.outer2.inner1 is undedined"
+    endif
+

+

Files prefixed by inner:// are embedded by BASM. +Example: +

 include "inner://opcodes_first_byte.asm"
+
+ org 0x4000
+
+ db opcode_inc_l
+ inc l
+
+ assert memory(0x4000) == memory(0x4001)
+

+

In case of conditional assembling, inclusion are only done in the executed branch. This code always assemble as it never includes 'unknonw' file.

+
truc equ 0:if truc:include'unknown':endif:nop
+
+

Data saving and export

+

EXPORT, NOEXPORT

+

Example: +

    org 0x4000
+
+    NOEXPORT
+    EXPORT toto
+
+
+label1
+label2
+toto ; only this one is exported
+

+

SAVE, WRITE

+
    +
  • SAVE "<fname>", [[[START], [SIZE]], AMSDOS|BASIC|TAPE]
  • +
  • SAVE "<fname>", START, SIZE, DSK, "<fname.dsk>" [, SIDE]
  • +
  • SAVE "<fname>", START, SIZE, HFE, "<fname.hfe>" [, SIDE]
  • +
  • SAVE "<fname>", START, SIZE, DISC, "<fname.hfe>"|"<dname.dsk>" [, SIDE]
  • +
+
+

Unimplemented

+

TAPE option is not coded. +Other options are not intensively tested

+
+

Example: +

    org 0x4000
+    run $
+FIRST_ADDRESS
+    ld hl, txt
+loop
+    ld a, (hl)
+    or a
+    jp z, $
+
+    push hl
+        call 0xbb5a
+    pop hl
+    inc hl
+    jp loop
+
+txt
+.start
+    defb "Hello World!"
+    defb 0
+.stop
+LAST_ADDRESS
+
+
+    save "good_save_whole_inner.bin" ; Save binary without header
+    save "hello.bin", FIRST_ADDRESS, LAST_ADDRESS-FIRST_ADDRESS, AMSDOS ; Save a binary with  header
+    save "hello.bin", FIRST_ADDRESS, LAST_ADDRESS-FIRST_ADDRESS, DSK, "hello.dsk" ; Save binary with  header INSIDE a dsk
+
+    if BASM_FEATURE_HFE
+        save "hello.bin", FIRST_ADDRESS, LAST_ADDRESS-FIRST_ADDRESS, HFE, "hello.hfe" ; Save binary with  header INSIDE a hfe file
+    endif
+
+    save "good_save_txt.bin", txt.start, (txt.stop - txt.start) ; save text without header
+
+
+; cmd line to generate the binary with header
+;    basm good_save.asm --binary -o run.bin 
+; cmd line to put it in a dsk
+;    dskmanager test.dsk format --format data42
+;    dskmanager test.dsk add run.bin 
+

+

Debug directives

+

ASSERT

+
ASSERT BOOLEAN_EXPRESSION [, PRINTABLE_EXPRESSION]*
+
+

PRINT

+

Example: +

    print "Hello world"
+
+world = "World"
+    print "hello ", world
+

+ +

TICKER

+

Description: +Compute the execution duration of a block of code

+

Synopsys: +

TICKER START variable
+ instructions
+TICKER STOP
+

+

Example 1: +

; http://mads.atari8.info/mads_eng.html
+
+    TICKER START count
+        WAITNOPS 3
+    TICKER STOP
+
+    assert count == 3
+
+    TICKER START count2
+        nop
+    TICKER STOP
+
+    assert count2 == 1
+

+

Example 2: +

    TICKER START duration_varying_code
+        xor a
+        ld b, 1
+    TICKER STOP
+    assert duration_varying_code == 1 + 2
+    UNDEF duration_varying_code
+
+
+    TICKER START duration_varying_code
+        xor a
+    TICKER STOP
+    assert duration_varying_code == 1 
+    UNDEF duration_varying_code
+
+    TICKER START duration_varying_code
+    TICKER STOP
+    assert duration_varying_code == 0
+    UNDEF duration_varying_code
+
+
+    assert duration(xor a) == 1
+    ;assert duration(xor a : xor a) == 2 ; Does not compile yet Could be a good idea
+
+
+    TICKER START duration_varying_code
+        WAITNOPS 64
+    TICKER STOP
+    assert duration_varying_code == 64
+    UNDEF duration_varying_code
+
+
+    TICKER START duration_stable_code
+        TICKER START duration_varying_code
+            out (c), c
+        TICKER STOP
+        WAITNOPS 64 - duration_varying_code
+    TICKER STOP
+    assert duration_stable_code == 64
+    UNDEF duration_varying_code
+
+
+    MACRO BUILD_STABLE_CODE duration, r#code
+        TICKER START .my_count
+            {code}
+        TICKER STOP
+        ASSERT {duration} >= .my_count
+        WAITNOPS {duration}-.my_count
+
+        IFDEF DEBUG_EXPECTED_DURATION
+            ASSERT .my_count == DEBUG_EXPECTED_DURATION
+        ENDIF
+        UNDEF .my_count
+    ENDM
+
+    DEBUG_EXPECTED_DURATION = 2
+    BUILD_STABLE_CODE 64, "xor a : xor a"
+

+

WAITNOPS

+

Generate a list of instructions that do not modify any registers or memory but is executed with the expected amount of nops. +(Currently it is synonym of NOP, but as soon as someone wants to provide clever rules to use less bytes, I'll implement them)

+

LOCOMOTIVE

+
    LOCOMOTIVE start
+10 REM Basic loader of binary exec
+20 REM yeah !!
+30 call {start}
+    ENDLOCOMOTIVE
+
+start
+        ld hl, txt
+.loop
+        ld a, (hl)
+        or a : jr z, .end
+        call #bb5a
+        inc hl
+        jr .loop
+.end
+        jp $
+
+txt
+    db "Hello world", 0
+
+    print "LOADER START IN ", {hex}start
+    save "LOADER.BAS",,,BASIC
+
+

SNASET

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/basm/index.html b/basm/index.html new file mode 100644 index 00000000..1e7beceb --- /dev/null +++ b/basm/index.html @@ -0,0 +1,679 @@ + + + + + + + + + + + + + + + + + + + + + + BASM documentation - WIP - Amstrad RUST cpcdemotools + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

BASM

+ +

BASM

+

Benediction ASsembler (BASM in short) is a modern Z80 assembler. +He has taken its inspiration from various Z80 assembler (Maxam/Winape, sjasmplus, rasm, vasm, BRASS, glass, zasm) as well as assemblers from other platforms (asm11, sarcasm). +It is tailored for Amstrad CPC demomaking and has been successfully used to develop the Amstrad CPC demo Can Robots Take Control?. +It has been still improved since and will serve for futur productions too.

+

The documentation is quite minimal at the moment, but included example code should be still valid and assembled propetly. +The user base being quite small, lots of bugs can remain. Do note hesitate to fill issues https://github.com/cpcsdk/rust.cpclib/issues or propose fixes.

+

Features of Interest

+
    +
  • Possibility to assemble fake instructions (e.g. ld hl, de).
  • +
  • Possibility to use standard directives (e.g. incbin 'file.asm).
  • +
  • Rare directives and functions (e.g. ld a, opcode(xor a)).
  • +
  • Macros definition and usage (e.g. MY_MACRO_WITH_TWO_ARGS 1, "string").
  • +
  • Function definition and usage (e.g. db 5, my_function(3)).
  • +
  • Expressions able to handle numbers, strings, lists, matrices.
  • +
  • Handling of Amstrad CPC snapshots.
  • +
  • Possibility to execute directly the assembled project in the Amstrad CPC thanks to the M4/CPC WIFI card.
  • +
  • Multi-pass (in fact, BASM uses as many passes as needed).
  • +
  • Multiplatform (mainly tested on Linux and Windows).
  • +
  • Embedding of various ASM source files inside BASM that can be used by the users.
  • +
  • Possibility to write LOCOMOTIVE BASIC for easily writting Amstrad CPC bootstrap loaders.
  • +
+

Hello World

+

An hello world representative of the functionalities of BASM would be: +

    snainit "../cpclib-sna/src/cpc6128.sna" ; should be uneeded by properly specifying sna properties
+
+    org 0x4000
+    run $
+
+
+
+    ld hl, text_content
+loop
+        ld a, (hl)
+        or a
+        jp z, finished
+
+        call TXT_OUTPUT
+        inc hl
+        jp loop
+
+finished
+    jp $
+
+text_content
+    db "Hello, world!", 0
+    include "inner://firmware/txtvdu.asm"
+

+

Download last version

+

Prefer to compile yourself basm. But you can still download latest versions here:

+ +
+

Failure

+

Continuous delivery system for Linux is broken. The executables are outdated of few years...

+
+

Differences with RASM

+
    +
  • slower on the parsing side
  • +
  • more buggy because not enough tested ;)
  • +
  • MODULE directive must be closed by ENDMODULE
  • +
  • REPEAT counter is not accessible by using the variable counter but {counter} as in a MACRO
  • +
  • It is possible to name a MACRO using the label before the MACRO directive
  • +
  • More data types (list, matrix, int, float, boolean)
  • +
  • As basm can use an unlimited number of pass (warning there is not infinite loop check ATM), it can assemble code that would not be assembled with rasm because labels have to be known at this moment
  • +
  • Weak support of DSK``, no support ofTAPEand `CPR. HFE is usable on Linux with the appropriate compilation option. AMSDOS support is buggy ATM
  • +
  • SNA should be ok
  • +
  • Possibility to add some BASIC tokens to create loaders that do not clear the screen when launched
  • +
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/basm/syntax/index.html b/basm/syntax/index.html new file mode 100644 index 00000000..fc13c9bc --- /dev/null +++ b/basm/syntax/index.html @@ -0,0 +1,2216 @@ + + + + + + + + + + + + + + + + + + + + + + Syntax - Amstrad RUST cpcdemotools + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Z80 Syntax

+

General syntax

+
LABEL OPCODE1
+      OPCODE2 : OPCODE3
+      DIRECTIVE
+
+
+

Warning

+

There may be still some subtle parser bugs, but it is possible to span instructions and directives on several lines by ending the previous line with \

+
+

Labels handling

+

BASM is quite lax on the z80 format: it does not impose to start a label at the very first char of a line and does not force an instruction or directive to not start at the very first line of a char (behavior stolen to rasm). +As a consequence there can be ambiguities between labels and macros. +If it fails in properly recognizing macros or label, you can guide it by suffixing label declaration by : or by using (void) for macros with no arguments.

+

Local labels

+
outer1
+    jp outer2
+    jp outer2.inner1
+
+
+outer2
+    jp .inner1
+.inner1
+
+    ifndef outer1
+        fail "outer1 is wrongly undefined"
+    endif
+
+    ifndef .inner1
+        fail ".inner1 is wrongly undefined"
+    endif
+
+    ifndef outer2.inner1
+        fail "outer2.inner1 is wrongly undefined"
+    endif
+
+

module handling

+

    module module1
+label1
+    jp module2.label1
+    endmodule
+
+
+
+    module module2
+label1 
+    jp module3.module31.label1
+    endmodule
+
+    module module3
+        module module31
+label1
+        jp ::label1
+        endmodule
+    endmodule
+label1
+
+would generate a binary similar to +
    jp label1
+label1
+    jp label2
+label2
+    jp label3
+label3
+

+

Labels generation

+

Labels can be generated thanks to the content of other ones. +

value=5
+label{value+2}
+
+    ifndef label7
+        fail "unable to build label with expression"
+    endif
+

+

Instructions

+

Here is the list of instructions used to validate BASM:

+
; Test of assembling of z80 instructions.
+    LIST
+
+    org $0
+
+des equ $05
+n   equ $20
+nn  equ $0584
+
+    ; Documented instructions
+;   ADC
+    adc a,(hl)
+    adc a,(ix + des)
+    adc a,(iy + des)
+    adc a,a
+    adc a,b
+    adc a,c
+    adc a,d
+    adc a,e
+    adc a,h
+    adc a,l
+    adc a,n
+
+    adc hl,bc
+    adc hl,de
+    adc hl,hl
+    adc hl,sp
+
+;   ADD
+    add a,(hl)
+    add a,(ix + des)
+    add a,(iy + des)
+    add a,a
+    add a,b
+    add a,c
+    add a,d
+    add a,e
+    add a,h
+    add a,l
+    add a,n
+
+    add hl,bc
+    add hl,de
+    add hl,hl
+    add hl,sp
+
+    add ix,bc
+    add ix,de
+    add ix,ix
+    add ix,sp
+
+    add iy,bc
+    add iy,de
+    add iy,iy
+    add iy,sp
+
+;   AND
+    and (hl)
+    and (ix + des)
+    and (iy + des)
+    and a
+    and b
+    and c
+    and d
+    and e
+    and h
+    and l
+    and n
+
+;   BIT
+    bit 0,(hl)
+    bit 0,(ix + des)
+    bit 0,(iy + des)
+    bit 0,a
+    bit 0,b
+    bit 0,c
+    bit 0,d
+    bit 0,e
+    bit 0,h
+    bit 0,l
+
+    bit 1,(hl)
+    bit 1,(ix + des)
+    bit 1,(iy + des)
+    bit 1,a
+    bit 1,b
+    bit 1,c
+    bit 1,d
+    bit 1,e
+    bit 1,h
+    bit 1,l
+
+    bit 2,(hl)
+    bit 2,(ix + des)
+    bit 2,(iy + des)
+    bit 2,a
+    bit 2,b
+    bit 2,c
+    bit 2,d
+    bit 2,e
+    bit 2,h
+    bit 2,l
+
+    bit 3,(hl)
+    bit 3,(ix + des)
+    bit 3,(iy + des)
+    bit 3,a
+    bit 3,b
+    bit 3,c
+    bit 3,d
+    bit 3,e
+    bit 3,h
+    bit 3,l
+
+    bit 4,(hl)
+    bit 4,(ix + des)
+    bit 4,(iy + des)
+    bit 4,a
+    bit 4,b
+    bit 4,c
+    bit 4,d
+    bit 4,e
+    bit 4,h
+    bit 4,l
+
+    bit 5,(hl)
+    bit 5,(ix + des)
+    bit 5,(iy + des)
+    bit 5,a
+    bit 5,b
+    bit 5,c
+    bit 5,d
+    bit 5,e
+    bit 5,h
+    bit 5,l
+
+    bit 6,(hl)
+    bit 6,(ix + des)
+    bit 6,(iy + des)
+    bit 6,a
+    bit 6,b
+    bit 6,c
+    bit 6,d
+    bit 6,e
+    bit 6,h
+    bit 6,l
+
+    bit 7,(hl)
+    bit 7,(ix + des)
+    bit 7,(iy + des)
+    bit 7,a
+    bit 7,b
+    bit 7,c
+    bit 7,d
+    bit 7,e
+    bit 7,h
+    bit 7,l
+
+;   CALL
+    call nn
+
+    call nz,nn
+    call z,nn
+    call nc,nn
+    call c,nn
+    call po,nn
+    call pe,nn
+    call p,nn
+    call m,nn
+
+;   CCF
+    ccf
+
+;   CP
+    cp (hl)
+    cp (ix + des)
+    cp (iy + des)
+    cp a
+    cp b
+    cp c
+    cp d
+    cp e
+    cp h
+    cp l
+    cp n
+
+    cpd
+    cpdr
+    cpir
+    cpi
+
+;   CPL
+    cpl
+
+;   DAA
+    daa
+
+;   DEC
+    dec (hl)
+    dec (ix + des)
+    dec (iy + des)
+    dec a
+    dec b
+    dec c
+    dec d
+    dec e
+    dec h
+    dec l
+
+    dec bc
+    dec de
+    dec hl
+    dec ix
+    dec iy
+    dec sp
+
+;   DI
+    di
+
+;   DJNZ
+l1  djnz l1
+
+;   EI
+    ei
+
+;   EX
+    ex af,af'
+
+    ex de,hl
+
+    ex (sp),hl
+    ex (sp),ix
+    ex (sp),iy
+
+    exx
+
+;   HALT
+    halt
+
+;   IM
+    im 0
+    im 1
+    im 2
+
+;   IN
+    in a,(c)
+    in b,(c)
+    in c,(c)
+    in d,(c)
+    in e,(c)
+    in h,(c)
+    in l,(c)
+
+    in a,(n)
+
+    ind
+    indr
+    ini
+    inir
+
+;   INC
+    inc (hl)
+    inc (ix + des)
+    inc (iy + des)
+    inc a
+    inc b
+    inc c
+    inc d
+    inc e
+    inc h
+    inc l
+
+    inc bc
+    inc de
+    inc hl
+    inc ix
+    inc iy
+    inc sp
+
+;   JP
+    jp nn
+
+    jp (hl)
+    jp (ix)
+    jp (iy)
+
+    jp nz,nn
+    jp z,nn
+    jp nc,nn
+    jp c,nn
+    jp po,nn
+    jp pe,nn
+    jp p,nn
+    jp m,nn
+
+;   JR
+    jr $ + $22
+
+    jr nz,$ + $22
+    jr z,$ + $22
+    jr nc,$ + $22
+    jr c,$ + $22
+
+;   LD
+    ld (bc),a
+    ld (de),a
+
+    ld (hl),a
+    ld (hl),b
+    ld (hl),c
+    ld (hl),d
+    ld (hl),e
+    ld (hl),h
+    ld (hl),l
+    ld (hl),n
+
+    ld (ix + des),a
+    ld (ix + des),b
+    ld (ix + des),c
+    ld (ix + des),d
+    ld (ix + des),e
+    ld (ix + des),h
+    ld (ix + des),l
+    ld (ix + des),n
+
+    ld (iy + des),a
+    ld (iy + des),b
+    ld (iy + des),c
+    ld (iy + des),d
+    ld (iy + des),e
+    ld (iy + des),h
+    ld (iy + des),l
+    ld (iy + des),n
+
+    ld (nn),a
+
+    ld (nn),bc
+    ld (nn),de
+    ld (nn),hl
+    ld (nn),ix
+    ld (nn),iy
+
+    ld (nn),sp
+
+    ld a,(bc)
+    ld a,(de)
+    ld a,(hl)
+    ld a,(ix + des)
+    ld a,(iy + des)
+    ld a,(nn)
+    ld a,a
+    ld a,b
+    ld a,c
+    ld a,d
+    ld a,e
+    ld a,h
+    ld a,l
+    ld a,n
+
+    ld b,(hl)
+    ld b,(ix + des)
+    ld b,(iy + des)
+    ld b,a
+    ld b,b
+    ld b,c
+    ld b,d
+    ld b,e
+    ld b,h
+    ld b,l
+    ld b,n
+
+    ld c,(hl)
+    ld c,(ix + des)
+    ld c,(iy + des)
+    ld c,a
+    ld c,b
+    ld c,c
+    ld c,d
+    ld c,e
+    ld c,h
+    ld c,l
+    ld c,n
+
+    ld d,(hl)
+    ld d,(ix + des)
+    ld d,(iy + des)
+    ld d,a
+    ld d,b
+    ld d,c
+    ld d,d
+    ld d,e
+    ld d,h
+    ld d,l
+    ld d,n
+
+    ld e,(hl)
+    ld e,(ix + des)
+    ld e,(iy + des)
+    ld e,a
+    ld e,b
+    ld e,c
+    ld e,d
+    ld e,e
+    ld e,h
+    ld e,l
+    ld e,n
+
+    ld h,(hl)
+    ld h,(ix + des)
+    ld h,(iy + des)
+    ld h,a
+    ld h,b
+    ld h,c
+    ld h,d
+    ld h,e
+    ld h,h
+    ld h,l
+    ld h,n
+
+    ld l,(hl)
+    ld l,(ix + des)
+    ld l,(iy + des)
+    ld l,a
+    ld l,b
+    ld l,c
+    ld l,d
+    ld l,e
+    ld l,h
+    ld l,l
+    ld l,n
+
+    ld a,i
+    ld i,a
+
+    ld a,r
+    ld r,a
+
+    ld bc,(nn)
+    ld de,(nn)
+    ld hl,(nn)
+    ld ix,(nn)
+    ld iy,(nn)
+    ld sp,(nn)
+
+    ld bc,nn
+    ld de,nn
+    ld hl,nn
+    ld ix,nn
+    ld iy,nn
+
+
+    ld sp,hl
+    ld sp,ix
+    ld sp,iy
+    ld sp,nn
+
+    ldd
+    lddr
+    ldi
+    ldir
+
+;   NEG
+    neg
+
+;   NOP
+    nop
+
+;   OR
+    or (hl)
+    or (ix + des)
+    or (iy + des)
+    or a
+    or b
+    or c
+    or d
+    or e
+    or h
+    or l
+    or n
+
+
+;   OUT
+    out (c),a
+    out (c),b
+    out (c),c
+    out (c),d
+    out (c),e
+    out (c),h
+    out (c),l
+    out (n),a
+
+    outd
+    otdr
+    outi
+    otir
+
+;   POP
+    pop af
+    pop bc
+    pop de
+    pop hl
+    pop ix
+    pop iy
+
+;   PUSH
+    push af
+    push bc
+    push de
+    push hl
+    push ix
+    push iy
+
+;   RES
+    res 0,(hl)
+    res 0,(ix + des)
+    res 0,(iy + des)
+    res 0,a
+    res 0,b
+    res 0,c
+    res 0,d
+    res 0,e
+    res 0,h
+    res 0,l
+
+    res 1,(hl)
+    res 1,(ix + des)
+    res 1,(iy + des)
+    res 1,a
+    res 1,b
+    res 1,c
+    res 1,d
+    res 1,e
+    res 1,h
+    res 1,l
+
+    res 2,(hl)
+    res 2,(ix + des)
+    res 2,(iy + des)
+    res 2,a
+    res 2,b
+    res 2,c
+    res 2,d
+    res 2,e
+    res 2,h
+    res 2,l
+
+    res 3,(hl)
+    res 3,(ix + des)
+    res 3,(iy + des)
+    res 3,a
+    res 3,b
+    res 3,c
+    res 3,d
+    res 3,e
+    res 3,h
+    res 3,l
+
+    res 4,(hl)
+    res 4,(ix + des)
+    res 4,(iy + des)
+    res 4,a
+    res 4,b
+    res 4,c
+    res 4,d
+    res 4,e
+    res 4,h
+    res 4,l
+
+    res 5,(hl)
+    res 5,(ix + des)
+    res 5,(iy + des)
+    res 5,a
+    res 5,b
+    res 5,c
+    res 5,d
+    res 5,e
+    res 5,h
+    res 5,l
+
+    res 6,(hl)
+    res 6,(ix + des)
+    res 6,(iy + des)
+    res 6,a
+    res 6,b
+    res 6,c
+    res 6,d
+    res 6,e
+    res 6,h
+    res 6,l
+
+    res 7,(hl)
+    res 7,(ix + des)
+    res 7,(iy + des)
+    res 7,a
+    res 7,b
+    res 7,c
+    res 7,d
+    res 7,e
+    res 7,h
+    res 7,l
+
+;   RET
+    ret
+
+    ret z
+    ret nz
+    ret c
+    ret nc
+    ret po
+    ret pe
+    ret p
+    ret m
+
+    reti
+    retn
+
+;   RL
+    rl (hl)
+    rl (ix + des)
+    rl (iy + des)
+    rl a
+    rl b
+    rl c
+    rl d
+    rl e
+    rl h
+    rl l
+
+;   RLA
+    rla
+
+;   RLC
+    rlc (hl)
+    rlc (ix + des)
+    rlc (iy + des)
+    rlc a
+    rlc b
+    rlc c
+    rlc d
+    rlc e
+    rlc h
+    rlc l
+
+;   RLCA
+    rlca
+
+;   RLD
+    rld
+
+;   RR
+    rr (hl)
+    rr (ix + des)
+    rr (iy + des)
+    rr a
+    rr b
+    rr c
+    rr d
+    rr e
+    rr h
+    rr l
+
+;   RRA
+    rra
+
+;   RRC
+    rrc (hl)
+    rrc (ix + des)
+    rrc (iy + des)
+    rrc a
+    rrc b
+    rrc c
+    rrc d
+    rrc e
+    rrc h
+    rrc l
+
+;   RRCA
+    rrca
+
+;   RRD
+    rrd
+
+;   RST
+    rst $00
+    rst $08
+    rst $10
+    rst $18
+    rst $20
+    rst $28
+    rst $30
+    rst $38
+
+;   SBC
+    sbc a,(hl)
+    sbc a,(ix + des)
+    sbc a,(iy + des)
+    sbc a,a
+    sbc a,b
+    sbc a,c
+    sbc a,d
+    sbc a,e
+    sbc a,h
+    sbc a,l
+    sbc a,n
+
+    sbc hl,bc
+    sbc hl,de
+    sbc hl,hl
+    sbc hl,sp
+
+;   SCF
+    scf
+
+;   SET
+label    set 0,(hl)
+    set 0,(ix + des)
+    set 0,(iy + des)
+    set 0,a
+    set 0,b
+    set 0,c
+    set 0,d
+    set 0,e
+    set 0,h
+    set 0,l
+
+    set 1,(hl)
+    set 1,(ix + des)
+    set 1,(iy + des)
+    set 1,a
+    set 1,b
+    set 1,c
+    set 1,d
+    set 1,e
+    set 1,h
+    set 1,l
+
+    set 2,(hl)
+    set 2,(ix + des)
+    set 2,(iy + des)
+    set 2,a
+    set 2,b
+    set 2,c
+    set 2,d
+    set 2,e
+    set 2,h
+    set 2,l
+
+    set 3,(hl)
+    set 3,(ix + des)
+    set 3,(iy + des)
+    set 3,a
+    set 3,b
+    set 3,c
+    set 3,d
+    set 3,e
+    set 3,h
+    set 3,l
+
+    set 4,(hl)
+    set 4,(ix + des)
+    set 4,(iy + des)
+    set 4,a
+    set 4,b
+    set 4,c
+    set 4,d
+    set 4,e
+    set 4,h
+    set 4,l
+
+    set 5,(hl)
+    set 5,(ix + des)
+    set 5,(iy + des)
+    set 5,a
+    set 5,b
+    set 5,c
+    set 5,d
+    set 5,e
+    set 5,h
+    set 5,l
+
+    set 6,(hl)
+    set 6,(ix + des)
+    set 6,(iy + des)
+    set 6,a
+    set 6,b
+    set 6,c
+    set 6,d
+    set 6,e
+    set 6,h
+    set 6,l
+
+    set 7,(hl)
+    set 7,(ix + des)
+    set 7,(iy + des)
+    set 7,a
+    set 7,b
+    set 7,c
+    set 7,d
+    set 7,e
+    set 7,h
+    set 7,l
+
+;   SLA
+    sla (hl)
+    sla (ix + des)
+    sla (iy + des)
+    sla a
+    sla b
+    sla c
+    sla d
+    sla e
+    sla h
+    sla l
+
+;   SRA
+    sra (hl)
+    sra (ix + des)
+    sra (iy + des)
+    sra a
+    sra b
+    sra c
+    sra d
+    sra e
+    sra h
+    sra l
+
+;   SRL
+    srl (hl)
+    srl (ix + des)
+    srl (iy + des)
+    srl a
+    srl b
+    srl c
+    srl d
+    srl e
+    srl h
+    srl l
+
+;   SUB
+    sub (hl)
+    sub (ix + des)
+    sub (iy + des)
+    sub a
+    sub b
+    sub c
+    sub d
+    sub e
+    sub h
+    sub l
+    sub n
+
+;   XOR
+    xor (hl)
+    xor (ix + des)
+    xor (iy + des)
+    xor a
+    xor b
+    xor c
+    xor d
+    xor e
+    xor h
+    xor l
+    xor n
+
+    ; Undocumented instructions
+; IN
+    in (c)      ; DEFB $ED,$70
+    in f,(c)    ; DEFB $ED,$70
+
+; OUT
+    out (c)     ; DEFB $ED,$71
+    out (c),f   ; DEFB $ED,$71
+
+; SLL
+    sll (hl)
+    sll (ix+des)
+    sll (iy+des)
+    sll a
+    sll b
+    sll c
+    sll d
+    sll e
+    sll h
+    sll l
+
+; IX and IY 8 bits halfs
+    add a,ixh
+    add a,ixl
+    add a,iyh
+    add a,iyl
+
+    adc a,ixh
+    adc a,ixl
+    adc a,iyh
+    adc a,iyl
+
+    and ixh
+    and ixl
+    and iyh
+    and iyl
+
+    cp ixh
+    cp ixl
+    cp iyh
+    cp iyl
+
+    dec ixh
+    dec ixl
+    dec iyh
+    dec iyl
+
+    inc ixh
+    inc ixl
+    inc iyh
+    inc iyl
+
+    ld a,ixh
+    ld b,ixh
+    ld c,ixh
+    ld d,ixh
+    ld e,ixh
+    ;ld h,ixh
+    ;ld l,ixh
+
+    ld a,ixl
+    ld b,ixl
+    ld c,ixl
+    ld d,ixl
+    ld e,ixl
+    ;ld h,ixl
+    ;ld l,ixl
+
+    ld a,iyh
+    ld b,iyh
+    ld c,iyh
+    ld d,iyh
+    ld e,iyh
+    ;ld h,iyh
+    ;ld l,iyh
+
+    ld a,iyl
+    ld b,iyl
+    ld c,iyl
+    ld d,iyl
+    ld e,iyl
+    ;ld h,iyl
+    ;ld l,iyl
+
+    ld ixh,a
+    ld ixh,b
+    ld ixh,c
+    ld ixh,d
+    ld ixh,e
+    ld ixh,ixh
+    ld ixh,ixl
+    ld ixh,n
+
+    ld ixl,a
+    ld ixl,b
+    ld ixl,c
+    ld ixl,d
+    ld ixl,e
+    ld ixl,ixh
+    ld ixl,ixl
+    ld ixl,n
+
+    ld iyh,a
+    ld iyh,b
+    ld iyh,c
+    ld iyh,d
+    ld iyh,e
+    ld iyh,iyh
+    ld iyh,iyl
+    ld iyh,n
+
+    ld iyl,a
+    ld iyl,b
+    ld iyl,c
+    ld iyl,d
+    ld iyl,e
+    ld iyl,iyh
+    ld iyl,iyl
+    ld iyl,n
+
+    or ixh
+    or ixl
+    or iyh
+    or iyl
+
+    sbc a,ixh
+    sbc a,ixl
+    sbc a,iyh
+    sbc a,iyl
+
+    sub ixh
+    sub ixl
+    sub iyh
+    sub iyl
+
+    xor ixh
+    xor ixl
+    xor iyh
+    xor iyl
+
+
+    end
+
+

Fake instructions

+

To ease coding, several fake instructions are allowed by BASM. It replaces them by the combination of true instructions.

+

Here is a subset of the possibilities.

+
+

Failure

+

Most accepted fake instructions are missing from the listing

+
+
    ld hl, de
+    jp hl
+    jp ix
+    jp iy
+    push hl, de, bc
+    pop bc, de, hl
+
+

Comments

+

Expressions

+

Special variables

+
    +
  • $: get the current code address
  • +
  • $$: get the current output address
  • +
+

Example: +

    assert $ == 0
+    assert $$ == 0
+
+    org 0x100
+    assert $ == 0x100
+    assert $$ == 0x100
+    nop
+    assert $ == 0x101
+    assert $$ == 0x101
+
+
+    org 0x200, 0x300
+    assert $ == 0x200
+    assert $$ == 0x300
+    nop
+    assert $ == 0x201
+    assert $$ == 0x301
+

+

Provided functions

+
+

Failure

+

Need to document all functions

+
+ +

assemble

+

assemble(str) consider the string str to be a list of instructions (no directives) and returns the list of bytes corresponding to the assembled version of the given string.

+
    assert list_len(assemble(" nop")) == 1
+    assert list_len(assemble(" nop : nop ")) == 2
+    assert list_len(assemble("")) == 0
+
+

duration

+
    +
  • duration(instruction) returns the number of nop of the instruction
  • +
+

opcode

+
    ld a, opcode(inc e)
+    ld a, opcode(dec e)
+
+

Amstrad CPC video handling

+
    +
  • mode0_byte_to_pen_at
  • +
  • mode1_byte_to_pen_at
  • +
  • mode2_byte_to_pen_at
  • +
  • pen_at_mode0_byte
  • +
  • pen_at_mode1_byte
  • +
  • pen_at_mode2_byte
  • +
  • pens_to_mode0_byte
  • +
  • pens_to_mode1_byte
  • +
  • pens_to_mode2_byte
  • +
+

+
+

List handling

+
    +
  • list_new
  • +
  • list_get(LIST, INDEX)
  • +
  • list_set
  • +
  • list_len
  • +
  • list_sublist(list, start, end) -> list: Return a new list from start until end not included
  • +
  • list_sort
  • +
  • list_argsort
  • +
  • list_push
  • +
+

String handling

+
    +
  • string_new
  • +
  • string_push
  • +
  • string_concat
  • +
  • string_from_list
  • +
+

Matrix handling

+
    +
  • matrix_new
  • +
  • matrix_set
  • +
  • matrix_get
  • +
  • matrix_col
  • +
  • matrix_row
  • +
  • matrix_set_row
  • +
  • matrix_set_col
  • +
  • matrix_width
  • +
  • matrix_height
  • +
+

File handing

+
    +
  • load(fname) -> list of bytes: return the bytes from the given file name
  • +
+

Memory handling

+

memory(addr)

+
    org 0x4000
+    assert memory(label2) == 4
+
+label1
+    db 1, 2, 3
+
+label2
+    db 4, 5, 6
+
+    assert memory(label1) == 1
+    assert memory(label1+2) == 3
+
+

User defined functions

+

BASM allows to define functions that can be used in any expression. +The functions are fed with parameters and execute conditional directives as well as directives able to handle variables. +They finish at the execution of the RETURN directive.

+
FUNCTION [ARG1 [, ARGN]]
+    INSTRUCTIONS
+    RETURN VALUE
+ENDFUNCTION
+
+
+

Failure

+

Better explain how to build function

+
+

Example of the fibonacci function:

+
    function fibo nb
+        if {nb} == 0
+            return 0
+        else if {nb} == 1
+            return 1
+        else
+            return fibo({nb}-1) + fibo({nb}-2)
+        endif
+
+    endfunction
+
+    assert fibo(0) == 0
+    assert fibo(1) == 1
+
+    assert fibo(5) == 5
+
+    assert fibo(10) == 55
+
+

Example of function to handle lists: +

    ; Skip the {start} first element of list {l}
+    FUNCTION SKIP, l, start
+        len = list_len({l})
+        if {start} < len
+            return list_sublist({l}, {start}, len)
+        else
+            return []
+        endif
+    ENDFUNCTION
+
+    ; Take the {amount} first element of list {l}
+    FUNCTION TAKE, l, amount
+        assert {amount} > 0
+        len = list_len({l})
+        start = 0
+        finish = start + min({amount}, len) ; seems to not work for un unknown reason
+        if {amount} > len
+            finish = len
+        else
+            finish = {amount}
+        endif
+        return list_sublist({l}, start, finish)
+    ENDFUNCTION
+
+    ; Reverse list {l}
+    FUNCTION REVERT, l
+        new = []
+        nb = list_len({l})
+        for idx, 0, nb-1
+            new = list_push(new, list_get({l}, nb-1-{idx}))
+        endfor
+        return new
+    ENDFUNCTION
+
+    assert list_len([1, 2, 3, 4]) == 4
+    assert list_sublist([1, 2, 3, 4], 0, 2) == [1,2]
+    assert list_sublist([1, 2, 3, 4], 0, 4) == [1, 2, 3, 4]
+
+
+    ; Various test to check appropriate behavior
+    assert SKIP([1, 2, 3, 4], 2) == [3, 4]
+    assert SKIP([1, 2, 3, 4], 5) == []
+
+    assert TAKE([1, 2, 3, 4], 2) == [1, 2]
+    assert min(4,5) == 4
+    assert TAKE([1, 2, 3, 4], 4) == [1, 2, 3, 4]
+    assert TAKE([1, 2, 3, 4], 10) == [1, 2, 3, 4]
+
+    assert REVERT([1, 2, 3, 4]) == [4, 3, 2, 1]
+    assert list_len(load("hello.sna")) == 4674
+
+    assert list_len(TAKE(load("hello.sna"), 8)) == 8
+
+
+
+    assert string_from_list(TAKE(load("hello.sna"), 8)) == "MV - SNA"
+
+    ; Write in memory 8 bytes from the given file
+    snapshot = load("hello.sna")
+    header_id = TAKE(snapshot, 8)
+    db header_id
+
+    ; Check that memory is correctly set
+    assert peek(0) == "M"
+    assert peek(7) == "A"
+

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/bndbuild/dummy.gif b/bndbuild/dummy.gif new file mode 100644 index 00000000..441705da Binary files /dev/null and b/bndbuild/dummy.gif differ diff --git a/bndbuild/index.html b/bndbuild/index.html new file mode 100644 index 00000000..a6fd789d --- /dev/null +++ b/bndbuild/index.html @@ -0,0 +1,654 @@ + + + + + + + + + + + + + + + + + + + + BNDBUILD - Amstrad RUST cpcdemotools + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Bndbuild

+

Synopsis

+

Makefile-like tool tailored to build Amstrad CPC project. +It embeds various cpclib tools such as basm, m4, img2cpc but can still execute external programs such as rasm, winape.

+

The rules are described in a yaml file. Check for example the test project in folder.

+

Help

+
Benediction CPC demo project builder
+
+Usage: bndbuilder [OPTIONS] [TARGET]...
+
+Arguments:
+  [TARGET]...
+          Provide the target(s) to run.
+
+Options:
+  -h, --help [<CMD>]
+          Show the help of the given subcommand CMD.
+
+          [default: bndbuild]
+          [possible values: img2cpc, basm, rm, bndbuild, xfer]
+
+  -V, --version
+          Print version
+
+  -f, --file <FILE>
+          Provide the YAML file for the given project.
+
+          [default: bndbuild.yml]
+
+  -w, --watch
+          Watch the targets and permanently rebuild them when needed.
+
+

Example

+

Here is an example to build a dummy Amstrad CPC project and execute on the real machine thanks to the m4. +It is available in tests/dummy (the repository does not contains the external tools needed to properly build the project. It is straighforward to add them). +Successive calls to the build task do nothing as soon as no file has been modified. +It is also possible to watch the dependencies of a given task to automatically build it when they are modified. +This cannot be seen with the capture, but each time m4 command is launched, the project is send into the CPC machine (it takes several seconds however).

+

Animation

+

Format

+

The rules description file must respect the yaml text file format. +It is preferably named bndbuild.yml but this can be overriden by the -f argument. +It contains list of rules. +Each rule can have the following keys:

+
    +
  • tgt: to list the files build by the rule
  • +
  • dep: to list the files needed to build the rule
  • +
  • cmd: a command, or a list of commands, executed by the rule. Commands prefixed by - can silently fail
  • +
  • help: an optional help text to describe the rule
  • +
  • phony: an optional tag to express the rule does not generate anyfile (it is infered when the commands are not extern). Mainly serve for the --watch argument.
  • +
+

The commands are either included by the application (so limited to cpclib commands and os agnostic) or accessible externally (no limitation, but os dependent). +They are: +- basm to launch basm assembler +- img2cpc to make image conversion +- rm to delete files +- xfer to transfer to the CPC with the M4 card +- extern to launch any command available on the machine

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..fabf7934 --- /dev/null +++ b/index.html @@ -0,0 +1,519 @@ + + + + + + + + + + + + + + + + + + + + Amstrad RUST cpcdemotools + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

cpclib is a rust library that aims at helping to develop Amstrad CPC demos. +Maybe it could be usefull for other z80 platform or even games. +Most functionalities are still in beta state; +I have only implemented the subset I need for my current Amstrad CPC demo projects. +Several tools are provided in addition to library.

+

There are more are less able to do:

+
- assemble z80 source code.
+   - Mainly interesting for auto-generated code, not for handcrafted one.
+   - Not all opcodes are managed.
+   - Functionalities not available in other assemblers:
+      -  Injection of basic source code (WIP)
+       - Function able to provided the opcode value of an instruction or its standard duration
+- manipulate .sna files
+   - Minimal support of chunks at the moment
+- convert images to CPC format. Usable for standard resolutions/modes
+- manipulate DSK (trying to mimick iDSK or dskmanager). Able to format and add files
+- communicate with cpcwifi board
+  -  Replication of xfer utility.
+  -  Only reset and run file have been coded at the moment
+  -  In opposite to the original xfer tool, cpclib one is able to start snapshots V3 (there are simply converted as snapshot v2 on the fly)
+- create basic tokens from basic source (WIP)
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 00000000..b89c2b9e --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"

cpclib is a rust library that aims at helping to develop Amstrad CPC demos. Maybe it could be usefull for other z80 platform or even games. Most functionalities are still in beta state; I have only implemented the subset I need for my current Amstrad CPC demo projects. Several tools are provided in addition to library.

There are more are less able to do:

- assemble z80 source code.\n   - Mainly interesting for auto-generated code, not for handcrafted one.\n   - Not all opcodes are managed.\n   - Functionalities not available in other assemblers:\n      -  Injection of basic source code (WIP)\n       - Function able to provided the opcode value of an instruction or its standard duration\n- manipulate .sna files\n   - Minimal support of chunks at the moment\n- convert images to CPC format. Usable for standard resolutions/modes\n- manipulate DSK (trying to mimick iDSK or dskmanager). Able to format and add files\n- communicate with cpcwifi board\n  -  Replication of xfer utility.\n  -  Only reset and run file have been coded at the moment\n  -  In opposite to the original xfer tool, cpclib one is able to start snapshots V3 (there are simply converted as snapshot v2 on the fly)\n- create basic tokens from basic source (WIP)\n
"},{"location":"basm/","title":"BASM documentation - WIP","text":""},{"location":"basm/#basm","title":"BASM","text":"

Benediction ASsembler (BASM in short) is a modern Z80 assembler. He has taken its inspiration from various Z80 assembler (Maxam/Winape, sjasmplus, rasm, vasm, BRASS, glass, zasm) as well as assemblers from other platforms (asm11, sarcasm). It is tailored for Amstrad CPC demomaking and has been successfully used to develop the Amstrad CPC demo Can Robots Take Control?. It has been still improved since and will serve for futur productions too.

The documentation is quite minimal at the moment, but included example code should be still valid and assembled propetly. The user base being quite small, lots of bugs can remain. Do note hesitate to fill issues https://github.com/cpcsdk/rust.cpclib/issues or propose fixes.

"},{"location":"basm/#features-of-interest","title":"Features of Interest","text":"
  • Possibility to assemble fake instructions (e.g. ld hl, de).
  • Possibility to use standard directives (e.g. incbin 'file.asm).
  • Rare directives and functions (e.g. ld a, opcode(xor a)).
  • Macros definition and usage (e.g. MY_MACRO_WITH_TWO_ARGS 1, \"string\").
  • Function definition and usage (e.g. db 5, my_function(3)).
  • Expressions able to handle numbers, strings, lists, matrices.
  • Handling of Amstrad CPC snapshots.
  • Possibility to execute directly the assembled project in the Amstrad CPC thanks to the M4/CPC WIFI card.
  • Multi-pass (in fact, BASM uses as many passes as needed).
  • Multiplatform (mainly tested on Linux and Windows).
  • Embedding of various ASM source files inside BASM that can be used by the users.
  • Possibility to write LOCOMOTIVE BASIC for easily writting Amstrad CPC bootstrap loaders.
"},{"location":"basm/#hello-world","title":"Hello World","text":"

An hello world representative of the functionalities of BASM would be:

    snainit \"../cpclib-sna/src/cpc6128.sna\" ; should be uneeded by properly specifying sna properties\n\n    org 0x4000\n    run $\n\n    ld hl, text_content\nloop\n        ld a, (hl)\n        or a\n        jp z, finished\n\n        call TXT_OUTPUT\n        inc hl\n        jp loop\n\nfinished\n    jp $\n\ntext_content\n    db \"Hello, world!\", 0\n    include \"inner://firmware/txtvdu.asm\"\n

"},{"location":"basm/#download-last-version","title":"Download last version","text":"

Prefer to compile yourself basm. But you can still download latest versions here:

  • Linux
  • Windows

Failure

Continuous delivery system for Linux is broken. The executables are outdated of few years...

"},{"location":"basm/#differences-with-rasm","title":"Differences with RASM","text":"
  • slower on the parsing side
  • more buggy because not enough tested ;)
  • MODULE directive must be closed by ENDMODULE
  • REPEAT counter is not accessible by using the variable counter but {counter} as in a MACRO
  • It is possible to name a MACRO using the label before the MACRO directive
  • More data types (list, matrix, int, float, boolean)
  • As basm can use an unlimited number of pass (warning there is not infinite loop check ATM), it can assemble code that would not be assembled with rasm because labels have to be known at this moment
  • Weak support of DSK``, no support ofTAPEand `CPR. HFE is usable on Linux with the appropriate compilation option. AMSDOS support is buggy ATM
  • SNA should be ok
  • Possibility to add some BASIC tokens to create loaders that do not clear the screen when launched
"},{"location":"basm/cmdline/","title":"Command line arguments","text":"

Here is the help provided by basm.

Profile debug compiled: Sun, 20 Aug 2023 20:55:05 +0000\n\nBenediction ASM -- z80 assembler that mainly targets Amstrad CPC\n\nUsage: basm.exe [OPTIONS] [INPUT]\n\nArguments:\n  [INPUT]  Input file to read.\n\nOptions:\n      --inline <INLINE>                Z80 code is provided inline\n  -o, --output <OUTPUT>                Filename of the output.\n      --db                             Write a db list on screen (usefull to get the value of an opcode)\n      --lst <LISTING_OUTPUT>           Filename of the listing output.\n      --sym <SYMBOLS_OUTPUT>           Filename of the output symbols file.\n      --sym_kind <SYMBOLS_KIND>        Format of the output symbols file [default: basm] [possible values: winape, basm]\n      --basic                          Request a Basic header (the very first instruction has to be the LOCOMOTIVE directive).\n      --binary                         Request a binary header\n      --snapshot                       Generate a snapshot\n  -i, --case-insensitive               Configure the assembler to be case insensitive.\n  -d, --directives-prefixed-by-dot     Expect directives to by prefixed with a dot\n  -I, --include <INCLUDE_DIRECTORIES>  Provide additional directories used to search files\n  -D, --define <DEFINE_SYMBOL>         Provide a symbol with its value (default set to 1)\n      --m4 <TO_M4>                     Provide the IP address of the M4\n  -l <LOAD_SYMBOLS>                    Load symbols from the given file\n      --Werror                         Warning are considered to be errors\n      --progress                       Show a progress bar.\n      --list-embedded                  List the embedded files\n      --view-embedded <VIEW_EMBEDDED>  Display one specific embedded file [possible values: inner://crtc.asm, inner://deexo.asm, inner://dzx0_fast.asm, inner://dzx0_standard.asm, inner://firmware/amsdos.asm, inner://firmware/casmng.asm, inner://firmware/gfxvdu.asm, inner://firmware/highkern.asm, inner://firmware/indirect.asm, inner://firmware/kernel.asm, inner://firmware/keymng.asm, inner://firmware/lowkern.asm, inner://firmware/machine.asm, inner://firmware/math6128.asm, inner://firmware/mathnot464.asm, inner://firmware/mathnot6xx.asm, inner://firmware/not464.asm, inner://firmware/scrpack.asm, inner://firmware/sound.asm, inner://firmware/txtvdu.asm, inner://ga.asm, inner://lz48decrunch.asm, inner://lz49decrunch.asm, inner://lz4_docent.asm, inner://opcodes_first_byte.asm, inner://pixels-routs.asm, inner://unaplib.asm, inner://unaplib_fast.asm]\n  -h, --help                           Print help\n  -V, --version                        Print version\n\nStill a Work In Progress assembler\n
"},{"location":"basm/directives/","title":"Directives","text":"

Failure

Not all directives have their synopsis, explanation, and examples

"},{"location":"basm/directives/#listing-related","title":"Listing related","text":""},{"location":"basm/directives/#list-nolist","title":"LIST, NOLIST","text":"

Example:

    org 0\n    LIST\n\n    ld a, 0\n    ; visible in the listing output\n\n    NOLIST\n\n    ld a, 1\n    ; Not visible in the listing ouput\n
"},{"location":"basm/directives/#memory-related","title":"Memory related","text":""},{"location":"basm/directives/#align","title":"ALIGN","text":"

Example:

    org 0x1234\n\n        align 256\n        assert $ == 0x1300\n\n        align 256\n        assert $ == 0x1300\n\n        nop\n\n        align 128, 3\n        assert $ == 0x1300 + 128\n
"},{"location":"basm/directives/#confined","title":"CONFINED","text":"

Confine a memory area of 256 bytes maximum in such a way that it is always possible to navigate in the data by only modifying the low byte address (i.e INC L always works).

CONFINED\n  LISTING\nENDCONFINED\n
;;\n; Confined directive is inspired by confine from rasm.\n; I guess confined is more  ergonomic has it does not requires to manually specify the size of the confined area\n\n    org 0x0000\n\n    CONFINED\n        assert $ == 0\n        defs 128, 0xff\n    ENDCONFINED\n\n    CONFINED\n        assert $ == 256\n        defs 200, 0xff\n    ENDCONFINED\n\n    CONFINED\n        assert $ == 256 + 200\n        defs 20, 0xff\n    ENDCONFINED\n
"},{"location":"basm/directives/#org","title":"ORG","text":""},{"location":"basm/directives/#limit","title":"LIMIT","text":"

On the code space ($), not physical space ($$)

Example of code that assembles:

    org 0x100\n\n    limit 102\n

Example of code that fails:

\n

"},{"location":"basm/directives/#phase-dephase","title":"PHASE, DEPHASE","text":"
; https://k1.spdns.de/Develop/Projects/zasm/Documentation/z71.htm\n    org 0x100\n\nlabel_100\n    nop\nlabel_101\n\n    assert $$ == 0x101\n    assert $ == 0x101\n\n    phase 0x200\n\n    assert $$ == 0x101\n    assert $ == 0x200\n\nlabel_200\n    nop\nlabel_201\n\n    dephase\nlabel_102\n\n    assert label_100 == 0x100\n    assert label_101 == 0x101\n    assert label_102 == 0x102\n    assert label_200 == 0x200\n    assert label_201 == 0x201\n
"},{"location":"basm/directives/#protect","title":"PROTECT","text":"

Synopsis:

PROTECT START, STOP\n
Description: Mark the memory between START and STOP as protected against write. Assembler fails when writting there.

On the code space ($), not physical space ($$)

Example:

    org 0x4000\n\n    protect 0x8000, 0xbfff\n\n    defb \"No memory issue\"\n

"},{"location":"basm/directives/#range-section","title":"RANGE, SECTION","text":"

Description: RANGE allows to define named portion of the memory, while SECTION allows to chose the portion of interest.

Example:

; sarcasm inspiration https://www.ecstaticlyrics.com/electronics/Z80/sarcasm/\n\nrange $0080, $3FFF, code\nrange $4000, $7FFF, data\n\nsection code\n  ld hl, message_1\n  call print_message\n\nsection data\nmessage_1: db \"This is message #1.\", $00\n\nsection code\n  ld hl, message_2\n  call print_message\n\nsection data\nmessage_2: db \"This is message #2.\", $00\n\nsection code\n  print_message: \n    ld a, (hl)\n    or a\n    ret z\n    call 0xbb5a\n    inc hl\n    jr print_message\n\n    assert section_start(\"data\") ==  0x4000\n    assert section_length(\"data\") == 0x4000\n    assert section_used(\"data\") == 40\n

"},{"location":"basm/directives/#bank","title":"BANK","text":"

Description:

When used with no argument, a bank corresponds to a memory area outside of the snapshot. All things read&write in memory are thus uncorrelated to the snapshot. Sections do not apply in a bank.

BANK page is similar to WRITE DIRECT -1 -1 page

Synopsis:

BANK [EXPRESSION]\n

Example:

    ; Set up a unique value in various banks\n    BANK 0xc0\n    org 0x4000 + 0\n    db 0xc0\n\n    BANK 0xc4\n    org 0x4000 + 1\n    db 0xc4\n\n    BANK 0xc5\n    org 0x4000 + 2\n    db 0xc5\n\n    BANK 0xc6\n    org 0x4000 + 3\n    db 0xc6\n\n    BANK 0xc7\n    org 0x4000 + 4\n    db 0xc7\n\n    BANKSET 0\n    assert memory(0x4000 + 0) == 0xC0 \n\n    BANKSET 1\n    assert memory(0x4000 + 2) == 0xC5\n    assert memory(0x8000 + 3) == 0xC6\n    assert memory(0xC000 + 4) == 0xC7\n

"},{"location":"basm/directives/#bankset","title":"BANKSET","text":"

Synopsis:

BANKSET EXPRESSION\n

Example:

    BANKSET 0\n\n    org 0x0000\n    db 1,2,3,4\n\n    org 0x4000\n    db 5,6,7,8\n\n    org 0x8000\n    db 9,10,11,12\n\n    org 0xc000\n    db 13, 14, 15, 16\n\n    BANKSET 1\n    org 0x0000\n    db 10,20,30,40\n\n    org 0x4000\n    db 50,60,70,80\n\n    org 0x8000\n    db 90,100,110,120\n\n    org 0xc000\n    db 130, 140, 150, 160\n\n    BANKSET 0\n    assert memory(0x0000) == 1\n    assert memory(0x4000) == 5\n    assert memory(0x8000) == 9\n    assert memory(0xc000) == 13\n\n    save \"good_bankset_0_0.o\", 0x0000, 4\n    save \"good_bankset_0_1.o\", 0x4000, 4\n    save \"good_bankset_0_2.o\", 0x8000, 4\n    save \"good_bankset_0_3.o\", 0xc000, 4\n\n    BANKSET 1\n    assert memory(0x0000) == 10\n    assert memory(0x4000) == 50\n    assert memory(0x8000) == 90\n    assert memory(0xc000) == 130\n\n    save \"good_bankset_1_0.o\", 0x0000, 4\n    save \"good_bankset_1_1.o\", 0x4000, 4\n    save \"good_bankset_1_2.o\", 0x8000, 4\n    save \"good_bankset_1_3.o\", 0xc000, 4\n

"},{"location":"basm/directives/#write-direct","title":"WRITE DIRECT","text":"

Description: WRITE DIRECT is a directive from Winape that we have not fully reproduced. It's two first arguments need to be -1.

Example:

    WRITE DIRECT -1, -1, 0xc0\n    org 0x4000+0\n    db 0xc0\n\n    WRITE DIRECT -1, -1,  0xc4\n    org 0x4000+1\n    db 0xc4\n\n    WRITE DIRECT -1, -1,  0xc5\n    org 0x4000+2\n    db 0xc5\n\n    WRITE DIRECT -1, -1,  0xc6\n    org 0x4000+3\n    db 0xc6\n\n    WRITE DIRECT -1, -1,  0xc7\n    org 0x4000+4\n    db 0xc7\n\n    BANKSET 0\n    assert memory(0x4000 + 0) == 0xC0 \n\n    BANKSET 1\n    assert memory(0x4000 + 2) == 0xC5\n    assert memory(0x8000 + 3) == 0xC6\n    assert memory(0xC000 + 4) == 0xC7\n

"},{"location":"basm/directives/#labels-related","title":"Labels related","text":""},{"location":"basm/directives/#set","title":"=, SET","text":"

Description:

Assign an expression to a label. Assignement can be repeated several times.

Synopsis:

LABEL = EXPRESSION\n

Example:

label = 1\nlabel =3\n.label=2\n\n    assert label == 3\n\nlabel = 5\n    assert label == 5\n\nlabel <<= 1\n    assert label == 10\n

"},{"location":"basm/directives/#equ","title":"EQU","text":"

Description: Assign an expression to a label. Assignement cannot be repeated several times.

Synopsis:

LABEL = EXPRESSION\n

Example:

label = 1\nlabel =3\n.label=2\n\n    assert label == 3\n\nlabel = 5\n    assert label == 5\n\nlabel <<= 1\n    assert label == 10\n

"},{"location":"basm/directives/#map","title":"MAP","text":"

MAP VALUE define a map counter to the required value.#` is used to assign the value to a given label and increment it of the appropriate amount.

Example:

    ; extract stolen here https://github.com/GuillianSeed/MetalGear/blob/master/Variables.asm#L10\n            map #c000\n\nGameStatus:     # 1\nGameSubstatus:      # 1\nControlConfig:      # 1\n                                ; Bit6: 1=Enable music/Player control\nTickCounter:        # 1\nWaitCounter:        # 1\nTickInProgress:     # 1\nControlsTrigger:    # 1\n                                ; 5 = Fire2 / M,  4 = Fire / Space, 3 = Right, 2 = Left, 1 = Down, 0 = Up\nControlsHold:       # 1\n                                ; 5 = Fire2 / M,  4 = Fire / Space, 3 = Right, 2 = Left, 1 = Down, 0 = Up\nPause_1_F5_2:       # 1\nTutorialStatus:     # 1\nDemolHoldTime:      # 1\nUnusedVar1:     # 1\nDemoPlayId:     # 1\nDemoDataPointer:    # 2\n                                ; Pointer to presaved demo controls\nSprShuffleOffset:   # 1\n\n    assert GameStatus = 0xc000\n    assert GameSubstatus = (0xc000 + 1)\n    assert ControlConfig = (0xc000 + 1 + 1)\n    assert TickCounter = (0xc000 + 1 + 1+1)\n    assert DemolHoldTime = (0xc000 + 10)\n    assert SprShuffleOffset = (0xc000 + 15)\n

"},{"location":"basm/directives/#setn-next","title":"SETN, NEXT","text":"

MAP directive is probably easier to use

Example:

 ; http://www.aspisys.com/asm11man.htm\n\n org 0x100\n\ndata set $\n    assert data == 0x100\n\ndata1 setn  data ; data1 could be modified\ndata2 next data, 2 ; data2 cannot be modified\ndata3 next data\n\n    assert data1 == 0x100\n    assert data2 == 0x101\n    assert data3 == 0x103\n    assert data == 0x104\n

"},{"location":"basm/directives/#undef","title":"UNDEF","text":"

Example:

my_label = 1\n\n    ifndef my_label\n        fail \"my_label must exist\"\n    endif\n\n    undef my_label\n\n    ifdef my_label\n        fail \"my_label must not exist\"\n    endif\n

"},{"location":"basm/directives/#data-related","title":"Data related","text":""},{"location":"basm/directives/#byte-text-db-defb-dm-defm","title":"BYTE, TEXT, DB, DEFB, DM, DEFM","text":"

Example:

    ; defb tests\n    org 0x200\n\n    defb 1, 2, 3, 4\n    defb \"hello\", ' ', \"world\"\n    defb $, $ ; should generate 2 different values\n    db \"Hello world\", 0\n

"},{"location":"basm/directives/#word-dw-defw","title":"WORD, DW, DEFW","text":""},{"location":"basm/directives/#defs","title":"DEFS","text":"

Example:

    org 0x100\n\n    defs 5\n    defs 5, 8, 4\n    defs 5, 8, 4, 1\n

"},{"location":"basm/directives/#str","title":"STR","text":"

Description: STR encodes string in AMSDOS format (i.e., adds 0x80 to the last char) and stores its bytes in memory.

Example:

    org 0x1000\n    defb \"hell\"\n    defb 'o' + 0x80\n\n    org 0x2000\n    str \"hello\"\n\n    org 0x3000\n    db \"Next one will be more complex\"\n    db \"   \\\" et voila\"\n    db \" \\\" et voila\"\n    db \"\\\" et voila\"\n\n    assert memory(0x1000) == memory(0x2000)\n    assert memory(0x1001) == memory(0x2001)\n    assert memory(0x1002) == memory(0x2002)\n    assert memory(0x1003) == memory(0x2003)\n

"},{"location":"basm/directives/#charset","title":"CHARSET","text":"

Example:

 org 0x100\n\n charset \"abcdefghijklmnopqrstuvwxyz\", 0\n charset \"AB\", 100\n db \"aA\"\n ASSERT memory(0x100) == 0x00\n ASSERT memory(0x101) == 100\n\n org 0x200\n charset\n db \"aA\"\n ASSERT memory(0x200) == 'a'\n ASSERT memory(0x201) == 'A' \n

"},{"location":"basm/directives/#conditional-directives","title":"Conditional directives","text":""},{"location":"basm/directives/#if-ifnot","title":"IF, IFNOT","text":""},{"location":"basm/directives/#ifdef-ifndef","title":"IFDEF, IFNDEF","text":"

Example:

    org 0x1000\n\n    ifndef toto\n    assert toto == $\ntoto\n        assert pouet == 0x1002\n        dw pouet\n    endif\npouet\n

"},{"location":"basm/directives/#ifused","title":"IFUSED","text":"

Example:

    org 0x1000\n; 3 passes are needed there\n\n    ifused toto\ntoto\n        ret\n    endif\n\n    call toto\n\n; test\n

"},{"location":"basm/directives/#nested-conditions","title":"Nested conditions","text":"

Conditions can be nested.

Example:

    org 0x100\n\n    if 0 == 1\n        fail \"not reachable\"\n    else ifdef toto\n        fail \"not reachable\"\n    else ifndef toto\n        print \"reached\"\n        db 1\n    else\n        fail \"not reachable\"\n    endif\n

"},{"location":"basm/directives/#switch-endswitch","title":"SWITCH, ENDSWITCH","text":"

Example:

    org 0x100\n\n    switch 3\n    ; one comment\n    case 1\n        db 1\n        break\n    case 3\n        db 3\n    ; another comment\n    case 4\n        db 4\n        break\n    case 5\n        db 5\n    default\n        db 6\n    endswitch\n\n        switch 5\n    case 1\n        db 1\n        break\n    case 3\n        db 3\n    case 4\n        db 4\n        break\n    case 5\n        db 5\n    default\n        db 6\n    endswitch\n

"},{"location":"basm/directives/#code-duplication-directives","title":"Code duplication directives","text":""},{"location":"basm/directives/#for","title":"FOR","text":"
FOR <variable> [, EXPRESSION]+\n  LISTING\nENDFOR|FEND\n

Example:

    ; Takes inspiration from BRASS assembler\n\n    for count, 0, 10, 3\n        db {count}\n    endfor\n\n    for x, 0, 3\n        for y, 0, 3\n            db {x}*4 + {y}\n        fend\n    endfor\n
Corresponds to
        db 0\n        db 3\n        db 6\n        db 9\n\n        db 0*4 + 0\n        db 0*4 + 1\n        db 0*4 + 2\n        db 0*4 + 3\n\n        db 1*4 + 0\n        db 1*4 + 1\n        db 1*4 + 2\n        db 1*4 + 3\n\n        db 2*4 + 0\n        db 2*4 + 1\n        db 2*4 + 2\n        db 2*4 + 3\n\n        db 3*4 + 0\n        db 3*4 + 1\n        db 3*4 + 2\n        db 3*4 + 3\n

"},{"location":"basm/directives/#while","title":"WHILE","text":"
CPT=3\n\n    while CPT > 0\n        db CPT\nCPT=CPT-1\n    wend\n
"},{"location":"basm/directives/#repeat","title":"REPEAT","text":"

REPEAT AMOUNT [, COUNTER [, START]] INNER LISTING REND

start\n    repeat 3, count\n        incbin 'AZERTY{{count}}.TXT'\n    rend\n\n    assert char(memory(start+0)) == 'A'\n    assert char(memory(start+1)) == 'Z'\n    assert char(memory(start+2)) == 'E'\n    assert char(memory(start+3)) == 'R'\n    assert char(memory(start+4)) == 'T'\n    assert char(memory(start+5)) == 'Y'\n    assert char(memory(start+6)) == 'U'\n    assert char(memory(start+7)) == 'I'\n    assert char(memory(start+8)) == 'O'\n    assert char(memory(start+9)) == 'P'\n\n    assert char(memory(start+10)) == 'Q'\n    assert char(memory(start+11)) == 'S'\n    assert char(memory(start+12)) == 'D'\n    assert char(memory(start+13)) == 'F'\n    assert char(memory(start+14)) == 'G'\n    assert char(memory(start+15)) == 'H'\n    assert char(memory(start+16)) == 'J'\n    assert char(memory(start+17)) == 'K'\n    assert char(memory(start+18)) == 'L'\n    assert char(memory(start+19)) == 'M'\n\n    assert char(memory(start+20)) == 'W'\n    assert char(memory(start+21)) == 'X'\n    assert char(memory(start+22)) == 'C'\n    assert char(memory(start+23)) == 'V'\n    assert char(memory(start+24)) == 'B'\n    assert char(memory(start+25)) == 'N'\n
"},{"location":"basm/directives/#iterate","title":"ITERATE","text":"
ITERATE COUNTER, EXPR...\n    INNER LISTING\nIEND\n

The expression $i$ is evaluated after having generated the code of expression $i-1$. Take that into account if expressions use $.

Example:

; Glass inspiration http://www.grauw.nl/projects/glass/\n\n    iterate value, 1, 2, 10\n        add {value}\n        jr nz, @no_inc\n            inc c\n@no_inc\n        call do_stuff\n    iend\n\n    iterate value in [11, 12, 110]\n        add {value}\n        jr nz, @no_inc\n            inc c\n@no_inc\n        call do_stuff\n    iend\n\ndo_stuff\n    ret\n
Corresponds to:
        add 1\n        jr nz, no_inc1\n            inc c\nno_inc1\n        call do_stuff\n\n        add 2\n        jr nz, no_inc2\n            inc c\nno_inc2\n        call do_stuff\n\n        add 10\n        jr nz, no_inc3\n            inc c\nno_inc3\n        call do_stuff\n\n        add 11\n        jr nz, no_inc4\n            inc c\nno_inc4\n        call do_stuff\n\n        add 12\n        jr nz, no_inc5\n            inc c\nno_inc5\n        call do_stuff\n\n        add 110\n        jr nz, no_inc6\n            inc c\nno_inc6\n        call do_stuff\n\ndo_stuff\n    ret\n

"},{"location":"basm/directives/#code-and-data-generation-directives","title":"Code and data generation directives","text":""},{"location":"basm/directives/#macro","title":"MACRO","text":"

Example of standard macro:

    ; rasm inspired\n    macro LDIXREG register,dep\n        if {dep}<-128 || {dep}>127\n            push BC\n            ld BC,{dep}\n            add IX,BC\n            ld (IX+0),{register}\n            pop BC\n        else\n            ld (IX+{dep}),{register}\n        endif\n    mend\n\n    LDIXREG H,200\n    LDIXREG L,32\n

Example of macro using raw arguments:

    macro BUILD_LABEL r#label\n{label}_first\n    endm\n\n    BUILD_LABEL \"HERE\"\n    BUILD_LABEL \"THERE\"\n\n    ifndef HERE_first\n        fail \"macro error\"\n    endif\n    ifndef THERE_first\n        fail \"macro error\"\n    endif\n\n    macro BUILD_CODE r#code\n        {code}\n    endm\n\nSTART_CODE1\n    BUILD_CODE \"xor a\"\n    BUILD_CODE \"ld hl, 0xc9fb : ld (0x38), hl\"\nEND_CODE1\n\nSTART_CODE2\n    xor a\n    ld hl, 0xc9fb : ld (0x38), hl\nEND_CODE2\n\n    assert END_CODE2 - START_CODE2 == END_CODE1 - START_CODE1\n    assert END_CODE2 - START_CODE2 == 7\n\n    assert memory(START_CODE1) == memory(START_CODE2)\n    assert memory(START_CODE1+1) == memory(START_CODE2+1)\n    assert memory(START_CODE1+2) == memory(START_CODE2+2)\n    assert memory(START_CODE1+3) == memory(START_CODE2+3)\n    assert memory(START_CODE1+4) == memory(START_CODE2+4)\n    assert memory(START_CODE1+5) == memory(START_CODE2+5)\n    assert memory(START_CODE1+6) == memory(START_CODE2+6)\n

"},{"location":"basm/directives/#struct","title":"STRUCT","text":"

Description: Structures allow to defined data blocs with semantic. In practice, they replace bunches of DEFB, DEFW directives and enforce checks at assembling (you cannot add more data than expected or forget some). If a label is used before the use of a struct, it is necessary to postfix it by :. Otherwise the assembler thinks the label is a macro or structure call.

Synopsis

STRUCT <name>\n<filed1> DB|DW|STR|<other struct> [<value>]\n...\n<filedn> DB|DW|<other struct> [<value>]\nENDSTRUCT\n\n[<label>:] <name> <arg1>, ... , <argn>\n

Standard example:

    struct color\nr db 1\ng db 2\nb db 3\n    endstruct\n\n    struct point\nx db 4\ny db 5\n    endstruct\n\ncol0:   color (void)\npt0:    point (void)\n\ncol1:   color 'a', 'b', 'c'\npt1:    point 'd', 'e'\n\n    struct colored_point\ncol     color 10, 20, 30\npt      point 10, 20\n    endstruct\n\n    colored_point (void)\n

Example using default values:

  ;; Define a 3 fields structure\n  struct point\nxx    db 4\nyy    db 5\nzz    db 6\n  endstruct\n\n  assert point == 3\n  assert point.xx == 0\n  assert point.yy == 1\n  assert point.zz == 2\n\n point 1, 2 , 3\n point ,,8\n point 9\n\n; force values\n; : after label name allows to disambiguate parser that does not try to check if label is a macro (less errors/faster)\nmy_point1: point 1, 2, 3\n\n; use all default values\nmy_point2: point (void)\n\n; use default at the end\nmy_point3: point 1\n\n; use default at the beginning\nmy_point4: point ,,1\n\np1: point 1, 2 , 3\np2: point ,,8\np3: point 9\n\n    struct triangle\np1 point 1, 2 , 3\np2 point ,,8\np3 point 9 ; third point\n    endstruct\n\n    assert triangle == 9\n    assert triangle.p1 == 0\n    assert triangle.p2 == 3\n    assert triangle.p3 == 6\n\nmy_triangle2: triangle [1, 2, 3], [4, 5, 6], [7, 8 , 9]\n\n if 0\n\nmy_triangle1: triangle\n\nmy_triangle2: triangle [1, 2, 3], , [7, 8 , 9]\n endif\n

"},{"location":"basm/directives/#data-loading-and-transformation-directives","title":"Data loading and transformation directives","text":"

Filenames are stored in a string. These string can do expansion of formulas embedded in {}.

basm embeds some files in its executable, they are access under the name \"inner://\" :

"},{"location":"basm/directives/#lzapu-lz48-lz49","title":"LZAPU, LZ48, LZ49","text":"

Example:

    org 0x100\n\n    ld hl, CS_START\n    ld de, 0xc000\n    call aplib.depack\n    jp $\n\nCS_START\n    LZAPU\nINNER_START\n        defs 100\nINNER_STOP\n    LZCLOSE\nCS_STOP\n\n    assert INNER_STOP - INNER_START == 100\n    assert CS_STOP - CS_START < 100\n\n    include \"inner://unaplib.asm\" namespace \"aplib\"\n

"},{"location":"basm/directives/#incbin-binclude","title":"INCBIN, BINCLUDE","text":"

INCBIN|BINCLUDE \"fname\" [[, SKIP], AMOUNT]

Fname can be build with variables.

Limitations:

  • File is loaded fully in memory before being sliced depending on arguments.

Example:

here\n    incbin \"AZERTY.TXT\", 2, 3\nthere\n\n    assert peek(here) == 'E'\n    assert peek(here+1) == 'R'\n\n    assert there-here == 3\n
with AZERTY.TXT containing the text AZERTYUIOPQSDFGHJKLMWXCVBN.

"},{"location":"basm/directives/#include-read","title":"INCLUDE, READ","text":"

INCLUDE|READ [ONCE] \"<fname>\" [AS|MODULE|NAMESPACE \"<module>\"]

Fname can be build with variables.

Example with once:

    org 0x4000\n\nSIZE1_start\n    include once \"include_once.asm\"\nSIZE1_stop\n\nSIZE2_start\n    include once \"include_once.asm\"\nSIZE2_stop\n\n    assert (SIZE2_stop - SIZE2_start) == 0\n

Example with namespace:

    include \"good_labels.asm\" namespace \"good\"\n\n    ifndef good.outer1\n        fail \"good.outer1 is undefined\"\n    endif\n\n    ifdef outer1\n        fail \"outer1 is defined\"\n    endif\n\n    ifndef good.outer2.inner1\n        fail \"good.outer2.inner1 is undedined\"\n    endif\n

Files prefixed by inner:// are embedded by BASM. Example:

 include \"inner://opcodes_first_byte.asm\"\n\n org 0x4000\n\n db opcode_inc_l\n inc l\n\n assert memory(0x4000) == memory(0x4001)\n

In case of conditional assembling, inclusion are only done in the executed branch. This code always assemble as it never includes 'unknonw' file.

truc equ 0:if truc:include'unknown':endif:nop\n
"},{"location":"basm/directives/#data-saving-and-export","title":"Data saving and export","text":""},{"location":"basm/directives/#export-noexport","title":"EXPORT, NOEXPORT","text":"

Example:

    org 0x4000\n\n    NOEXPORT\n    EXPORT toto\n\nlabel1\nlabel2\ntoto ; only this one is exported\n

"},{"location":"basm/directives/#save-write","title":"SAVE, WRITE","text":"
  • SAVE \"<fname>\", [[[START], [SIZE]], AMSDOS|BASIC|TAPE]
  • SAVE \"<fname>\", START, SIZE, DSK, \"<fname.dsk>\" [, SIDE]
  • SAVE \"<fname>\", START, SIZE, HFE, \"<fname.hfe>\" [, SIDE]
  • SAVE \"<fname>\", START, SIZE, DISC, \"<fname.hfe>\"|\"<dname.dsk>\" [, SIDE]

Unimplemented

TAPE option is not coded. Other options are not intensively tested

Example:

    org 0x4000\n    run $\nFIRST_ADDRESS\n    ld hl, txt\nloop\n    ld a, (hl)\n    or a\n    jp z, $\n\n    push hl\n        call 0xbb5a\n    pop hl\n    inc hl\n    jp loop\n\ntxt\n.start\n    defb \"Hello World!\"\n    defb 0\n.stop\nLAST_ADDRESS\n\n    save \"good_save_whole_inner.bin\" ; Save binary without header\n    save \"hello.bin\", FIRST_ADDRESS, LAST_ADDRESS-FIRST_ADDRESS, AMSDOS ; Save a binary with  header\n    save \"hello.bin\", FIRST_ADDRESS, LAST_ADDRESS-FIRST_ADDRESS, DSK, \"hello.dsk\" ; Save binary with  header INSIDE a dsk\n\n    if BASM_FEATURE_HFE\n        save \"hello.bin\", FIRST_ADDRESS, LAST_ADDRESS-FIRST_ADDRESS, HFE, \"hello.hfe\" ; Save binary with  header INSIDE a hfe file\n    endif\n\n    save \"good_save_txt.bin\", txt.start, (txt.stop - txt.start) ; save text without header\n\n; cmd line to generate the binary with header\n;    basm good_save.asm --binary -o run.bin \n; cmd line to put it in a dsk\n;    dskmanager test.dsk format --format data42\n;    dskmanager test.dsk add run.bin \n

"},{"location":"basm/directives/#debug-directives","title":"Debug directives","text":""},{"location":"basm/directives/#assert","title":"ASSERT","text":"
ASSERT BOOLEAN_EXPRESSION [, PRINTABLE_EXPRESSION]*\n
"},{"location":"basm/directives/#print","title":"PRINT","text":"

Example:

    print \"Hello world\"\n\nworld = \"World\"\n    print \"hello \", world\n

"},{"location":"basm/directives/#amstrad-cpc-related-directives","title":"Amstrad CPC related directives","text":""},{"location":"basm/directives/#ticker","title":"TICKER","text":"

Description: Compute the execution duration of a block of code

Synopsys:

TICKER START variable\n instructions\nTICKER STOP\n

Example 1:

; http://mads.atari8.info/mads_eng.html\n\n    TICKER START count\n        WAITNOPS 3\n    TICKER STOP\n\n    assert count == 3\n\n    TICKER START count2\n        nop\n    TICKER STOP\n\n    assert count2 == 1\n

Example 2:

    TICKER START duration_varying_code\n        xor a\n        ld b, 1\n    TICKER STOP\n    assert duration_varying_code == 1 + 2\n    UNDEF duration_varying_code\n\n    TICKER START duration_varying_code\n        xor a\n    TICKER STOP\n    assert duration_varying_code == 1 \n    UNDEF duration_varying_code\n\n    TICKER START duration_varying_code\n    TICKER STOP\n    assert duration_varying_code == 0\n    UNDEF duration_varying_code\n\n    assert duration(xor a) == 1\n    ;assert duration(xor a : xor a) == 2 ; Does not compile yet Could be a good idea\n\n    TICKER START duration_varying_code\n        WAITNOPS 64\n    TICKER STOP\n    assert duration_varying_code == 64\n    UNDEF duration_varying_code\n\n    TICKER START duration_stable_code\n        TICKER START duration_varying_code\n            out (c), c\n        TICKER STOP\n        WAITNOPS 64 - duration_varying_code\n    TICKER STOP\n    assert duration_stable_code == 64\n    UNDEF duration_varying_code\n\n    MACRO BUILD_STABLE_CODE duration, r#code\n        TICKER START .my_count\n            {code}\n        TICKER STOP\n        ASSERT {duration} >= .my_count\n        WAITNOPS {duration}-.my_count\n\n        IFDEF DEBUG_EXPECTED_DURATION\n            ASSERT .my_count == DEBUG_EXPECTED_DURATION\n        ENDIF\n        UNDEF .my_count\n    ENDM\n\n    DEBUG_EXPECTED_DURATION = 2\n    BUILD_STABLE_CODE 64, \"xor a : xor a\"\n

"},{"location":"basm/directives/#waitnops","title":"WAITNOPS","text":"

Generate a list of instructions that do not modify any registers or memory but is executed with the expected amount of nops. (Currently it is synonym of NOP, but as soon as someone wants to provide clever rules to use less bytes, I'll implement them)

"},{"location":"basm/directives/#locomotive","title":"LOCOMOTIVE","text":"
    LOCOMOTIVE start\n10 REM Basic loader of binary exec\n20 REM yeah !!\n30 call {start}\n    ENDLOCOMOTIVE\n\nstart\n        ld hl, txt\n.loop\n        ld a, (hl)\n        or a : jr z, .end\n        call #bb5a\n        inc hl\n        jr .loop\n.end\n        jp $\n\ntxt\n    db \"Hello world\", 0\n\n    print \"LOADER START IN \", {hex}start\n    save \"LOADER.BAS\",,,BASIC\n
"},{"location":"basm/directives/#snaset","title":"SNASET","text":""},{"location":"basm/syntax/","title":"Z80 Syntax","text":""},{"location":"basm/syntax/#general-syntax","title":"General syntax","text":"
LABEL OPCODE1\n      OPCODE2 : OPCODE3\n      DIRECTIVE\n

Warning

There may be still some subtle parser bugs, but it is possible to span instructions and directives on several lines by ending the previous line with \\

"},{"location":"basm/syntax/#labels-handling","title":"Labels handling","text":"

BASM is quite lax on the z80 format: it does not impose to start a label at the very first char of a line and does not force an instruction or directive to not start at the very first line of a char (behavior stolen to rasm). As a consequence there can be ambiguities between labels and macros. If it fails in properly recognizing macros or label, you can guide it by suffixing label declaration by : or by using (void) for macros with no arguments.

"},{"location":"basm/syntax/#local-labels","title":"Local labels","text":"
outer1\n    jp outer2\n    jp outer2.inner1\n\nouter2\n    jp .inner1\n.inner1\n\n    ifndef outer1\n        fail \"outer1 is wrongly undefined\"\n    endif\n\n    ifndef .inner1\n        fail \".inner1 is wrongly undefined\"\n    endif\n\n    ifndef outer2.inner1\n        fail \"outer2.inner1 is wrongly undefined\"\n    endif\n
"},{"location":"basm/syntax/#module-handling","title":"module handling","text":"

    module module1\nlabel1\n    jp module2.label1\n    endmodule\n\n    module module2\nlabel1 \n    jp module3.module31.label1\n    endmodule\n\n    module module3\n        module module31\nlabel1\n        jp ::label1\n        endmodule\n    endmodule\nlabel1\n
would generate a binary similar to
    jp label1\nlabel1\n    jp label2\nlabel2\n    jp label3\nlabel3\n

"},{"location":"basm/syntax/#labels-generation","title":"Labels generation","text":"

Labels can be generated thanks to the content of other ones.

value=5\nlabel{value+2}\n\n    ifndef label7\n        fail \"unable to build label with expression\"\n    endif\n

"},{"location":"basm/syntax/#instructions","title":"Instructions","text":"

Here is the list of instructions used to validate BASM:

; Test of assembling of z80 instructions.\n    LIST\n\n    org $0\n\ndes equ $05\nn   equ $20\nnn  equ $0584\n\n    ; Documented instructions\n;   ADC\n    adc a,(hl)\n    adc a,(ix + des)\n    adc a,(iy + des)\n    adc a,a\n    adc a,b\n    adc a,c\n    adc a,d\n    adc a,e\n    adc a,h\n    adc a,l\n    adc a,n\n\n    adc hl,bc\n    adc hl,de\n    adc hl,hl\n    adc hl,sp\n\n;   ADD\n    add a,(hl)\n    add a,(ix + des)\n    add a,(iy + des)\n    add a,a\n    add a,b\n    add a,c\n    add a,d\n    add a,e\n    add a,h\n    add a,l\n    add a,n\n\n    add hl,bc\n    add hl,de\n    add hl,hl\n    add hl,sp\n\n    add ix,bc\n    add ix,de\n    add ix,ix\n    add ix,sp\n\n    add iy,bc\n    add iy,de\n    add iy,iy\n    add iy,sp\n\n;   AND\n    and (hl)\n    and (ix + des)\n    and (iy + des)\n    and a\n    and b\n    and c\n    and d\n    and e\n    and h\n    and l\n    and n\n\n;   BIT\n    bit 0,(hl)\n    bit 0,(ix + des)\n    bit 0,(iy + des)\n    bit 0,a\n    bit 0,b\n    bit 0,c\n    bit 0,d\n    bit 0,e\n    bit 0,h\n    bit 0,l\n\n    bit 1,(hl)\n    bit 1,(ix + des)\n    bit 1,(iy + des)\n    bit 1,a\n    bit 1,b\n    bit 1,c\n    bit 1,d\n    bit 1,e\n    bit 1,h\n    bit 1,l\n\n    bit 2,(hl)\n    bit 2,(ix + des)\n    bit 2,(iy + des)\n    bit 2,a\n    bit 2,b\n    bit 2,c\n    bit 2,d\n    bit 2,e\n    bit 2,h\n    bit 2,l\n\n    bit 3,(hl)\n    bit 3,(ix + des)\n    bit 3,(iy + des)\n    bit 3,a\n    bit 3,b\n    bit 3,c\n    bit 3,d\n    bit 3,e\n    bit 3,h\n    bit 3,l\n\n    bit 4,(hl)\n    bit 4,(ix + des)\n    bit 4,(iy + des)\n    bit 4,a\n    bit 4,b\n    bit 4,c\n    bit 4,d\n    bit 4,e\n    bit 4,h\n    bit 4,l\n\n    bit 5,(hl)\n    bit 5,(ix + des)\n    bit 5,(iy + des)\n    bit 5,a\n    bit 5,b\n    bit 5,c\n    bit 5,d\n    bit 5,e\n    bit 5,h\n    bit 5,l\n\n    bit 6,(hl)\n    bit 6,(ix + des)\n    bit 6,(iy + des)\n    bit 6,a\n    bit 6,b\n    bit 6,c\n    bit 6,d\n    bit 6,e\n    bit 6,h\n    bit 6,l\n\n    bit 7,(hl)\n    bit 7,(ix + des)\n    bit 7,(iy + des)\n    bit 7,a\n    bit 7,b\n    bit 7,c\n    bit 7,d\n    bit 7,e\n    bit 7,h\n    bit 7,l\n\n;   CALL\n    call nn\n\n    call nz,nn\n    call z,nn\n    call nc,nn\n    call c,nn\n    call po,nn\n    call pe,nn\n    call p,nn\n    call m,nn\n\n;   CCF\n    ccf\n\n;   CP\n    cp (hl)\n    cp (ix + des)\n    cp (iy + des)\n    cp a\n    cp b\n    cp c\n    cp d\n    cp e\n    cp h\n    cp l\n    cp n\n\n    cpd\n    cpdr\n    cpir\n    cpi\n\n;   CPL\n    cpl\n\n;   DAA\n    daa\n\n;   DEC\n    dec (hl)\n    dec (ix + des)\n    dec (iy + des)\n    dec a\n    dec b\n    dec c\n    dec d\n    dec e\n    dec h\n    dec l\n\n    dec bc\n    dec de\n    dec hl\n    dec ix\n    dec iy\n    dec sp\n\n;   DI\n    di\n\n;   DJNZ\nl1  djnz l1\n\n;   EI\n    ei\n\n;   EX\n    ex af,af'\n\n    ex de,hl\n\n    ex (sp),hl\n    ex (sp),ix\n    ex (sp),iy\n\n    exx\n\n;   HALT\n    halt\n\n;   IM\n    im 0\n    im 1\n    im 2\n\n;   IN\n    in a,(c)\n    in b,(c)\n    in c,(c)\n    in d,(c)\n    in e,(c)\n    in h,(c)\n    in l,(c)\n\n    in a,(n)\n\n    ind\n    indr\n    ini\n    inir\n\n;   INC\n    inc (hl)\n    inc (ix + des)\n    inc (iy + des)\n    inc a\n    inc b\n    inc c\n    inc d\n    inc e\n    inc h\n    inc l\n\n    inc bc\n    inc de\n    inc hl\n    inc ix\n    inc iy\n    inc sp\n\n;   JP\n    jp nn\n\n    jp (hl)\n    jp (ix)\n    jp (iy)\n\n    jp nz,nn\n    jp z,nn\n    jp nc,nn\n    jp c,nn\n    jp po,nn\n    jp pe,nn\n    jp p,nn\n    jp m,nn\n\n;   JR\n    jr $ + $22\n\n    jr nz,$ + $22\n    jr z,$ + $22\n    jr nc,$ + $22\n    jr c,$ + $22\n\n;   LD\n    ld (bc),a\n    ld (de),a\n\n    ld (hl),a\n    ld (hl),b\n    ld (hl),c\n    ld (hl),d\n    ld (hl),e\n    ld (hl),h\n    ld (hl),l\n    ld (hl),n\n\n    ld (ix + des),a\n    ld (ix + des),b\n    ld (ix + des),c\n    ld (ix + des),d\n    ld (ix + des),e\n    ld (ix + des),h\n    ld (ix + des),l\n    ld (ix + des),n\n\n    ld (iy + des),a\n    ld (iy + des),b\n    ld (iy + des),c\n    ld (iy + des),d\n    ld (iy + des),e\n    ld (iy + des),h\n    ld (iy + des),l\n    ld (iy + des),n\n\n    ld (nn),a\n\n    ld (nn),bc\n    ld (nn),de\n    ld (nn),hl\n    ld (nn),ix\n    ld (nn),iy\n\n    ld (nn),sp\n\n    ld a,(bc)\n    ld a,(de)\n    ld a,(hl)\n    ld a,(ix + des)\n    ld a,(iy + des)\n    ld a,(nn)\n    ld a,a\n    ld a,b\n    ld a,c\n    ld a,d\n    ld a,e\n    ld a,h\n    ld a,l\n    ld a,n\n\n    ld b,(hl)\n    ld b,(ix + des)\n    ld b,(iy + des)\n    ld b,a\n    ld b,b\n    ld b,c\n    ld b,d\n    ld b,e\n    ld b,h\n    ld b,l\n    ld b,n\n\n    ld c,(hl)\n    ld c,(ix + des)\n    ld c,(iy + des)\n    ld c,a\n    ld c,b\n    ld c,c\n    ld c,d\n    ld c,e\n    ld c,h\n    ld c,l\n    ld c,n\n\n    ld d,(hl)\n    ld d,(ix + des)\n    ld d,(iy + des)\n    ld d,a\n    ld d,b\n    ld d,c\n    ld d,d\n    ld d,e\n    ld d,h\n    ld d,l\n    ld d,n\n\n    ld e,(hl)\n    ld e,(ix + des)\n    ld e,(iy + des)\n    ld e,a\n    ld e,b\n    ld e,c\n    ld e,d\n    ld e,e\n    ld e,h\n    ld e,l\n    ld e,n\n\n    ld h,(hl)\n    ld h,(ix + des)\n    ld h,(iy + des)\n    ld h,a\n    ld h,b\n    ld h,c\n    ld h,d\n    ld h,e\n    ld h,h\n    ld h,l\n    ld h,n\n\n    ld l,(hl)\n    ld l,(ix + des)\n    ld l,(iy + des)\n    ld l,a\n    ld l,b\n    ld l,c\n    ld l,d\n    ld l,e\n    ld l,h\n    ld l,l\n    ld l,n\n\n    ld a,i\n    ld i,a\n\n    ld a,r\n    ld r,a\n\n    ld bc,(nn)\n    ld de,(nn)\n    ld hl,(nn)\n    ld ix,(nn)\n    ld iy,(nn)\n    ld sp,(nn)\n\n    ld bc,nn\n    ld de,nn\n    ld hl,nn\n    ld ix,nn\n    ld iy,nn\n\n    ld sp,hl\n    ld sp,ix\n    ld sp,iy\n    ld sp,nn\n\n    ldd\n    lddr\n    ldi\n    ldir\n\n;   NEG\n    neg\n\n;   NOP\n    nop\n\n;   OR\n    or (hl)\n    or (ix + des)\n    or (iy + des)\n    or a\n    or b\n    or c\n    or d\n    or e\n    or h\n    or l\n    or n\n\n;   OUT\n    out (c),a\n    out (c),b\n    out (c),c\n    out (c),d\n    out (c),e\n    out (c),h\n    out (c),l\n    out (n),a\n\n    outd\n    otdr\n    outi\n    otir\n\n;   POP\n    pop af\n    pop bc\n    pop de\n    pop hl\n    pop ix\n    pop iy\n\n;   PUSH\n    push af\n    push bc\n    push de\n    push hl\n    push ix\n    push iy\n\n;   RES\n    res 0,(hl)\n    res 0,(ix + des)\n    res 0,(iy + des)\n    res 0,a\n    res 0,b\n    res 0,c\n    res 0,d\n    res 0,e\n    res 0,h\n    res 0,l\n\n    res 1,(hl)\n    res 1,(ix + des)\n    res 1,(iy + des)\n    res 1,a\n    res 1,b\n    res 1,c\n    res 1,d\n    res 1,e\n    res 1,h\n    res 1,l\n\n    res 2,(hl)\n    res 2,(ix + des)\n    res 2,(iy + des)\n    res 2,a\n    res 2,b\n    res 2,c\n    res 2,d\n    res 2,e\n    res 2,h\n    res 2,l\n\n    res 3,(hl)\n    res 3,(ix + des)\n    res 3,(iy + des)\n    res 3,a\n    res 3,b\n    res 3,c\n    res 3,d\n    res 3,e\n    res 3,h\n    res 3,l\n\n    res 4,(hl)\n    res 4,(ix + des)\n    res 4,(iy + des)\n    res 4,a\n    res 4,b\n    res 4,c\n    res 4,d\n    res 4,e\n    res 4,h\n    res 4,l\n\n    res 5,(hl)\n    res 5,(ix + des)\n    res 5,(iy + des)\n    res 5,a\n    res 5,b\n    res 5,c\n    res 5,d\n    res 5,e\n    res 5,h\n    res 5,l\n\n    res 6,(hl)\n    res 6,(ix + des)\n    res 6,(iy + des)\n    res 6,a\n    res 6,b\n    res 6,c\n    res 6,d\n    res 6,e\n    res 6,h\n    res 6,l\n\n    res 7,(hl)\n    res 7,(ix + des)\n    res 7,(iy + des)\n    res 7,a\n    res 7,b\n    res 7,c\n    res 7,d\n    res 7,e\n    res 7,h\n    res 7,l\n\n;   RET\n    ret\n\n    ret z\n    ret nz\n    ret c\n    ret nc\n    ret po\n    ret pe\n    ret p\n    ret m\n\n    reti\n    retn\n\n;   RL\n    rl (hl)\n    rl (ix + des)\n    rl (iy + des)\n    rl a\n    rl b\n    rl c\n    rl d\n    rl e\n    rl h\n    rl l\n\n;   RLA\n    rla\n\n;   RLC\n    rlc (hl)\n    rlc (ix + des)\n    rlc (iy + des)\n    rlc a\n    rlc b\n    rlc c\n    rlc d\n    rlc e\n    rlc h\n    rlc l\n\n;   RLCA\n    rlca\n\n;   RLD\n    rld\n\n;   RR\n    rr (hl)\n    rr (ix + des)\n    rr (iy + des)\n    rr a\n    rr b\n    rr c\n    rr d\n    rr e\n    rr h\n    rr l\n\n;   RRA\n    rra\n\n;   RRC\n    rrc (hl)\n    rrc (ix + des)\n    rrc (iy + des)\n    rrc a\n    rrc b\n    rrc c\n    rrc d\n    rrc e\n    rrc h\n    rrc l\n\n;   RRCA\n    rrca\n\n;   RRD\n    rrd\n\n;   RST\n    rst $00\n    rst $08\n    rst $10\n    rst $18\n    rst $20\n    rst $28\n    rst $30\n    rst $38\n\n;   SBC\n    sbc a,(hl)\n    sbc a,(ix + des)\n    sbc a,(iy + des)\n    sbc a,a\n    sbc a,b\n    sbc a,c\n    sbc a,d\n    sbc a,e\n    sbc a,h\n    sbc a,l\n    sbc a,n\n\n    sbc hl,bc\n    sbc hl,de\n    sbc hl,hl\n    sbc hl,sp\n\n;   SCF\n    scf\n\n;   SET\nlabel    set 0,(hl)\n    set 0,(ix + des)\n    set 0,(iy + des)\n    set 0,a\n    set 0,b\n    set 0,c\n    set 0,d\n    set 0,e\n    set 0,h\n    set 0,l\n\n    set 1,(hl)\n    set 1,(ix + des)\n    set 1,(iy + des)\n    set 1,a\n    set 1,b\n    set 1,c\n    set 1,d\n    set 1,e\n    set 1,h\n    set 1,l\n\n    set 2,(hl)\n    set 2,(ix + des)\n    set 2,(iy + des)\n    set 2,a\n    set 2,b\n    set 2,c\n    set 2,d\n    set 2,e\n    set 2,h\n    set 2,l\n\n    set 3,(hl)\n    set 3,(ix + des)\n    set 3,(iy + des)\n    set 3,a\n    set 3,b\n    set 3,c\n    set 3,d\n    set 3,e\n    set 3,h\n    set 3,l\n\n    set 4,(hl)\n    set 4,(ix + des)\n    set 4,(iy + des)\n    set 4,a\n    set 4,b\n    set 4,c\n    set 4,d\n    set 4,e\n    set 4,h\n    set 4,l\n\n    set 5,(hl)\n    set 5,(ix + des)\n    set 5,(iy + des)\n    set 5,a\n    set 5,b\n    set 5,c\n    set 5,d\n    set 5,e\n    set 5,h\n    set 5,l\n\n    set 6,(hl)\n    set 6,(ix + des)\n    set 6,(iy + des)\n    set 6,a\n    set 6,b\n    set 6,c\n    set 6,d\n    set 6,e\n    set 6,h\n    set 6,l\n\n    set 7,(hl)\n    set 7,(ix + des)\n    set 7,(iy + des)\n    set 7,a\n    set 7,b\n    set 7,c\n    set 7,d\n    set 7,e\n    set 7,h\n    set 7,l\n\n;   SLA\n    sla (hl)\n    sla (ix + des)\n    sla (iy + des)\n    sla a\n    sla b\n    sla c\n    sla d\n    sla e\n    sla h\n    sla l\n\n;   SRA\n    sra (hl)\n    sra (ix + des)\n    sra (iy + des)\n    sra a\n    sra b\n    sra c\n    sra d\n    sra e\n    sra h\n    sra l\n\n;   SRL\n    srl (hl)\n    srl (ix + des)\n    srl (iy + des)\n    srl a\n    srl b\n    srl c\n    srl d\n    srl e\n    srl h\n    srl l\n\n;   SUB\n    sub (hl)\n    sub (ix + des)\n    sub (iy + des)\n    sub a\n    sub b\n    sub c\n    sub d\n    sub e\n    sub h\n    sub l\n    sub n\n\n;   XOR\n    xor (hl)\n    xor (ix + des)\n    xor (iy + des)\n    xor a\n    xor b\n    xor c\n    xor d\n    xor e\n    xor h\n    xor l\n    xor n\n\n    ; Undocumented instructions\n; IN\n    in (c)      ; DEFB $ED,$70\n    in f,(c)    ; DEFB $ED,$70\n\n; OUT\n    out (c)     ; DEFB $ED,$71\n    out (c),f   ; DEFB $ED,$71\n\n; SLL\n    sll (hl)\n    sll (ix+des)\n    sll (iy+des)\n    sll a\n    sll b\n    sll c\n    sll d\n    sll e\n    sll h\n    sll l\n\n; IX and IY 8 bits halfs\n    add a,ixh\n    add a,ixl\n    add a,iyh\n    add a,iyl\n\n    adc a,ixh\n    adc a,ixl\n    adc a,iyh\n    adc a,iyl\n\n    and ixh\n    and ixl\n    and iyh\n    and iyl\n\n    cp ixh\n    cp ixl\n    cp iyh\n    cp iyl\n\n    dec ixh\n    dec ixl\n    dec iyh\n    dec iyl\n\n    inc ixh\n    inc ixl\n    inc iyh\n    inc iyl\n\n    ld a,ixh\n    ld b,ixh\n    ld c,ixh\n    ld d,ixh\n    ld e,ixh\n    ;ld h,ixh\n    ;ld l,ixh\n\n    ld a,ixl\n    ld b,ixl\n    ld c,ixl\n    ld d,ixl\n    ld e,ixl\n    ;ld h,ixl\n    ;ld l,ixl\n\n    ld a,iyh\n    ld b,iyh\n    ld c,iyh\n    ld d,iyh\n    ld e,iyh\n    ;ld h,iyh\n    ;ld l,iyh\n\n    ld a,iyl\n    ld b,iyl\n    ld c,iyl\n    ld d,iyl\n    ld e,iyl\n    ;ld h,iyl\n    ;ld l,iyl\n\n    ld ixh,a\n    ld ixh,b\n    ld ixh,c\n    ld ixh,d\n    ld ixh,e\n    ld ixh,ixh\n    ld ixh,ixl\n    ld ixh,n\n\n    ld ixl,a\n    ld ixl,b\n    ld ixl,c\n    ld ixl,d\n    ld ixl,e\n    ld ixl,ixh\n    ld ixl,ixl\n    ld ixl,n\n\n    ld iyh,a\n    ld iyh,b\n    ld iyh,c\n    ld iyh,d\n    ld iyh,e\n    ld iyh,iyh\n    ld iyh,iyl\n    ld iyh,n\n\n    ld iyl,a\n    ld iyl,b\n    ld iyl,c\n    ld iyl,d\n    ld iyl,e\n    ld iyl,iyh\n    ld iyl,iyl\n    ld iyl,n\n\n    or ixh\n    or ixl\n    or iyh\n    or iyl\n\n    sbc a,ixh\n    sbc a,ixl\n    sbc a,iyh\n    sbc a,iyl\n\n    sub ixh\n    sub ixl\n    sub iyh\n    sub iyl\n\n    xor ixh\n    xor ixl\n    xor iyh\n    xor iyl\n\n    end\n
"},{"location":"basm/syntax/#fake-instructions","title":"Fake instructions","text":"

To ease coding, several fake instructions are allowed by BASM. It replaces them by the combination of true instructions.

Here is a subset of the possibilities.

Failure

Most accepted fake instructions are missing from the listing

    ld hl, de\n    jp hl\n    jp ix\n    jp iy\n    push hl, de, bc\n    pop bc, de, hl\n
"},{"location":"basm/syntax/#comments","title":"Comments","text":""},{"location":"basm/syntax/#expressions","title":"Expressions","text":""},{"location":"basm/syntax/#special-variables","title":"Special variables","text":"
  • $: get the current code address
  • $$: get the current output address

Example:

    assert $ == 0\n    assert $$ == 0\n\n    org 0x100\n    assert $ == 0x100\n    assert $$ == 0x100\n    nop\n    assert $ == 0x101\n    assert $$ == 0x101\n\n    org 0x200, 0x300\n    assert $ == 0x200\n    assert $$ == 0x300\n    nop\n    assert $ == 0x201\n    assert $$ == 0x301\n

"},{"location":"basm/syntax/#provided-functions","title":"Provided functions","text":"

Failure

Need to document all functions

"},{"location":"basm/syntax/#z80-related-functions","title":"Z80 related functions","text":""},{"location":"basm/syntax/#assemble","title":"assemble","text":"

assemble(str) consider the string str to be a list of instructions (no directives) and returns the list of bytes corresponding to the assembled version of the given string.

    assert list_len(assemble(\" nop\")) == 1\n    assert list_len(assemble(\" nop : nop \")) == 2\n    assert list_len(assemble(\"\")) == 0\n
"},{"location":"basm/syntax/#duration","title":"duration","text":"
  • duration(instruction) returns the number of nop of the instruction
"},{"location":"basm/syntax/#opcode","title":"opcode","text":"
    ld a, opcode(inc e)\n    ld a, opcode(dec e)\n
"},{"location":"basm/syntax/#amstrad-cpc-video-handling","title":"Amstrad CPC video handling","text":"
  • mode0_byte_to_pen_at
  • mode1_byte_to_pen_at
  • mode2_byte_to_pen_at
  • pen_at_mode0_byte
  • pen_at_mode1_byte
  • pen_at_mode2_byte
  • pens_to_mode0_byte
  • pens_to_mode1_byte
  • pens_to_mode2_byte
"},{"location":"basm/syntax/#list-handling","title":"List handling","text":"
  • list_new
  • list_get(LIST, INDEX)
  • list_set
  • list_len
  • list_sublist(list, start, end) -> list: Return a new list from start until end not included
  • list_sort
  • list_argsort
  • list_push
"},{"location":"basm/syntax/#string-handling","title":"String handling","text":"
  • string_new
  • string_push
  • string_concat
  • string_from_list
"},{"location":"basm/syntax/#matrix-handling","title":"Matrix handling","text":"
  • matrix_new
  • matrix_set
  • matrix_get
  • matrix_col
  • matrix_row
  • matrix_set_row
  • matrix_set_col
  • matrix_width
  • matrix_height
"},{"location":"basm/syntax/#file-handing","title":"File handing","text":"
  • load(fname) -> list of bytes: return the bytes from the given file name
"},{"location":"basm/syntax/#memory-handling","title":"Memory handling","text":""},{"location":"basm/syntax/#memoryaddr","title":"memory(addr)","text":"
    org 0x4000\n    assert memory(label2) == 4\n\nlabel1\n    db 1, 2, 3\n\nlabel2\n    db 4, 5, 6\n\n    assert memory(label1) == 1\n    assert memory(label1+2) == 3\n
"},{"location":"basm/syntax/#user-defined-functions","title":"User defined functions","text":"

BASM allows to define functions that can be used in any expression. The functions are fed with parameters and execute conditional directives as well as directives able to handle variables. They finish at the execution of the RETURN directive.

FUNCTION [ARG1 [, ARGN]]\n    INSTRUCTIONS\n    RETURN VALUE\nENDFUNCTION\n

Failure

Better explain how to build function

Example of the fibonacci function:

    function fibo nb\n        if {nb} == 0\n            return 0\n        else if {nb} == 1\n            return 1\n        else\n            return fibo({nb}-1) + fibo({nb}-2)\n        endif\n\n    endfunction\n\n    assert fibo(0) == 0\n    assert fibo(1) == 1\n\n    assert fibo(5) == 5\n\n    assert fibo(10) == 55\n

Example of function to handle lists:

    ; Skip the {start} first element of list {l}\n    FUNCTION SKIP, l, start\n        len = list_len({l})\n        if {start} < len\n            return list_sublist({l}, {start}, len)\n        else\n            return []\n        endif\n    ENDFUNCTION\n\n    ; Take the {amount} first element of list {l}\n    FUNCTION TAKE, l, amount\n        assert {amount} > 0\n        len = list_len({l})\n        start = 0\n        finish = start + min({amount}, len) ; seems to not work for un unknown reason\n        if {amount} > len\n            finish = len\n        else\n            finish = {amount}\n        endif\n        return list_sublist({l}, start, finish)\n    ENDFUNCTION\n\n    ; Reverse list {l}\n    FUNCTION REVERT, l\n        new = []\n        nb = list_len({l})\n        for idx, 0, nb-1\n            new = list_push(new, list_get({l}, nb-1-{idx}))\n        endfor\n        return new\n    ENDFUNCTION\n\n    assert list_len([1, 2, 3, 4]) == 4\n    assert list_sublist([1, 2, 3, 4], 0, 2) == [1,2]\n    assert list_sublist([1, 2, 3, 4], 0, 4) == [1, 2, 3, 4]\n\n    ; Various test to check appropriate behavior\n    assert SKIP([1, 2, 3, 4], 2) == [3, 4]\n    assert SKIP([1, 2, 3, 4], 5) == []\n\n    assert TAKE([1, 2, 3, 4], 2) == [1, 2]\n    assert min(4,5) == 4\n    assert TAKE([1, 2, 3, 4], 4) == [1, 2, 3, 4]\n    assert TAKE([1, 2, 3, 4], 10) == [1, 2, 3, 4]\n\n    assert REVERT([1, 2, 3, 4]) == [4, 3, 2, 1]\n    assert list_len(load(\"hello.sna\")) == 4674\n\n    assert list_len(TAKE(load(\"hello.sna\"), 8)) == 8\n\n    assert string_from_list(TAKE(load(\"hello.sna\"), 8)) == \"MV - SNA\"\n\n    ; Write in memory 8 bytes from the given file\n    snapshot = load(\"hello.sna\")\n    header_id = TAKE(snapshot, 8)\n    db header_id\n\n    ; Check that memory is correctly set\n    assert peek(0) == \"M\"\n    assert peek(7) == \"A\"\n

"},{"location":"bndbuild/","title":"Bndbuild","text":""},{"location":"bndbuild/#synopsis","title":"Synopsis","text":"

Makefile-like tool tailored to build Amstrad CPC project. It embeds various cpclib tools such as basm, m4, img2cpc but can still execute external programs such as rasm, winape.

The rules are described in a yaml file. Check for example the test project in folder."},{"location":"bndbuild/#help","title":"Help","text":"

Benediction CPC demo project builder\n\nUsage: bndbuilder [OPTIONS] [TARGET]...\n\nArguments:\n  [TARGET]...\n          Provide the target(s) to run.\n\nOptions:\n  -h, --help [<CMD>]\n          Show the help of the given subcommand CMD.\n\n          [default: bndbuild]\n          [possible values: img2cpc, basm, rm, bndbuild, xfer]\n\n  -V, --version\n          Print version\n\n  -f, --file <FILE>\n          Provide the YAML file for the given project.\n\n          [default: bndbuild.yml]\n\n  -w, --watch\n          Watch the targets and permanently rebuild them when needed.\n
"},{"location":"bndbuild/#example","title":"Example","text":"

Here is an example to build a dummy Amstrad CPC project and execute on the real machine thanks to the m4. It is available in tests/dummy (the repository does not contains the external tools needed to properly build the project. It is straighforward to add them). Successive calls to the build task do nothing as soon as no file has been modified. It is also possible to watch the dependencies of a given task to automatically build it when they are modified. This cannot be seen with the capture, but each time m4 command is launched, the project is send into the CPC machine (it takes several seconds however).

"},{"location":"bndbuild/#format","title":"Format","text":"

The rules description file must respect the yaml text file format. It is preferably named bndbuild.yml but this can be overriden by the -f argument. It contains list of rules. Each rule can have the following keys:

  • tgt: to list the files build by the rule
  • dep: to list the files needed to build the rule
  • cmd: a command, or a list of commands, executed by the rule. Commands prefixed by - can silently fail
  • help: an optional help text to describe the rule
  • phony: an optional tag to express the rule does not generate anyfile (it is infered when the commands are not extern). Mainly serve for the --watch argument.

The commands are either included by the application (so limited to cpclib commands and os agnostic) or accessible externally (no limitation, but os dependent). They are: - basm to launch basm assembler - img2cpc to make image conversion - rm to delete files - xfer to transfer to the CPC with the M4 card - extern to launch any command available on the machine

"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 00000000..f6ad7e6d --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,33 @@ + + + + None + 2024-02-18 + daily + + + None + 2024-02-18 + daily + + + None + 2024-02-18 + daily + + + None + 2024-02-18 + daily + + + None + 2024-02-18 + daily + + + None + 2024-02-18 + daily + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 00000000..d97d4beb Binary files /dev/null and b/sitemap.xml.gz differ