HN user

loadzero

429 karma

blog.loadzero.com

loadzero dot dev at gmail dot com

Posts0
Comments38
View on HN
No posts found.
[GET] "/api/user/loadzero/stories?hitsPerPage=30&page=0": 500 Failed to fetch user stories
Space Invaders 1 year ago

I think at least some of the NOPs are due to this

From my C transliteration: https://github.com/loadzero/si78c/blob/master/si78c.c

    // xref 0462
    //
    // This code is using the shot counter as an index into the ROM
    // (where some code resides), for the purposes of random number generation.
    //
    // For the saucer direction logic, only bit 0 of each bytecode is used.
    //
    // The 256 bytes used reside at 0800 -> 08FF
    //
    // If you check bit 0 of each byte in that ROM section, you will find that there is no bias,
    // and there are exactly 128 0's and 128 1's.
    //
    // It seems unlikely that this was an accident, I think Nishikado deliberately constructed
    // the ROM this way, and used some well placed NOPs to achieve fair balance.
    //
    // E.g. these NOPs
    //
    // 0854: 00 00 00
    // 0883: 00 00 00
    //
    // This information can be exploited to the player's advantage.
    //
    // If using the shot counting trick to get high scores, the
    // expected saucer direction for the first 6 saucers (if counting),
    // will be as follows:
    //
    // [22,37,52,67,82,97]
    // [0, 1, 1, 0, 1, 1]
    // [L, R, R, L, R, R]

I have been down this road a little bit, applying the ideas from jockey to write and ship a deterministic HFT system, so I have some understanding of the difficulties here.

We needed that for fault tolerance, so we could have a hot synced standby. We did have to record all inputs (and outputs for sanity checking) though.

We did also get a good taste of the debugging superpowers you mention in your blog article. We could pull down a trace from a days trading and replay on our own machines, and skip back and forth in time and find the root cause of anything.

It sounds like what you have done is something similar, but with your own (AMD64) virtual machine implementation, making it fully deterministic and replayable, and providing useful and custom hardware impls (networking, clock, etc).

That sounds like a lot of hard but also fun work.

I am missing something though, in that you are not using it just for lockstep sync or deterministic replays, but you are using it for fuzzing. That is, you are altering the replay somehow to find crashes or assertion failures.

Ah, I think perhaps you are running a large number of sims with a different seed (for injecting faults or whatnot) for your VM, and then just recording that seed when something fails.

I use this in my `~/.jq` when I have a problem like this.

    def flat_json_keys:
        [leaf_paths as $path | {"key": $path | map(if (type=="string") then (if (test("([?:\\W]+)")) then "['"+.+"']"  else . end) else "["+tostring+"]" end) | join(".") | gsub(".\\[";"[") , "value": getpath($path)}] | from_entries;

    def ukeys:
        keys_unsorted;
Use like so:
    cat wat.json | jq flat_json_keys

Birdi | QA Engineer (junior) | Remote | 6mo contract | https://www.birdi.io/qa-engineer | Australian working rights required.

Birdi runs drone capture projects across Australia. We acquire and process drone imagery, and provide an online platform for our customers to interact with rich geospatial data.

We are a fully remote, growing and highly experienced team that moves fast and builds flexible and powerful solutions to real problems.

Tech stack:

  Infra: AWS/Kops/K8s/Terraform/Golang
  BE: NodeJS/Postgresql
  FE: TypeScript/React/Maplibre/DeckGl
We are currently looking for the following roles:
  QA Engineer (6mo contract, junior role)
For more detail on the specific role see: https://www.birdi.io/qa-engineer

For more general detail, see our careers page : https://www.birdi.io/careers

We are always looking for good people, so even if the above role is not a fit for you, please reach out.

Email me at jason.mcsweeney@birdi.io

Birdi | Senior Front-End | Remote | Full-time | https://www.birdi.io/careers | Australian working rights required.

Birdi runs drone capture projects across Australia. We acquire and process drone imagery, and provide an online platform for our customers to interact with rich geospatial data.

We are a fully remote, growing and highly experienced team that moves fast and builds flexible and powerful solutions to real problems.

Tech stack:

  Infra: AWS/Kops/K8s/Terraform/Golang
  BE: NodeJS/Postgresql
  FE: TypeScript/React/Maplibre/DeckGl
We are currently looking for the following roles:
  Senior Front End Developer (full-time)
For more detail, see our careers page : https://www.birdi.io/careers

We are always looking for good people, so even if the above roles are not a fit for you, please reach out.

Email me at jason.mcsweeney@birdi.io

Birdi | Multiple roles | Remote | Full-time | https://www.birdi.com.au/careers Australian working rights required.

Birdi runs drone capture projects across Australia. We acquire and process drone imagery, and provide an online platform for our customers to interact with rich geospatial data.

We are a fully remote, growing and highly experienced team that moves fast and builds flexible and powerful solutions to real problems.

Tech stack:

  Infra: AWS/Kops/K8s/Terraform/Golang
  BE: NodeJS/Postgresql
  FE: TypeScript/React/Maplibre/DeckGl
We are currently looking for the following roles:
  DevOps (full-time)
  Senior Front End Developer (full-time)
  QA Engineer (6-month contract, full-time)
For more detail, see our careers page : https://www.birdi.com.au/careers

We are always looking for good people, so even if the above roles are not a fit for you, please reach out.

Email me at jason.mcsweeney@birdi.com.au

Ah, it does have a Microprose feel with the campaign, mission structure, and ejecting.

Thanks for giving me permission to publish the port, and cheers for writing a game that has given people some fun memories.

It's great also to see that you're still making games, 30 years on from this.

As a postscript,

For the web hackers out there - the lossless animation at the start of the article is not a <video> or a gif.

I got annoyed with how video codecs destroy pixel art, and other things, so I wrote my own.

This was almost more fun than doing the port.

I have not played it, but it does look to likely be an early inspiration for Chopper Commando.

It would be nice if someone made a web version of 'Sopwith', too.

With these restoration projects, I am usually looking to maximise code portability and minimise dependencies, which for me means C.

Sticking with Pascal would have been more authentic to the original source code, but I think that would have been more painful for me to deal with, and come with a lot of unknown unknowns.

I would likely also have been sacrificing my ability to port it onto the web and other interesting targets.

I'm glad to see that others remember this fondly as well.

The Pascal to C translation was a bit gruelling. I'd like to say that I'd written a fancy transpiler for it, but it came down to a 20 line ruby script, some vim macros and a ton of elbow grease.

I added the functions to emulate the Turbo Pascal library as I went. This was a bit more fun, because I got to play around with implementing line drawing, circle drawing and flood filling, and really low level stuff like that.

The final stages, adding in threading to handle emulating the keyboard buffer, framebuffer and PC speaker was also a lot of fun.

I plan to cover at least some of these things in part two.

Author here.

I used to play this 2D flick-screen CGA DOS helicopter game as a kid, and I remember enjoying the simple presentation combined with what would now be called sandbox elements.

I thought it was really cool that you could eject from the helicopter and still run around and do things as a little sprite dude, and then get back in and fly off.

When I saw that the source was available, and had a poke around, I decided it wouldn't take (too) much effort to do a modern port, and make the game natively playable on today's machines.

It was a fun little project, certainly easier than my previous game restoration (Space Invaders in C), and it was interesting to explore the creation of a young Mark Currie, cranking out a bedroom coded game in Turbo Pascal.

So, here it is, a modern port of "Chopper Commando" from early 90s Turbo Pascal on DOS, to C and SDL running on modern unix (linux/mac) and the web.

Enjoy.

This is a good answer, and does reflect a good chunk of the reason for picking C. Dealing with such low level tasks is what the language was made for.

The other big reason I used C, is that it is more of a lingua franca than something more modern, and will make the code more accessible to a wider audience.

It's a great technique.

Using it, and a suitable test program, you can bootstrap an emulator core for something simple like a mips, z80 or 6502 in a day or two.

I highly recommend it as a low-level itch scratching programming exercise.

BTW, I generally agree about extra indentation and braces for these kind of statements.

The code is a bit terse due to a mechanical issue - my current laptop screen only gives me about 25 lines vertically.

Yeah, there's probably a good article or two in that.

Cliff notes:

It's basically an extension of the Dual CPU setup mentioned in http://www.gtoal.com/sbt/

In that article, Graham Toal discusses a hack where you can bootstrap a new emulator core from an existing one by making a custom emulator that drives both cores at the same time.

After each clock tick, you check the states of both processors for divergence and halt with the diff if there is one.

Yes, I would say that those constraints are the main factor in not compacting the code further.

The C version also loses a few lines here and there for function prototypes and structured control flow.

Handwritten 8085 can be quite compact in some places due to sharing code fragments. It's a bit like self ROP.

Thanks for pulling the code and trying it out, jacquesm!

That kind of feedback is gold.

I have updated the README with the correct Ubuntu package details.

I think the issue with the includes is likely to do with having both SDL1 and 2 installed, and the slightly dirty way I am pulling in the header (so it works on Mac too).

I will have a bit of a think about how best to resolve that issue, likely needs some ifdefing.

Good question. The sound is a hardware component (synth circuit) that I haven't looked into much, because it's essentially outside the game code.

si78c is faithfully sending all the right bits to the right port, but the hardware component would have to be emulated to get it going.

The relevant code could most likely be borrowed from MAME.

Author here.

This is a bit of a love letter to Space Invaders, and video games in general.

I started working on this as a simple emulation project, to rekindle my own passion in low level video game hacking, but then realized with a bit of care I could take it further.

So, this is not a simple clone of the game, but rather a painstaking recreation of the source code in clean, readable C code.

I wanted to make something nice that would last a while, as a tribute to the original, and hopefully function a bit like a rosetta stone for future audiences.

Enjoy.