Showing posts with label BASIC. Show all posts
Showing posts with label BASIC. Show all posts

Sunday, May 20, 2018

Easy add-on Projects for Spectrum ZX81 & ACE (Redux): Part 3

2 comments

Let There Be Light Pen

Now that we have a working Decoder Board from 'Easy Add-on Projects for Spectrum, ZX81 & Ace', it's time to get down to some projects. There are a couple in the book I've really been wanting to try out,  Project 2: Picture Digitser and Project 7: Light Pen. Despite our guide books numeric ordering, the Light Pen is by far the simpler build, so lets start there.

The Light Pen Project

As everybody from the 80s knows, the Light Pen is the control mechanism of the future, mice touch screens and keyboards all redundant when you have a light pen by your side, it's truly the wonder input device for the ages.

Typically light pens work with only on CRT monitors; as lines are drawn on a CRT screen a light pen detects the CRTs scan line once it reaches the pen. The time it takes for the light pen to detect the scan line allows the computer to pinpoint exactly where on the screen the pen is placed.

The light pen featured in Easy add-on Projects for Spectrum ZX81 & ACE does not work in the typical way. Essentially the projects light pen functions as a light detector that doesn't detect CRT scan line progression. Working out where the light pen is on the screen is left entirely up to our BASIC programs. As it turns out (thirty plus years on from the books publications) this simplicity is exceptionally beneficial for the projects light pen, marking it just as usable on LCD monitor as it ever was with a CRT.

Original Light Pen Circuit from Easy Add-on Projects for Spectrum, ZX81 & Ace
Building the Light Pen and Circuit is not a difficult. I constructed the majority of the circuit on a breadboard, which sits quite nicely just behind the ZX81's keyboard. The LDR is mounted in the tip of an old pen, with a cable running down through the centre of the x-writing implement.  I hot glued the cable and resistor legs to removable nib holder (is that what it's called?) and the cable again where it leaves the top of the pen. This hold everything together quite firmly.

ZX81 and Light Pen attached to the Decoder Board
I was forced to make some minor changes to the circuit as some components can be harder to come by than others. The local (read Australia) walk in Electronics supplier Jaycar don't stock the projects prescribed ICL7611 CMOS Op Amp. In order to get the Light Pen up an running with minimal fuss I substituted the ICL7611 for a general purpose LM741 Op Amp.

Modified Light Pen Circuit
The IC change also made the addition of a couple of resistors necessary. The Output of the Substitute LM741 Op Amp doesn't lower the voltage close enough to TTL logic levels when detecting variances between the light-dependent resistor and reference potential. Two resistors, a 10k and a 4.7k are added to the IC Output that's feed back to the Decoder Board.

ZX81 Light Pen Test Menu Application
Based on the books listings and general project information I wrote up a simple BASIC application to test out the new pen with my trusty ZX81. The light pens status is read by input 3 of the Decoder Board, lines 10 and 20 of the BASIC listing reflect this. Line 10 also stores the machine code routines required for a ZX81 to read the Decoder Board: Refer to Appendix A of  'Easy Add-on Projects for Spectrum, ZX81 & Ace' for how all that works.

Finally, I've added a short YouTube Video of the Light Pen and the BASIC program in action. As can be seen it's really quite effective for simple input tasks.




See more entries for this project: Forward, Part 1, Part 2, Part 3


Read More

Friday, October 27, 2017

RetroChallenge 2017/10: Part 7

Leave a Comment

Developing Software on the NEC PC-8401?


Just a bit of fun for this entry. After experimenting with some software development last post, it quickly became apparent that writing software directly on the PC-8401 is a little inconvenient (at least without a memory expansion). This lead to the use of Z88dk for external development and a little cross-compiling to CPM to suite our purposes.

I couldn't help thinking that although the outcome was successful, it seemed a little like cheating. So lets cheat a tiny bit less.

As we know, the PC-8401 comes with a very capable Vt100 compatible Terminal program, one that's perfect for interfacing with LINUX. Now with minimal imagination required  lets pretend it's 1985 and we're developing on some extremely expensive time sharing remote platform tended by white coat wearing professionals.

There are many ways to configure serial / rs232 terminal sessions within LINIX, so here's one way, and one that's really simple although not a permanent on boot ready option.

First, we need to find the correct Serial Port. I'm using a USB to serial adaptor and need to know which exact device to target.

From the command line in LINUX issue: dmesg | grep USB

This yields a load of messages, but I'm looking for something as below.

[   22.444199] usbserial: USB Serial support registered for pl2303
[   22.444774] usb 1-10: pl2303 converter now attached to ttyUSB1


Now knowing knowing which USB device is the serial converter, it's an easy matter to setup a terminal console.

sudo stty -F /dev/ttyUSB1 cols 80 rows 15 1200
TERM=vt100 ksh </dev/ttyUSB1 > /dev/ttyUSB1 2>&1 &


Once that's all done, I can start up the PC-8401s Terminal program, configure it to 1200 baud 1 stop bit, no parity and 8 bit word length and I'm up and running a LINUX remote console. From there it's time to start up a text editor, VI, Emacs or Nano and get developing.

NEC-PC8401 with and open LINUX console running nano and editing code

Once some very impressive software has been developed, it'll need to be transferred to the PC-8401 to be executed in all it's glory, and LINUX provides a couple of easy to use xmodem commands to do just that.

To send files from LINUX via Xmodem:
sx my_file.com

To receive files from the PC-8401
rx my_file.com

Now there is absolutely no excuse, not in the slightest to use a 27 inch widescreen monitor to interact with a high powered modern PC to write applications.

Finally, thanks to Mike Spooner for indirectly generating the idea behind this post.

See RetroChallenge Intro, Part 1, Part_2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8
Read More

Wednesday, October 25, 2017

RetroChallenge 2017/10: Part 6

2 comments

Writting New Software for an NEC PC-8401


As noted previously, the PC-8401 came sans BASIC interpreter, which was quite an anathema in the day. This lack of BASIC presents no real impediment in producing new software for the machine today, even back in the 80s a CPM targeted variety of BASIC could be sourced for the machine (if not a specific PC-8401 version). 30 years on, being equipt with a Z80A processor and the CPM 2.2 operating systems puts this laptop a good position for some software development.


Getting into BASIC


To start we'll need to copy BASIC interpreters onto the PC-8401. AS with all software, BASIC will be taking up valuable chunks of the 32k reserved as drive space. Our own BASIC text files will then need to fit in whatever space remains. Ideally we'd have a RAM extension, either a PC-8406A 32K RAM pack or a PC-8407A 128K pack, in order to program something of a reasonable size. Still even without a RAM pack we can at least try out a number of BASIC flavors.

Both the versions of BASIC mentioned below are available from Gary J. Webes' excellent NEC PC-8201 support site WEB8201, where he holds a selection of software for the NEC PC-8401. NEC PC-8401. Check out the NEC 8401A / 8500 File Collection portion of the File Downloads page.

Microsoft BASIC


In the stakes to use the greatest amount of memory possible, Microsoft BASIC wins hands down. The last CPM version 5.29 will take up huge 23.4k of 'disk space' and when executed leaves a little over 1k of active memory on the PC-8401 to play around with. On the plus side, it's the version of BASIC that's the most familiar, and baring some commands unavailable in the CPM version, there are a wealth of examples laying around to learn from.

Unfortunately the size of MS BASIC makes it a non stater, it's more of a curiosity than something of practical usage. There are compilers available for MS BASIC, though a you still require libraries on the disk to run complied applications. Due to lack of disk space, compilation would need to be run on a host computer before moving the end product over to the PC-8401.


ZBAS


Luckily there are other options, ZBAS is quite a usable option only requiring 16.4k, leaving us with some room to write programs interactively, and some space to save these applications to disk.

Interestingly and extra fortunately when saving files, ZBAS tokenises BASIC Commands, much like on a 128k ZX Spectrum. Thus allowing for some larger than expected applications to be saved on our rather limited 'solid' state storage.

If your going to leave BASIC laying around on the System, then ZBAS is clearly the one to have.


Moving to Modern 'C' Developement


While there are plenty of period development platforms and languages available for CPM, including 'C's and Pascals, you'll need to run these in a emulated environment as there is no room on the PC-8401 for such niceties. A load of CPM software and utilities are available on the retroarchive, although none of these programs are specific to the PC-8401.



Z88DK


Perhaps the easiest way to pursue software development for a CPM machine and the PC-8401 today is via the use of Z88dk. Z88dk is a 'C' compiler targeting TRS80s, Commodore 128s, Sinclair ZX81s and just about any machine containing a Z80 processor. Specifically for out purposes there is a dedicated CPM library.

In order to test Z88DK out with the PC-8401 I borrowed from an older ZX81 program I wrote up some time ago, "ZX Roman Numeral-Izer". The program is a simple roman numeral format checker, it takes Roman numerals as an argument and then correctly formats them to the agreed standards (Standards that even the Romans didn't always adhere to). After a couple of minor changes to remove some specific ZX81 extensions and put in some specific PC-8401-isations the project compiled perfectly.




If you're interested then the full source is below, bit of a rush and there will be better ways to achieve the same result I'm sure, still proof of concept proven.


NEC PC-8401 Roman Numeral-iser Listing

// To Compile for CPM do as below.
// zcc +cpm -lm -o rome.com rome.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef enum { true = 0, false = !true } bool;

static short isaNumArab[7] = {1, 5, 10,50,100,500,1000};
static char csaNumRome[8] = "ivxlcdm";

// Function Get Arabic value of Roman Numeral
short GetArabValue(char csMyNumerals[15]){

 char csMyNumeral[2];
 char csNumRome[2];

 short iNumberNow = 0;
 short iNumberLast = 0;
 short iNumberTotal = 0;

 short iCount1 = 0;
 short iCount2 = 0;

 bool bTest = false;
 bool bNegative = false;

 //Go through sMyNumerals input string backwards for easier rule matching
 for (iCount1=strlen (csMyNumerals)-1; iCount1>=0; iCount1--){
  strncpy(csMyNumeral, csMyNumerals+(iCount1*1), 1);
  csMyNumeral[1]='\0';

  for (iCount2=0; iCount2<=strlen(csaNumRome)-1; iCount2++){
   strncpy(csNumRome, csaNumRome+(iCount2*1), 1);
   csNumRome[1]='\0';
   bTest = strnicmp(csMyNumeral, csNumRome,1);

   if (bTest == true){
    iNumberNow = isaNumArab[iCount2];

    if ((iNumberNow > iNumberLast) || ((iNumberNow == iNumberLast) && (bNegative == false))){
     iNumberTotal = iNumberTotal + iNumberNow;
     bNegative = false;
    } else {
     iNumberTotal = iNumberTotal - iNumberNow;
     bNegative = true;
    }
   }
   iNumberLast = iNumberNow;
  }
 }

 return iNumberTotal;
}

// Function Get Roman value of Arabic Numeral
void PrintRomeNumerals(int iMyNumberArab){
 char csNumRome[16];
 char csMyNumerals[16];
 char csMyNumeral[2];

 short iTemp[16];

 short iNumberNow;

 short iCount1 = 0;
 short iCount2 = 0;
 short iCount3 = 15;

 memset(csNumRome,0,strlen(csNumRome));

 memset(iTemp, 0, sizeof(iTemp));

 if(iMyNumberArab>=4000){
  strcpy(csNumRome,"Max Value 3999");
 } else {

  itoa(iMyNumberArab,csMyNumerals,10);
  //csMyNumerals[15]='\0';
  //Go through sMyNumerals input string backwards for easier rule matching

  for (iCount1=strlen(csMyNumerals)-1; iCount1>=0; iCount1--){

   strncpy(csMyNumeral, csMyNumerals+(iCount1*1), 1);
   iNumberNow = atoi(csMyNumeral);

   switch (iNumberNow) {
    case 1: case 2: case 3:
     for (iCount2=0;iCount2<iNumberNow;iCount2++){

      iTemp[iCount3] = csaNumRome[(strlen(csMyNumerals)-1)*2-iCount1*2];

      iCount3--;
     }

    break;

    case 4:

      iTemp[iCount3] = csaNumRome[(strlen(csMyNumerals)-1)*2-iCount1*2+1];
      iTemp[iCount3-1] = csaNumRome[(strlen(csMyNumerals)-1)*2-iCount1*2];
      iCount3=iCount3-2;
    break;

    case 5: case 6: case 7: case 8:

     for (iCount2=0;iCount2<iNumberNow-5;iCount2++){

      iTemp[iCount3] = csaNumRome[(strlen(csMyNumerals)-1)*2-iCount1*2];
      iCount3--;
     }
     iTemp[iCount3] = csaNumRome[(strlen(csMyNumerals)-1)*2-iCount1*2+1];
     iCount3--;
    break;

    case 9:

     iTemp[iCount3] = csaNumRome[(strlen(csMyNumerals)-1)*2-iCount1*2+2];
     iTemp[iCount3-1] = csaNumRome[(strlen(csMyNumerals)-1)*2-iCount1*2];
     iCount3=iCount3-2;
    break;
   }

  }
 }

 printf("\n Correct Format: ");
 for (iCount2=0;iCount2<16;iCount2++){
  if(iTemp[iCount2]!=0){
   printf("%c",iTemp[iCount2]);
  }

 }
 printf("\n");

 return;
}


void BannerLine(short iLength, char cCharter){
 short iCount1 = 0;
 for (iCount1=0; iCount1<iLength; iCount1++){
   printf("%c",cCharter);
 }
}


void BannerSet(void){
 short iCount1 = 0;
 printf("\n");
 BannerLine(32,149);
 printf( "\n PC-8401 Roman Numeral-iser\n" );
 BannerLine(32,149);

 for(iCount1=0;iCount1<=strlen(csaNumRome)-1;iCount1++){

  printf("\n Numeral: %c = Numeric: %d",csaNumRome[iCount1],isaNumArab[iCount1]);
  if(iCount1 == strlen(csaNumRome)-1){
   printf("\n");
  }
 }

 BannerLine(32,149);

 printf("\n Roman Numeral Format Check\n");

 BannerLine(32,149);

}


short PressAnyKey(void){

 char chr;

 BannerLine(32,149);
 printf("\n Input Another Numeral? Y/N: ");
 chr = getchar();

 if(chr == 'n' || chr == 'N'){
  return 1;
 } else {
  return 0;
 }
}


main(void)
{

 char csMyNumerals[15];

 bool PressKey = true;

 char csMyNumberRome[15];
 int iMyNumberArab = 0;

 while( PressKey != false ) {

  BannerSet();

  printf("\n Roman Numerals: ");
  fgets(csMyNumerals,15,stdin);
  iMyNumberArab = GetArabValue(csMyNumerals);
  printf(" Numeric  Value: %d",iMyNumberArab);

  PrintRomeNumerals(iMyNumberArab);

  memset(csMyNumerals,0,strlen(csMyNumerals));
  memset(csMyNumberRome,0,strlen(csMyNumberRome));

  PressKey = PressAnyKey();

 }
}

See RetroChallenge Intro, Part 1, Part_2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8
Read More

Thursday, March 23, 2017

Peeking into the ZX81s Screen Maze

4 comments
While thinking about some possibilities of how to approach various projects in my to-do list, I realised that these were going to need some screen reading elements, or rather I'd need to PEEK into the display file to see what was going on. This lead to some re-research into how the ZX81 handles its screen output. While some excellent information on the subject is not hard to find, I figure a poke into this might be of use to others.

What's being displayed by the ZX81 on a monitor at any given time is not exactly a mystery, nor is how it got there. What  can be mystery is how to retrieve that information for (re)usage in an application. Actually that's not much of a puzzle either, though possibly a little ambiguous at first.

The ZX81 stores screen related information in a area of memory known as the "display file" or DFILE for short, this is outlined briefly in chapters 27 of the ZX81 manual. What's not made quite so clear is how to access that area of memory, or how that area is configured at any given moment by the machine. This last part is particularly crucial if your ZX81 has less than 4k of RAM (Not of any real concern these days I suppose, but you never know.)

The relationship between the ZX81 Display File and D_File system variables laid out for easy reference.

First off we need to know where the DFILE resides. The location is not static (unlike the ZX Spectrum's DFILE) and moves up or down depending on the size the BASIC program listing. Thankfully there is a system variable, D_FILE, which stores this starting location. What we need to do is PEEK the address of the D_FILE variable to ascertain the location of the actual DFILE. Note that address is stored in 2 bytes.

PRINT PEEK 16396 + PEEK 16397 * 256

On a freshly booted system the result of  the above should be 16509. You might notice that this is also the starting address for the "Program" memory area, which indicates that there is currently no program stored.

Next we can determine how large the DFILE is by reading the system variable VARS. This is where a non expanded ZX81 will differ from one with a RAM pack attached. The returned value will give you the starting location of the user Variables memory allocation area. Again note that the returned listed values from PEEKing the VARS system variable assume there in no program loaded.

PRINT PEEK 16400 + PEEK 16401 * 256

Variables starting address on a 1k ZX81 (or 2k Timex 1000) is: 16534
On a ZX81 with 4k or more expanded memory: 17302


If we subtract the value of D_FILE from VARS, the byte allocation or size of the DFILE is revealed. What we notice is that on a 1k ZX81 the default size of the DFILE is 25 bytes, and on a 4k plus system the DFILE is allocated 793 bytes. The massive (overstatement) size difference between an expanded and unexpaned machine comes down to how the ZX81 handles the DFILE. On a 2k or less machine the DFILE is expanded as it is required, while on a 4k plus computer the DFILE is always fully extended.

On a 1k or 2k ZX81, each of those 25 bytes contains a CHR$ 118, the Newline Character. One CHR$ 118 marks the start of the DFILE , and when a line is printed to, the DFILE is expanded to a maximum of 32 characters per line, with each line always being terminated by a Newline.

A ZX81 with 4k or more always has a fully expanded DFILE, containing 25 CHR$ 118, marking the start of the DFILE and end of each line, plus 32 * 24 characters, which are initially CHR$ 0, the space character, yielding a 793 byte total.

Putting the above into practice, two programs below demonstrate how to POKE to the screen directly, instead of PRINTing. The key lines in both applications are 80 (highlighted), where the second PEEK address is adjusted for either the expanded or collapsed DFILE.


1) Program For a 1K ZX81. If using an emulator make sure it's set for 1K
10 PRINT "POKE MY SCREEN 1K"
20 PRINT AT 2,8;"+++"
30 PRINT TAB 8;"+ +"
40 PRINT TAB 8;"+++"
50 PRINT AT 6,0;"ENTER A CHARACTER AND NEWLINE","OR JUST NEWLINE TO STOP"
60 INPUT A$
70 IF A$="" THEN STOP
80 POKE PEEK 16396+PEEK 16397*256+41,CODE A$
90 GOTO 60

2) Program For a 4K and up ZX81. If using an emulator make sure it's set for 4K or more
10 PRINT "POKE MY SCREEN 4K AND UP"
20 PRINT AT 2,8;"+++"
30 PRINT TAB 8;"+ +"
40 PRINT TAB 8;"+++"
50 PRINT AT 6,0;"ENTER A CHARACTER AND NEWLINE","OR JUST NEWLINE TO STOP"
60 INPUT A$
70 IF A$="" THEN STOP
80 POKE PEEK 16396+PEEK 16397*256+109,CODE A$
90 GOTO 60

The programs above have been modified from listings originally published in the September / October 1981 issue of Sync Magazine, which is available from the Internet Archive. It's well worth trawling through the entire Sync back catalogue for all manner of useful insights.

Using the information above you can see how easy it is to read or write to the ZX81s screen, and then take that into more complex programs. For a deeper insights into the ZX81s display, you can't go past Wilf Rigters' extensive write up The ZX81 Video Display System.

Finally, yes you really can do something interesting with this information, the below maze is generated by a program written in C for the Z88DK compiler. The Maze generator relies heavily on being able to read the Screen / DFILE (that and a maze algorithm). Feel free to download The Maze C source and ZX81 P file for perusal.

Output of the ZX81 Maze Program.


Read More

Sunday, February 19, 2017

Lode Runner on the ZX81 - Part 2 (Level Design)

Leave a Comment
There are going to be numerous challenges facing the design and implementation of Lode Runner on the ZX81, and one of the first I need to consider is level storage.

The original Apple II version of Lode Runner comprised 150 levels, these were loaded from disk when required. The ZX81 doesn't afford us the luxury of being able to load from a disk or tape without clearing the running application and memory. So even if we assume our ZX81 has 32k of RAM (about the maximum for the time), squeezing all 150 levels into the diminutive black box is an insurmountable task.

There are modern storage solutions available such as the ZXpand, that could be used to negate the space restrictions, however there is no common file access method shared across these modern deceives. So regardless of current available solutions, the challenge here is to fit as many levels as possible into the resources we do have at our disposal.

To make the challenge slightly easier I'm going to base the level design on the Apple II version, not the (possibly expected) ZX Spectrum incarnation. The reason for this is a simple matter of level storage space. The Apple II maps are a convenient space saving 28 wide x 16 tiles high, where as the Spectrum versions comes in at 32 wide x 22 tiles high. Or to put it another way, 448 tiles on the Apple version versus 704 tiles on the Spectrum version per level to define.

If we look to any "type in" game from the period as a (bad) example, most defined entire screens in the program listings on a one to one tile basis. This method would uses 1 byte per tile, and clearly there is not enough space in a ZX81 for even 10 levels defined in this manner (and still have a game to play). It's imperative to compress each level down as far as possible.

The solution is to store the tile type and the number of tiles(of the same type)  in succession into 1 byte. To achieve this, we can use two 4 bit numbers. This affords us up to 16 available tile types, and 16 successions of that tile. Wwe add the number of tile repeats, 0 to 15 to the tile type value. The tile type value is bit shifted before the addition, and this will produce an 8bit number we can store.


Lode Runner Map Tiles: 4 bit Number Values Chart
Tile No4 Bit ShiftedLevel Starting Position Tile Type
000000Empty: Clear Tile / Background
001016Block: Can't dig through tile
002032Bricks: Can be dug into to create traps
003048Bricks, Fake: Player falls through fake bricks
004064Rope: Player can move horizontally, or jump down
005080Ladder: Visible all game / level
006096Ladder, Escape: Visible only after all gold is collected on a level
007112Gold: Player to collect all gold
008128Guard: Starting position of Guards. After level begins guards fall from the top of screen (after being trapped).
009144Player: The Lode Runner


For example, using the table above, if we require 4 Bircks in a row, we take the value of Bricks, 32 and add it to the number of required repeats 3, for a total of 35. In, in order to produce the entire starting positions of the first level of the Apple II version of Load Runner, each of the 16 rows would be defined as bellow.

01) 15,1,96,8,
02) 3,112,12,96,8,
03) 38,80,38,2,96,8,
04) 6,80,73,96,3,112,3,
05) 6,80,3,33,80,2,38,80,33,
06) 6,80,3,33,80,9,80,1,
07) 4,128,0,80,3,33,80,9,80,1, (missing right guard and gold)
08) 33,80,36,3,39,80,38,
09) 1,80,15,0,80,6,
10) 1,80,10,128,4,80,6,
11) 40,80,41,80,6,
12) 8,80,9,80,6,
13) 6,112,0,80,73,80,2,112,2,
14) 3,80,37,8,38,80,
15) 3,80,8,144,1,112,8,80,
16) 47,43



Lode Runner, Level 1, Apple II Version

After reading the level data as outlined, the ZX81 level would look something like the bellow screen shot (if using standard character set, no hires graphics yet). Notice that the the escape ladder is drawn in with the "S" character.

Lode Runner, Level 1, ZX81 level Map., Starting Position.


Rather than guess the levels layout, I converted directly from the LodeRunner TotalRecall levels, as (re-)implented by Simon Hung. The TotalRecall levels are implemented in ASCII, which makes reading them easy. The ZX81 map is missing the 2nd guard and gold on line 7, I overlooked these items when writting up the test.

That's all for now, be assured I'm still wotking away on the project, it's just going a little slower than anticipated due to some time and life constraints.
Read More

Thursday, December 08, 2016

ZX81 Draughts Challenge - Part 3 - Tims Checkers

Leave a Comment
As this whole little (and I say little in heavy quotes) escapade has been inspired by two very informative ZX-Computing articles penned by the late great Tim Hartnell, the game he inspired now bears the official title of "Tims' Checkers".

And as such this is now the official announcement and launch of the hightly anticipated, completely compelling retro-tastic ZX81 game "Tims' Checkers".

After the last blog entry I had hopped to have a couple of varieties of checkers available in the one game, unfortunately this was not to be. No doubt some of this is down to some slightly shoddy C programming, however there is one very valuable lesson to be learnt when using the WRX hires graphics mode in z88dk, namely that you loose at least 4k of valuable game writing space to the hires graphics screen itself. So what this largely means is that in order to keep the game within 16k limits, some things just had to be dropped.

Would You Like to Play a Game?
So yes due to space constraints I've had to drop the multiple game play options, there is no option to play Spanish checkers or Corners as originally envisaged, instead what we do have is a full-ish checkers implementation.

The computer player has been enhanced from the basic opponent provided in Tims' ZX-Computing articles. Although again due to the self imposed space issues the ZX81 is not the most brilliant of strategists, yet competent enough to play an enjoyable and somewhat surprising game.

Basic Rules:

  • Men may move and capture only diagonally forwards.
  • Kings may move and capture diagonally forwards or backwards, but can not jump over empty squares.
  • If a player is in a position to make a capture then a capture move must be taken. If there are multiple capture options the player is free to choose. Once a man or king has captured that piece must continue to capture until there are no more capture options available.
  • If a man lands on the final row, the row furthest from a players starting position, the man is kinged.

A Bit Further in. The ZX81 has KInged.

Playing The Computer:

  • Select if you or the ZX81 goes first.
  • Use standard algebraic notation to enter moves.
  • There is no backspace, so if you start to enter the wrong move just make the rest of the entry an impossible move.

Really there is not much to it, after all checkers is a simple game and perfect for the ZX81. I'm considering this to a beta release, if you the prospective player find any glaring errors then please feel free to report them.

Download Tims' Checkers and give it a go in your favorite ZX81 emulator. Remember that you'll need to enable WRX graphics in your emulator to play correctly.

Read More

Monday, November 14, 2016

ZX81 Draughts Challenge - Part 2 - A Little Hi-Res

Leave a Comment
In the last post I took up a challenge set by Tim Hartnell 34 years ago, namely apply his BASIC ZX81 board games layout to multiple draughts games types. In this entry I'll delve into some of what's been put together so far.

In the Dec / Feb 1983 edition of ZX-Computing, Tim presented two versions of his finalised BASIC listing, one that plays the Corners variant of draughts from the previous ZX-Computing article, and another version that implements a Spanish checkers style game. The other standout new feature is the addition of a full screen and
 somewhat more graphical checkers board.

As graphics are where it's all at these days, best to start by bringing some major graphical improvements to Tims' Board. As covered last time, I'm developing (or is that re-developing?) the draughts game using the brilliant  Z88DK / C compiler. Of course C in itself does not have any real graphical capabilities, but thankfully within Z88DK are a host of ZX81 (and other micro-computer) targeted graphical options. Desire Hi-Res graphics on a ZX81? Yes we do. Well Z88DK has them, so of course we're going to be using those.

Draughts Board in Hi-Res ZX81 Style
There are three main parts to how I approached drawing the board and game men. Firstly, you can print regular characters with a simple printf("blah") statement, or the ZX81 character can be got at by switching with the zx_asciimode[0] command. More importantly the ZX81 BASIC "PRINT AT" statments are also catered for by Z88DK with the provision of the zx_setcursorpos(Y,X) function. Armed with these tools, the underlying checker board can be printed up quite easily.

Secondly, some nice Hi-Res flourished are easy enough to factor in with ZX88DK draw functions, such as drawing a boarder with drawb. All quite straight forward, with the exception that the Hi-Res screen does not allow normal characters to be output directly, as a different memory area is allocated to Hi-Res Graphics, one that swaps out the normal display page for its own. Again however once again there are commands for that. Anything written to the normal display can be copied to the Hi-Res display with a variety of copytxt() function options. So that's most of the standard display options accounted for.

Draughts Board Set up for Spanish Checks.
Thirdly, and lastly, the game men / pieces: There are options to define sprites for use with Z88DK, the men could have been created via this method, though at least for now, I've not used this functionality. Instead I've implemented a kind of User Definable Graphics option for the game men. The men are plotted via the Hi_Res functions onto the game board, thankfully this option is quite fast, and adds a nice animation quality. The UDGs are quarter of a full game piece, and credit to goes to the speccy_charater_builder website for making prototyping the men painlessly. The same UDG is used for both player and computer opponent. King pieces have also been defined for use in a fuller draughts game than described in the ZX-Computing articles.

That's it for the moment, in Part 3 I'll cover further graphic details as they affect the general game play and setup. I should say Games set up, as there are to be multiple draughts variants to choose from before the start of game play.



Read More

Sunday, October 23, 2016

ZX81 Draughts - Challenge Accepted 34 Years to Late

Leave a Comment
Way back in 1982, Tim Hartnell wrote the first part of a two article series detailing a method of creating board games on a computer for ZX-Computing magazine. At the end of the feature Tim expressed a desire to see what people made of his system, and send in their own programs derived from the article listings. Even though 34 years have passed since the article was first published, I thought I'd give it a shot. (Sadly Tim passed away in 1991).

Actually this is a multi level challenge, as I'm using Tims program and system to fiddle around some more with Z88DK, the C compiler for Z80 processors. Alongside this, I thought it would be interesting to see just how much faster a complied C program would run in comparison to a native ZX81 basic listing.

Tim Hartnells' Corners Program from 1982
I started by simply entering the listing as presented in the original feature, 'Board-Game Design' that can be found in ZX-Computing from Oct/Nov 1982. The entered program plays a fun rudimentary game of draughts, called Corners. Being a BASIC listing, the speed of the end result is best described as painfully slow. Of course given that we are talking about a BASIC program form 1982, written for a computer as simple as a ZX81, playing any sort of board game would have been considered a minor miracle at the time.

Next came a nearly straight conversion into C. I've pretty much used the exact structure of Tims' program as far as possible, in writing a version that would compile in Z88DK. Also none of the the more fancy features provided in the exteneded Z88DK ZX81 libraries were used (or for that matter any advanced C programing techniques) which is one reason why as you will notice when running the complied version that the screen redraw is not particularly seamless.

Z88DK complied C version of Corners
I did make some minor changes, the most noticeable being the layout, this is purely cosmetic, Another change, or rather oversight, I assume the Player always goes first. The real change was to add some extra checking into the validity of the Human players move. The original program assumed that the player was a humble honest sole, and never felt the need to cheat. That assumption also had a side effect of the program not checking the players move was even possible, and if not, the players move was basically ignored and the computer would gain a free turn.

In the end we have 2 quite passable ZX81 Corners (draughts) playing programs. But what about the speed test? Well the speed results are quite dramatic. The BASIC listing clocks in at around 12 seconds, just setting up the board in the background for the initial run (not including drawing the board itself). The Compiled C version takes about 2 seconds, including the initial board drawing. The overall speed difference just becomes more apparent from there on in.

Having tried out the BASIC listing and equivalent in C, it's now it's on to extending the program as Tim suggested. I'll continue to base the next version on the original idea. There is also the second article in the Dec 82 / Jan 1983 edition of ZX-Computing to peer into before proceeding.

Both versions of the Corners program are available in separate P files contained in zx81_corners_c_and_basic_files.tar.gz, and should run on any ZX81 emulator.

Hopefully soon I'll have a fine ZX81 board game playing program, 34 years after the initial call to action.
Read More