Hi all.
I've finally finished my conversion of an old BASIC program to ccz80 and assembler.
I've converted a type-in game from Amstrad Computer User, October 1985.
It is the 3D-Maze game by Nigel Sharp.
I've wanted to create an Amstrad machine code program for 24 years.
I really liked this game when I was a child, and I thought converting it would be a good way to learn machine code.
ccz80 has made the process MUCH easier.
The code isn't very nice. In fact it's probably quite hard to follow in places.
And I haven't commented it very much unfortunately.
But it works, and is MANY MANY times faster than the BASIC original.
In addition to the huge increase in speed, I was able to figure out how to make the display double-buffered, so there is no flickering during the screen redraw.
During the conversion, I discovered just how slow the ROM draw routines are. They are very good, and very flexible, but so slow...
So I wrote new routines to draw the lines, based on the fast plotting routines I found on cpcwiki.
I was able to speed them up further due to the fact that I didn't need a general line drawing routine.
All the lines are either vertical, horizontal, or a perfect 45 degree diagonal.
This meant that I could take several shortcuts when calculating the memory addresses of pixels in a line.
I've attached the code, and the dsk image can be downloaded from here:
http://www.cpcwiki.eu/imgs/f/f1/3d-maze.zip
To compile the code, I used the following command-line statement:
ccz80 3d-maze.ccz80 /org=#8000
To write the compiled binary file to a dsk image, I used the following code inside WinAPE's assembler:
write direct "a:3d-maze.bin"
org &8000
incbin "c:\ccz80\3d-maze.bin"
Enjoy!
I've finally finished my conversion of an old BASIC program to ccz80 and assembler.
I've converted a type-in game from Amstrad Computer User, October 1985.
It is the 3D-Maze game by Nigel Sharp.
I've wanted to create an Amstrad machine code program for 24 years.
I really liked this game when I was a child, and I thought converting it would be a good way to learn machine code.
ccz80 has made the process MUCH easier.
The code isn't very nice. In fact it's probably quite hard to follow in places.
And I haven't commented it very much unfortunately.
But it works, and is MANY MANY times faster than the BASIC original.
In addition to the huge increase in speed, I was able to figure out how to make the display double-buffered, so there is no flickering during the screen redraw.
During the conversion, I discovered just how slow the ROM draw routines are. They are very good, and very flexible, but so slow...
So I wrote new routines to draw the lines, based on the fast plotting routines I found on cpcwiki.
I was able to speed them up further due to the fact that I didn't need a general line drawing routine.
All the lines are either vertical, horizontal, or a perfect 45 degree diagonal.
This meant that I could take several shortcuts when calculating the memory addresses of pixels in a line.
I've attached the code, and the dsk image can be downloaded from here:
http://www.cpcwiki.eu/imgs/f/f1/3d-maze.zip
To compile the code, I used the following command-line statement:
ccz80 3d-maze.ccz80 /org=#8000
To write the compiled binary file to a dsk image, I used the following code inside WinAPE's assembler:
write direct "a:3d-maze.bin"
org &8000
incbin "c:\ccz80\3d-maze.bin"
Enjoy!
- Code:
include "cpc6128.ccz80";
byte dir;
byte en;
byte d;
byte ky;
byte dtt;
byte sn;
byte flash=0;
byte wfc,place;
word a;
word moves;
word mx,my;
word lev,levOffset;
word x,y;
word otx,oty;
word tx,ty;
word targX,targY;
word tmp1,tmp2,tmp20;
byte tmp3,tmp4,tmp5,tmp6,tmp7,tmp8,tmp9,tmp10,tmp11,tmp12,tmp13,tmp14,tmp15,tmp16,tmp17,tmp18,tmp19,tmp21;
array byte clock[4];
array byte text[21];
array byte sLeft={0,30,51,66,76,83,88,92,94,96,97,98};
array byte sRight={199,169,148,133,123,116,111,107,105,103,102,101};
array byte entSections1={130,5,255,1,10,1,1}; // 2 sections with 3 bytes each. The section number has had 128 added, as the env number is to be treated as negative.
array byte entSections2={129,1,15,1}; // 1 section with 3 bytes. The section number has had 128 added, as the env number is to be treated as negative.
array byte envSections1={1,5,255,1,100,0,100};
array byte envSections2={2,15,255,1};
array byte symbol_buffer[8]; // (256-255)*8=8
array byte symbol_arrowUp={24,60,126,255,24,24,24,24};
array byte symbol_arrowDown={24,24,24,24,255,126,60,24};
array byte symbol_arrowLeft={16,48,112,255,255,112,48,16};
array byte symbol_arrowRight={8,12,14,255,255,14,12,8};
array byte endSoundNote={119,119,119,119,95,95,95,95,80,80,80,60};
array byte endSoundLen={20,10,10,20,20,10,10,20,20,20,20,60};
array byte levSoundVol={0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,8};
symbolafter(255,symbol_buffer);
array byte hiTable[315]; // 15 elements of 21 bytes each.
array word hiScore[15];
word hsc1,hsc2;
array byte ma={
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,
1,0,1,1,1,0,1,0,1,0,1,1,1,1,0,1,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,
1,0,1,0,1,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,
1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,0,1,0,1,0,1,
1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,0,0,1,
1,0,1,0,1,1,1,0,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,
1,0,1,0,1,0,1,0,1,0,1,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,1,1,1,
1,0,1,1,1,1,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,1,1,0,0,1,
1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,0,0,0,0,1,1,
1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0,1,
1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0,1,1,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,
1,0,1,0,0,0,1,0,1,1,0,1,1,1,0,1,0,1,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,0,1,
1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,
1,0,1,0,0,0,1,0,0,0,1,1,0,1,0,1,1,0,1,1,0,1,0,1,1,0,0,0,1,0,0,0,1,0,1,
1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,1,
1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,
1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,
1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,1,
1,0,1,0,0,0,1,0,0,0,1,1,0,1,0,1,1,0,1,1,0,1,0,1,1,0,0,0,1,0,0,0,1,0,1,
1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,
1,0,1,0,0,0,1,0,1,1,0,1,1,1,0,1,0,1,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,0,1,
1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,
1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0,0,0,1,0,1,1,1,0,1,0,1,1,1,1,0,1,0,0,1,
1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,0,1,1,0,1,
1,0,0,0,1,0,1,0,1,0,1,0,0,0,1,0,0,0,1,0,1,1,1,0,0,0,1,0,1,1,0,1,0,0,1,
1,1,1,1,1,0,0,0,1,0,1,0,1,1,0,0,1,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1,0,1,1,
1,0,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,1,1,0,1,1,0,0,0,0,1,
1,0,1,0,0,0,1,1,0,0,1,1,0,0,1,0,0,1,1,0,1,0,0,1,0,0,0,0,0,1,0,1,1,0,1,
1,0,1,1,1,0,1,0,0,1,1,0,1,0,0,0,1,1,0,0,0,1,0,0,1,1,0,1,0,1,0,0,0,1,1,
1,0,0,0,0,0,1,0,1,0,0,0,0,1,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,1,1,1,0,0,1,
1,0,1,1,1,1,0,0,1,1,0,1,0,1,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0,1,0,1,1,
1,0,0,0,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,0,1,
1,1,1,1,1,1,0,1,0,1,1,1,0,1,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,1,1,0,1,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,1,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,
1,0,1,1,0,0,0,1,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,1,0,1,1,1,0,1,
1,0,0,0,0,1,0,0,0,1,0,1,1,0,1,1,1,1,1,0,1,1,1,0,0,0,0,0,1,0,1,0,1,0,1,
1,0,1,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,1,0,1,1,0,1,0,0,0,1,
1,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,1,1,0,0,1,0,0,0,1,0,1,0,1,1,1,
1,1,1,0,0,1,1,1,1,1,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0,1,
1,0,0,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,0,1,0,1,1,0,0,1,0,1,
1,0,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,1,
1,0,0,0,1,0,1,0,0,0,0,0,1,0,1,1,0,0,0,0,0,1,0,0,1,1,1,1,1,1,0,1,0,1,1,
1,0,1,1,1,0,1,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,
1,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,1,1,0,1,
1,0,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,1,0,0,1,1,0,0,0,1,0,1,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
};
array byte view={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
srand(**time(clock));
printc(22);
printc(0);
printc(23);
printc(0);
ent(1,entSections1);
ent(2,entSections2);
env(1,envSections1);
env(2,envSections2);
for (a=0;a<=14;a++)
{
**(hiScore+(a*2))=(a+1)*100;
strcpy(hiTable+(a*21),"Nobody in particular");
}
asm{"ld iyl,0"}
s230:
asm
{
"ld hl,#0a01","call __km_set_delay",
"ld a,1","call __scr_set_mode",
"xor a","ld bc,#0000","call __scr_set_ink",
"ld a,1","ld bc,#1a1a","call __scr_set_ink",
"ld a,2","ld bc,#0c0c","call __scr_set_ink",
"ld a,3","ld bc,#0e0e","call __scr_set_ink",
"ld bc,#0b0b","call __scr_set_border",
"ld a,1","call __txt_set_pen",
"xor a","call __txt_set_paper",
"ld hl,#0101","call __txt_set_cursor"
}
prints("3-D Maze");
asm
{
"ld hl,#0102","call __txt_set_cursor",
"call print2",
"ld a,2","call __txt_set_pen",
"ld hl,#0103","call __txt_set_cursor"
}
prints("Original by Nigel Sharp (1985)\r\nccz80 version by Ervin Pajor (2009)\r\n\r\n");
asm{"ld a,3","call __txt_set_pen"}
prints("Work your way down through the four\r\nlevels of the maze to the ground\r\nfloor, where you must find the target\r\nmarked with a blue cross.\r\n\r\nOn each level there is a hole leading\r\nto the next level.\r\n\r\nThere are several things to help you.\r\n\r\nMost useful is the map, which is built\r\nup as you explore.\r\n\r\nThe hole/target is shown as a black\r\ndot, and your current position is\r\nshown flashing.\r\n\r\nTurn: LEFT & RIGHT CURSOR KEYS\r\nMove: COPY KEY");
asm
{
"ld hl,#1e19","call __txt_set_cursor",
"ld a,1","call __txt_set_paper",
"ld a,2","call __txt_set_pen"
}
prints("PRESS A KEY");
clearinput();
while (!inkey());
moves=0;
lev=0;
asm
{
"ld a,2","call __gra_set_pen",
"ld a,1","call __scr_set_mode",
"ld bc,#0202","call __scr_set_border",
"xor a","ld bc,#0000","call __scr_set_ink",
"ld a,1","ld bc,#0e0e","call __scr_set_ink",
"ld a,2","ld bc,#0c0c","call __scr_set_ink",
"ld a,3","ld bc,#0303","call __scr_set_ink",
"ld a,1","call __txt_str_select",
"ld hl,#1900","ld de,#2718","call __txt_win_enable",
"ld a,3","call __txt_set_paper",
"call __txt_clear_window",
"xor a","call __txt_set_pen",
"ld hl,#0302","call __txt_set_cursor"
}
prints("3-D Maze");
asm
{
"ld hl,#0303","call __txt_set_cursor",
"call print2",
"ld a,1","call __txt_set_pen",
"ld hl,#0305","call __txt_set_cursor"
}
prints("Level:");
asm{"ld hl,#0307","call __txt_set_cursor"}
prints("Moves taken");
asm{"ld hl,#0308","call __txt_set_cursor"}
prints("so far:");
asm{"ld hl,#030a","call __txt_set_cursor"}
prints("Moves to");
asm{"ld hl,#030b","call __txt_set_cursor"}
prints("target:");
asm
{
"ld hl,#080e","call __txt_set_cursor",
"ld a,78","call __txt_output",
"ld hl,#0a10","call __txt_set_cursor",
"ld a,69","call __txt_output",
"ld hl,#0812","call __txt_set_cursor",
"ld a,83","call __txt_output",
"ld hl,#0610","call __txt_set_cursor",
"ld a,87","call __txt_output",
"ld a,2","call __txt_set_paper",
"ld a,iyl","cp 1","jp c,copy4000",
"ld de,#c000","ld hl,#4000",
"jp performCopy",
"copy4000:",
"ld de,#4000","ld hl,#c000",
"performCopy:",
"ld bc,#4000","ldir"
}
s870:
dir=(rand()%4)+1;
lev++;
levOffset=(lev-1)*525; // level*rows*columns = level*15*35 = level*525
mx=520;
my=48;
asm
{
"ld a,2","call __txt_set_pen",
"ld a,3","call __txt_set_paper",
"ld hl,#0a05","call __txt_set_cursor"
}
prints(strltrm(btoa(text,lev),48));
asm
{
"call virtualFlip",
"ld hl,#0a05","call __txt_set_cursor"
}
prints(strltrm(btoa(text,lev),48));
asm
{
"ld hl,#080f","call __txt_set_cursor",
"ld a,32","call __txt_output",
"ld hl,#0910","call __txt_set_cursor",
"ld a,32","call __txt_output",
"ld hl,#0811","call __txt_set_cursor",
"ld a,32","call __txt_output",
"ld hl,#0710","call __txt_set_cursor",
"ld a,32","call __txt_output"
}
for (a=21;a<=24;a++)
{
asm
{
"ld h,4","ld a,(_a)","ld l,a","call __txt_set_cursor",
"call print3"
}
}
asm
{
"call virtualFlip",
"ld hl,#080f","call __txt_set_cursor",
"ld a,32","call __txt_output",
"ld hl,#0910","call __txt_set_cursor",
"ld a,32","call __txt_output",
"ld hl,#0811","call __txt_set_cursor",
"ld a,32","call __txt_output",
"ld hl,#0710","call __txt_set_cursor",
"ld a,32","call __txt_output"
}
for (a=21;a<=24;a++)
{
asm
{
"ld h,4","ld a,(_a)","ld l,a","call __txt_set_cursor",
"call print3"
}
}
s880:
x=(rand()%33)+2;
y=(rand()%13)+2;
otx=x;
oty=y;
if (lev==1)
{
otx=1;
oty=1;
}
if (*(ma+levOffset+(y*35)+x-36)==1) goto s880;
s920:
tx=(rand()%33)+2;
ty=(rand()%13)+2;
if (*(ma+levOffset+(ty*35)+tx-36)==1) goto s920;
targX=(tx-x)*2;
targY=(ty-y)*2;
asm
{
"call virtualFlip",
"ld de,520","ld hl,48","call __gra_set_origin",
"ld a,3","call __gra_set_pen",
"ld de,(_targX)","ld hl,(_targY)","call __gra_plot_absolute",
"call virtualFlip",
"ld de,(_targX)","ld hl,(_targY)","call __gra_plot_absolute",
"ld de,0","ld hl,0","call __gra_set_origin",
"ld a,2","call __gra_set_pen"
}
gosub s2890;
s980:
flash++;
if (flash==4) flash=0;
asm
{
"call virtualFlip",
"ld a,(_flash)","call __gra_set_pen",
"ld de,(_mx)","ld hl,(_my)","call __gra_plot_absolute",
"ld a,2","call __gra_set_pen",
"call virtualFlip"
}
a=inkey();
ky=0;
if (a==224) ky=9;
else if (a==242) ky=8;
else if (a==243) ky=1;
else goto s980;
if (ky==9)
{
if (*(view+17)==1) goto s980;
}
else if (ky==8)
{
dir--;
if (dir==0) dir=4;
gosub s2890;
goto s980;
}
else if (ky==1)
{
dir++;
if (dir==5) dir=1;
gosub s2890;
goto s980;
}
asm
{
"call virtualFlip",
"xor a","call __gra_set_pen",
"ld de,(_mx)","ld hl,(_my)","call __gra_plot_absolute",
"ld a,2","call __gra_set_pen",
"call virtualFlip"
}
sound(129,50,0,15,2,2,0);
moves++;
if (dir==1)
{
y++;
my+=2;
}
else if (dir==2)
{
x++;
mx+=2;
}
else if (dir==3)
{
y--;
my-=2;
}
else if (dir==4)
{
x--;
mx-=2;
}
gosub s2890;
if ((tx!=x) || (ty!=y)) goto s980;
if (lev<4)
{
sound(129,50,200,15,0,1,0);
for (sn=31;sn>=1;sn--)
{
asm
{
"sound_1:",
"ld a,1","ld (soundQueue),a",
"xor a","ld (soundQueue+1),a","ld (soundQueue+2),a","ld (soundQueue+3),a",
"ld a,2","ld (soundQueue+7),a",
"ld a,(_sn)","ld (soundQueue+5),a",
"ld d,0","ld e,a","ld hl,_levSoundVol","add hl,de","ld a,(hl)","ld (soundQueue+6),a",
"ld hl,soundQueue","call __sound_queue","jp nc,sound_1"
}
}
goto s870;
}
else
{
sound(129,*(endSoundNote),*(endSoundLen),15,1,0,0);
for (sn=1;sn<=11;sn++)
{
asm
{
"sound_2:",
"ld a,1","ld (soundQueue),a","ld (soundQueue+1),a",
"xor a","ld (soundQueue+2),a","ld (soundQueue+5),a",
"ld a,15","ld (soundQueue+6),a",
"ld a,(_sn)","ld d,0","ld e,a","ld hl,_endSoundNote","add hl,de","ld a,(hl)","ld (soundQueue+3),a",
"ld a,(_sn)","ld d,0","ld e,a","ld hl,_endSoundLen","add hl,de","ld a,(hl)","ld (soundQueue+7),a",
"ld hl,soundQueue","call __sound_queue","jp nc,sound_2"
}
}
for (a=1;a<=40000;a++);
asm
{
"call virtualFlip",
"call __scr_clear",
"call virtualFlip",
"call __scr_clear"
}
// Hi-scores.
if (**(hiScore+28)<moves)
{
wfc=1;
goto s1230;
}
**(hiScore+28)=moves;
strcpy(hiTable+294,"");
place=14;
for (a=14;a>=1;a--)
{
hsc1=**(hiScore+((a-1)*2));
hsc2=**(hiScore+(a*2));
if (hsc1>hsc2)
{
**(hiScore+(a*2))=hsc1;
**(hiScore+((a-1)*2))=hsc2;
strncpy(text,hiTable+(a*21),20);
strncpy(hiTable+(a*21),hiTable+((a-1)*21),20);
strncpy(hiTable+((a-1)*21),text,20);
place=a-1;
}
}
wfc=0;
gosub s1230;
asm
{
"ld h,16","ld a,(_place)","add a,8","ld l,a","call __txt_set_cursor",
"ld a,2","call __txt_set_paper",
"xor a","call __txt_set_pen"
}
clearinput();
input(text);
strncpy(hiTable+(place*21),text,20);
wfc=1;
s1230:
asm
{
"ld a,2","call __txt_set_paper",
"ld a,1","call __scr_set_mode",
"call __txt_clear_window",
"ld a,3","call __txt_set_pen",
"ld hl,#1002","call __txt_set_cursor"
}
prints("3-D Maze");
asm
{
"ld hl,#1003","call __txt_set_cursor",
"call print2",
"xor a","call __txt_set_pen",
"ld hl,#1005","call __txt_set_cursor"
}
prints("HISCORES");
asm
{
"ld hl,#1006","call __txt_set_cursor",
"call print2",
"ld a,3","call __txt_set_pen"
}
for (a=1;a<=15;a++)
{
asm{"ld h,5","ld a,(_a)","add a,7","ld l,a","call __txt_set_cursor"}
if (a<10) prints(" ");
prints(strltrm(btoa(text,a),48));
prints(": ");
prints(strltrm(wtoa(text,**(hiScore+((a-1)*2))),48));
asm{"ld h,16","ld a,(_a)","add a,7","ld l,a","call __txt_set_cursor"}
prints(hiTable+((a-1)*21));
}
asm
{
"ld hl,#0e18","call __txt_set_cursor",
"xor a","call __txt_set_paper",
"ld a,1","call __txt_set_pen"
}
if (wfc==0)
{
prints(" ENTER NAME ");
return;
}
else
{
prints(" PRESS A KEY ");
clearinput();
while (!inkey());
goto s230;
}
}
s2290:
for (a=0;a<=10;a++)
{
tmp1=view+16+a;
tmp20=y+a;
tmp2=ma+levOffset+(tmp20*35)+x;
*(view+a)=*(tmp2-37);
if ((tx!=x) || (ty!=tmp20)) goto s2370;
if (lev==4) *(tmp1)=2;
else *(tmp1)=3;
goto s2380;
s2370:
*(tmp1)=*(tmp2-36);
s2380:
if (otx==x) {if (oty==tmp20) {if (tmp21!=1) *(tmp1)=4;}}
*(view+32+a)=*(tmp2-35);
if (*(tmp1)==1) goto s2420;
}
s2420:
return;
s2440:
for (a=0;a<=10;a++)
{
tmp1=view+16+a;
tmp20=x+a;
tmp2=ma+levOffset+(y*35)+tmp20;
*(view+a)=*(tmp2-1);
if ((tx!=tmp20) || (ty!=y)) goto s2520;
if (lev==4) *(tmp1)=2;
else *(tmp1)=3;
goto s2530;
s2520:
*(tmp1)=*(tmp2-36);
s2530:
if (otx==tmp20) {if (oty==y) {if (tmp21!=1) *(tmp1)=4;}}
*(view+32+a)=*(tmp2-71);
if (*(tmp1)==1) goto s2570;
}
s2570:
return;
s2590:
for (a=0;a<=10;a++)
{
tmp1=view+16+a;
tmp20=y-a;
tmp2=ma+levOffset+(tmp20*35)+x;
*(view+a)=*(tmp2-35);
if ((tx!=x) || (ty!=tmp20)) goto s2670;
if (lev==4) *(tmp1)=2;
else *(tmp1)=3;
goto s2680;
s2670:
*(tmp1)=*(tmp2-36);
s2680:
if (otx==x) {if (oty==tmp20) {if (tmp21!=1) *(tmp1)=4;}}
*(view+32+a)=*(tmp2-37);
if (*(tmp1)==1) goto s2720;
}
s2720:
return;
s2740:
for (a=0;a<=10;a++)
{
tmp1=view+16+a;
tmp20=x-a;
tmp2=ma+levOffset+(y*35)+tmp20;
*(view+a)=*(tmp2-71);
if ((tx!=tmp20) || (ty!=y)) goto s2820;
if (lev==4) *(tmp1)=2;
else *(tmp1)=3;
goto s2830;
s2820:
*(tmp1)=*(tmp2-36);
s2830:
if (otx==tmp20) {if (oty==y) {if (tmp21!=1) *(tmp1)=4;}}
*(view+32+a)=*(tmp2-1);
if (*(tmp1)==1) goto s2870;
}
s2870:
return;
s2890:
tmp21=*(ma+levOffset+(oty*35)+otx-36);
if (dir==1) gosub s2290;
else if (dir==2) gosub s2440;
else if (dir==3) gosub s2590;
else if (dir==4) gosub s2740;
// Fast clear screen.
asm
{
"di","ld (stackPointer),sp","ld de,0",
"exx","ld hl,#c032",
"ld a,iyl","cp 1","jp c,normalScreen",
"ld de,#8000","sbc hl,de",
"normalScreen:",
"ld sp,hl","ld de,#50","exx",
"ld hl,0","add hl,sp","ld c,25",
"cls_loop1:",
"ld b,8",
"cls_loop2:",
"push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de","push de",
"ld sp,#800","add hl,sp","ld sp,hl","djnz cls_loop2",
"exx","add hl,de","ld sp,hl","exx",
"ld hl,0","add hl,sp","dec c","jp nz,cls_loop1",
"ld sp,(stackPointer)","ei"
}
en=0;
for (d=0;d<=10;d++)
{
tmp5=*(sLeft+d);
tmp6=*(sLeft+d+1);
tmp7=*(sRight+d);
tmp8=*(sRight+d+1);
tmp9=(((tmp5/8)+1)*8)-tmp5;
tmp10=(((tmp8/8)+1)*8)-tmp8;
tmp11=(((tmp6/8)+1)*8)-tmp6;
tmp12=tmp7-tmp5+1;
tmp13=tmp6-tmp5+1;
tmp14=tmp7-tmp8+1;
tmp15=tmp8-tmp6+1;
tmp16=*(view+d+16);
tmp17=*(view+d+32);
tmp18=*(view+d+17);
tmp19=*(view+d);
if (tmp16!=1) goto s2980;
asm
{
"ld a,(_tmp5)","ld ixh,a","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp12-1)","call drawHoriz",
"ld a,(_tmp5)","ld ixh,a","ld a,(_tmp7)","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp12-1)","call drawHoriz"
}
if (*(view+d-1)==1)
{
asm{"ld a,(_tmp5)","ld ixh,a","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp12-1)","call drawVert"}
}
if (*(view+31+d)==1)
{
asm{"ld a,(_tmp7)","ld ixh,a","ld a,(_tmp5)","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp12-1)","call drawVert"}
}
en=1;
s2980:
if (en==1) goto s3080;
if (tmp19==1)
{
asm
{
"ld a,(_tmp5)","ld ixh,a","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp13-1)","call drawDiag_down",
"ld a,(_tmp5)","ld ixh,a","ld a,(_tmp7)","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp13-1)","call drawDiag_up"
}
}
else
{
asm
{
"ld a,(_tmp5)","ld ixh,a","ld a,(_tmp6)","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp13-1)","call drawHoriz",
"ld a,(_tmp5)","ld ixh,a","ld a,(_tmp8)","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp13-1)","call drawHoriz"
}
}
if (tmp17==1)
{
asm
{
"ld a,(_tmp8)","ld ixh,a","ld ixl,a","ld de,(_tmp10)","ld bc,(_tmp14-1)","call drawDiag_down",
"ld a,(_tmp8)","ld ixh,a","ld a,(_tmp6)","ld ixl,a","ld de,(_tmp10)","ld bc,(_tmp14-1)","call drawDiag_up"
}
}
else
{
asm
{
"ld a,(_tmp8)","ld ixh,a","ld a,(_tmp6)","ld ixl,a","ld de,(_tmp10)","ld bc,(_tmp14-1)","call drawHoriz",
"ld a,(_tmp8)","ld ixh,a","ld ixl,a","ld de,(_tmp10)","ld bc,(_tmp14-1)","call drawHoriz"
}
}
if (tmp18!=1)
{
if (tmp19 != *(view+d+1))
{
asm{"ld a,(_tmp6)","ld ixh,a","ld ixl,a","ld de,(_tmp11)","ld bc,(_tmp15-1)","call drawVert"}
}
}
if (tmp18!=1)
{
if (tmp17 != *(view+d+33))
{
asm{"ld a,(_tmp8)","ld ixh,a","ld a,(_tmp6)","ld ixl,a","ld de,(_tmp11)","ld bc,(_tmp15-1)","call drawVert"}
}
}
// Draw target X.
if (tmp16==2)
{
asm
{
"ld a,1","call __gra_set_pen",
"ld a,(_tmp5)","ld h,0","ld l,a","add hl,hl","ld d,h","ld e,l",
"call __gra_move_absolute",
"ld a,(_tmp8)","ld h,0","ld l,a","add hl,hl","ld d,h","ld e,l",
"ld a,(_tmp6)","ld h,0","ld l,a","add hl,hl",
"call __gra_line_absolute",
"ld a,(_tmp7)","ld h,0","ld l,a","add hl,hl","ld d,h","ld e,l",
"ld a,(_tmp5)","ld h,0","ld l,a","add hl,hl",
"call __gra_move_absolute",
"ld a,(_tmp6)","ld h,0","ld l,a","add hl,hl","ld d,h","ld e,l",
"call __gra_line_absolute",
"ld a,2","call __gra_set_pen"
}
}
// Draw floor hole.
else if (tmp16==3)
{
asm
{
"ld a,(_tmp6)","ld ixh,a","ld a,(_tmp8)","ld ixl,a","ld de,(_tmp11)","ld bc,(_tmp15-1)","call drawHoriz",
"ld a,(_tmp5)","ld ixh,a","ld a,(_tmp7)","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp12-1)","call drawHoriz",
"ld a,(_tmp6)","ld ixh,a","ld a,(_tmp8)","ld ixl,a","ld de,(_tmp10)","ld bc,(_tmp13-1)","call drawVert",
"ld a,(_tmp8)","ld ixh,a","ld ixl,a","ld de,(_tmp10)","ld bc,(_tmp13-1)","call drawVert",
"ld a,(_tmp5)","ld ixh,a","ld a,(_tmp7)","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp13-1)","call drawDiag_up",
"ld a,(_tmp8)","ld ixh,a","ld ixl,a","ld de,(_tmp10)","ld bc,(_tmp13-1)","call drawDiag_down"
}
}
// Draw ceiling hole.
else if (tmp16==4)
{
asm
{
"ld a,(_tmp5)","ld ixh,a","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp12-1)","call drawHoriz",
"ld a,(_tmp6)","ld ixh,a","ld ixl,a","ld de,(_tmp11)","ld bc,(_tmp15-1)","call drawHoriz",
"ld a,(_tmp6)","ld ixh,a","ld a,(_tmp5)","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp13-1)","call drawVert",
"ld a,(_tmp8)","ld ixh,a","ld a,(_tmp5)","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp13-1)","call drawVert",
"ld a,(_tmp5)","ld ixh,a","ld ixl,a","ld de,(_tmp9)","ld bc,(_tmp13-1)","call drawDiag_down",
"ld a,(_tmp8)","ld ixh,a","ld a,(_tmp6)","ld ixl,a","ld de,(_tmp10)","ld bc,(_tmp13-1)","call drawDiag_up"
}
}
en=tmp16;
}
s3080:
asm
{
"ld a,2","call __txt_set_pen",
"ld a,3","call __txt_set_paper",
"ld hl,#0b08","call __txt_set_cursor"
}
if (moves==0) prints("0");
else prints(strltrm(wtoa(text,moves),48));
// Horizontal distance to target.
tmp3=0;
if (tx>x) tmp3=tx-x;
else if (x>tx) tmp3=x-tx;
// Vertical distance to target.
tmp4=0;
if (ty>y) tmp4=ty-y;
else if (y>ty) tmp4=y-ty;
// Print distance to target.
dtt=tmp3+tmp4;
asm{"ld hl,#0b0b","call __txt_set_cursor"}
if (dtt==0) prints("0");
else prints(strltrm(btoa(text,dtt),48));
asm
{
"ld a,32","call __txt_output",
"ld hl,#080f","call __txt_set_cursor",
"ld a,32","call __txt_output",
"ld hl,#0910","call __txt_set_cursor",
"ld a,32","call __txt_output",
"ld hl,#0811","call __txt_set_cursor",
"ld a,32","call __txt_output",
"ld hl,#0710","call __txt_set_cursor",
"ld a,32","call __txt_output"
}
if (dir==1)
{
symbol(255,symbol_arrowUp);
asm{"ld hl,#080f","call __txt_set_cursor"}
}
else if (dir==2)
{
symbol(255,symbol_arrowRight);
asm{"ld hl,#0910","call __txt_set_cursor"}
}
else if (dir==3)
{
symbol(255,symbol_arrowDown);
asm{"ld hl,#0811","call __txt_set_cursor"}
}
else if (dir==4)
{
symbol(255,symbol_arrowLeft);
asm{"ld hl,#0710","call __txt_set_cursor"}
}
asm
{
"ld a,255","call __txt_output",
"call virtualFlip",
"xor a","call __gra_set_pen",
"ld de,(_mx)","ld hl,(_my)","call __gra_plot_absolute",
"call virtualFlip",
"ld a,iyl","cp 1","jp c,screen4000",
"ld iyl,0","ld a,#40","call __scr_set_base",
"ld a,#c0","ld hl,0","call __scr_set_position",
"ld iyh,#0","jp screenFlipped",
"screen4000:",
"ld iyl,1","ld a,#c0","call __scr_set_base",
"ld a,#40","ld hl,0","call __scr_set_position",
"ld iyh,#80",
"screenFlipped:"
}
return;
asm
{
"stackPointer: equ #0",
"cmask: equ #B6A3",
"soundQueue: defs 9",
"bTemp: defb 0",
"print2:",
"ld a,45","ld b,8",
"print2_a:",
"call __txt_output",
"djnz print2_a",
"ret",
"print3:",
"ld a,143","ld b,9",
"print3_a:",
"call __txt_output",
"djnz print3_a",
"ret",
"virtualFlip:",
"ld hl,0","ld a,iyl","cp 1","jp c,virtualFlip_1",
"ld iyl,0","ld a,#c0","jp virtualFlip_done",
"virtualFlip_1:",
"ld iyl,1","ld a,#40",
"virtualFlip_done:",
"call __scr_set_position",
"ret",
"pixAddr:",
"push de",
"ld a,ixl","ld l,a","and %00000111","ld h,a","xor l","ld l,a","ld e,a","ld d,#60","add hl,hl","add hl,hl","add hl,de","add hl,hl",
"ld d,0","ld e,ixh","rr e","srl e","add hl,de","ld d,iyh","ld e,0","sbc hl,de",
"pop de",
"ld a,4","cp e","jp nc,pixAddr_ok",
"ld a,e","sub 4","ld d,a","jp pixAddr_cont",
"pixAddr_ok:",
"ld d,e",
"pixAddr_cont:",
"ld c,%10001000","ld a,ixh","and %00000011","jp z,pixAddr_end",
"pixAddr_shift:",
"srl c","dec a","jp nz,pixAddr_shift",
"pixAddr_end:",
"ret",
"drawHoriz:",
"di","call pixAddr",
"horiz_loop:",
"ld a,(cmask)","xor (hl)","and c","xor (hl)","ld (hl),a",
"dec d","jp z,horiz_4",
"srl c","djnz horiz_loop","jp horiz_end",
"horiz_4:",
"ld d,4","inc hl","ld c,%10001000","djnz horiz_loop",
"horiz_end:",
"ei",
"ret",
"drawVert:",
"di","ld (stackPointer),sp","ld sp,#800","call pixAddr",
"vert_loop:",
"ld a,(cmask)","xor (hl)","and c","xor (hl)","ld (hl),a",
"dec e","jp z,vert_8",
"add hl,sp","djnz vert_loop","jp vert_end",
"vert_8:",
"ld e,8","ld sp,#37b0","sbc hl,sp","ld sp,#800","djnz vert_loop",
"vert_end:",
"ld sp,(stackPointer)","ei",
"ret",
"drawDiag_down:",
"di","ld (stackPointer),sp","ld sp,#800","call pixAddr",
"diagDown_loop:",
"ld a,(cmask)","xor (hl)","and c","xor (hl)","ld (hl),a",
"dec d","jp z,diagDown_4",
"dec e","add hl,sp","srl c","djnz diagDown_loop","jp diagDown_end",
"diagDown_4:",
"ld d,4","dec e","jp z,diagDown_8",
"add hl,sp","inc hl","ld c,%10001000","djnz diagDown_loop","jp diagDown_end",
"diagDown_8:",
"ld e,8","ld sp,#37af","sbc hl,sp","ld sp,#800","ld c,%10001000","djnz diagDown_loop",
"diagDown_end:",
"ld sp,(stackPointer)","ei",
"ret",
"drawDiag_up:",
"di","ld (stackPointer),sp","ld sp,#800","call pixAddr",
"diagUp_loop:",
"ld a,(cmask)","xor (hl)","and c","xor (hl)","ld (hl),a",
"dec d","jp z,diagUp_4",
"dec e","sbc hl,sp","srl c","djnz diagUp_loop","jp diagUp_end",
"diagUp_4:",
"ld d,4","dec e","jp z,diagUp_8",
"sbc hl,sp","inc hl","ld c,%10001000","djnz diagUp_loop","jp diagUp_end",
"diagUp_8:",
"ld e,8","ld sp,#37b1","add hl,sp","ld sp,#800","ld c,%10001000","djnz diagUp_loop",
"diagUp_end:",
"ld sp,(stackPointer)","ei",
"ret"
}