www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - TIC-80 WebAssembly: pointers to fixed addresses

reply Pierce Ng <pierce samadhiweb.com> writes:
Hi all,

D newbie here. I'm building a D WebAssembly binding for 
[TIC-80](https://github.com/nesbox/TIC-80), a fantasy gaming 
console.

TIC-80 has a [fixed size 
RAM](https://github.com/nesbox/TIC-80/wiki/RAM) that is directly 
addressable by a running program using peek() and poke() 
functions. Basically, 16,384 bytes starting at address zero form 
the video RAM, next 8192 bytes are for storing tiles, next 8192 
bytes for sprites, etc.

Here's how Zig's TIC-80 binding describes the memory layout:

```
pub const FRAMEBUFFER: *allowzero volatile [16320]u8 = 
 intToPtr(*allowzero volatile [16320]u8, 0);
pub const TILES : *[8192]u8 =  intToPtr(*[8192]u8, 0x4000);
pub const SPRITES : *[8192]u8 =  intToPtr(*[8192]u8, 0x6000);
```

I believe the above is declaring that FRAMEBUFFER is a pointer to 
16320 (sic) bytes starting at address 0, TILES is a pointer to 
8192 bytes starting at address 0x4000, and SPRITES a pointer to 
8192 bytes starting at address 0x6000.

Currently for D I have the following, copying the D binding for 
Wasm4, another fantasy console:

```
const FRAMEBUFFER = cast(uint*)0;
const TILES = cast(uint*)0x4000;
const SPRITES = cast(uint*)0x6000;
```

How to express in D, similarly to Zig, that FRAMEBUFFER refers to 
a byte[16384] array starting from address zero, and so on?

Pierce
Apr 16 2022
parent reply Adam Ruppe <destructionator gmail.com> writes:
On Saturday, 16 April 2022 at 14:29:09 UTC, Pierce Ng wrote:
 ```
 pub const FRAMEBUFFER: *allowzero volatile [16320]u8 = 
  intToPtr(*allowzero volatile [16320]u8, 0);
 pub const TILES : *[8192]u8 =  intToPtr(*[8192]u8, 0x4000);
 pub const SPRITES : *[8192]u8 =  intToPtr(*[8192]u8, 0x6000);
 ```

 I believe the above is declaring that FRAMEBUFFER is a pointer 
 to 16320 (sic) bytes starting at address 0, TILES is a pointer 
 to 8192 bytes starting at address 0x4000, and SPRITES a pointer 
 to 8192 bytes starting at address 0x6000.

 Currently for D I have the following, copying the D binding for 
 Wasm4, another fantasy console:

 ```
 const FRAMEBUFFER = cast(uint*)0;
 const TILES = cast(uint*)0x4000;
 const SPRITES = cast(uint*)0x6000;
 ```

 How to express in D, similarly to Zig, that FRAMEBUFFER refers 
 to a byte[16384] array starting from address zero, and so on?
Take the pointer and slice the pointer: __gshared ubyte[] framebuffer = (cast(uint*) 0) [0 .. 16320]; // gshared cuz otherwise D assumes it is TLS and it isn't Now you can notice it isn't const. You don't want it const since the point is to write to the thing. What you might do to keep the pointer itself from ever changing is to make it a property: ubyte[] framebuffer() { return (cast(uint*) 0) [0 .. 16320]; } And the compiler will see how trivial that is and inline it so it works the same way, but then nobody can ever rebind the framebuffer symbol.
Apr 16 2022
parent Pierce Ng <pierce samadhiweb.com> writes:
On Saturday, 16 April 2022 at 20:36:12 UTC, Adam Ruppe wrote:
 __gshared ubyte[] framebuffer = (cast(ubyte*) 0) [0 .. 16320];
 
 ubyte[] framebuffer() { return (cast(ubyte*) 0) [0 .. 16320]; }
Thank you, Adam. I'll go with both, as existing examples in other languages use pointer arithmetic. Now re-implementing a few Lua examples shown on TIC-80's wiki. Will be checking out the [Wasm-compatible D RTL](https://github.com/skoppe/druntime), which I found browsing these forums. Pierce
Apr 17 2022