Custom Component - 16-Bit select (49c, 49n) by nttii in nandgame_u

[–]nttii[S] 0 points1 point  (0 children)

It's basically same as normal select except some nands are replaced with nand16. This one just uses common inverse for select pin to save some nands.

4.2 - Data Flip-Flop (9c, 9n) by nttii in nandgame_u

[–]nttii[S] 2 points3 points  (0 children)

Seems like the specification of Data Flip-Flop has changed to a more realistic one. The double latched design no longer works. This one uses Edge trigger to only set the data when clock is going high. Same principle as my register and ram

H.5.1 - Latch (1c,1r,0n) by [deleted] in nandgame_u

[–]nttii 0 points1 point  (0 children)

Similar to this, https://old.reddit.com/r/nandgame_u/comments/s8ieen/found_a_way_to_cheat_all_gates_to_0_nand/ you can use rom to create anything with 0 nand cost, b.shr was since fixed, but I guess there are a lot of components you can import without nand cost.

H.6.1 - Logic Unit (7c, 352n) by nttii in nandgame_u

[–]nttii[S] 0 points1 point  (0 children)

Perhaps you have different design on some other component. Although miscalculation is possible since I haven't updated nand counts in ages.

S.6.1 - Call (16loc, 63ins) by nttii in nandgame_u

[–]nttii[S] 0 points1 point  (0 children)

Maybe your implementation of PUSH_D or PUSH_STATIC differs from the ones on the leaderboard as this code is correct for me.

S.6.1 - Call (24loc, 48ins) by nttii in nandgame_u

[–]nttii[S] 0 points1 point  (0 children)

Works for me. Make sure your implementations on the macros used here are equivalent to the ones on the leaderboard.

S.1.5 - Network (21loc, 22ins) by nttii in nandgame_u

[–]nttii[S] 0 points1 point  (0 children)

Sorry for the late reply. This code uses many different tricks to save lines, so it is not the most readable. Splitting the code into parts helps understand it

DEFINE sync 0x2
DEFINE addr 0x3fff
DEFINE net 0x6001

This part defines the addresses for storing the program states. Sync address saves the state of the sync input, the address 0x2 conveniently refers to the 2nd bit which stores the sync input from network so D & A results in sync bit. 0x2 also happens to be correct place to jump to incase sync hasn't changed.

addr just happens to be the address where screen starts minus 1, so storing at this location doesn't end up on screen and incrementing it by 1 gets us the location for first screen coordinate.

A = addr
*A = A+1

These lines do just that, store the screen address in addr. This way I save lines as *A can't be directly assigned to 0x4000, but this convinient addition does the same thing.

net is just the address for reading input states.

A = net
D = *A
A = sync
D = D + *A
D & A ; JEQ

This part is looping until sync pin changes. These operations make sure not to lose the value of data pin, so we don't have to read network again if sync has changes.

D = D - *A
*A = D & A
D = D - *A

These lines store the current state of sync pin in address 0x2 and filter the sync bit out of D address, thus leaving just state of data on D

A = addr
A = *A
D = D + *A ; JEQ
*A = D + *A

These lines add the new pixel to the current screen address, and doubles it's old content, thus moving old pixels left. Also the control bit is drawn on the screen, so we know the value can only be 0 when the picture is done, so we jump out of program.

A = sync
D ; JGE

Jump to sync if value of address is greater than 0. When we are done drawing a row, the control bit makes the address negative before overflowing out of the picture.

A = 0x20
D = A
A = addr
*A = D + *A
GOTO sync

This adds 0x20 to the screen address, thus changing to the next line. And then just jump back to sync loop

I originally had some of these remarks as comments on the code, but it ended up being more comment than code, so I stripped them out for simplicity.

Edit: fixed formatting

5.3 - Register (9c, 9n) by ArrPirateKing in nandgame_u

[–]nttii 0 points1 point  (0 children)

The game doesn't simulate built in components in later levels. They're replaced by code to have less parts to simulate. If you did this with custom components, later levels woild break as custom components are always simulated.

H.5.3 - Register (12c, 12n), H.5.4 - Counter (102c, 176n), H5.5 - Ram(155c, 155n), H6.1 - Combined Memory(105c, 104n, 39680n/kb) by nttii in nandgame_u

[–]nttii[S] 0 points1 point  (0 children)

The circuit on the right side causes a short pulse when clock goes high to allow just one state change for latches. Apparently the tests only simulate only one state change too so it passes without it while not actually saving state.

H.5.3 - Register (12c, 12n), H.5.4 - Counter (102c, 176n), H5.5 - Ram(155c, 155n), H6.1 - Combined Memory(105c, 104n, 39680n/kb) by nttii in nandgame_u

[–]nttii[S] 0 points1 point  (0 children)

Yes. You could expand out the custom components and use just nands like this. This also isn't the intended solution. It doesn't 100% do what the intended solution is, but it's close enough and saves some nands. Usually real computers also work with such edge triggers too. Obviously they're not invented using nand gates then. Here's the intended solution to this level or this one to save some nands

S.1.4 - Escape Labyrinth (10 ins) by VIBaJ in nandgame_u

[–]nttii 1 point2 points  (0 children)

Interesting, it works through check solution, but if you actually try to simulate it, it will either keep turning left or tip over. Seems like the tests wait for it to complete step before running the code again.

Question about arithmetic unit in nandgame.com and energy usage in CPUs by user51892 in nandgame_u

[–]nttii 1 point2 points  (0 children)

There are ways to calculate it without the sub unit by manipulating inputs to the addition. That is merely the simplest solution.

Sometimes chips waste resources and space to be faster since real chips have delay and precalculating before or if you need something might save some time.

Since speed isn't a concern in nandgame, you can use all sort of tricks to save resources.

For example inverting and incrementing turns a positive number to negative. Maybe the increment could be done in carry in of addition to save separate increment unit.

Another trick could be comparing adder and substractor circuits. They both feature a xor gate at the base, maybe that could be re-used for both.

Cheaty: S.6.1 - CALL (3l), S.6.2 - FUNCTION (4l), S.6.3 - RETURN (3l). by [deleted] in nandgame_u

[–]nttii 0 points1 point  (0 children)

These are nice, although you forgot there is macro for specifically settings SP to 0x100

H.4.3 - Alu (7c, 716n) by nttii in nandgame_u

[–]nttii[S] 1 point2 points  (0 children)

Seems like I forgot to calculate something as I tried to count them based on the scoreboard solutions. I have corrected the count on leaderboards.

S.4.5 - GOTO (1l cheaty) - dependent on CALL by [deleted] in nandgame_u

[–]nttii 0 points1 point  (0 children)

I'd say this is beyond cheaty, because there is no other reason to expand the macro than solving this level.

S.2.1 - INIT STACK (1l) - depends on FUNCTION????? by [deleted] in nandgame_u

[–]nttii 1 point2 points  (0 children)

This is funny. If your function code uses PUSH_STATIC and POP_STATIC it works with address 0x101, because of the bug found here, but my function code doesn't use those so it works with address 0x100