Tuesday, 28 July 2015

Game# 13: How it works

Hi. I'm back from a sunny week in Germany. Remarkably I've lost weight on Holiday, because the place we stayed is on a steep hill in a river valley (Heimbach in the West of Germany), so lots of climbing up and down.

Anyway, how Jawbreaker works.

Globals and Constants

Lots of globals and constants here. Have some quasi constants as well "Pseudo Constants" - the idea here is they are assigned one value at the start, which then is unchanging - obviously this isn't enforceable in C2 but it's a good idea code wise. Event 3 initialises these values which represent various screen positions.

There are some utility functions here, updating the score and lives, and resetting things when a new game/retry occurs. When you start a new level or game, the layout is reloaded.

Finally this game has an FSM, which was grafted on afterwards, lazily :)

Setup

This game doesn't usee the painting at all, pretty much, so this sets up the screen - event 1 draws the border, repositions the vitamin (it is always there, just not always visible) and the level text. Event 2 creates the moving walls (actually solid walls with a black overlay), and event 3,4 and 5 create the monsters and the sweets.

Play State, 

This is the main game stuff. Event 1 initialises everything on layout start. Events 2-4 control the music and the 8 direction controls depending on whether the game is actually being played.

The game code proper starts at event 5.  Event 6 clamps the player into the game space, and 7 and 8 handle the potential horizontal movement - this is only permitted either in the left or right columns, or where you are passing through a gateway (gap in the wall).

Event 9 through 13 handle eating sweets - 10/11 have different effects for eating the different coloured sweets, and 13 handles the end of level.

Event 14 makes the vitamin pill appear on its timer, and 15 and 16 make it go into chase mode on collision with appropriate sound and effects, also setting the timer for "end of chase warning" (fired at 17-18) and "end of chase" (fired at 19-23). This also puts the monsters to reappear at the other end of the game board from where you are, allowing the player to get away (i.e. monsters don't reappear on top of you)

Finally 24-26 handle collisions with monsters - this can either be during the chase mode (26) in which case you score, or not, when you lose a life.

Moveables

This handles the monsters.  Events 2-4 set up the monstes, with a position and a reverse timer - they are driven by wrapped bullets. On event 5, the monsters reverse direction periodically.

Event 6 shouldn't be here (arguably), it's purpose is to make the gateways invisible or visible depending on the horizontal position, otherwise they will appear over the top of the left and right border. I probably should have done his with z-order/layers, but it's a blitz.

Other states

This handles various states. "New level" (1-7) animates the brush coming in and brushing and out using a bullet and a sine. This is messy but it works by firing timers and checking the position.

Event 8 onwards handles lost life, and this makes the player disappear from the top down. Finally Game over, in events 15-18 fades the Game Over text in and goes back to the title page when the fade is completed.

Saturday, 18 July 2015

Off on Holiday (again)

Eifel National Park near Heimbach, Germany
I'm off to Germany tomorrow for a week, so I probably won't do the write up for Jawbreaker before I go.

When I get back I'll do that and then finish off my list which is (probably) Robotron, Defender, Lode Runner and (maybe) Tempest. Also thinking of porting Richard Garriott's Akalabeth (aka "Ultima 0") to C2 (I have already ported this to "C")

Then maybe some proper work :) This is just practice for a project, which is itself a rewrite of something I did on an Acorn Archimedes a few years ago.

Fortunately for the sanity of the world, it isn't my 3D signing robot for Special Needs that both sang, and signed "When Goldilocks went to the House of the Bears".

Game # 13 : Complete

Jawbreaker can be played here. The source is in the usual github. I will write it up later on.

Friday, 17 July 2015

Game#13 : Jawbreaker (A blitz)

As a blitz, because I'm off for a week tomorrow, yesterday I wrote most of a version of the Atari 2600 game "Jawbreaker" (original below) in a couple of hours. It's nearly finished, except the objects aren't actually moving (yet). Should be available later today, but the write up might be delayed.

When I get back I will move onto Robotron.

Jawbreaker is a Pacman variant. Amazingly they were sued for "copying Pacman" - this was a time when there were umpteen dodgy Pacman clones. Pacman isn't really suited to the Atari 2600 for reasons relating to its hardware, so its a sort of horizontal version, though it has many of the same elements - the sprites only move horizontally as do the gaps in the maze.

This is because it is very difficult to get multiple sprites on the same line, and even if you do it is Space Invaders like (e.g. very repetitive) - Pacman's maze is doable, but the five sprites on the screen at once (4 ghosts, Pacman) flicker because they can be drawn in any vertical position.  This homebrew is much better in terms of its resemblance to the original, but it still flickers, for the same reasons.

14500 Board, how it works.

Interface

This is probably the interesting bit. The interface works through a dictionary which contains settings of the 'controls' (switches and LEDs), and automatically updates the dictionary or display.

Rather than copying umpteen objects, it uses an IOMarker which specifies detail, this expands at event 2. For each "bit" it requires, it creates an interface object which has different animations for different objects, and tells it whether it is input or output and which bit of which data item it is. 6 and 7 allow it to be labelled.

Events 8 through 10 copy data either to or from the interface object to the dictionary. Event 11 makes toggle switches work. Event 12 handles pushbuttons initialises pushbuttons and their labels - they do not have an entry in the dictionary, but call a function "On<actionName>" (this is done in 15).

Event 17 onwards is a short cut. Data is stored in a 256 x 4 bit memory on this machine, and this allows code to be typed in by pressing 0-9A-F which writes it to the current memory and bumps the program counter - otherwise you'd have to set the switches, press load data, and press single step - this does it for you - you can type 0 A 9 F C 3 etc. to load a program in.

InterfaceRefresh

This is related to interface but it copies data from the emulation globals into the interface dictionary - then they are updated to the display by the code in interface. These are the current address in the program counter (8 + 1 + 1) LEDs, the data at that location (4), the Result Register (14500 Accumulator) (1), the 16 output latches (16 LEDs) in 3 to 6). Event 7 maintains the state of the step/run switch in a global for convenience.

Event 8 is added to make things easier - it displays the mnemonic equivalent of the code in data memory, rather than having to read binary.

Commands

These handle the push buttons, they are all "OnXXX" functions. LoadPC copies the address switches into the program counter, Reset resets the program counter, the 14500 MCU and the run latch, Single step executes a single half-instruction (see emulation), Load Data loads the data switches into memory, and OnRunMode starts the program running by setting the run latch. Finally event 8 causes the emulation to free run at one half-instruction per tick if the run latch is set.


Emulation

This is a classic emulation of the MCU, with one tweak. Each single step is a half instruction - for even address instructions (opcode) it loads the opcode into an internal latch (Event 3), and on odd ones, it loads the operand (IO Address) into an external latch (Event 4) - so it requires two single steps to execute each instruction.

The emulations follow the 14500 Specification, except NOP0 (0000) resets the run latch and NOPF (1111) presets the program counter, loading the address switches into the program counter.

A couple of helper functions read input (Starting at 23) - this supports the "wiring" of input pin 15 to the RR (25) and input pins 8-14 to their corresponding output latches (26), these can be then used as data storage. This is my own addition, as it is not fixed on the original board but done by wiring.

App#1 : MC14500 Board Released

It can be "played" here. It's a reasonably faithful mimic of the original, though the Input and Output have been changed - on the original they ware just headers, but I've put switches in and LEDs to display the input and output. Also Pin 15 of Input is permanently connected to the Result Register pin (the 14500 Accumulator) and Pins 8-14 are routed from the output latch so they can be used as 7 bits of data storage.

An emulator in C2 is perfectly feasible, but for anything significant probably needs to be written in pure Javascript. The tilemap would be very good for old fashioned memory mapped screens, but wouldn't be much use for a pixel graphic one.

Note that the source is available in a different github, see the links bar.

Thursday, 16 July 2015

App # 1 : MC14500B Evaluation Board

Well, I changed my mind about this. Partly because all the documentation regarding the WDR-1 is in German, and this emulation (on the right) is the Motorola Evaluation kit, which is very similar (the primary difference is memory is arranged as 4 bits rather than 8 bits) and it's in English. I don't speak a lot of German (may improve as I'm spending a week in Germany from Monday, but I'm probably not going to use the German for "Program Counter" much).

Most of this is done, the only bit missing is the actual emulation of the processor.

Seems a bit pointless, but it gave me some opportunities to experiment with ideas for interfaces. It's also an insane thing to program as it has no loops (other than reset to the start) in most implementations, which means everything is state machines. You can have branches and subroutines but none of the hardware is present in the 14500, all it does is pulse a chip pin "Jump" or whatever.

Almost none of the switches and LEDs are placed manually, they are generated by having another object create it, below is what the design screen actually looks like. Each purple IO says what to draw, how many bits, and whether it is input or output. This data is then copied to and from a dictionary, which acts as an intermediary between the interface and the program. Push buttons call a function derived from an instance variable. It works quite well.

Part of Construct 2's Editor Window