Posted in Programming

## How I made the attack waves to my experimental Amiga game

I’m trying to relax from my studies..

I seem to live very much in the past. Now I would like to share the strange idea I had, when I made the attack waves to my experimental Amiga game. I mean the following:

Well, the asteroids were easy, their y-coordinate is just increased with different steps (3 speeds). The movement to different kind of ships was done in a different way. I drew the paths they were meant to move in a drawing program, Deluxe Paint II.

Then I wrote a C language program that interpreted the curves from Deluxe Paint II’s IFF-pictures. Each (xy) coordinate of the curves was saved to a file and in the game program read from a file.

The problem was, that what to do, if the curve crossed itself? Which direction to follow? I solved this using different colors that told from which direction the ship was coming and some colors told, that which direction not to follow… 🙂

I have the assembly source code to this game here on this blog.

Posted in Programming

## The Koch Curve as Snowflake with Python Turtle Graphics

It’s over midnight here.. Since the source code in one of my videos is not very readable, I decided to publish the Python source code of the video in this blog post.

```import turtle

def draw_curve():
window = turtle.Screen()
turt=turtle.Turtle()
turt.setpos(-300,-100)
turt.clear()
turt.speed('fastest')
turt.hideturtle()

vonKoch(turt,5,500)
turt.left(120)
vonKoch(turt,5,500)
turt.left(120)
vonKoch(turt,5,500)
turt.left(120)
vonKoch(turt,5,500)
window.exitonclick()

def vonKoch(turt,depth,length):
if depth == 0: turt.forward(length)
else:
vonKoch(turt,depth-1,length/3)
turt.right(60)
vonKoch(turt,depth-1,length/3)
turt.left(120)
vonKoch(turt,depth-1,length/3)
turt.right(60)
vonKoch(turt,depth-1,length/3)

draw_curve()
```

That’s it for now. Time to go to sleep.

Posted in Programming

## Amiga nostalgia: C language source code to Quest of Love

Quest of Love is an Amiga project that I never finished, but always wanted to create…

The project started as an assembly language project, but it was too much work, so I switched to C language. The video below shows, what I managed to do:

For curiosity and historical — on the other hand educational — reasons, I’ve decided to publish the C language source I have for this project. The assembly version is published in this old blog post..

The comments and names of some variables are in Finnish..

```#include <math.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/gfx.h>
#include <graphics/displayinfo.h>
#include <graphics/modeid.h>
#include <intuition/intuition.h>
#include <dos/stdio.h>
#include <dos/dos.h>
#include <proto/exec.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <libraries/iff.h>

#define INTUI_V38_NAMES_ONLY

#define LIBVER 39

#define TURN 83

struct IntuitionBase *IntuitionBase=NULL;
struct GfxBase *GfxBase=NULL;
struct Library *IFFBase=NULL;

struct Screen *screen=NULL;
struct Window *window=NULL;

struct ViewPort *viewport;
struct RastPort *rastport;

ULONG   errorcode;

unsigned char *BM_block=NULL, *BM0, *BM1;
unsigned char *source0, *source1, *source2, *source3, *source4;
unsigned char *dest0, *dest1, *dest2, *dest3, *dest4;

struct BitMap blockbitmap = {2, 1088, 0, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
struct BitMap myBitMap0 = {40, 256, 0, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
struct BitMap myBitMap1 = {40, 256, 0, 5, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
struct BitMap *DrawBitMap=NULL,*ShowBitMap=NULL;

struct Monster {
int x,y;
WORD block;
WORD vital;
WORD exp;
char frame;
char delay;
char elossa;
};

struct Monster Monsters[21];
struct Monster MonType[1];

int Blocked(int x, int y, short suunta);
void    DoubleBuffering(short *);
void    DrawMap(UWORD *Map);
void    DrawBlock(int,int,int);
void    Cycle(void);
void  HandleMonsters(void);
void  InitMonsters(void);
void    SetDelay(WORD,WORD);
void  DeAllocateResources();
char  ReadMapFile(char [], UWORD *buffer, int lkm);

int cind, block, k, j;
UWORD colortable[32];
UWORD copytable[4];
UWORD *buffer=NULL;
LONG  count;

UWORD *Map = NULL;
UWORD *WorldMap = NULL;
int   map_width, map_heigth;

WORD MapX=0, MapY=0,isoX=0,isoY=0;
char delay=-1;
char turn=TURN;

int main(void) {

short   keepgoing=TRUE;
struct  IntuiMessage *msg;
ULONG       class;
UWORD       code,qualifier;
IFFL_HANDLE iff=NULL;
short       *Which;

if((GfxBase=(struct GfxBase *)
OpenLibrary("graphics.library",LIBVER))==NULL)
{
printf("graphics open failed (V39 kickstart required)\n");
DeAllocateResources();
exit(1);
}

if((IntuitionBase=(struct IntuitionBase *)
OpenLibrary("intuition.library",LIBVER))==NULL)
{
printf("intuition open failed (V39 mkickstart required)\n");
DeAllocateResources();
exit(1);
}

IFFBase=(struct Library*)OpenLibrary(IFFNAME, IFFVERSION);
if (IFFBase == NULL) {
printf("Can not open iff.library\n");
DeAllocateResources();
exit(1);
}

BM_block = (unsigned char *)AllocMem(11520, MEMF_CHIP);
if (!BM_block) {
printf("Memory allocation failed\n");
DeAllocateResources();
exit(1);
}

BM0 = (unsigned char *)AllocMem(51200,MEMF_CHIP|MEMF_CLEAR);
if (!BM0) {
printf("Memory allocation failed\n");
DeAllocateResources();
exit(1);
}

BM1 = (unsigned char *)AllocMem(51200,MEMF_CHIP|MEMF_CLEAR);
if (!BM1) {
printf("Memory allocation failed\n");
DeAllocateResources();
exit(1);
}

buffer=(UWORD *)AllocMem(40, MEMF_CHIP);
if (!buffer) {
printf("Memory allocation failed\n");
DeAllocateResources();
exit(1);
}

InitMonsters();

blockbitmap.Planes[0]=&BM_block[0];
blockbitmap.Planes[1]=&BM_block[2176];
blockbitmap.Planes[2]=&BM_block[4352];
blockbitmap.Planes[3]=&BM_block[6528];
blockbitmap.Planes[4]=&BM_block[8704];

myBitMap0.Planes[0]=&BM0[0];
myBitMap0.Planes[1]=&BM0[10240];
myBitMap0.Planes[2]=&BM0[20480];
myBitMap0.Planes[3]=&BM0[30720];
myBitMap0.Planes[4]=&BM0[40960];

myBitMap1.Planes[0]=&BM1[0];
myBitMap1.Planes[1]=&BM1[10240];
myBitMap1.Planes[2]=&BM1[20480];
myBitMap1.Planes[3]=&BM1[30720];
myBitMap1.Planes[4]=&BM1[40960];

*Which=1;

if((screen=OpenScreenTags(NULL,
SA_Width, 320,
SA_Height, 256,
SA_Depth, 5,
SA_Overscan, FALSE,
SA_AutoScroll, TRUE,
SA_Type, CUSTOMSCREEN|CUSTOMBITMAP,
SA_DisplayID,PAL_MONITOR_ID,
SA_PubName, "My Screen",
SA_BitMap, &myBitMap0,
TAG_END, NULL)
)==NULL)
{
printf("Screen open failed\n");
DeAllocateResources();
exit(1);
}

if((window=OpenWindowTags(NULL,
WA_Left, 0,
WA_Top, 0,
WA_Width, screen->Width,
WA_Height, screen->Height,
WA_IDCMP,IDCMP_VANILLAKEY,
WA_Flags,WFLG_ACTIVATE|WFLG_RMBTRAP|WFLG_BORDERLESS,
WA_ReportMouse, TRUE,
WA_MinWidth,    50,
WA_MinHeight,   20,
WA_MaxWidth,    ~0,
WA_MaxHeight,   ~0,
WA_PubScreen,   screen,
TAG_END, NULL)
)==NULL)
{
printf("Window open failed\n");
DeAllocateResources();
exit(1);
}

viewport=&screen->ViewPort;
rastport=window->RPort;

/* Bittikartoille on aiemmin varattu tila, mikä pitää laskea uudestaan, jos koko muuttuu */

if (!iff) {
printf("IFF file open failed\n");
DeAllocateResources();
exit(1);
}

if (!(IFFL_DecodePic(iff, &blockbitmap))) {
printf("IFF file decoding failed\n");
DeAllocateResources();
exit(1);
}

count = IFFL_GetColorTab(iff, colortable);
IFFL_CloseIFF(iff);

if (!iff) {
printf("IFF file open failed\n");
DeAllocateResources();
exit(1);
}

if (!(IFFL_DecodePic(iff,&myBitMap0))) {
printf("IFF file decoding failed\n");
DeAllocateResources();
exit(1);
}

IFFL_CloseIFF(iff);

for (int i=0; i<4; i++) copytable[i]=colortable[16+i];     BltBitMap(&myBitMap0,0,0,&myBitMap1,0,0,320,256,0xc0,0x1f,&buffer);     source0 = blockbitmap.Planes[0];     source1 = blockbitmap.Planes[1];     source2 = blockbitmap.Planes[2];     source3 = blockbitmap.Planes[3];     source4 = blockbitmap.Planes[4];     dest0 = screen->BitMap.Planes[0]+1001;
dest1 = screen->BitMap.Planes[1]+1001;
dest2 = screen->BitMap.Planes[2]+1001;
dest3 = screen->BitMap.Planes[3]+1001;
dest4 = screen->BitMap.Planes[4]+1001;

WorldMap=(UWORD *)AllocMem(9920,MEMF_PUBLIC);
if (WorldMap == NULL) {
printf("Could not allocate memory for WorldMap\n");
DeAllocateResources();
exit(1);
}

DeAllocateResources();
exit(1);
}

Map = WorldMap;
map_width = 80;
map_heigth = 62;

/* -------------------------------------------------------------------------- */

while(keepgoing)
{
WaitTOF();
DoubleBuffering(&Which);
DrawMap(Map);
HandlePlayer();
HandleMonsters();
GeneralRoutines();
Cycle();
/*      printf("Delay %d ; Turn %d\n",delay,turn); */

/*      printf("Blocked %d\n",Blocked(MapX, MapY, 8)); */

while(msg=(struct IntuiMessage *)GetMsg(window->UserPort))
{
class=msg->Class;
code=msg->Code;
qualifier=msg->Qualifier;
/*          printf("%d\n",code); */

switch(class) {
case IDCMP_VANILLAKEY :
switch (code) {
case 27 : /* ESC */
keepgoing=FALSE;
DeAllocateResources();
break;

/***
* Pelaajan ohjaus pääkartalla. Aluksi katsotaan, onko kulkusuunta blokattu;
* jos ei ole ja delay == -1 (eli maastotyypin viive on suoritettu), niin
* liikutaan
* painettuun kulkusuuntaan ja asetetaan uusi delay. Lisäksi tulostetaan
* joko kulkusuunta tai "Slow progress", jos viiveen takia kulkusuuntaan
* ei voinut mennä. Jos tulostettiin "Slow progress", niin delay-arvoa
* vähennetään yhdellä.

***/
case '2' : if (!Blocked(MapX, MapY, 2) && delay<0) {                                             MapY++;                                             isoY++;                                             if (MapY> map_heigth - 1) MapY=0;
SetDelay(MapX,MapY);
Print("South.",6);
} else if (delay>-1) {
Print("Slow progress.",14);
delay--;
}
turn=TURN;
break;

case '8' : if (!Blocked(MapX, MapY, 8) && delay<0) {
MapY--;
isoY--;
if (MapY<0) MapY= map_heigth - 1;                                             SetDelay(MapX,MapY);                                             Print("North.",6);                                      } else if (delay>-1) {
Print("Slow progress.",14);
delay--;
}
turn=TURN;
break;

case '6' : if (!Blocked(MapX, MapY, 6) && delay<0) {                                             MapX++;                                             isoX++;                                             if (MapX> map_width - 1) MapX=0;
SetDelay(MapX,MapY);
Print("East.",5);
} else if (delay>-1) {
Print("Slow progress.",14);
delay--;
}
turn=TURN;
break;

case '4' : if (!Blocked(MapX, MapY, 4) && delay<0) {
MapX--;
isoX--;
if (MapX<0) MapX= map_width - 1;                                             SetDelay(MapX,MapY);                                             Print("West.",5);                                         } else if (delay>-1) {
Print("Slow progress.",14);
delay--;
}
turn=TURN;
break;

case ' ' :  turn=TURN;
Print("Pass.",5);
break;
}
}

}
}
} /* END main */

void DeAllocateResources() {
if (buffer) FreeMem(buffer,40);
/*  if (iff) IFFL_CloseIFF(iff); */
/*  if (BM0) FreeMem(BM0,51200);
if (BM1) FreeMem(BM1,51200); */
if (BM_block) FreeMem(BM_block,11520);
if (window) CloseWindow(window);
if (screen) CloseScreen(screen);
if (BM0) FreeMem(BM0,51200);
if (BM1) FreeMem(BM1,51200);
if (GfxBase) CloseLibrary((struct Library *)GfxBase);
if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
if (IFFBase) CloseLibrary(IFFBase);
if (WorldMap) FreeMem(WorldMap,9920);
}

void HandlePlayer(void) {
DrawBlock(5,6,10);
}

void SetDelay(WORD x,WORD y) {
x+=5; y+=6;
if (x > map_width - 1) x=x - map_width;
if (y > map_heigth - 1) y=y - map_heigth;
/*  printf("%d;%d; %d\n",x,y,Map[x+y*80]); */

switch(Map[x+y*map_width]) {
case 5 : delay=(char)Random(0,4); break;
case 16: delay=(char)Random(0,2); break;
default: delay=-1;
}
/*  printf("%d\n",delay); */
}

void DoubleBuffering(short *Which) {
switch(*Which) {
case 0 : viewport->RasInfo->BitMap=&myBitMap0; *Which=1;
rastport->BitMap=&myBitMap1;
dest0 = myBitMap1.Planes[0]+1001;
dest1 = myBitMap1.Planes[1]+1001;
dest2 = myBitMap1.Planes[2]+1001;
dest3 = myBitMap1.Planes[3]+1001;
dest4 = myBitMap1.Planes[4]+1001;
DrawBitMap=&myBitMap1;
ShowBitMap=&myBitMap0;
break;
case 1 : viewport->RasInfo->BitMap=&myBitMap1; *Which=0;
rastport->BitMap=&myBitMap0;
dest0 = myBitMap0.Planes[0]+1001;
dest1 = myBitMap0.Planes[1]+1001;
dest2 = myBitMap0.Planes[2]+1001;
dest3 = myBitMap0.Planes[3]+1001;
dest4 = myBitMap0.Planes[4]+1001;
DrawBitMap=&myBitMap0;
ShowBitMap=&myBitMap1;
break;
}
ScrollVPort(viewport);
}

/***
* Blocked-rutiini: Parametreina saadaan näkymän vasen yläkulma, mihin lisätään
* arvot, joilla saadan pelaajan sijainti eli näkymän keskikohta. Jos suunnassa,
* johon ollaan menossa on blocki, jonka päälle ei voi mennä palautetaan 1,
* mikä on merkkinä siitä, että hahmoa ei liikuteta, muutoin 0.
***/
int Blocked (int x, int y, short suunta) {
int arvo;

x+=5; y+=6;

if (x > map_width - 1) x=x-map_width;
if (y> map_heigth - 1) y=y- map_heigth;

/*  printf("Block: %d\n", Map[x+y*map_width]); */

switch (suunta) {
case 2 : y+=1; break;
case 8 : y-=1; break;
case 6 : x+=1; break;
case 4 : x-=1; break;
}

/*  printf("Block: %d\n", Map[x+y*map_width]); */

switch (Map[x+y*map_width]) {
case 3 :        arvo = 1; break;
case 8 :        arvo = 1; break;
case 12 :   arvo = 1; break;
case 14 :   arvo = 1; break;
default :   arvo = 0;
}
return arvo;
}

void DrawMap (UWORD *Map) {

/*  printf("DrawMap"); */

int x,y,xg=0,yg=0,xx,yy;

for (y=MapY,yg=0;y<MapY+14;y++,yg++) {
for (x=MapX,xg=0;x<MapX+11;x++,xg++) { /*          printf("xx: %d", xx); */             if (x > map_width - 1) xx=x-map_width; else xx=x;
if (y> map_heigth - 1) yy=y-map_heigth; else yy=y;

if (x > map_width - 1 || y>map_heigth - 1) block = Map[xx+yy*map_width];
else block = Map[x+y*map_width];

block = block << 5;

j=yg*640;
for (int i=block; i<32+block; i++) {
k=xg*2;
dest0[k+j]=source0[i];
i++; k++;
dest0[k+j]=source0[i];
j+=40;
}

j=yg*640;
for (int i=block; i<32+block; i++) {
k=xg*2;
dest1[k+j]=source1[i];
i++; k++;
dest1[k+j]=source1[i];
j+=40;
}

j=yg*640;
for (int i=block; i<32+block; i++) {
k=xg*2;
dest2[k+j]=source2[i];
i++; k++;
dest2[k+j]=source2[i];
j+=40;
}

j=yg*640;
for (int i=block; i<32+block; i++) {
k=xg*2;
dest3[k+j]=source3[i];
i++; k++;
dest3[k+j]=source3[i];
j+=40;
}

j=yg*640;
for (int i=block; i<32+block; i++) {
k=xg*2;
dest4[k+j]=source4[i];
i++; k++;
dest4[k+j]=source4[i];
j+=40;

}

}
}
}

/* Koordinaatit blockeina */

void DrawBlock (int x, int y, int block) {

block = block << 5;             /* kerrotaan 32:lla */

j=y*640;                                /* kerrottaan 40 x 16:a */
for (int i=block; i<32+block; i++) {
k=x*2;
dest0[k+j]=source0[i];
i++; k++;
dest0[k+j]=source0[i];
j+=40;
}

j=y*640;
for (int i=block; i<32+block; i++) {
k=x*2;
dest1[k+j]=source1[i];
i++; k++;
dest1[k+j]=source1[i];
j+=40;
}

j=y*640;
for (int i=block; i<32+block; i++) {
k=x*2;
dest2[k+j]=source2[i];
i++; k++;
dest2[k+j]=source2[i];
j+=40;
}

j=y*640;
for (int i=block; i<32+block; i++) {
k=x*2;
dest3[k+j]=source3[i];
i++; k++;
dest3[k+j]=source3[i];
j+=40;
}

j=y*640;
for (int i=block; i<32+block; i++) {
k=x*2;
dest4[k+j]=source4[i];
i++; k++;
dest4[k+j]=source4[i];
j+=40;
}

}

void Cycle (void) {
int Rs = cind;

for (int i=0; i<4; i++, Rs++) {         if (Rs > 3) Rs=0;
colortable[i+16]=copytable[Rs];
}
cind++;
if (cind > 3) cind = 0;

}

void Print(char teksti[], int pituus) {
ScrollRaster(rastport,0,8,195,119,300,245);
Move(rastport,195,243);
Text(rastport,teksti,pituus);
BltBitMap(DrawBitMap,195,119,ShowBitMap,195,119,105,127,0xc0,0x1f,NULL);
}

char BlockedMonster(WORD x, WORD y, WORD count) {
char i;

for (i=0; i<21; i++) {
if (Monsters[i].x==x && count!=i && Monsters[i].elossa==1)
if (Monsters[i].y==y) return 1;
}

switch (Map[x+y*map_width]) {
case 3 : return 1;
case 8 : return 1;
case 12 : return 1;
case 14 : return 1;
default : return 0;
}

}

void HandleMonsters(void) {
int i,apuX,apuY,RS;

if (turn==TURN) {
for(i=0; i<21; i++) {             if (Monsters[i].elossa) { /* 75% TN:llä lähdetään liikkeelle */                 RS=Random(0,4);                 if (RS>=1) {
apuX=Monsters[i].x;
apuY=Monsters[i].y;
RS=Random(0,2);
if (RS==0) {
if (isoX+5>apuX) apuX++;
else apuX--;
if (!BlockedMonster(apuX, apuY, i)) Monsters[i].x=apuX;
} else if (isoY+6>apuY) apuY++;
else apuY--;
if (!BlockedMonster(apuX,apuY, i)) Monsters[i].y=apuY;
}

}
}
}

/* Laskeskellaan, piirretäänkö monsteria näkyviin */

for(i=0; i<21; i++) {
apuX=Monsters[i].x-isoX;
apuY=Monsters[i].y-isoY;
Monsters[i].frame=Monsters[i].block+Random(0,4);
if (apuX<=10 && apuX>=0)
if (apuY<=13 && apuY>=0) {
/*              printf("%d;%d\n",apuX,apuY); */
DrawBlock(apuX,apuY,Monsters[i].frame);
}
}
}

void InitMonsters (void) {
short type;

MonType[0].block=64;
MonType[0].vital=10;
MonType[0].exp=10;
MonType[0].delay=0;
MonType[0].frame=64;

for (int i=0; i<21; i++) {
Monsters[i].x=Random(0,map_width);
Monsters[i].y=Random(0,map_heigth);
switch (Map[Monsters[i].x+Monsters[i].y*map_width]) {
case 3,8,12,14 : Monsters[i].elossa=0; break;
default : Monsters[i].elossa=1;
}

Monsters[i].block=64;
type=Monsters[i].block;
Monsters[i].vital=MonType[type-64].vital;
Monsters[i].exp=MonType[type-64].exp;
Monsters[i].delay=0;
Monsters[i].frame=0;
}

}

void GeneralRoutines() {
turn--;
if (turn<=0) {
delay--;
/*        printf("%d\n",delay); */
if (delay<-1) delay=-1;
turn=TURN;
Print("Pass.",5);
}

}

char ReadMapFile(char nimi[], UWORD *buffer, int koko) {
BPTR file;
LONG length;

/*   printf("%s\n",nimi); */

file=Open(nimi,MODE_OLDFILE);

if (length != koko) {
Close(file);
return 1;
}
return 0;
}

int Random (int alaraja, int ylaraja) {
int Luku;
Luku=rand();
Luku=alaraja+Luku%(ylaraja-alaraja);
return Luku;
}
```
Posted in Mathematics, Programming

## Generating the Cantor’s set with recursion

In my old article I have implementation for Cantor’s set without recursion. Now I implemented the Cantor’s set with recursion in JavaScript. This is better solution.

The definition of the Cantor’s set in the language of set theory is the following:

If this doesn’t mean anything to you, you might want to check the old post. 🙂

Below is a picture from the output of the program of this post:

Below is the JavaScript listing from Notepad++ in full as png-file:

You could also divide the segement length in the recursive call. This way you would get the first straight line directly…

Posted in Programming

## Amiga Nostalgia: The differences between Forbid() and Disable()

For example on Commodore 64 one can use absolute memory addresses somewhat freely; it is sufficient to know the memory map of C64. But on Amiga the case is completely different, because Amiga has multitasking operating system.

As it comes to allocating memory, even if one programs ”hard coded” program, that is: A program that overrides the operation of the operating system and use use directly Amiga’s hardware (Amiga has few co-processors), one can’t assume, that one can ”steal” memory anywhere one wants. In other words one can’t use absolute memory addressing and put one’s data anywhere one wants, because when the user closes the program, the whole multitasking environment can be ”broken”: There can be ”garbage” on the screen or some programs may have crashed, because the ”hard coded” program may have written its own data instead of the data on previously running programs in multitasking environment.

Still, on Amiga there is one absolute memory address, that every programmer in practice must use to get anything done when using the OS, namely address 4. From that memory address one gets so called execbase, that is necessary to call any system routines.

In order to make ”hard coded” program run faster on an Amiga it is practically necessary to stop the operation of the operating system (on an Amiga the OS routines are in ROM, though there are libraries, that are loaded (”opened” by the language of the programmer) to RAM that add more functionality to the OS). There are two ways to do that: To call OS’s Forbid() or Disable().

Using Forbid() is ”nice” way to stop the operation of the operating system, it forbids the task swapping of the OS, that is: All the programs on the background on the OS are stopped, until Wait() routine is called (or some of the Intuition library’s routines). Of course, when one codes “hard coded” program, one probably doesn’t use OS’s Wait(), but one’s own code using directly the hardware. When exiting ”hard coded” program, the programmer must now call Permit() in order to make the OS continue its tasks normally.

A way to get ”hard coded” program to run even faster, is to use Disable(), but that is quite naughty way to stop OS considering that the user may have a lot of programs and tasks running on the OS. Disable() stops the interruptions of the OS on the background, that is: The running of all the programs and also the interruption routines of them are stopped.

Wait() routine allows interruptions regardless of Disable(), but returns the ”disabled state” after the CPU has finished the Wait() routine. Though, again in ”hard coded” programs, the programmer doesn’t probably use Wait(), but one’s own code to wait for something using directly the hardware.

If Disable() has been used, in the end of the program, one must use Enable() in order to get the OS functioning again. But if the programmer has used Disable(), there is no way to guarantee that even after Enable(), the OS is functioning normally as it was before executing the ”hard coded” program.

Still, there are some speed critical things or things where OS must be stopped for just a ”short” time on Amiga, where Disable() may be the only way to get a program working properly. Now, because Disable() ”forbids” interruption requests of the OS by setting Paula’s (a co-processor) INTENA register’s bit 14, it’s also a question of how long Disable() has stopped the OS; the longer the Disable() has stopped the OS, the more uncertain it is, that the OS is working completely – if at all – normally after Enable(). Usually the interruptions of the OS should not be stopped for over 250 microseconds at once.

Posted in Programming

## Assembly source code to my old Amiga project

Here’s source code to my old experiment in Amiga game coding. The source I found, doesn’t seem to be exactly the same used in the code of the video showing below. There are more than one pieces of music in the unfinished game, but in the source there isn’t “incbin” for any Amiga music module.

The project started in 1992, when I was at high school (lukio), when I was experimenting in multiplexing Amiga’s hardware sprites. Much later I continued the project in order to see, if I could still do some Amiga coding in assembly.

The musics are not made by me, I used some nice music modules, I found from the Aminet.

There should be color stripes in the energy bar made with Copper, but for some reason the colors were lost in the emulation.

The source is a bit messy and labels and comments are partly in English and partly in Finnish.

As a reminder old Amigas have Motorola’s processors and the assembly is Motorola’s 68000 processor’s assembly code.

As you can see from the source, the ProTracker replay routine is not coded by me.

Some words about the vertical scrolling… This “game” 🙂 works on an A500 with only 512kb of CHIP memory, if my memory serves my right. The reason why this little project uses quite a lot of CHIP memory is because of the way the vertical scrolling is made: The game uses in fact three (3) screens in CHIP memory in total, two for double buffering and in addition there is one screen that only scrolls vertically. The latter is “ClearScreen”, it is used for clearing the drawing buffer from earlier bob (blitter object) movement (of course for sake of limited speed, the whole ClearScreen is not copied, but only the needed 16 x 16 pixel areas). As a reminder, the movement of sprites doesn’t need the clearing of earlier position, the sprites are drawn in a special way to the screen. Bobs (blitter objects) represent “normal” graphical objects, that require clearing of earlier position.

The smartest idea for fast (that is: takes only little raster time) vertical scrolling on an Amiga 500 I’ve ever seen, was on one book written in Finnish. In that idea if the area to be scrolled vertically is for example 320 x 256 pixels, again a lot of CHIP memory is used: For only scrolling the screen vertically 3 * (320 x 256) pixels area is used for scrolling and this area is used in a very smart manner in order to achieve vertical scrolling that takes on only few raster lines. Probably this idea also requires little extra CHIP memory for blitting new graphics to area… Over 20 years ago I implemented and tested this idea and this really is  a fast way to implement vertical scrolling on an Amiga!

The game isn’t any state of the art assembly code, just an experiment… See below:

```        incdir  "ADCD_2.1:NDK/NDK_3.5/Include/include_i"

include "exec/types.i"
include "libraries/dosextens.i"
include "graphics/gfxbase.i"
include "exec/libraries.i"
include "exec/execbase.i"
include "Hardware/intbits.i"

;------------------------------------------------------------------------------
; Makroja
;------------------------------------------------------------------------------
WaitForBlitter  MACRO
W\@     btst    #14,\$2(a5)
bne.s   W\@
ENDM

;------------------------------------------------------------------------------
; Vakioita
;------------------------------------------------------------------------------
Forbid         equ     -\$0084
Permit         equ     -\$008a
Disable        equ     -\$0078
Enable         equ     -\$007e
Write          equ     -\$0030
Output         equ     -\$003c
OpenLibrary    equ     -\$0228
CloseLibrary   equ     -\$019e

Execbase       equ      4

Screen_X_Size  equ     320
Screen_Y_Size  equ     256
Height_OBullet equ     8       ; Oman laakin korkeus
Frames         equ     3
OwnSpeed       equ     3       ; Oman aluksen nopeus
BSpeed         equ     4       ; Oman laakin nopeus
AmountBullets  equ     (Screen_Y_Size/(Height_OBullet*BSpeed))-1
AmountEBullets equ     10-1    ; Vihollisten laakien määrä
Dest           equ     (256+16+16)*4*32        ; Palikka sinne alapuolelle
max_bobs       equ     32
max_asteroids_on_screen equ 20

NOCHIPREV      equ 0

;------------------------------------------------------------------------------
; Startup-koodi
;------------------------------------------------------------------------------

SECTION CODE,code

startup:
movem.l d0/a0,-(sp)             ; Tallennetaan d0 ja a0
move.l  4,a6                    ; SysBase
move.l  #0,a1
jsr     -\$0126(a6)              ; Haetaan oma prosessi, FindTask()
move.l  d0,a4
move.l  d0,process
tst.l   pr_CLI(a4)              ; CLI?
; tst.l \$ac(a4)
bne.s   check_aga               ; jos CLI niin check_aga
wb:
lea     pr_MsgPort(a4),a0       ; Haetaan prosessin viestiportti
; lea \$5c(a4),a0
jsr     -\$0180(a6)              ; Odotetaan viestiä, WaitPort()
lea     pr_MsgPort(a4),a0
jsr     -\$0174(a6)              ; Haetaan viesti
; GetMsg()
move.l  d0,wbenchmsg            ; tallennetaan ohjelman tarvetta
; varten
check_aga:                              ; Tämä toimii OCS ja ECS koneissa,
moveq   #0,d0                   ; joten AGA-checkiä ei tarvita...
lea     gfxname,a1
jsr     -\$0228(a6)              ; OpenLibrary()
move.l  d0,gfxbase
beq.w   reply_to_wb             ; jostain syystä ei saatu avattua
move.l  d0,a4

moveq   #0,d0
lea     intuiname,a1
jsr     -\$0228(a6)
move.l  d0,intuibase
beq     Sulje

;        move.l  4,a6
;        jsr     -\$0078(a6)              ; keskeytykset pois, Disable()
cmp.w   #39,LIB_VERSION(a4)     ; onko ChipRevBits0 määritelty
; cmp.w #39,\$14(a4)
bne.s   no_chiprev

move.b  gb_ChipRevBits0(a4),chiprev
; move.b \$ec(a4),chiprev
bra.s   check_proc
no_chiprev:
move.b  #NOCHIPREV,chiprev      ; Ei pystyta hakemaan ChipRevBits:ia
check_proc:
move.w  AttnFlags(a6),processor ; CPU ja FPU
; move.w \$128(a6),processor
clear_view:
move.l  gfxbase,a6
move.l  gb_ActiView(a6),oldview ; nykyinen View talteen
; move.l \$22(a6),oldview
move.l  #0,a1                   ; NULL View tilalle
jsr     -\$010e(a6)
jsr     -\$010e(a6)              ; WaitTOF()

move.l  4,a6                    ; SysBase valmiiksi
movem.l (sp)+,d0/a0             ; d0/a0 pois pinosta
bsr.s   _start                  ; hypätään pääohjelmaan
move.l  d0,-(sp)                ; palautuskoodi turvaan
old_view:
move.l  gfxbase,a0
move.l  \$26(a0),\$dff080         ; Copperlistan palautus

move.l  gfxbase,a6
move.l  oldview,a1              ; vanha View
;        move.l  4,a6
;        jsr     -\$007e(a6)              ; keskeytykset päälle, Enable()
move.l  intuibase,a6
jsr     -\$0186(a6)              ; RethinkDisplay()

move.l  4,a6
move.l  intuibase,a1
jsr     -\$019e(a6)              ; CloseLibrary()

Sulje   move.l  4,a6
move.l  gfxbase,a1              ; suljetaan graphics.library
jsr     -\$019e(a6)              ; CloseLibrary()

tst.l   wbenchmsg               ; onko workbench
beq.s   exit                    ; jos ei niin exit
jsr     -\$0084(a6)              ; huomaa ettei tarvitse Permit()
; Forbid()
move.l  wbenchmsg,a1
exit:
move.l  (sp)+,d0
rts                             ; poistutaan ohjelmasta

_start

;------------------------------------------------------------------------------
; Itse ohjelma!
;------------------------------------------------------------------------------

movem.l d2-d7/a2-a6,-(sp)

;         move.l  4,a6
;        lea     dosname,a1
;        moveq   #0,d0
;        jsr         OpenLibrary(a6)
;        move.l  d0,dosbase

;         move.l  dosbase,a6
;        jsr     Output(a6)           ; For printing...
;        move.l  d0,outfile           ;

move.l  4,a6
jsr     Forbid(a6)

move.l  4,a6
move.l  #((256+16)*2+16)*32*4,d0
move.l  #65538,d1
jsr     -\$00c6(a6)
move.l  d0,ClearScreen
beq     Pois

move.l  #((256+16)*2+16)*32*4,d0
move.l  #65538,d1
jsr     -\$00c6(a6)
move.l  d0,BitMap1
beq     Vap1

move.l  #((256+16)*2+16)*32*4,d0
move.l  #65538,d1
jsr     -\$00c6(a6)
move.l  d0,BitMap2
beq     Vap2

move.l  #32768,d0                       ; 256 x 256 pixeliä
move.l  #65538,d1
jsr     -\$00c6(a6)
move.l  d0,bitmap
beq     Vap3

lea     Gamefield,a6                ; Lisätään blockien osoite valmiiksi
lea     Coolfield,a4
move.l  #5120-1,d7
GBSil:  move.l  #Blocks,a1
moveq   #0,d0
move.w  (a6)+,d0
lsl.l   #1,d0
move.l  a1,(a4)+
dbf     d7,GBSil

lea      Gamefield2,a6
lea      Coolfield2,a4
move.l   #5120-1,d7
GBSil2  move.l  #Blocks,a1
moveq   #0,d0
move.w  (a6)+,d0
lsl.l   #1,d0
move.l  a1,(a4)+
dbf      d7,GBSil2

lea     Gamefield3,a6
lea     Coolfield3,a4
move.l  #5120-1,d7
GBSil3  move.l  #Blocks,a1
moveq   #0,d0
move.w  (a6)+,d0
lsl.l   #1,d0
move.l  a1,(a4)+
dbf     d7,GBSil3

;  move.l  4,a6
;   move.l  #0,d0
;    lea     gfxname,a1
;     jsr     -\$228(a6)
;      move.l  d0,gfxbase
;       cmp.l   #0,d0
;        beq     CleanUp

;           bsr     mt_init
;           st          mt_Enable

;           move.l  #INTB_VERTB,d0
;           move.l  #Vert_str,a1    ; VBI -keskeytysstrukture
;           move.l  4,a6

move.l      #Laakit,LaakiPT

move.l      #\$dff000,a5
move.l      #CopperLista,\$080(a5)
tst.w       \$088(a5)

move.w      #\$87f0,\$096(a5)
;       move.w  #\$0400,\$096(a5)
;       move.w  #\$0020,\$096(a5)
move.l   #\$ffffffff,\$044(a5)
;         move.l  #\$0,\$044(a5)
move.w  #\$cce,\$01a2(a5)
move.w  #\$789,\$01a4(a5)
move.w  #\$446,\$01a6(a5)
;         move.w  #\$0fff,\$01aa(a5)
;           move.w  #0,\$106(a5) ; Spritet lo-res -tilaan (ECS default)
and.w      #%1111111100111111,\$106(a5)

bsr     AlkuRoskat

JumpToAlkuScreen

bra     AlkuScreen

JumpToAlustus

bsr      Alustus                ; Nollataan "muuttujat"

bsr     FillTheScreen
bsr     SwapScreens

MainProgram
cmp.b   #1,gameOver
beq     GameOver

cmp.b  #4,level
beq    LoppuScreen

bsr     SwapScreens
bsr     Show
bsr     Scroll
bsr     ClearScore
bsr     HandlePlayer
bsr     Joystick
bsr     PalautaExpTausta
bsr     CheckUnits
bsr     CheckCoordBobs    ; Tsekataan koordinaattivalmiit enemyt
bsr     CheckAsteroids
bsr     CheckMonster
bsr     HandleExplosions
bsr     BlitScore
;           move.w  #\$0f0,\$180(a5)
bsr     BlitNumbers
;           move.w  #\$000f,\$180(a5)
bsr        HandleEnergySprite

move.w  #\$000,\$180(a5)
bsr     WaitForBeam
;         move.w  #\$333,\$180(a5)
;         move.w  #\$779,\$1a4(a5)

bsr     RMB

btst    #6,\$bfe001
bne.s   MainProgram

CleanUp
;move.l  4,a6
;move.l  #0,d0
;        lea     gfxnimi,a1
;        jsr     -\$228(a6)
;        move.l  d0,gfxbase
;        move.l  #0,d0
;        lea     intuinimi,a1
;        jsr     -\$228(a6)
;        move.l  d0,intuibase
;        move.l  gfxbase,a0
;        move.l  \$26(a0),\$dff080
;        move.l  intuibase,a6
;        jsr     -\$186(a6)
;        move.l  4,a6
;        move.l  intuibase,a1
;        jsr     -\$19e(a6)
;        move.l  gfxbase,a1
;        jsr     -\$19e(a6)

;         move.l  4,a6
;         move.l  dosbase,d0
;         beq.s   Vap3
;         move.l  d0,a1
;         jsr     CloseLibrary(a6)

;           bsr     mt_end

;           move.l  #INTB_VERTB,d0
;           lea     Vert_str,a1
;           move.l  4,a6
;           jsr     -\$00ae(a6)          ; RemIntServer

move.l  4,a6
move.l  #32768,d0
move.l  bitmap,a1
jsr     -\$00d2(a6)

Vap3:     move.l  4,a6
move.l  #((256+16)*2+16)*32*4,d0
move.l  BitMap2,a1
jsr     -\$00d2(a6)
Vap2:     move.l  4,a6
move.l  #((256+16)*2+16)*32*4,d0
move.l  BitMap1,a1
jsr     -\$00d2(a6)
Vap1:     move.l  4,a6
move.l  #((256+16)*2+16)*32*4,d0
move.l  ClearScreen,a1
jsr     -\$00d2(a6)

Pois      move.l  4,a6
jsr     Permit(a6)
movem.l (sp)+,d2-d7/a2-a6
moveq   #0,d0
rts

CheckUnits
bsr       HandleUnit
rts

CheckAsteroids
cmp.b   #1,AsteroidsRunning
bne.s   ExitCA

cmp.b   #1,LastAsteroidFrames
beq.s   LastFrames

cmp.w   #0,Nr_of_asteroids
ble.s   IsThereOnScreen
bra.s   Mene
IsThereOnScreen
cmp.b   #0,Asteroids_on_screen
bne.s   Mene
move.b  #1,LastAsteroidFrames
rts

Mene      bsr     PalautaAsteroidienTausta
bsr     PutAsteroid
bsr     MoveAsteroids
bsr     AsteroidCollisions

ExitCA    rts
LastFrames
bsr     PalautaAsteroidienTausta
subq.b  #1,LastAsteroidFrames
Okay      move.b  #0,AsteroidsRunning
rts

;-----------------------------------------------------------------------------
; Käsitellään unit. Pointteri tietueeseen annetaan A1:ssä.
;-----------------------------------------------------------------------------
HandleUnit
bsr      PalautaUnitinTausta
bsr      PalautaUnitBulletinTausta
move.l   UnitsVanhaSij,a6
lea      Units,a1
moveq        #5-1,d7

WaitForBlitter
move.w   #0000,\$062(a5)  ; BLTBMOD
move.w   #0028,\$060(a5)  ; BLTCMOD
move.w   #0000,\$064(a5)  ; BLTAMOD
move.w   #0028,\$066(a5)  ; BLTDMOD

HUSil      cmp.w    #0,(a1)         ; Onko liikkeellä?
beq.s    NextUnit
move.l   2(a1),d0        ; X
move.l   6(a1),d1        ; Y
move.l   28(a1),a2       ; Bob-data

bsr      BlitBob

cmp.w    #1,46(a1)
beq.s    liikutetaan
cmp.w    #0,6(a1)
bge.s    NextUnit
bra.s    NextUnit

liikutetaan
cmp.l    #256,6(a1)
bge.s    RemoveUnit
NextUnit
dbf      d7,HUSil

bra.s    HandleUnitBullet

RemoveUnit
move.w   #0,(a1)
dbf      d7,HUSil

; Käsitellään unitin laaki

HandleUnitBullet
moveq   #5-1,d7
move.l  UnitsVBSij,a6

lea     Units,a1
HUBSil      cmp.w   #1,10(a1)
beq.s   BlitAndMoveUnitBullet

; Jos ei ole liikkeellä, niin katsotaan, onko unit kehissä; jos on, niin
; laitetaan laaki liikkeelle ehkä.

cmp.l   #ExplodedUnit,28(a1)
beq.s   Eilaakia
cmp.w   #1,(a1)                 ; Onko unit kehissä?
beq.s   Ampuukho
dbf     d7,HUBSil

bra.s   HandleUnitCollisions

Ampuukho
move.w  \$6(a5),d0               ; Jos ei ollut, niin arvotaan,
and.l   #7,d0
cmp.w   #7,d0
beq.s   Ampuu

dbf     d7,HUBSil

bra.s       HandleUnitCollisions

Ampuu       move.l      2(a1),d0                ; Asetetaan laakille alkukoordinaatit
move.l      6(a1),d1
lsl.l       #7,d0
lsl.l       #7,d1
move.l      d0,12(a1)               ; Talletetaan
move.l      d1,16(a1)

lsr.l       #7,d0
lsr.l       #7,d1

moveq       #0,d2                   ; Tähdätyt laukauset uniteille
moveq       #0,d3
move.w      x,d2
move.w      y,d3

sub.l       d0,d2
sub.l       d1,d3

lsl.l       #7,d2                   ; "desimaaliluvuksi"
lsl.l       #7,d3
lsr.l       #6,d2
lsr.l       #6,d3

move.w      #1,10(a1)              ; Laaki liikkeellä -merkki

dbf         d7,HUBSil
rts

bra.s       HandleUnitCollisions

BlitAndMoveUnitBullet
move.l      12(a1),d0       ; x
move.l      16(a1),d1       ; y
lsr.l       #7,d0               ; Kokonaisluvuksi
lsr.l       #7,d1
bsr         BlitBullet

move.l      12(a1),d0
move.l      16(a1),d1
lsr.l       #7,d0
lsr.l       #7,d1

cmp.w       #255-4,d0
bgt.s       RemoveUnitBullet
cmp.w       #4,d0
ble.s       RemoveUnitBullet

cmp.w       #256,d1
bge.s       RemoveUnitBullet
cmp.w       #4,d1
ble.s       RemoveUnitBullet

dbf         d7,HUBSil
rts

bra.s       HandleUnitCollisions

RemoveUnitBullet
move.w      #0,10(a1)

dbf         d7,HUBSil
rts

; Käsitellään unittien törmäykset

HandleUnitCollisions
lea         Units,a1
moveq       #5-1,d6

HUCSil      cmp.w       #1,(a1)         ; Unit kehissä?
beq.s       Proceed
cmp.w       #1,10(a1)       ; Laaki kehissä?
beq.s       Proceed

dbf         d6,HUCSil
rts

Proceed
move.l      2(a1),d0
move.l      6(a1),d1
move.l      12(a1),d4
move.l      16(a1),d5
asr.l       #7,d4
asr.l       #7,d5
bsr         UnitCollisions

dbf         d6,HUCSil
rts

;-----------------------------------------------------------------------------
; Unit törmäykset
; Idea: Verrataan pelaajan koordinaatteja unitiin ja sen bullettiin
;-----------------------------------------------------------------------------
UnitCollisions

; Vihollisien x,y on D0,D1:ssä

; Player to enemies

;         cmp.l   #ExplodedUnit,28(a1)      ; Jos unit on ammuttu, niin
;        beq.s   NoCollisionToEnemy         ; törmäystä ei tsekata

;         moveq   #0,d2
;         moveq   #0,d3
;         move.w  x,d2
;         move.w  y,d3
; x-test
;         sub.w  d0,d2
;         cmp.w  #-15,d2
;         blt.s  NoCollisionToEnemy
;        cmp.w   #15,d2
;         bge.s  NoCollisionToEnemy
; y-test
;         sub.w   d1,d3
;         cmp.w   #-15,d3
;         blt.s   NoCollisionToEnemy
;         cmp.w   #15,d3
;         bge.s   NoCollisionToEnemy
;         move.w     #\$0f00,\$01a4(a5)

NoCollisionToEnemy

; Player bullets to enemies
cmp.l   #ExplodedUnit,28(a1)
beq.s   PlayerToUnitBullet

lea     Laakit,a0
move.w  #AmountBullets,d7
OnkoLaakiLiikkeella
cmp.w   #0,(a0)
bne.s   LaakiLiikkeellä
dbf     d7,OnkoLaakiLiikkeella
bra.s   PlayerToUnitBullet
LaakiLiikkeellä
move.l  d0,d2
move.l  d1,d3
sub.w   2(a0),d2
cmp.w   #-16,d2
blt.s   NextBullet
cmp.w   #4,d2
bge.s   NextBullet
sub.w   4(a0),d3
cmp.w   #16,d3
bge.s   NextBullet
cmp.w   #-16,d3
blt.s   NextBullet

move.l  #ExplodedUnit,28(a1)
move.l  #ExplodedUnitM,32(a1)
move.w  #0,(a0)                   ; Laaki pois kehistä
;        subq.b  #1,OwnBulletsOnScreen

addq.w  #5,Pisteet                ; Jos osuttu niin listään pelaajan
; pisteitä
move.l  Exp_PT,a4             ; Piirretään räjähdys
move.w  #1,(a4)
move.w  d0,2(a4)
move.w  d1,4(a4)
move.w  #4,6(a4)
cmp.w   #-1,(a4)
bne.s   Jatkuu
move.l  #Explosions,Exp_PT
bra.s   NextBullet
Jatkuu    move.l  a4,Exp_PT

NextBullet
dbf       d7,OnkoLaakiLiikkeella

; Vihollisen laakin x,y on d4,d5
PlayerToUnitBullet
moveq   #0,d2
moveq   #0,d3
move.w  x,d2
move.w  y,d3
sub.w   d2,d4
cmp.w   #-3,d4
blt.s   ExitUnitCollisions
cmp.w   #14,d4
bge.s   ExitUnitCollisions
sub.w   d3,d5
cmp.w   #-3,d5
ble.s   ExitUnitCollisions
cmp.w   #14,d5
bge.s   ExitUnitCollisions
move.w  #\$0ff0,\$01a4(a5)
;           move.b  #1,gameOver
subq.b  #1,energia

ExitUnitCollisions
rts

;-----------------------------------------------------------------------------
; Palautetaan unitin alta tausta
;-----------------------------------------------------------------------------
PalautaUnitinTausta
move.l  UnitsVanhaSij,a6
moveq   #5-1,d7

PalUniTau
cmp.l   #0,(a6)
beq.s   NextYksi

WaitForBlitter
move.w  #\$9f0,\$040(a5)  ; BLTCON0
move.w  #\$0000,\$042(a5) ; BLTCON1
move.w  #0028,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD
move.l  (a6),\$050(a5)   ; BLTAPTR
move.l  4(a6),\$054(a5)  ; BLTDPTR kohde
move.w  8(a6),\$058(a5)  ; BLTSIZE
move.l  #0,(a6)
dbf     d7,PalUniTau
rts

PalautaUnitBulletinTausta:
move.l  UnitsVBSij,a6
moveq   #5-1,d7

PalUniBul
cmp.l   #0,(a6)
beq.s   NextUnitBullet

WaitForBlitter
move.w  #\$9f0,\$040(a5)  ; BLTCON0
move.w  #\$0000,\$042(a5) ; BLTCON1
move.w  #0028,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD
move.l  (a6),\$050(a5)   ; BLTAPTR
move.l  4(a6),\$054(a5)  ; BLTDPTR kohde
move.w  8(a6),\$058(a5)  ; BLTSIZE
move.l  #0,(a6)
NextUnitBullet
dbf     d7,PalUniBul
rts

;-----------------------------------------------------------------------------
; Blitataan unit-bob
;-----------------------------------------------------------------------------
BlitBob
move.w  #4098,d6        ; BLTSIZE

asl.l   #2,d1           ; Kerrotaan y-koord. 4:llä
cmp.l   #256*4,d1
bge.s   ExitBlitBob
cmp.l   #-16*4,d1       ; -(Bobin korkeus)
ble.s   ExitBlitBob

;        move.l  28(a1),a2
;        move.l  32(a1),a3
cmp.l   #(255-16)*4,d1  ; Alalaita
ble.s   NxtTest
move.l  #256*4,d6       ; Screenin lainien määrä (eli korkeus)
sub.l   d1,d6           ; Kuinka monta pixelia näkyvissä
addq.l  #2,d6           ; X lisätään suoraan tässä versiossa..
NxtTest
cmp.l   #0,d1           ; Ylälaita (käsitellään negatiiviset
moveq    #0,d6
move.l  #16*4,d6        ; Bobin korkeus (siis y-pituus)
add.l   d1,d6           ; Nyt d6:ssa bobin korkeus!
add.l   #2,d6           ; X lisätään suoraan tässä versiossa..
neg.l   d1              ; Lasketaan kohta, mistä bobbi-dataa
lsl.l   #2,d1           ; aletaan blittaamaan
moveq   #0,d1           ; Y-koordinaatti on tietysti nolla..
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
lsl.l   #5,d1
move.b  d0,d2
lsr.l   #3,d0
ext.l   d0
and.l   #\$000f,d2
mulu    #\$1000,d2
move.l  DrawScreen,a4
move.l  ClearScreen,a0

move.l  a0,(a6)         ; Vastaava paikka ClearScreenissä
move.l  a4,4(a6)        ; Vanha Sijainti
move.w  d6,8(a6)        ; Talletetaan BLTSIZE

;        WaitForBlitter
;        move.w  #0000,\$062(a5)  ; BLTBMOD
;        move.w  #0028,\$060(a5)  ; BLTCMOD
;        move.w  #0000,\$064(a5)  ; BLTAMOD
;        move.w  #0028,\$066(a5)  ; BLTDMOD

move.w  d2,\$042(a5)     ; BLTCON1
or.w   #\$0fce,d2       ; ynnätään minterm+use shift valueen
move.w  d2,\$040(a5)     ; BLTCON0
move.l  a4,\$048(a5)     ; BLTCPTR kohde
move.l  a2,\$04c(a5)     ; BLTBPTR bob-data
move.l  a4,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE
ExitBlitBob
rts

BlitBullet
move.w  #1026,d6        ; BLTSIZE

asl.l   #2,d1             ; Kerrotaan y-koord. 4:llä
cmp.l   #256*4,d1
bge.s   ExitBlitBullet
cmp.l   #-4*4,d1       ; -(Bobin korkeus)
ble.s   ExitBlitBullet

move.l  #EnBulletBob,a2
cmp.l   #(255-4)*4,d1  ; Alalaita
ble.s   NxTest
move.l  #256*4,d6       ; Screenin lainien määrä (eli korkeus)
sub.l   d1,d6           ; Kuinka monta pixelia näkyvissä
addq.l  #2,d6           ; X lisätään suoraan tässä versiossa..
NxTest
cmp.l   #0,d1           ; Ylälaita (käsitellään negatiiviset
moveq   #0,d6
move.l  #4*4,d6        ; Bobin korkeus (siis y-pituus)
add.l   d1,d6           ; Nyt d6:ssa bobin korkeus!
add.l   #2,d6           ; X lisätään suoraan tässä versiossa..
neg.l   d1              ; Lasketaan kohta, mistä bobbi-dataa
lsl.l   #2,d1           ; aletaan blittaamaan
moveq   #0,d1           ; Y-koordinaatti on tietysti nolla..
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
lsl.l   #5,d1
move.b  d0,d2
lsr.l   #3,d0
ext.l   d0
and.l   #\$000f,d2
mulu    #\$1000,d2
move.l  DrawScreen,a4
move.l  ClearScreen,a0

move.l  a0,(a6)         ; Vastaava paikka ClearScreenissä
move.l  a4,4(a6)        ; Vanha Sijainti
move.w  d6,8(a6)        ; Talletetaan BLTSIZE

WaitForBlitter
move.w  #0000,\$062(a5)  ; BLTBMOD
move.w  #0028,\$060(a5)  ; BLTCMOD
move.w  #0000,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD

move.w  d2,\$042(a5)     ; BLTCON1
or.w    #\$0fce,d2       ; ynnätään minterm+use shift valueen
move.w  d2,\$040(a5)     ; BLTCON0
move.l  a4,\$048(a5)     ; BLTCPTR kohde
move.l  a2,\$04c(a5)     ; BLTBPTR bob-data
move.l  a4,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE
ExitBlitBullet
rts

;------------------------------------------------------------------------------
;
;------------------------------------------------------------------------------
move.l  pt_toCoolF,d0

moveq   #0,d1
move.b  level,d1
cmp.b   #2,d1
beq     Level2

cmp.b   #3,d1
beq     Level3

; LEVEL 1

cmp.l  #1280,d0
beq.s  Kla
;         beq.s LM  ; HUOM!

cmp.l   #2904,d0
beq.s   Yep

cmp.l   #6400,d0
beq.s   AsteroiditKehiin

cmp.l   #13480,d0
beq.s   LM

rts

Level2
cmp.l  #1216,d0
beq.s  putunits

cmp.l  #2904,d0
beq.s  putships

cmp.l  #6400,d0
beq.s  AsteroiditKehiin

cmp.l #13408,d0
beq.s  PutLoppuUnits

cmp.l  #13440,d0
beq    LM

rts

Level3
cmp.l  #320,d0
beq.s  l3_aw1

cmp.l  #6400,d0
beq.s  AsteroiditKehiin

cmp.l  #13480,d0
beq    LM

rts

; 3. hyökkäysaalto

Yep       move.b  #1,CoordBobsRunning

move.l  #Coords1,Coords

move.l  #RengasBob,a3
move.b  #16,nr_of_bobs
lea     PTRsAndONOFF,a0
moveq   #0,d7
move.b  nr_of_bobs,d7
subq.l     #1,d7
moveq   #0,d0
DefSil    move.l  d0,(a0)+        ; Pointteri koordinaatteihin
move.w  #1,(a0)+        ; "Enemy kehissä" -merkki
move.w  #1,(a0)+        ; Kestävyys
move.l  a3,(a0)+        ; Bob-data

dbf     d7,DefSil
move.b  nr_of_bobs,AmEnemies
rts

; 2. Hyökkäysaalto

Kla
lea     Units,a1
move.w  #1,(a1)
move.l  #96,2(a1)
move.l  #-16,6(a1)

move.l  #Unit,28(a1)
move.l  #ExplodedUnit,36(a1)
move.l  #ExplodedUnitM,40(a1)
move.w  #1,46(a1)

move.w  #1,(a1)
move.l  #112,2(a1)
move.l  #-16,6(a1)

move.l  #Unit,28(a1)
move.l  #ExplodedUnit,36(a1)
move.l  #ExplodedUnitM,40(a1)
move.w  #1,46(a1)

move.w  #1,(a1)
move.l  #128,2(a1)
move.l  #-16,6(a1)

move.l  #Unit,28(a1)
move.l  #ExplodedUnit,36(a1)
move.l  #ExplodedUnitM,40(a1)
move.w  #1,46(a1)

move.w  #1,(a1)
move.l  #144,2(a1)
move.l  #-16,6(a1)

move.l  #Unit,28(a1)
move.l  #ExplodedUnit,36(a1)
move.l  #ExplodedUnitM,40(a1)
move.w  #1,46(a1)

rts

; 3. Hyökkäysaalto

;Yea      move.b  #1,CoordBobsRunning
;
;        move.l  #Coords2,Coords
;
;         move.l     #UfoBob,a1
;         move.b  #16,nr_of_bobs
;       lea     PTRsAndONOFF,a0
;         moveq   #0,d7
;        move.b  nr_of_bobs,d7
;         subq.l  #1,d7
;         moveq   #0,d0
;DSil    move.l  d0,(a0)+               ; Pointteri koordinaatteihin
;         move.w  #1,(a0)+              ; Kehissä
;         move.w  #3,(a0)+              ; Kestävyys
;         move.l  a1,(a0)+              ; Bob-data
;        dbf     d7,DSil
;        move.b  nr_of_bobs,AmEnemies

;         rts

; 4. Hyökkäysaalto

AsteroiditKehiin
move.b  #1,AsteroidsRunning
move.w  #164,Nr_of_asteroids
rts

LM      move.b  #1,MonsterKehissa
rts

; Level 2

PutLoppuUnits
lea     Units,a1
move.w  #1,(a1)
move.l  #112,2(a1)
move.l  #-16,6(a1)
move.l  #Unit,28(a1)
move.l  #ExplodedUnit,36(a1)
move.l  #ExplodedUnitM,40(a1)
move.w  #0,46(a1)

move.w  #1,(a1)
move.l  #128,2(a1)
move.l  #-16,6(a1)
move.l  #Unit,28(a1)
move.l  #ExplodedUnit,36(a1)
move.l  #ExplodedUnitM,40(a1)
move.w  #0,46(a1)

rts

putunits
lea     Units,a1
move.w  #1,(a1)
move.l  #112,2(a1)
move.l  #-16,6(a1)
move.l  #Unit,28(a1)
move.l  #ExplodedUnit,36(a1)
move.l  #ExplodedUnitM,40(a1)
move.w  #1,46(a1)

move.w  #1,(a1)
move.l  #128,2(a1)
move.l  #-16,6(a1)
move.l  #Unit,28(a1)
move.l  #ExplodedUnit,36(a1)
move.l  #ExplodedUnitM,40(a1)
move.w  #1,46(a1)
rts

putships
move.b  #1,CoordBobsRunning

move.l  #Coords2,Coords

move.l  #ShipBob,a3
move.b  #16,nr_of_bobs
lea     PTRsAndONOFF,a0
moveq   #0,d7
move.b  nr_of_bobs,d7
subq.l  #1,d7
moveq   #0,d0
initSil     move.l  d0,(a0)+          ; Pointteri koordinaatteihin
move.w  #1,(a0)+        ; "Enemy kehissä" -merkki
move.w  #3,(a0)+          ; Kestävyys
move.l  a3,(a0)+          ; Bob-data

dbf     d7,initSil
move.b  nr_of_bobs,AmEnemies
rts

l3_aw1
move.b  #1,CoordBobsRunning

move.l  #Coords3,Coords

move.l  #WBob,a3
move.b  #16,nr_of_bobs
lea     PTRsAndONOFF,a0
moveq   #0,d7
move.b  nr_of_bobs,d7
subq.l   #1,d7
moveq   #0,d0
init_l3_aw1
move.l  d0,(a0)+          ; Pointteri koordinaatteihin
move.w  #1,(a0)+        ; "Enemy kehissä" -merkki
move.w  #3,(a0)+          ; Kestävyys
move.l  a3,(a0)+          ; Bob-data

dbf     d7,init_l3_aw1
move.b  nr_of_bobs,AmEnemies
rts

;------------------------------------------------------------------------------
; Katsotaan pitääkö koordinaativalmiita bobbjea liikuttaa
;------------------------------------------------------------------------------
CheckCoordBobs
cmp.b  #1,CoordBobsRunning
beq.s  Yes
rts
Yes       cmp.b  #0,AmEnemies
beq.s  Ye
bra.s  CCBR
Ye        cmp.b  #0,MovingEBullets
beq.s  Chess

CCBR      bsr    PalautetaanTaustat
bsr    HandleBob
bsr    HandleEBullets
bsr    Collisions
ExitCheck
rts
Chess     cmp.b   #1,DoLastCoordBobFrames
beq.s   Yeah
move.b  #1,DoLastCoordBobFrames
move.b  #1,LastCBFrames
Yeah      bsr     PalautetaanTaustat
subq.b  #1,LastCBFrames
cmp.b   #0,LastCBFrames
beq.s   OliNolla
rts
OliNolla
move.b  #0,LastCBFrames
move.b  #0,CoordBobsRunning
move.b  #0,DoLastCoordBobFrames
rts

;------------------------------------------------------------------------------
Collisions
; 1° Ovatko pelaajan laakit osuneet vihollisiin?
; Periaate: Otetaan laaki 1. Verrataan sitä kaikkiin enemyihin.
;           Otetaan laaki 2. Verrataan sitä kaikkiin enemyihin. JNE.
;------------------------------------------------------------------------------
;        move.w  #\$0779,\$01a4(a5)
lea     Laakit,a0
move.w  #AmountBullets,d7       ; Omien laakien määrä
CSil1:  lea     PTRsAndONOFF,a1
moveq    #0,d6
move.b  nr_of_bobs,d6        ; Vihollisten määrä -1
subq.l  #1,d6

CSil2:  cmp.w   #0,(a0)
bne.s   CSil3
dbf     d7,CSil2
bra.s   EnemiesToPlayer
CSil3:  cmp.w   #0,4(a1)        ; Katsotaan onko ko. enemy kehissä;
beq.s   Nxt             ; ei -> seuraava enemy
move.w  4(a0),d0        ; y-test ; Otetaan laakin (Ply) y-koord.
move.l  Coords,a2       ; Pointteri enemyn
move.w  (a2),d2        ; Enemyn x-koord.
move.w  2(a2),d1         ; Enemyn y-koord.
sub.w   d1,d0
;       cmp.w   #0,d0
blt.s   Nxt
cmp.w   #8+8,d0
bgt.s   Nxt
move.w  2(a0),d0        ; x-test ; Laakin (Ply) x-koord.
sub.w   d2,d0           ; Pelaajan x miinus enemyn x
cmp.w   #-5,d0
blt.s   Nxt
cmp.w   #13,d0
bgt.s   Nxt
move.w  #0,(a0)         ; Laaki pois kehistä -merkki
;         subq.b  #1,OwnBulletsOnScreen
subq.w  #1,6(a1)
cmp.w   #0,6(a1)          ; Onko hajalla?
bne.s   Nxt

move.w  #0,4(a1)        ; Enemy pois kehistä -merkki
subq.b  #1,AmEnemies
addq.w  #5,Pisteet        ; Lisätään pelaajan pisteitä

move.l   Exp_PT,a4
move.w   #1,(a4)
move.w   (a2),2(a4)
move.w   2(a2),4(a4)
move.w   #4,6(a4)
cmp.w    #-1,(a4)
bne.s     ptr_ok
move.l   #Explosions,Exp_PT
;         move.w   #\$fff,\$dff180
bra.s    Nxt
ptr_ok  move.l   a4,Exp_PT

Nxt     add.l   #16,a1          ; Seuraava enemy
dbf     d6,CSil3
addq.l  #6,a0           ; Seuraava laaki (Ply)
dbf     d7,CSil1

;------------------------------------------------------------------------------
; 2° Onko joku vihulainen onnistunut krunssaamaan pelaajan aluksen?
; Periaate: Verrataan kaikkien vihollisten koordinaatteja pelaajan x,y:hyn
;------------------------------------------------------------------------------
EnemiesToPlayer
moveq   #0,d7
move.b  nr_of_bobs,d7       ; Tässä oli bugi ennen!
subq.l  #1,d7

lea     PTRsAndONOFF,a0 ; Vihollisten pointterit koordinaatteihin
move.w  x,d0            ; Pelaajan x ja
move.w  y,d1            ; y
EToPly: cmp.w   #0,4(a0)        ; Jos vihulainen ei oo kehissä, niin next!
beq.s   Nekst
move.l  Coords,a1
move.w  (a1)+,d2        ; Vihollisen x
move.w  (a1),d3         ; Vihollisen y
sub.w   d0,d2           ; VihX-PelX
cmp.w   #-16,d2         ; Vasemmanpuoleinen raja
blt.s   Nekst
cmp.w   #13,d2          ; Oikeanpuolinen raja
bgt.s   Nekst
sub.w   d1,d3           ; VihY-PelY
cmp.w   #-15,d3         ; Yläraja
blt.s   Nekst
cmp.w   #14,d3          ; Alaraja
bgt.s   Nekst
move.w  #\$0ff0,\$01a4(a5) ; CRASH!!!!!!!!!!!!!!
;         move.b  #1,gameOver
subq.b  #1,energia

;        bra.s   EBulletsToPlayer   ; ???
dbf     d7,EToPly

;------------------------------------------------------------------------------
; 3° Onko vihulaisen laaki ehkä jopa osunut?
; Periaate: Verrataan kaikkien enemylaakien koordinaatteja pelaajan x,y:hyn
;------------------------------------------------------------------------------
; Tähän tultaessa pelaajan x on D0:ssa ja y D1:ssä

EBulletsToPlayer
move.w  #AmountEBullets,d7
lea     EnemyLaakit,a0  ; Vihollisten laakien koordinaatit
BToPly  move.w  (a0)+,d2        ; Laakin x
bmi.s   Seuraava        ; Jos x=-1, niin seuraava laaki!
move.w  (a0)+,d3        ; Laakin y
sub.w   d0,d2           ; LaakiX-PelaX
cmp.w   #-3,d2          ; Vasemmanpuoleinen raja
blt.s   Nekzt
cmp.w   #14,d2        ; Oikeanpuolinen raja
bgt.s   Nekzt
sub.w   d1,d3           ; LaakiY-PelaY
cmp.w   #-3,d3           ; Yläraja
blt.s   Nekzt
cmp.w   #14,d3           ; Alaraja
bgt.s   Nekzt
move.w  #\$0ff0,\$01a4(a5) ; CRASH!!!!!!!!!!!!!!!!
;         move.b     #1,gameOver
subq.b  #1,energia
bra.s   Ex_BTP          ; (Future: Lives/Energy -1)
Nekzt   dbf     d7,BToPly
Ex_BTP  rts
Seuraava
dbf     d7,BToPly
rts

;------------------------------------------------------------------------------
PalautetaanTaustat
;------------------------------------------------------------------------------
; Enemyiden alla olevat taustat

move.l  VanhaSij,a2     ; ClearScreen,VanhaSij,BLTSIZE
moveq   #0,d7
move.b  nr_of_bobs,d7
subq.l   #1,d7
move.l  VanhaESij,a1    ; ClearScreen,VanhaESij
move.w  #AmountEBullets,d6
move.w  #1026,d0
WaitForBlitter
move.w  #\$09f0,\$040(a5) ; BLTCON0
move.w  #\$0000,\$042(a5) ; BLTCON0
move.w  #0028,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD
PalautaTausta
cmp.l   #0,(a2)
bne.s   NoSkip
dbf     d7,PalautaTausta
bra.s   PalautaTausta2
NoSkip  WaitForBlitter
move.l  (a2)+,\$050(a5)  ; BLTAPTR
move.l  (a2)+,\$054(a5)  ; BLTDPTR kohde
move.w  (a2)+,\$058(a5)  ; BLTSIZE
dbf     d7,PalautaTausta

; Vihollisten laakien alla olevat taustat
PalautaTausta2
cmp.l   #0,(a1)
bne.s   NoSkip2
dbf     d6,PalautaTausta2
bra.s   ExitPal
NoSkip2 WaitForBlitter
move.l  (a1)+,\$050(a5)  ; BLTAPTR
move.l  (a1)+,\$054(a5)  ; BLTDPTR kohde
move.w  d0,\$058(a5)     ; BLTSIZE
dbf     d6,PalautaTausta2
ExitPal move.w  \$6(a5),Random   ; Avitetaan satunnaislukugeneraattoria
rts

;------------------------------------------------------------------------------
; Palautetaan asteroidien alta tausta
;------------------------------------------------------------------------------
PalautaAsteroidienTausta
moveq   #max_asteroids_on_screen-1,d7
;         lea       Asteroids,a0
move.l  VanhaAstSij,a6

WaitForBlitter
move.w  #\$09f0,\$040(a5) ; BLTCON0
move.w  #\$0000,\$042(a5) ; BLTCON0
move.w  #0028,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD

PalAstTausta
cmp.l   #0,(a6)          ; Onko liikkeellä?
beq.s   SkipAst
WaitForBlitter
move.l  (a6)+,\$050(a5) ; BLTAPTR
move.l  (a6)+,\$054(a5) ; BLTDPTR
move.w  (a6)+,\$058(a5) ; BLTSIZE
;         move.l  #0,-10(a6)
SkipAst
;         add.l   #10,a0                ; Oli 20
dbf     d7,PalAstTausta

rts

;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
HandlePlayer:
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Put the player's ship
lea     SPR1,a1         ; Oma alus
move.w  x,d0            ; x
move.w  y,d1            ; y
move.w  #15,d2          ; korkeus
bsr     SpriteKondikseen

;------------------------------------------------------------------------------
; Tässä liikutetaan ja pistetään kehiin omat spritelaakit.
; Laakimuuttujille täytyy
; siis varata kiinteästi muistia kuvaruudulle mahtuvien laakien määrä kertaa 3!
;------------------------------------------------------------------------------
moveq   #AmountBullets,d7

move.l  LaakiPT,a0
lea     SPR0,a1         ; Laakisprite

BSil:   cmp.w   #0,(a0)         ; Onko laaki liikenteessä = kehiinkö?
beq.s   NextB
subq.w  #BSpeed,4(a0)   ; Laakin liikutus!
move.w  2(a0),d0        ; Laakin x
move.w  4(a0),d1        ; Laakin y
cmp.w   #-8,d1
bgt.s   Continue
move.w  #0,(a0)         ; Laaki ei kehissä -merkki
;         subq.b  #1,OwnBulletsOnScreen
bra.s   NextB
Continue:
moveq   #8,d2           ; Laakispriten korkeus
bsr     SpriteKondikseen

cmp.w   #-1,(a0)
bne.s   NoEi
lea     Laakit,a0
NoEi:   dbf     d7,BSil
move.l  #0,(a1)         ; Stop usage of LaakiSprite (SPR 0 tai 1)
Ex:     rts

;------------------------------------------------------------------------------
Joystick:
;------------------------------------------------------------------------------
move.w  \$c(a5),d6       ; Joikkis rekisteri

btst    #1,d6           ; Ohjataanko oikealle?
beq.s   jskip           ; Jos ei niin ...

cmp.b   #1,phase
beq.s   rdec1
cmp.b   #2,phase
beq.s   rdec2
cmp.b   #3,phase
beq.s   rdec3

move.b   #1,phase
move.b   #10,delay
rdec1   subq.b   #1,delay
cmp.b   #0,delay
bne.s   ei1
move.b  #5,delay
ei1     bra.s   ROnkoRajoissa

rdec2   subq.b  #1,delay
cmp.b   #0,delay
bne.s   ei2
ei2     bra.s   ROnkoRajoissa

ROnkoRajoissa

cmp.w   #255-16,x
ble.s   Nappi
move.w  #255-16,x
bra.s   EsiNappi

jskip:  btst    #9,d6           ; Ohjataanko vasemalle?
beq.s   EsiNappi           ; Jos ei niin ...

cmp.b   #1,phase
beq.s   ldec1
cmp.b   #2,phase
beq.s   ldec2
cmp.b   #3,phase
beq.s   ldec3

move.b  #1,phase
move.b  #10,delay
ldec1   subq.b  #1,delay
subq.w  #1,x
cmp.b   #0,delay
bne.s   ei3
move.b  #5,delay
ei3     bra.s   LOnkoRajoissa

ldec2   subq.b  #1,delay
subq.w  #2,x
cmp.b   #0,delay
bne.s   ei4
ei4     bra.s   LOnkoRajoissa

ldec3   subq.w  #3,x

LOnkoRajoissa

cmp.w   #0,x
bge.s   Nappi
move.w  #0,x

EsiNappi
move.b  #0,phase

beq.s   Test
rts
Test:   btst    #7,\$bfe001      ; Katsotaan painetaanko joikkiksen nappia ja
bne.s   ExitJoystick    ; jos kyllä, niin laaki kehiin jos ei niin ei
cmp.b   #1,NPohjassa
bne.s   EiOo
Here:   rts
EiOo:
;        cmp.b   #3,OwnBulletsOnScreen
;         beq.s   Here
move.b  #1,NPohjassa
move.l  LaakiPT,a0
move.w  x,d0            ; Laakille koordinaatit
move.w  y,d1
subq.w  #8,d1
move.w  #1,(a0)         ; Laaki liikkellä merkki
move.w  d0,2(a0)        ; Laakille alku-x
move.w  d1,4(a0)        ; Laakille alky-y
cmp.w   #-1,(a0)
bne.s   Tedve
lea     Laakit,a0
Tedve:  move.l  a0,LaakiPT
rts
ExitJoystick
cmp.b   #1,NPohjassa
bne.s   Eij
move.b  #0,NPohjassa
Eij:    rts

;------------------------------------------------------------------------------
; Sprite Kondikseen
; Usage: a1=sprite,d0=x,d1=y,d2=korkeus
; Kantsii ehkä kehitellä semmoinen sprite-macro, niin koodi lyhenee vähän
SpriteKondikseen
X_kuntoon
and.b   #%10000000,3(a1)
add.w   #128,d0         ; Koodia kannattanee optimoida niin, että
add.w   #44,d1          ; nämä on jo lisätty valmiiksi..

ror.w   #1,d0           ; 8 ylintä x:n bittiä
move.b  d0,1(a1)        ; HSTARTiin.
btst    #15,d0          ; Katsotaan pitääkö
beq.s   Y_kuntoon       ; "the HSTART low bit"
bset    #0,3(a1)        ; asettaa.
Y_kuntoon
move.b  d1,(a1)         ; 8 alinta y:n bittiä VSTARTiin
btst    #8,d1           ; Katsotaan pitääkö
beq.s   VSTOP_kuntoon   ; "the VSTART high bit"
bset    #2,3(a1)        ; asettaa.
VSTOP_kuntoon
move.b  d2,2(a1)        ; 8 alinta vstop:in bittiä VSTOPpiin
btst    #8,d2           ; Katsotaan pitääkö
beq.s   SprOut          ; "the VSTOP high bit"
bset    #1,3(a1)        ; asettaa.
SprOut  rts

;------------------------------------------------------------------------------
; Käsitellään energiasprite
;------------------------------------------------------------------------------
HandleEnergySprite
moveq   #0,d2
move.b  energia,d2            ; Korkeus
cmp.b   #0,d2
bgt.s   energiaa
moveq   #0,d2
move.b  #1,gameOver
energiaa
moveq   #16,d3
sub.l   d2,d3
move.l  #235,d0
moveq   #5,d1
move.l  #SPR2,a1
bsr     SpriteKondikseen
rts

;------------------------------------------------------------------------------
Scroll  cmp.b   #1,MonsterKehissa
beq.s   GoOn

;        lea     Coolfield,a6
move.l  coolfield,a6
cmp.l   #5120*4,pt_toCoolF
bne.s   Neij
move.l  #0,pt_toCoolF

bsr     DrawBlocks      ; Piirrettän 1 blocki kaikkiin (3) screeneihin
sub.l   #32*4,ScrollOffset      ; Scrollataan 1 pixeli

cmp.b   #16,Frame
bne.s   GoOn
move.l  #0,Bl_paikka
move.b  #0,Frame
cmp.b   #1,LameFrame
bne.s   EiLameFrame
move.b  #0,LameFrame
move.l  #(256+16+16)*4*32,ScrollOffset
EiLameFrame
sub.l   #16,LineN
cmp.l   #-16,LineN
bne.s   GoOn
move.l  #0,Bl_paikka
move.b  #1,LameFrame
move.l  #256+16,LineN
GoOn    rts

;------------------------------------------------------------------------------
Show:   move.l  ShowScreen,d1
move.w  d1,low1
swap    d1
move.w  d1,high1
swap    d1
move.w  d1,low2
swap    d1
move.w  d1,high2
swap    d1
move.w  d1,low3
swap    d1
move.w  d1,high3
swap    d1
move.w  d1,low4
swap    d1
move.w  d1,high4
rts

;------------------------------------------------------------------------------
DrawBlocks:
move.w  #4097,d6        ; BLTSIZE (16*(16*4))
move.l  LineN,d1        ; Rivinumero, mihin blocki blitataan
lsl.l   #7,d1           ; Kerrotaan 32*4:llä = screen's width * nr. bpls

cmp.b   #1,LameFrame
beq     Lame

; Kopsataan aluksi sama pala kahteen eri paikkaan ClearScreeniin

move.l  ClearScreen,a2

WaitForBlitter
move.w  #\$09f0,\$040(a5) ; BLTCON0
move.w  #\$0000,\$042(a5) ; BLTCON0
move.w  #0038,\$064(a5)  ; BLTAMOD
move.w  #0030,\$066(a5)  ; BLTDMOD

move.l  (a6),\$050(a5)   ; BLTAPTR source
move.l  a2,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE

WaitForBlitter
move.l  (a6),\$050(a5)   ; BLTAPTR source
move.l  a2,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE (16*(16*4))

; ..sitten BitMap1:een

move.l  BitMap1,a2

WaitForBlitter
move.l  (a6),\$050(a5)   ; BLTAPTR source
move.l  a2,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE

WaitForBlitter
move.l  (a6),\$050(a5)   ; BLTAPTR source
move.l  a2,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE (16*(16*4))

; ..sitten BitMap2:een

move.l  BitMap2,a2

WaitForBlitter
move.l  (a6),\$050(a5)   ; BLTAPTR source
move.l  a2,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE

WaitForBlitter
move.l  (a6),\$050(a5)   ; BLTAPTR source
move.l  a2,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE (16*(16*4))
rts

; Blitataan ensin ClearScreeniin

Lame:   move.l  ClearScreen,a2

WaitForBlitter
move.w  #\$09f0,\$040(a5) ; BLTCON0
move.w  #\$0000,\$042(a5) ; BLTCON0
move.w  #0038,\$064(a5)  ; BLTAMOD
move.w  #0030,\$066(a5)  ; BLTDMOD

move.l  (a6),\$050(a5)   ; BLTAPTR source
move.l  a2,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE (16*(16*4))

; Sitten BitMap1:een

move.l  BitMap1,a2

WaitForBlitter
move.l  (a6),\$050(a5)   ; BLTAPTR source
move.l  a2,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE (16*(16*4))

; Sitten BitMap2:een

move.l  BitMap2,a2

WaitForBlitter
move.l  (a6),\$050(a5)   ; BLTAPTR source
move.l  a2,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE (16*(16*4))
rts

;------------------------------------------------------------------------------
SwapScreens:
cmp.b   #1,Kumpainen
beq     LetItBeOneThen
move.l  BitMap2,DrawScreen
move.l  BitMap1,ShowScreen
;         cmp.b   #1,CoordBobsRunning
;         bne.s   Ej
move.l  #VanhaSij1,VanhaSij
move.l  #VanhaESij1,VanhaESij
;         lea     Asteroids,a0
;         move.l  #AstVanhaSij0,10(a0)
cmp.b   #1,AsteroidsRunning
bne.s   Eii
move.l  #VanhaAstSij0,VanhaAstSij
Eii
move.l  #UnitsVanhaSij0,UnitsVanhaSij
move.l  #UnitsVBSij0,UnitsVBSij

move.l  #ExpVanhaSij0,VanhaExpSij

move.l  #MonstVanhaSij0,MonsterVanhaSij
move.l  #MonstBVanhaSij0,MonstBVanhaSij

move.l  #MExp_VanhaSij0,MExp_vanhasij

move.b  #1,Kumpainen
rts

LetItBeOneThen:
move.l  BitMap1,DrawScreen
move.l  BitMap2,ShowScreen
;         lea     Asteroids,a0
;        move.l  #AstVanhaSij1,10(a0)
cmp.b   #1,AsteroidsRunning
bne.s   Eiii
move.l  #VanhaAstSij1,VanhaAstSij
Eiii    move.l  #VanhaSij2,VanhaSij
move.l  #VanhaESij2,VanhaESij

move.l  #UnitsVanhaSij1,UnitsVanhaSij
move.l  #UnitsVBSij1,UnitsVBSij

move.l  #ExpVanhaSij1,VanhaExpSij

move.l  #MonstVanhaSij1,MonsterVanhaSij
move.l  #MonstBVanhaSij1,MonstBVanhaSij

move.l  #MExp_VanhaSij1,MExp_vanhasij

move.b  #0,Kumpainen
rts

;------------------------------------------------------------------------------
; Tsekataan ovatko pelaajan laakit osuneet asteroideihin tai asteroidit pelaajaan
;------------------------------------------------------------------------------
AsteroidCollisions
; Ovatko pelaajan laakit osuneet asteroideihin
; Idea: Otetaan järjestyksessä pelaajan laakeja ja verrataan niitä liikkeellä
; oleviin asteroideihin.

moveq    #0,d4
moveq    #0,d5
move.w   x,d4                      ; Pelaajan X
move.w   y,d5                      ; Pelaajan Y

lea      Laakit,a0
moveq    #AmountBullets,d7
LaakiKehissa
cmp.w    #0,(a0)                  ; Onko laaki liikkeellä
beq.s    NextLaaki           ; Jos ei ole, niin otetaan seuraava laaki
;       moveq    #0,d0
;       moveq    #0,d1
move.w   2(a0),d0              ; Laakin X
move.w   4(a0),d1              ; Laakin Y
bra.s    CompareToAsteroids
NextLaaki
dbf      d7,LaakiKehissa
bra.s    PlayerToAsteroids

CompareToAsteroids
moveq    #max_asteroids_on_screen-1,d6
lea      Asteroids,a1
AstCollSil
cmp.w    #0,(a1)                   ; Onko liikkeellä
beq.s    NextAster           ; Jos ei ole niin seuraava asteroidi
;        moveq    #0,d2
;       moveq    #0,d3
move.w   2(a1),d2              ; Asteroidin X
move.w   4(a1),d3              ; Asteroidin Y
sub.w    d0,d2                 ; AstX - PelX
cmp.w    #-15,d2               ; -15
blt.s    NextAster
cmp.w    #2,d2             ; 2
bgt.s    NextAster
sub.w    d1,d3
cmp.w    #-15,d3           ; -15
blt.s    NextAster
cmp.w    #16,d3            ; 16
bgt.s    NextAster

move.w   #0,(a0)                   ; Jos osuttu asteroidiin, niin laaki pois
;        subq.b   #1,OwnBulletsOnScreen

subq.w   #1,8(a1)              ; Vähennetään asteroidin kestävyyttä
cmp.w    #0,8(a1)              ; Jos tuhoutunut, niin laitetaan
bne.s    NextAster             ; pois kehistä ja lisätään
move.w   #0,(a1)                   ; pelaajan pisteitä
subq.b   #1,Asteroids_on_screen ; Vähennetään ruudulla olevien
; asteroidien määrää
move.l   Exp_PT,a4
move.w   #1,(a4)
move.w   2(a1),2(a4)
move.w   4(a1),4(a4)
move.w   #4,6(a4)
move.l   a4,Exp_PT
cmp.w    #-1,(a4)
bne.s   NextAster
move.l   #Explosions,Exp_PT

NextAster
dbf      d6,AstCollSil         ; Kun kaikki asteroidit on katsottu
addq.l   #6,a0                 ; otetaan seuraava laaki
dbf      d7,LaakiKehissa

; Katsotaan onko pelaaja törmännyt asteroidiin

PlayerToAsteroids
moveq   #max_asteroids_on_screen-1,d7
lea     Asteroids,a1
AsterSil
cmp.w   #0,(a1)                    ; Jos asteroidi ei ole liikkeellä, niin
beq.s   NxtAster                   ; seuraava asteroidi
moveq   #0,d2
moveq   #0,d3
move.w  2(a1),d2                  ; Asteroidin X
move.w  4(a1),d3                   ; Asteroidin Y
sub.w   d4,d2
cmp.w   #-15,d2
blt.s   NxtAster
cmp.w   #13,d2
bgt.s   NxtAster
sub.w   d5,d3
cmp.w   #-15,d3
blt.s   NxtAster
cmp.w   #14,d3
bgt.s   NxtAster
move.w  #\$0ff0,\$1a4(a5)
;        move.b #1,gameOver
subq.b  #1,energia
NxtAster
dbf     d7,AsterSil
rts

;------------------------------------------------------------------------------
; Laitetaan uusi asteroidi näytölle
;------------------------------------------------------------------------------
PutAsteroid
cmp.w    #0,Nr_of_asteroids    ; Paljonko asteroideja jäljellä
ble.s    ExitPA              ; (yo. on kokonaismäärä)

cmp.b   #max_asteroids_on_screen,Asteroids_on_screen
bge.s    ExitPA

move.w   Random,d5
lea      Asteroids,a0
moveq    #max_asteroids_on_screen-1,d7
PASil    cmp.w    #0,Nr_of_asteroids    ; Onko kaikki asteroidit käytetty?
ble.s    ExitPA

cmp.b    #max_asteroids_on_screen,Asteroids_on_screen ; Onko ruudulla max määrä
beq.s    ExitPA                  ; asteroideja

cmp.w    #1,(a0)                   ; Onko jo kehissä?
beq.s    NextAsteroid         ; Jos on niin seuraava asteroidi
move.w   \$6(a5),d0            ; Arvotaan uudelle asteroidille
and.l    #255,d0
cmp.w    #239,d0
blt.s    Ookoo
sub.l    #16,d0
Ookoo    move.w   d0,2(a0)
move.w   #-16,4(a0)                ; Y-koordinaatti
add.w    d5,d0                ; Arvotaan nopeus, D5:ssä random
and.l    #3,d0
cmp.l    #0,d0                ; Nolllaa ei kelpuuteta nopeudeksi
bne.s    EiNolla
moveq    #1,d0
EiNolla
move.w   d0,6(a0)             ; Speed
move.w   #9,8(a0)             ; Kestävyys, asteroidit kestävät 3 laakia
move.w   #1,(a0)                  ; Asteroidi kehissä merkki
subq.w   #1,Nr_of_asteroids
NextAsteroid
dbf      d7,PASil

ExitPA rts
OutOfAsteroidField
cmp.b    #0,Asteroids_on_screen
beq.s    Out
rts
Out
move.b   #1,LastAsteroidFrames
rts

;------------------------------------------------------------------------------
; Liikutetaan ja piirretään asteroidit
;------------------------------------------------------------------------------
MoveAsteroids

lea        Asteroids,a1
;        move.l   a1,a6
move.l   VanhaAstSij,a6

moveq    #max_asteroids_on_screen-1,d7

move.l  ScrollOffset,d5
WaitForBlitter
move.w  #0000,\$062(a5)  ; BLTBMOD
move.w  #0028,\$060(a5)  ; BLTCMOD
move.w  #0000,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD

AstSil  cmp.w    #0,(a1)              ; Onko liikkeellä? Jos ei ole, niin mennään
beq.s    NextAst              ; seuraavan asteroidin kohdalle
moveq    #0,d0
moveq    #0,d1
move.w   2(a1),d0         ; Asteroidin X
move.w   4(a1),d1         ; Asteroidin Y
;        move.l   a1,a6           ; PutBob-rutiinia varten pointteri
move.l   #AsteroidBob,a2 ; A2:ssa bob-data
bsr      PutBob
moveq    #0,d0
move.w   6(a1),d0         ; Speed
cmp.w    #256+4,4(a1)         ; Onko poissa näkyvistä?
blt.s    NextAst
move.w   #0,(a1)              ; Jos on, niin pois kehistä merkki päälle
subq.b   #1,Asteroids_on_screen
NextAst
dbf      d7,AstSil
rts
Jooo    cmp.b    #0,Asteroids_on_screen
beq.s    Out

;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
HandleBob:
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
cmp.b   #0,AmEnemies      ; Jos ei ole yhtään enemyä kehissä, niin
bne.s   SumLeft          ; poistutaan
rts

SumLeft lea     PTRsAndONOFF,a1 ; Pointterit koordinaatteihin + ON/OFF merkki
move.l  VanhaSij,a6
moveq   #0,d7
move.b  nr_of_bobs,d7
subq.l   #1,d7

move.l  ScrollOffset,d5
WaitForBlitter
move.w  #0000,\$062(a5)  ; BLTBMOD
move.w  #0028,\$060(a5)  ; BLTCMOD
move.w  #0000,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD
;------------------------------------------------------------------------------
BobbyLoop:
;------------------------------------------------------------------------------
cmp.w   #0,4(a1)        ; Jos "Pois päältä" -merkki on päällä,
bne.s   Cont            ; mennään seuraavaan bobbiin
add.l   #4+4+2,a6       ; Seuraava vanhasijainti stuff
dbf     d7,BobbyLoop
rts
Cont:   move.l  Coords,a0       ; Täällä on koordinaatit
cmp.w   #999,(a0)       ; Jos A0:ssa on loppumerkki, niin
bne.s   GoMan           ; pistetään "pois päältä"-merkki päälle
move.w  #0,4(a1)

;        subq.l  #4,(a1)+        ; Pointteri pois 999:n kohdalta
;        move.w  #0,(a1)+        ; "Pois päältä" -merkki päälle
;        move.l  #0,(a6)+
subq.b  #1,AmEnemies
dbf     d7,BobbyLoop
rts

GoMan:  moveq    #0,d1
addq.l  #4,(a1)         ; Pointteri seuraaviin koordinaatteihin
move.w  (a0)+,d0        ; x
move.w  (a0),d1         ; y
move.l  8(a1),a2
move.l  12(a1),a3

bsr     PutBob

add.l   #16,a1          ; Mennään seuraavan bobin tietojen kohdalle
dbf     d7,BobbyLoop
rts

;------------------------------------------------------------------------------
; Blitataan 16 x 16 pixelin bob.
; D5:ssä on oltava ScrollOffsett ja A6:ssa pointteri rakenteeseen, missä on
; LONG, LONG, WORD, mitkä tarkoittavat ClearScreen sijainti, vanha sijainti ja
; BLTSIZE. Modulorekisterit asetettava alussa.
;------------------------------------------------------------------------------

PutBob  move.w  #4098,d6        ; BLTSIZE

;------------------------------------------------------------------------------
asl.w   #2,d1             ; 4 bittitasoa
cmp.w   #256*4,d1
bge.w   ExitPutBob

cmp.w   #-16*4,d1       ; -(Bobin korkeus)
ble.w   ExitPutBob

cmp.w   #(255-16)*4,d1  ; Alalaita
ble.s   NextTest
move.w  #256*4,d6       ; Screenin lainien määrä (eli korkeus)
sub.w   d1,d6           ; Kuinka monta pixelia näkyvissä
addq.w  #2,d6           ; X lisätään suoraan tässä versiossa..
NextTest
cmp.w   #0,d1           ; Ylälaita (käsitellään negatiiviset
moveq   #0,d6
move.w  #16*4,d6        ; Bobin korkeus (siis y-pituus)
add.w   d1,d6           ; Nyt d6:ssa bobin korkeus!
add.w   #2,d6           ; X lisätään suoraan tässä versiossa..
neg.w   d1              ; Lasketaan kohta, mistä bobbi-dataa
GMan    lsl.w   #2,d1           ; aletaan blittaamaan
moveq   #0,d1           ; Y-koordinaatti on tietysti nolla..
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
lsl.w   #5,d1
moveq   #0,d2
move.b  d0,d2
lsr.w   #3,d0
ext.l   d0
and.w   #\$000f,d2
mulu    #\$1000,d2
move.l  DrawScreen,a4
move.l  ClearScreen,a0
move.l  a0,(a6)         ; Vastaava paikka ClearScreenissä
move.l  a4,4(a6)        ; Vanha Sijainti
move.w  d6,8(a6)        ; Talletetaan BLTSIZE

WaitForBlitter
move.w  d2,\$042(a5)     ; BLTCON1
or.w    #\$0fce,d2       ; ynnätään minterm+use shift valueen
move.w  d2,\$040(a5)     ; BLTCON0
move.l  a4,\$048(a5)     ; BLTCPTR kohde
move.l  a2,\$04c(a5)     ; BLTBPTR bob-data
move.l  a4,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE
ExitPutBob
rts

;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
HandleEBullets:
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
NewEBullets:
;------------------------------------------------------------------------------
cmp.b   #AmountEBullets+1,MovingEBullets
bge.s   MoveEBullets
moveq   #0,d5
move.w  #AmountEBullets,d7
moveq    #0,d6
move.b  nr_of_bobs,d6
subq.l   #1,d6

lea     PTRsAndONOFF,a0 ; Enemyiden koordinaatit ja ON/OFF
lea     EnemyLaakit,a2  ; x,y
HEBSil: cmp.w   #0,4(a0)        ; Onko enmy kehissä? Jos ei, niin seuraava
beq.s   NextE
Hee:    cmp.w   #-1,(a2)        ; Onko laaki jo liikkeellä? (-1=EI , >-1=ON)
beq.s   Ok
dbf     d7,Hee
bra.s   MoveEBullets
Ok:     move.w  \$6(a5),d0       ; Katsotaan "satunnaisluvun" perusteella
add.w   Random,d0       ; pistetäänkö sittenkään laakia kehiin
and.w   #%0000000000000111,d0
cmp.w   #7,d0
bne.s   NextE
move.l  Coords,a1
move.l  (a0),d0         ; Kas näin se bugi-laaki eliminoidaan!!
subq.l  #4,d0           ; ..näin..
;        move.w  (a1)+,(a2)+     ; Enemyn x laakin alku-x:ksi
;        move.w  (a1),(a2)+      ; Enemyn y laakin alku-y:ksi
moveq   #0,d5             ; Jos y-koordinaatti
subq.l   #1,d5

cmp.l   #-1,d5
beq.s    dsil

;        add.l    d5,a2                 ; Nyt numerot alkavat oikeasta kohdasta
nolla     move.b      #0,(a2)+
dbf         d5,nolla
subq.l   #1,d7                    ; DBF-käskyn vuoksi

dsil  move.l   d0,d1              ; Working copy of D0

moveq    #1,d3                ; Määritetään 10 potensiin
move.l   d7,d2                ; digitin järjestysnumero - 1
potsil  subq.l   #1,d2              ;
cmp.l    #-1,d2               ;
ble.s    Jatka              ;
mulu.w   #10,d3             ;
bra.s    potsil             ;

Jatka   move.l   d3,d2              ; Jaetaan muutettava luku
divu.w   d2,d1              ; yllä määritetyllä luvulla
and.l    #\$0000ffff,d1      ; Nollataan jakojäännös
divu.w   #10,d1             ; Jaetaan vielä 10:llä
swap     d1                 ; Otetaan jakojäännös ja nollataan
and.l    #\$0000ffff,d1      ; muu osa luvusta; jäljellä on
; on haettu digit!
move.b   d1,(a2)+           ; ja kirjoitetaan digit talteen
dbf      d7,dsil

; Tulostetaan Number "muuttujassa" oleva numerosarja

Blit    lea     Number,a1
moveq   #5-1,d7

move.l  #192,d5             ; x-koordinaatti

WaitForBlitter
move.w  #0000,\$062(a5)  ; BLTBMOD
move.w  #0028,\$060(a5)  ; BLTCMOD
move.w  #0000,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD

BNSil   lea      Numbers,a2

moveq   #0,d4
move.b  (a1)+,d4
lsl.l   #7,d4
move.l  d5,d0
moveq   #13,d1              ; y-koordinaatti
lsl.l   #2,d1               ; 4 bittitasoa
bsr     BlitNumber

dbf     d7,BNSil
ExitBlitNumbers
rts

;------------------------------------------------------------------------------
; Tulostetaan numero
;------------------------------------------------------------------------------
BlitNumber
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
lsl.l   #5,d1
move.b  d0,d2
lsr.l   #3,d0
ext.l   d0
and.l   #\$000f,d2
mulu    #\$1000,d2
move.l  DrawScreen,a4

WaitForBlitter
move.w  d2,\$042(a5)     ; BLTCON1
or.w    #\$0fce,d2       ; ynnätään minterm+use shift valueen
move.w  d2,\$040(a5)     ; BLTCON0
move.l  a4,\$048(a5)     ; BLTCPTR kohde
move.l  a2,\$04c(a5)     ; BLTBPTR bob-data
move.l  a4,\$054(a5)     ; BLTDPTR kohde
move.w  #2050,\$058(a5)  ; BLTSIZE

rts

;------------------------------------------------------------------------------
; Palautetaan räjähdysten tausta
;------------------------------------------------------------------------------
PalautaExpTausta
move.l  VanhaExpSij,a1
moveq   #20-1,d7

WaitForBlitter
move.w  #\$09f0,\$040(a5) ; BLTCON0
move.w  #\$0000,\$042(a5) ; BLTCON0
move.w  #0028,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD
Pal
cmp.l   #0,(a1)
bne.s   Palauta
dbf     d7,Pal
rts
Palauta WaitForBlitter
move.l  (a1)+,\$050(a5)  ; BLTAPTR
move.l  (a1)+,\$054(a5)  ; BLTDPTR kohde
move.w  (a1)+,\$058(a5)  ; BLTSIZE
move.l  #0,-10(a1)
dbf     d7,Pal
rts

;------------------------------------------------------------------------------
; Hoidellaan räjähdykset
;------------------------------------------------------------------------------
HandleExplosions

lea     Explosions,a1
moveq   #20-1,d7
move.l  ScrollOffset,d5
move.l  VanhaExpSij,a6

WaitForBlitter
move.w  #0000,\$062(a5)  ; BLTBMOD
move.w  #0028,\$060(a5)  ; BLTCMOD
move.w  #0000,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD

ExpSil  cmp.w   #0,(a1)             ; Onko kehissä
beq.s    NextExp
move.l  #Explosion,a2
moveq   #0,d0
moveq   #0,d1
move.w  2(a1),d0
move.w  4(a1),d1
cmp.b   #1,MonsterKehissa
beq.s   blit
cmp.w   #256,4(a1)
blt.s   blit
move.w  #0,(a1)
bra.s   NextExp
blit    bsr     PutBob

cmp.w   #0,6(a1)            ; Onko viive nolla
beq.s   NextExpFrame        ; Jos on, niin mennään seuraavaan frameen
subq.w  #1,6(a1)            ; Jos ei ollut, niin vähennetään viivettä
bra.s   NextExp

NextExpFrame
move.w  #4,6(a1)            ; Laitetaan viive ennalleen
cmp.l   #256*8,8(a1)        ; Ollaanko käyty kaikissa?
bne.s   NextExp             ; Jos ei olla, niin mennään seuraavaan
move.l  #0,8(a1)            ; Jos oltiin, niin nollataan framepointteri
move.w  #0,(a1)             ; ja laitetaan pois kehistä-merkki

dbf     d7,ExpSil
exithe  rts

;------------------------------------------------------------------------------
; Katsotaan, onko monsteri liikkeellä
;------------------------------------------------------------------------------
CheckMonster
cmp.b   #1,MonsterKehissa
beq.s   HandleMonster
rts

;------------------------------------------------------------------------------
; Käsitellään monsteri
;------------------------------------------------------------------------------
HandleMonster
lea     Monster,a1
cmp.w   #32,2(a1)
bge.s   LiikutaHorisontaalisesti
moveq   #0,d0
moveq   #0,d1
moveq   #0,d2
move.w  (a1),d0
move.w  2(a1),d1
bsr     PyyhiMonster

moveq   #0,d0
moveq   #0,d1
lea     Monster,a1
move.w  (a1),d0
move.w  2(a1),d1

move.l  60(a1),a2          ; Bob-data
move.l  MonsterVanhaSij,a6

bsr     BlitMonster
bsr     CheckMColl
rts

LiikutaHorisontaalisesti
cmp.b   #1,Monster_destroyed
beq.s   ME
move.w  DX,d0
cmp.w   #96,(a1)
bne.s   Tst
neg.w   DX
Tst       cmp.w   #0,(a1)
bne.s   Blittaa
neg.w   DX
Blittaa
bsr     PyyhiMonster
moveq   #0,d0
moveq   #0,d1

bsr     AmpuukoMonster
bsr     HandleMonsterBullet

moveq   #0,d0
moveq   #0,d1
lea     Monster,a1
move.w  (a1),d0
move.w  2(a1),d1
move.l  60(a1),a2
move.l  64(a1),a3
move.l  MonsterVanhaSij,a6

bsr     BlitMonster

ME        lea        Monster_explosion,a0
;         cmp.w   #0,(a0)
;         beq.s   CheckMColl
cmp.b   #0,Monster_destroyed
beq.s   CheckMColl
bsr     HandleMonstExplosion

CheckMColl
lea     Monster,a1
bsr     MCollisions
rts

;------------------------------------------------------------------------------
; Hoidellaan hirviön räjähdys
;------------------------------------------------------------------------------
HandleMonstExplosion
cmp.b   #3,MExpFinished                   ; Peli on pelattu, kun MExpFinished = 3
beq.s   NextLevel

cmp.b   #1,MExpFinished
bne.s   jatkuu
bsr        PM                             ; Huom!
bsr     PyyhiMonstExplosion
subq.b  #1,LastMExpFrames
cmp.b   #0,LastMExpFrames
bne.s   erteees
move.b  #3,MExpFinished
rts

jatkuu  ;bsr      PM
bsr     PyyhiMonstExplosion
bsr     PyyhiMonster
bsr     HandleMonsterBullet
move.l  #Monster,a1
bsr     MCollisions
move.l  #Monster_explosion,a0
moveq   #0,d0
moveq   #0,d1
move.w  2(a0),d0
move.w  4(a0),d1

subq.w  #1,6(a0)              ; Vähennetään viivettä yhdellä
cmp.w   #0,6(a0)
bgt.s   MonstExp
move.w  #4,6(a0)              ; Viive
cmp.l   #3840*2,8(a0)
bne.s   MonstExp
move.l  #0,8(a0)              ; Mennään räjähdysframen alkuun
cmp.b   #9,kierros
bne.s  MonstExp

move.b  #1,MExpFinished
move.b  #3,LastMExpFrames ; 3
move.l  #0,8(a0)
rts

NextLevel
cmp.b   #3,level
beq     putlevel3
cmp.b   #4,level
beq.s   erteees

move.l  #Coolfield2,coolfield
bsr     Alustus
bsr     FillTheScreen
erteees rts
putlevel3
move.l  #Coolfield3,coolfield
bsr     Alustus
bsr     FillTheScreen
rts

MonstExp
move.l  8(a0),d4
move.l  #MonsterExplosionBob,a2
move.l  MExp_vanhasij,a6
bsr     BlitMonster

rts

HandleMonsterBullet
moveq   #3-1,d7
lea     Monster,a1
move.l  ScrollOffset,d5
move.l  MonstBVanhaSij,a6

WaitForBlitter
move.w  #0000,\$062(a5)  ; BLTBMOD
move.w  #0028,\$060(a5)  ; BLTCMOD
move.w  #0000,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD

HMBSil    cmp.w   #0,(a1)
beq.s   NextMonsterBullet

move.l  2(a1),d0              ; Bullet X
move.l  6(a1),d1              ; Bullet Y
lsr.l   #7,d0
lsr.l   #7,d1

;         move.l  #MonsterBullet,a2

bsr     BlitBullet            ; Tulostetaan monsterin laaki

move.l  10(a1),d0
move.l  14(a1),d1

move.l  2(a1),d0
move.l  6(a1),d1
asr.l   #7,d0
asr.l   #7,d1

; Katsotaan pysyykö laaki rajoissa

cmp.w   #256+4,d1
blt.s   ookoo
move.w  #0,(a1)
bra.s   NextMonsterBullet
ookoo     cmp.w   #0,d0
bge.s   AllRight
move.w  #0,(a1)
bra.s   NextMonsterBullet
AllRight
cmp.w   #255-4,d0
blt.s   NextMonsterBullet
move.w  #0,(a1)

NextMonsterBullet

dbf     d7,HMBSil
rts

AmpuukoMonster
cmp.b  #1,Monster_destroyed
beq.s  xit
moveq  #3-1,d7
moveq  #0,d0
moveq  #0,d1
move.w (a1),d0
move.w 2(a1),d1
move.l d0,d4                  ; Monsterin X
move.l d1,d5                  ; Monsterin Y

AMPSil    cmp.w  #0,(a1)                ; Onko laaki vapaa?
beq.s  Ampuuko                ; Jos on, niin arvotaan, ammutaanko
dbf    d7,AMPSil
xit       rts

Ampuuko   move.w \$6(a5),d0
and.l  #7,d0
cmp.w  #7,d0
beq.s  MAmpuu
dbf    d7,AMPSil
rts

MAmpuu
move.w #1,(a1)
moveq  #0,d2
moveq  #0,d3
move.w x,d2                   ; Pelaajan X
move.w y,d3                   ; Pelaajan Y

move.l d4,d0                  ; Otetaan monsterin X ja Y
move.l d5,d1                  ; tallesta

lsl.l  #7,d2
lsl.l  #7,d3
lsr.l  #6,d2
lsr.l  #6,d3

lsl.l  #7,d0
lsl.l  #7,d1

move.l d0,2(a1)               ; Talletetaan bullet X
move.l d1,6(a1)               ; Talletataan bullet Y
dbf    d7,AMPSil
ExitAmpuuko
rts

MCollisions
; Ovatko pelaajan laakit osuneet monsteriin

lea   Monster_explosion,a0    ; Jos monsteri räjähtänyt,
cmp.w #1,(a0)                 ; niin ei tsekata törmäyksiä
beq.s OMLOP

lea    Laakit,a0
lea    Monster,a4
moveq  #AmountBullets,d7

MCSil     cmp.w  #1,(a0)
beq.s  OnkoOsunut
dbf    d7,MCSil
bra.s  OMLOP
OnkoOsunut
move.w 2(a0),d0               ; Laakin X
move.w 4(a0),d1               ; Laakin Y

sub.w  (a1),d0

cmp.w  #0,d0
blt.s  Seur
cmp.w  #144,d0                ; 192
bge.s  Seur
sub.w  2(a1),d1

cmp.w  #48,d1             ; 64
bgt.s  Seur
cmp.w  #0,d1
blt.s  Seur
;         move.w #\$fff,\$1a4(a5)
move.w #0,(a0)
subq.w #1,4(a4)               ; Vähennetään monsterin kestävyyttä
addq.w #5,Pisteet         ; Lisätään pelaajan pisteitä
cmp.w  #0,4(a4)               ; Onko tuhoutunut?
bne.s Seur
move.b #1,Monster_destroyed
lea    Monster_explosion,a2
move.w #1,(a2)
move.w (a4),2(a2)
move.w 2(a4),4(a2)

dbf    d7,MCSil

; Onko monsterin laakit osuuneet pelaajaan

OMLOP    lea     Monster,a1
moveq   #3-1,d7

OMLOPSil
cmp.w   #0,(a1)                ; Onko laaki liikkeellä?
beq.s   nextbullet

moveq   #0,d0
moveq   #0,d1
move.w  x,d0
move.w  y,d1
move.l  2(a1),d2               ; Monst bullet X
move.l  6(a1),d3               ; Monst bullet Y
asr.l   #7,d2
asr.l   #7,d3

sub.w   d0,d2

cmp.w   #-3,d2
blt.s   nextbullet
cmp.w   #14,d2
bge.s   nextbullet

sub.w   d1,d3

cmp.w   #-3,d3
blt.s   nextbullet
cmp.w   #14,d3
blt.s   nextbullet
move.w  #\$fff,\$1a4(a5)
subq.b #1,energia

nextbullet
dbf     d7,OMLOPSil

rts

;------------------------------------------------------------------------------
; Piirretään monsteri
;------------------------------------------------------------------------------
BlitMonster
move.l  #12298,d6
asl.w   #2,d1             ; 4 bittitasoa
cmp.w   #-4*48,d1
ble.s   ExitBM

cmp.w   #0,d1           ; Ylälaita (käsitellään negatiiviset
bge.s   Valmis             ; koordinaatit)
moveq  #0,d6
move.w  #4*48,d6        ; Bobin korkeus (siis y-pituus)
add.w   d1,d6           ; Nyt d6:ssa bobin korkeus!
add.w   #10,d6          ; X lisätään suoraan tässä versiossa..
neg.w   d1              ; Lasketaan kohta, mistä bobbi-dataa
mulu    #20,d1              ; aletaan blittaamaan.
moveq   #0,d1           ; Y-koordinaatti on tietysti nolla..

Valmis  moveq    #0,d2

lsl.l   #5,d1
move.b  d0,d2
lsr.l   #3,d0
ext.l   d0
and.l   #\$000f,d2
mulu    #\$1000,d2
move.l  DrawScreen,a4
move.l  ClearScreen,a0
move.l  a0,(a6)+
move.l  a4,(a6)+
move.w  d6,(a6)+

WaitForBlitter
move.w  #0000,\$062(a5)  ; BLTBMOD
move.w  #0012,\$060(a5)  ; BLTCMOD
move.w  #0000,\$064(a5)  ; BLTAMOD
move.w  #0012,\$066(a5)  ; BLTDMOD

move.w  d2,\$042(a5)     ; BLTCON1
or.w    #\$0fce,d2       ; ynnätään minterm+use shift valueen
move.w  d2,\$040(a5)     ; BLTCON0
move.l  a4,\$048(a5)     ; BLTCPTR kohde
move.l  a2,\$04c(a5)     ; BLTBPTR bob-data
move.l  a4,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE
ExitBM
rts

PyyhiMonstExplosion
move.l  MExp_vanhasij,a6
cmp.l   #0,(a6)
beq.s   ExitPME

WaitForBlitter
move.w  #\$9f0,\$040(a5)  ; BLTCON0
move.w  #\$0000,\$042(a5) ; BLTCON0
move.w  #0012,\$064(a5)  ; BLTAMOD
move.w  #0012,\$066(a5)  ; BLTDMOD

move.l  (a6)+,\$050(a5)  ; BLTAPTR
move.l  (a6)+,\$054(a5)  ; BLTDPTR kohde
move.w  (a6)+,\$058(a5)  ; BLTSIZE

ExitPME rts

PyyhiMonster
; Pyyhitään ensin mahdollinen monsterin bullet
move.l  MonstBVanhaSij,a4
moveq   #3-1,d7

PML     cmp.l   #0,(a4)
beq.s   NextMonstBullet

WaitForBlitter
move.w  #\$9f0,\$040(a5)  ; BLTCON0
move.w  #0000,\$042(a5)  ; BLTCON0
move.w  #0028,\$064(a5)  ; BLTAMOD
move.w  #0028,\$066(a5)  ; BLTDMOD
move.l  (a4)+,\$050(a5)  ; BLTAPTR
move.l  (a4)+,\$054(a5)  ; BLTDPTR
move.w  (a4)+,\$058(a5)  ; BLTSIZE
dbf     d7,PML
bra.s   PM
NextMonstBullet
dbf     d7,PML

PM      move.l  MonsterVanhaSij,a4
cmp.l   #0,(a4)
beq.s   ExitPM

WaitForBlitter
move.w  #\$9f0,\$040(a5)  ; BLTCON0
move.w  #\$000,\$042(a5)  ; BLTCON0
move.w  #0012,\$064(a5)  ; BLTAMOD
move.w  #0012,\$066(a5)  ; BLTDMOD

move.l  (a4)+,\$050(a5)  ; BLTAPTR
move.l  (a4)+,\$054(a5)  ; BLTDPTR kohde
move.w  (a4)+,\$058(a5)  ; BLTSIZE
ExitPM  rts

;------------------------------------------------------------------------------
;
;------------------------------------------------------------------------------
GameOver
move.l      #Dummy,d0           ; Spritet pois päältä
move.w      d0,s0_low
swap        d0
move.w      d0,s0_high

move.w      d0,s1_low
swap        d0
move.w      d0,s1_high

move.w      d0,s2_low
swap        d0
move.w      d0,s2_high

move.b      #0,gameOver
move.b      #0,letterstyped

move.b   #1,level
move.l   #Coolfield,coolfield
;           move.w   #0,Pisteet

move.l   #0,\$180(a5)

bsr     pyyhi_bitmap

move.l  bitmap,d1
move.w  d1,low1
swap     d1
move.w   d1,high1
swap     d1
move.w   d1,low2
swap     d1
move.w   d1,high2
swap     d1
move.w   d1,low3
swap     d1
move.w   d1,high3
swap     d1
move.w   d1,low4
swap     d1
move.w   d1,high4

lea     gameover,a2
move.l  bitmap,a1
bsr     TulostaTeksti

moveq    #5-1,d7
lea      hiscoretable,a1
vertailu    move.w   4(a1),d1
cmp.w    Pisteet,d1
blt.s    typeinname
dbf     d7,vertailu

bra.s    waitforjoybutton
typeinname

move.l  bitmap,a1
lea     usejoy,a2
bsr     TulostaTeksti

move.l  bitmap,a1
lea     type,a2
bsr     TulostaTeksti

move.l   bitmap,a1
move.b  #1,NPohjassa
bsr     PrintLetter

gosil       bsr     JoystickForLetters
bsr     WaitForBeam

cmp.b   #3,letterstyped
beq.s   JumpToAlkuScreen

btst    #6,\$bfe001
beq     CleanUp

bra.s   gosil

;          bra.s    JumpToAlkuScreen

waitforjoybutton
lea     pressjoy,a2
move.l  bitmap,a1
bsr     TulostaTeksti

loop        btst    #6,\$bfe001
beq     CleanUp

bsr     WaitForBeam
cmp.b   #1,NPohjassa
bne.s   checkjoybutton
move.b  #0,NPohjassa
bra.s   loop

checkjoybutton
btst    #7,\$bfe001      ; Katsotaanko painetaanko joikkiksen nappia
bne.s   loop
move.b  #1,NPohjassa
bra     JumpToAlkuScreen

;------------------------------------------------------------------------------
;
;------------------------------------------------------------------------------
LoppuScreen
move.l   #Dummy,d0
move.w   d0,s0_low
swap     d0
move.w   d0,s0_high

move.w   d0,s1_low
swap     d0
move.w   d0,s1_high

move.w   d0,s2_low
swap     d0
move.w   d0,s2_high

bsr      WaitForBeam
bsr      pyyhi_bitmap

move.l   bitmap,d1
move.w   d1,low1
swap     d1
move.w   d1,high1
swap     d1
move.w   d1,low2
swap     d1
move.w   d1,high2
swap     d1
move.w   d1,low3
swap     d1
move.w   d1,high3
swap     d1
move.w   d1,low4
swap     d1
move.w   d1,high4

move.w  #0,\$180(a5)

lea     udidit,a2
move.l  bitmap,a1
bsr     TulostaTeksti

checkbut    btst    #6,\$bfe001
beq     CleanUp

btst    #7,\$bfe001      ; Katsotaanko painetaanko joikkiksen nappia
bne.s   exitcbut
cmp.b   #1,NPohjassa
bne.s   eio
bra.s   checkbut
eio         bra     GameOver
exitcbut    cmp.b   #1,NPohjassa
bne.s   eiole
move.b  #0,NPohjassa
eiole       bra.s   checkbut

;------------------------------------------------------------------------------
; Level-Screen. Tämä tulostuu ennen alkavaa tasoa. Tänne hypätään alustuksesta.
;------------------------------------------------------------------------------
LevelScreen
move.l  #Dummy,d0
move.w  d0,s0_low
swap    d0
move.w  d0,s0_high

move.w  d0,s1_low
swap    d0
move.w  d0,s1_high

move.w  d0,s2_low
swap    d0
move.w  d0,s2_high

bsr     pyyhi_bitmap

move.l  bitmap,d1
move.w   d1,low1
swap     d1
move.w   d1,high1
swap     d1
move.w   d1,low2
swap     d1
move.w   d1,high2
swap     d1
move.w   d1,low3
swap     d1
move.w   d1,high3
swap     d1
move.w   d1,low4
swap     d1
move.w   d1,high4

moveq    #0,d0
move.b   level,d0

lea      LevelTXT,a2
move.b   d0,7(a2)

move.l   bitmap,a1
bsr      TulostaTeksti

move.l   #150,d7
Wait        bsr      WaitForBeam
dbf      d7,Wait

rts

;------------------------------------------------------------------------------
; Alkuscreen-rutiineita
;------------------------------------------------------------------------------
AlkuScreen

move.w   #0,Pisteet

bsr      pyyhi_bitmap

move.l   bitmap,d1
move.w   d1,low1
swap     d1
move.w   d1,high1
swap     d1
move.w   d1,low2
swap     d1
move.w   d1,high2
swap     d1
move.w   d1,low3
swap     d1
move.w   d1,high3
swap     d1
move.w   d1,low4
swap     d1
move.w   d1,high4

move.w   #\$0,\$180(a5)

bsr      WaitForBeam

lea      xwars,a2
move.l   bitmap,a1
bsr      TulostaTeksti

move.b   #1,small_font
lea      press,a2
move.l   bitmap,a1
bsr      TulostaTeksti

lea      leftmouse,a2
move.l   bitmap,a1
bsr      TulostaTeksti

lea      codingby,a2
move.l   bitmap,a1
bsr      TulostaTeksti

lea      musicby,a2
move.l   bitmap,a1
bsr      TulostaTeksti

move.b   #0,small_font
bsr      PrintHiScoreList

AlkuMP      btst     #6,\$bfe001
beq      CleanUp

bsr      WaitForBeam
checkbutton
btst     #7,\$bfe001      ; Katsotaanko painetaanko joikkiksen nappia
bne.s    exitcb
cmp.b    #1,NPohjassa
bne.s    eioo
bra.s    AlkuMP
eioo        bra      JumpToAlustus
exitcb      cmp.b    #1,NPohjassa
bne.s    eij
move.b   #0,NPohjassa
eij         bra.s    AlkuMP

;------------------------------------------------------------------------------
; Pyyhitään bitmap
;------------------------------------------------------------------------------
pyyhi_bitmap
move.l   #4*2048-1,d7
move.l   bitmap,a1
pyyhi       move.l   #0,(a1)+
dbf      d7,pyyhi
rts

;------------------------------------------------------------------------------
; Tulostetaan tekstiä kunnes törmätään nollaan
;------------------------------------------------------------------------------
TulostaTeksti
lea         Fontti,a0

moveq       #0,d0
move.b      (a2)+,d0
cmp.b       #0,d0
beq.s       ExitPrintLetter
sub.b       #'0',d0
lsl.l       #6,d0

cmp.b       #1,small_font
beq.s       printsmallletter

moveq       #64-1,d7                    ; 64 - 1
lettersil
move.b      (a0)+,(a1)
dbf         d7,lettersil
sub.l       #2048,a1                    ; 1024
bra.s       TulostaTeksti

ExitPrintLetter
rts

printsmallletter
move.l      #4*8-1,d7
smalllettersil
move.b      (a0)+,(a1)
dbf         d7,smalllettersil
sub.l       #1024,a1
bra.s       TulostaTeksti

;------------------------------------------------------------------------------
; Tulostetaan yksi merkki fontista.
; A0:ssa osoitin fonttiin. A1:ssä osoitin kohteeseen.
;------------------------------------------------------------------------------
PrintLetter
lea          Fontti+17*64,a0

moveq       #64-1,d7
letsil
move.b      (a0)+,(a1)
dbf         d7,letsil
sub.l       #2048,a1                    ; 1024

; Kirjoitetaan merkki myös merkki-bufferiin

merkkibufferiin

lea         Nimi,a2
moveq       #0,d0
move.b      letterstyped,d0
move.b      currentchar,(a2)

rts

;------------------------------------------------------------------------------
; Tulostetaan HiScore-lista
;------------------------------------------------------------------------------
PrintHiScoreList

move.l      bitmap,a1

lea         hiscoretable,a4
moveq       #5-1,d6
hiscoresil
move.l      (a4)+,a2
bsr         TulostaTeksti
moveq       #0,d0
move.w      (a4)+,d0
addq.l      #1,a1                   ; 1 välilyönti nimien jälkeen
lea         Luku,a2
bsr         ConvertToASCII
lea         Luku,a2
bsr         TulostaTeksti
sub.l       #9,a1
dbf         d6,hiscoresil
rts

;------------------------------------------------------------------------------
JoystickForLetters
; A0:ssa on fontin osoite
;------------------------------------------------------------------------------
move.w      \$c(a5),d6       ; Joikkis rekisteri

cmp.b     #0,viive
beq.s     oikealle
subq.b    #1,viive
bra.s     JNappi
oikealle
btst        #1,d6           ; Ohjataanko oikealle?
beq.s       vasemmalle      ; Jos ei niin ...

move.b      #10,viive

cmp.b       #'[',currentchar
blt.s       pri
move.b      #'Z',currentchar
sub.l       #64,pt_Font

pri     bsr         PrintLetter
bra.s       JNappi

vasemmalle
btst        #9,d6            ; Ohjataanko vasemalle?
beq.s       JNappi           ; Jos ei niin ...

move.b      #10,viive

sub.l       #64,pt_Font
subq.b      #1,currentchar
cmp.b       #'@',currentchar
bgt.s       prin
move.b      #'A',currentchar

prin    bsr      PrintLetter

beq.s   TestN
rts
TestN   btst    #7,\$bfe001      ; Katsotaanko painetaanko joikkiksen nappia
bne.s   ExtJoystick    ;
cmp.b   #1,NPohjassa
bne.s   EiO
rts
EiO     move.b  #1,NPohjassa
bsr      PrintLetter
cmp.b    #3,letterstyped    ; Nollas on ensimmäinen kirjain
bne.s    ei

bsr      NewEntry
;         bsr        PrintHiScoreList
rts

ExtJoystick
cmp.b   #1,NPohjassa
bne.s   ei
move.b  #0,NPohjassa
ei      rts

NewEntry
moveq    #5-1,d7
lea     hiscoretable,a1
nesil   moveq   #0,d0
move.w  4(a1),d0
cmp.w   Pisteet,d0          ; Jos tietuessa oleva arvo on pienempi, on
blt.s   yeah                    ; Pisteet suurempi...
dbf     d7,nesil
rts
yeah    lea     hiscoretable,a4
subq.l  #1,d7
cmp.l   #-1,d7              ; Jos kyseessä alimmainen, niin vain
beq.s   JustPutNewEntry ; laitetaan entry...
move.l  d7,d6
mulu    #6,d6

; Siirretään listaa yhdellä pykälällä alaspäin

;       moveq       #4-1,d7
sil moveq    #4-1,d5
move.l  (a4),a1
move.l  6(a4),a2
move.l  (a2),a2
csil    move.b   (a1)+,(a2)+
dbf     d5,csil

move.w  4(a4),10(a4)
subq.l  #6,a4
dbf     d7,sil

move.l  a4,a1
move.l  (a4),a4
lea     Nimi,a3
moveq   #4-1,d7
nimisil
move.b  (a3)+,(a4)+
dbf     d7,nimisil

move.w  Pisteet,4(a1)
rts

JustPutNewEntry

move.l  a4,a1
move.l  (a4),a4
lea     Nimi,a3
moveq   #4-1,d7
anothernimisil
move.b  (a3)+,(a4)+
dbf     d7,anothernimisil
move.w  Pisteet,4(a1)
rts

;------------------------------------------------------------------------------
; Muutetaan kokonaisluku ASCII:ksi
;------------------------------------------------------------------------------
ConvertToASCII
; Muutettava luku D0:aan, tulos tulee A2:een.

moveq    #0,d2

move.l   d0,d1              ; Lasketaan digittien määrä
nrdigits
divu.w   #10,d1
and.l    #\$0000ffff,d1
cmp.w    #0,d1
bgt.s    nrdigits
move.l   d2,d7              ; Digittien määrä-1 D7:ään

moveq    #5,d5                  ; Hoidellaan eteen tarpeellinen
sub.l    d7,d5                  ; määrä nollia -->
subq.l   #1,d5
cmp.l    #0,d5
blt.s    skipnolla
zerosil
move.b    #'0',(a2)+
dbf       d5,zerosil
;        add.l    d5,a2                 ; Nyt numerot alkavat oikeasta kohdasta

skipnolla

subq.l   #1,d7                  ; DBF-käskyn vuoksi

digitsil
move.l   d0,d1              ; Working copy of D0

moveq    #1,d3                  ; Määritetään 10 potensiin
move.l   d7,d2                  ; digitin järjestysnumero - 1
posil   subq.l   #1,d2              ;
cmp.l    #-1,d2                 ;
ble.s    Jaa                ;
mulu.w   #10,d3             ;
bra.s    posil              ;

Jaa     move.l   d3,d2              ; Jaetaan muutettava luku
divu.w   d2,d1              ; yllä määritetyllä luvulla
and.l    #\$0000ffff,d1      ; Nollataan jakojäännös
divu.w   #10,d1             ; Jaetaan vielä 10:llä
swap     d1                 ; Otetaan jakojäännös ja nollataan
and.l    #\$0000ffff,d1      ; muu osa luvusta; jäljellä on
add.b    #'0',d1            ; on haettu digit!
move.b   d1,(a2)+           ; ja kirjoitetaan digit talteen
move.b   #0,(a2)
dbf      d7,digitsil
rts

;------------------------------------------------------------------------------
FillTheScreen:
; Fillataan 16*17 suuruinen alue blo(c)keisssa(16*16,what else?)
; (..ja tietysti kaikkissa (3) screeneissä!!)

move.l  #(256+16)*4*32,d1
move.l  BitMap1,a1
move.l  BitMap2,a2
move.l  ClearScreen,a3
move.l  coolfield,a6
;        lea     Coolfield,a6
move.w  #16/16+(16*4*64),d6
WaitForBlitter
move.w  #\$09f0,\$040(a5) ; BLTCON0
move.w  #\$0000,\$042(a5) ; BLTCON0
move.w  #0038,\$064(a5)  ; BLTAMOD
move.w  #0030,\$066(a5)  ; BLTDMOD

moveq   #17-1,d7
YSil:   moveq   #16-1,d5
XSil:   WaitForBlitter
move.l  (a6),\$050(a5)   ; BLTAPTR source
move.l  a1,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE 16*(16*4)

WaitForBlitter
move.l  (a6),\$050(a5)   ; BLTAPTR source
move.l  a2,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE 16*(16*4)

WaitForBlitter
move.l  (a6)+,\$050(a5)  ; BLTAPTR source
move.l  a3,\$054(a5)     ; BLTDPTR kohde
move.w  d6,\$058(a5)     ; BLTSIZE 16*(16*4)
dbf     d5,XSil
dbf     d7,YSil
rts

WaitForBeam
cmp.b   #\$ff,\$006(a5)
bne.s   WaitForBeam
WFBeam
cmp.b   #\$2c,\$006(a5)
bne.s   WFBeam
rts

RMB     btst    #10,\$016(a5)
beq.s    changecol
rts
changecol
move.w  #\$333,\$180(a5)
rts

;------------------------------------------------------------------------------
; Asetetaan tarvittavt alkuarvot, jotta uusi peli voi alkaa
;------------------------------------------------------------------------------
Alustus
bsr     LevelScreen     ; Tulostetaan tason numero

move.l  #(256+16+16)*4*32,ScrollOffset
;       move.w  #0,Pisteet
move.l  #256,LineN      ; Blo(c)kin y-paikka
move.l  #0,Bl_paikka   ; Blo(c)kin x-paikka
move.l  #0,pt_toCoolF
move.l  #0,pt_toClear
move.b  #0,Frame            ; Scrollaukseen liittyvä
move.b  #0,LameFrame
;
move.b   #16,energia

lea     Explosions,a0
lea     ExpVanhaSij0,a1
lea     ExpVanhaSij1,a4

moveq   #20-1,d7
Exps    move.w  #0,(a0)+        ; Kehissä
move.w  #0,(a0)+        ; x
move.w  #0,(a0)+        ; y
move.w  #4,(a0)+        ; viive

move.l  #0,(a1)+        ; ClearScreen-osoite
move.l  #0,(a1)+        ; VanhaSijainti-osoite
move.w  #0,(a1)+        ; BLTSIZE

move.l  #0,(a4)+
move.l  #0,(a4)+
move.w  #0,(a4)+

dbf     d7,Exps

move.l  #0,Exp_PT
move.l  #0,VanhaExpSij
move.l  #Explosions,Exp_PT

;
lea     MExp_VanhaSij0,a1
lea     MExp_VanhaSij1,a4
move.l  #0,(a1)+        ; ClearScreen-sijainti
move.l  #0,(a1)+        ; VanhaSijainti
move.w  #0,(a1)+        ; BLTSIZE

move.l  #0,(a4)+        ; ClearScreen-sijainti
move.l  #0,(a4)+        ; VanhaSijainti
move.w  #0,(a4)+        ; BLTSIZE

move.l  #0,MExp_vanhasij

moveq   #3-1,d7
lea     MonstBVanhaSij0,a0
lea     MonstBVanhaSij1,a1

MBalustus
move.l  #0,(a0)+
move.l  #0,(a0)+
move.w  #0,(a0)+

move.l  #0,(a1)+
move.l  #0,(a1)+
move.w  #0,(a1)+
dbf     d7,MBalustus

; Coordbob-stuff

lea     VanhaSij1,a0
lea     VanhaSij2,a1
lea     PTRsAndONOFF,a4
moveq   #max_bobs-1,d7
CoordBobAlustus
move.l  #0,(a0)+        ; ClearScreen
move.l  #0,(a0)+        ; VanhaSijainti
move.w  #0,(a0)+        ; BLTSIZE
move.l  #0,(a1)+        ; ClearScreen
move.l  #0,(a1)+        ; VanhaSijainti
move.w  #0,(a1)+        ; BLTSIZE

move.l  #0,(a4)+        ; Pointteri koordinaatteihin
move.w  #0,(a4)+        ; ON/OFF
move.w  #0,(a4)+        ; Kestävyys
move.l  #0,(a4)+        ; Pointteri bob-dataan
dbf     d7,CoordBobAlustus

move.b  #0,DoLastCoordBobFrames
move.b  #0,CoordBobsRunning
move.b  #0,nr_of_bobs
move.b  #0,AmEnemies

move.l  #0,VanhaSij

; Enemylaakit coordbobeille

lea     VanhaESij1,a0
lea     VanhaESij2,a1
lea     EnemyLaakit,a2
moveq   #AmountEBullets,d7

enbullet
move.l  #0,(a0)+
move.l  #0,(a0)+
move.l  #0,(a1)+
move.l  #0,(a1)+

move.w  #-1,(a2)+   ; x HUOM!!!
move.w  #0,(a2)+        ; y

dbf     d7,enbullet

; Omat laakit

lea     Laakit,a0
moveq   #AmountBullets,d7
omatlaakitalustus
move.w  #0,(a0)+        ; Kehissä
move.w  #0,(a0)+        ; x
move.w  #0,(a0)+        ; y
dbf     d7,omatlaakitalustus

move.l  #0,LaakiPT
move.l   #Laakit,LaakiPT

; Unittien alkuarvot kuntoon

lea     Units,a0
lea     UnitsVanhaSij0,a1
lea     UnitsVanhaSij1,a2
lea     UnitsVBSij0,a3
lea     UnitsVBSij1,a4
moveq       #5-1,d7
UnitInit
move.w  #0,(a0)+        ; Liikkeellä
move.l  #0,(a0)+        ; UnitX
move.l  #0,(a0)+        ; UnitY
move.w  #0,(a0)+        ; Laaki liikkeellä
move.l  #0,(a0)+        ; BulletX
move.l  #0,(a0)+    ; BulletY
move.l  #0,(a0)+        ; Bullet add X
move.l  #0,(a0)+        ; Bullet add Y
move.l  #0,(a0)+        ; UnitBob
move.l  #0,(a0)+        ; ExplodedUnit
move.w  #0,(a0)+        ; Kestävyys
move.w  #0,(a0)+        ; Liikkuvako

move.l  #0,(a1)+
move.l  #0,(a1)+
move.w  #0,(a1)+
move.l  #0,(a2)+
move.l  #0,(a2)+
move.w  #0,(a2)+
move.l  #0,(a3)+
move.l  #0,(a3)+
move.w  #0,(a3)+
move.l  #0,(a4)+
move.l  #0,(a4)+
move.w  #0,(a4)+

dbf     d7,UnitInit

; Asteroidien alkuarvot kuntoon

lea     Asteroids,a0
moveq       #28-1,d7
AsterInit
move.w  #0,(a0)+        ; Liikkeellä merkki
move.w  #0,(a0)+        ; X
move.w  #0,(a0)+        ; Y
move.w  #0,(a0)+        ; Speed
move.w  #0,(a0)+        ; Kestävyys
dbf     d7,AsterInit
moveq       #28-1,d7
lea     VanhaAstSij0,a0
lea     VanhaAstSij1,a1
AsterVSijInit
move.l  #0,(a0)+        ; ClearScreen
move.l  #0,(a0)+        ; VanhaSijainti
move.w  #0,(a0)+        ; BLTSIZE
move.l  #0,(a1)+
move.l  #0,(a1)+
move.w  #0,(a1)+
dbf     d7,AsterVSijInit

move.b  #0,Asteroids_on_screen
move.b  #0,AsteroidsRunning
move.b  #3,LastAsteroidFrames

; Monsterin alkuarvot kuntoon

move.b  #0,MExpFinished
move.b  #0,Monster_destroyed
move.b  #0,MonsterKehissa

lea     Monster,a0
move.w  #32,(a0)+       ; X-koordinaatti
move.w  #-64,(a0)+      ; Y
move.w  #60,(a0)+       ; Kestävyys
move.w  #0,(a0)+            ; Laaki liikkeellä
move.l  #0,(a0)+
move.l  #0,(a0)+
move.l  #0,(a0)+
move.l  #0,(a0)+
move.w  #0,(a0)+
move.l  #0,(a0)+
move.l  #0,(a0)+
move.l  #0,(a0)+
move.l  #0,(a0)+
move.w  #0,(a0)+
move.l  #0,(a0)+
move.l  #0,(a0)+
move.l  #0,(a0)+
move.l  #0,(a0)+

cmp.b    #2,level
beq.s    level2monsterbob

cmp.b    #3,level
beq.s    level3monsterbob

move.l   #MonsterBob,(a0)+
bra.s    monsterjatkuu

level2monsterbob
move.l   #Monster2Bob,(a0)+
bra.s    monsterjatkuu

level3monsterbob
move.l  #Monster3Bob,(a0)+

monsterjatkuu
move.w  #1,DX

lea     Monster_explosion,a0
move.w  #0,(a0)+
move.w  #0,(a0)+
move.w  #0,(a0)+
move.w  #4,(a0)+        ; Viive
move.l  #0,(a0)+

move.b  #0,kierros

; Taso 1 aloitustasoksi

;       move.b  #1,level
;       move.l   #Coolfield,coolfield

move.l  #SPR0,d0
move.w  d0,s0_low
swap    d0
move.w  d0,s0_high

move.l  #SPR1,d0
move.w  d0,s1_low
swap    d0
move.w  d0,s1_high

move.l  #SPR2,d0
move.w  d0,s2_low
swap      d0
move.w  d0,s2_high

;

move.l  #0,pt_Font
move.b  #'A',currentchar

move.w  #128,x          ; Pelaajan koordinaatit
move.w  #235,y

rts

;------------------------------------------------------------------------------
;
;------------------------------------------------------------------------------
AlkuRoskat:
move.w  #5-1,d7         ; Spritejen määrä (mitkä "nollataan")
move.l  #Dummy,d0       ; "Nollataan" käyttämättämät spritet
lea     empty,a0
SprNl:  move.w  d0,2(a0)
swap    d0
move.w  d0,6(a0)
dbf     d7,SprNl

;        lea     PTRsAndONOFF,a0 ; Lasketaan Enemyille koord. PTR:t
;         moveq   #0,d7
;        move.b  nr_of_bobs,d7
;         subq.l     #1,d7

;        move.l  #0,d0
;AlArv:  move.l  d0,(a0)+
;        move.w  #1,(a0)+        ; "Enemy kehissä" -merkki
;        dbf     d7,AlArv

lea     EnemyLaakit,a0
move.l  #AmountEBullets,d7
ELSil:  move.w  #-1,(a0)+
move.w  #0,(a0)+
dbf     d7,ELSil

lea     Laakit,a0
move.l  #AmountBullets,d7
SilL:   move.w  #0,(a0)+
move.w  #0,(a0)+
move.w  #0,(a0)+
dbf     d7,SilL

lea     VanhaESij1,a0
move.l  #AmountEBullets,d7
VES1Sil move.l  #0,(a0)+
move.l  #0,(a0)+
dbf     d7,VES1Sil

lea     VanhaESij2,a0
move.l  #AmountEBullets,d7
VES2Sil move.l  #0,(a0)+
move.l  #0,(a0)+
dbf     d7,VES2Sil

;        lea     VanhaSij1,a0
;         moveq   #0,d7
;        move.b  nr_of_bobs,d7
;         subq.l     #1,d7
;ZIL:    move.l  #0,(a0)+
;        move.l  #0,(a0)+
;        move.w  #0,(a0)+
;        dbf     d7,ZIL

;        lea     VanhaSij2,a0
;         moveq  #0,d7
;        move.b  nr_of_bobs,d7
;         subq.l     #1,d7
;ZIL2:   move.l  #0,(a0)+
;        move.l  #0,(a0)+
;        move.w  #0,(a0)+
;        dbf     d7,ZIL2

move.l  #SPR0,d0
move.w  d0,s0_low
swap    d0
move.w  d0,s0_high

move.l  #SPR1,d0
move.w  d0,s1_low
swap    d0
move.w  d0,s1_high

move.l  #SPR2,d0
move.w   d0,s2_low
swap    d0
move.w  d0,s2_high

;        lea     Blocks+2560+2,a0               ; Blockien loppu + skip 1 väri
move.l   #Blocks+2560+2,a0
;        lea     Colours+2,a1
move.l   #Colours+2,a1
moveq   #15-1,d7
CSil    move.w  (a0)+,(a1)                      ; Asetetaan värit
dbf     d7,CSil

;         lea        Monster,a0
;         move.w  #60,4(a0)         ; Monsterin kestävyys

move.b  #1,level
move.l  #Coolfield,coolfield
rts

;------------------------------------------------------------------------------
; Musiikkikeskeytys
;------------------------------------------------------------------------------
Keskeytysrutiini
bsr mt_music
rts

;********************************************
;* ----- Protracker V1.1B Playroutine ----- *
;* Lars "Zap" Hamre/Amiga Freelancers 1991  *
;* Bekkeliveien 10, N-2010 STRØMMEN, Norway *
;********************************************

; CIA Version 1:
; Call SetCIAInt to install the interrupt server. Then call mt_init
; to initialize the song. Playback starts when the mt_enable flag
; is set to a nonzero value. To end the song and turn off all voices,
; call mt_end. At last, call ResetCIAInt to remove the interrupt.

; This playroutine is not very fast, optimized or well commented,
; but all the new commands in PT1.1 should work.
; If it's not good enough, you'll have to change it yourself.
; We'll try to write a faster routine soon...

; Changes from V1.0C playroutine:
; - ViBRAto depth changed to be compatible with Noisetracker 2.0.
;   You'll have to double all vib. depths on old PT modules.
; - Funk Repeat changed to Invert Loop.
; - Period set back earlier when stopping an effect.

; You can use this routine to play a module. Just remove the semicolons.
; Exit by pressing both mousebuttons.
;
;main   BSR.S   SetCIAInt
;   BSR mt_init
;   ST  mt_Enable
;   MOVE.L  4.W,A6
;   LEA DOSname(PC),A1
;   MOVEQ   #0,D0
;   JSR LVOOpenLiBRAry(A6)
;   TST.L   D0
;   BEQ.S   theend
;   MOVE.L  D0,A6
;wloop  MOVEQ   #10,D1
;   JSR LVODelay(A6)
;   BTST    #6,\$BFE001
;   BNE.S   wloop
;   BTST    #2,\$DFF016
;   BNE.S   wloop
;   MOVE.L  A6,A1
;   MOVE.L  4.W,A6
;   JSR LVOCloseLiBRAry(A6)
;theend BSR mt_end
;   BSR ResetCIAInt
;   RTS
;
;DOSname    dc.b "dos.liBRAry",0

;---- CIA Interrupt ----

RemICRVector    =  -12
LVOOpenResource = -498
LVOOpenLiBRAry  = -552
LVOCloseLiBRAry = -414
LVODelay    = -198

ciatalo = \$400
ciatahi = \$500
ciatblo = \$600
ciatbhi = \$700
ciacra  = \$E00
ciacrb  = \$F00

SetCIAInt
MOVEQ   #2,D6
LEA \$BFD000,A5
MOVE.B  #'b',CIAAname+3
SetCIALoop
MOVEQ   #0,D0
LEA CIAAname(PC),A1
MOVE.L  4.W,A6
JSR LVOOpenResource(A6)
MOVE.L  D0,CIAAbase
BEQ mt_Return

LEA GfxName(PC),A1
MOVEQ   #0,D0
JSR LVOOpenLiBRAry(A6)
TST.L   D0
BEQ ResetCIAInt
MOVE.L  D0,A1
MOVE.W  206(A1),D0  ; DisplayFlags
BTST    #2,D0       ; PAL?
BEQ.S   WasNTSC
MOVE.L  #1773447,D7 ; PAL
WasNTSC MOVE.L  #1789773,D7 ; NTSC
DIVU    #125,D7 ; Default to normal 50 Hz timer
JSR CloseLiBRAry(A6)

MOVE.L  CIAAbase(PC),A6
CMP.W   #2,D6
BEQ.S   TryTimerA
TryTimerB
LEA MusicIntServer(PC),A1
MOVEQ   #1,D0   ; Bit 1: Timer B
MOVE.L  #1,TimerFlag
TST.L   D0
BNE.S   CIAError
MOVE.B  D7,ciatblo(A5)
LSR.W   #8,D7
MOVE.B  D7,ciatbhi(A5)
BSET    #0,ciacrb(A5)
RTS

TryTimerA
LEA MusicIntServer(PC),A1
MOVEQ   #0,D0   ; Bit 0: Timer A
CLR.L   TimerFlag
TST.L   D0
BNE.S   CIAError
MOVE.B  D7,ciatalo(A5)
LSR.W   #8,D7
MOVE.B  D7,ciatahi(A5)
BSET    #0,ciacra(A5)
RTS

CIAError
MOVE.B  #'a',CIAAname+3
LEA \$BFE001,A5
SUBQ.W  #1,D6
BNE SetCIALoop
CLR.L   CIAAbase
RTS

ResetCIAInt
MOVE.L  CIAAbase(PC),D0
BEQ mt_Return
CLR.L   CIAAbase
MOVE.L  D0,A6
TST.L   TimerFlag
BEQ.S   ResTimerA

BCLR    #0,ciacrb(A5)
MOVEQ   #1,D0
BRA.S   RemInt

ResTimerA
BCLR    #0,ciacra(A5)
MOVEQ   #0,D0
RemInt  LEA MusicIntServer(PC),A1
MOVEQ   #0,d0
JSR RemICRVector(A6)
RTS

;---- Tempo ----

SetTempo
MOVE.L  CIAAbase(PC),D2
BEQ mt_Return
CMP.W   #32,D0
BHS.S   setemsk
MOVEQ   #32,D0
setemsk MOVE.W  D0,RealTempo
MOVE.L  TimerValue(PC),D2
DIVU    D0,D2
MOVE.L  TimerFlag(PC),D0
BEQ.S   SetTemA
MOVE.B  D2,ciatblo(A4)
LSR.W   #8,D2
MOVE.B  D2,ciatbhi(A4)
RTS

SetTemA MOVE.B  D2,ciatalo(A4)
LSR.W   #8,D2
MOVE.B  D2,ciatahi(A4)
RTS

RealTempo   dc.w 125
CIAAname    dc.b "ciaa.resource",0
CIAAbase    dc.l 0
TimerFlag   dc.l 0
TimerValue  dc.l 0
GfxName     dc.b "graphics.liBRAry",0,0

MusicIntServer
dc.l 0,0
dc.b 2,5 ; type, priority
dc.l musintname
dc.l 0,mt_music

musintname  dc.b "Protracker MusicInt",0

;---- Playroutine ----

n_note      EQU 0  ; W
n_cmd       EQU 2  ; W
n_cmdlo     EQU 3  ; B
n_start     EQU 4  ; L
n_length    EQU 8  ; W
n_loopstart EQU 10 ; L
n_replen    EQU 14 ; W
n_period    EQU 16 ; W
n_finetune  EQU 18 ; B
n_volume    EQU 19 ; B
n_dmabit    EQU 20 ; W
n_toneportdirec EQU 22 ; B
n_toneportspeed EQU 23 ; B
n_wantedperiod  EQU 24 ; W
n_viBRAtocmd    EQU 26 ; B
n_viBRAtopos    EQU 27 ; B
n_tremolocmd    EQU 28 ; B
n_tremolopos    EQU 29 ; B
n_wavecontrol   EQU 30 ; B
n_glissfunk EQU 31 ; B
n_sampleoffset  EQU 32 ; B
n_pattpos   EQU 33 ; B
n_loopcount EQU 34 ; B
n_funkoffset    EQU 35 ; B
n_wavestart EQU 36 ; L
n_reallength    EQU 40 ; W

mt_init ;LEA    mt_data,A0
MOVE.L  A0,mt_SongDataPtr
MOVE.L  A0,A1
LEA 952(A1),A1
MOVEQ   #127,D0
MOVEQ   #0,D1
MOVEQ   #0,D2
mtloop  MOVE.B  (A1)+,D1
CMP.B   D2,D1
BCS.S   mtloop2
MOVE.L  D1,D2
mtloop2 DBRA    D0,mtloop

LEA mt_SampleStarts(PC),A1
ASL.L   #8,D2
ASL.L   #2,D2
MOVE.L  D2,A2
MOVEQ   #30,D0
mtloop3 CLR.L   (A2)
MOVE.L  A2,(A1)+
MOVEQ   #0,D1
MOVE.W  42(A0),D1
ASL.L   #1,D1
DBRA    D0,mtloop3

OR.B    #2,\$BFE001
MOVE.B  #6,mt_speed
CLR.B   mt_counter
CLR.B   mt_SongPos
CLR.W   mt_PatternPos
mt_end  SF  mt_Enable
LEA \$DFF000,A0
CLR.W   \$A8(A0)
CLR.W   \$B8(A0)
CLR.W   \$C8(A0)
CLR.W   \$D8(A0)
MOVE.W  #\$F,\$DFF096
RTS

mt_music
MOVEM.L D0-D4/A0-A6,-(SP)
TST.B   mt_Enable
BEQ mt_exit
MOVE.B  mt_counter(PC),D0
CMP.B   mt_speed(PC),D0
BLO.S   mt_NoNewNote
CLR.B   mt_counter
TST.B   mt_PattDelTime2
BEQ.S   mt_GetNewNote
BSR.S   mt_NoNewAllChannels
BRA mt_dskip

mt_NoNewNote
BSR.S   mt_NoNewAllChannels
BRA mt_NoNewPosYet

mt_NoNewAllChannels
LEA \$DFF0A0,A5
LEA mt_chan1temp(PC),A6
BSR mt_CheckEfx
LEA \$DFF0B0,A5
LEA mt_chan2temp(PC),A6
BSR mt_CheckEfx
LEA \$DFF0C0,A5
LEA mt_chan3temp(PC),A6
BSR mt_CheckEfx
LEA \$DFF0D0,A5
LEA mt_chan4temp(PC),A6
BRA mt_CheckEfx

mt_GetNewNote
MOVE.L  mt_SongDataPtr(PC),A0
LEA 12(A0),A3
LEA 952(A0),A2  ;pattpo
LEA 1084(A0),A0 ;patterndata
MOVEQ   #0,D0
MOVEQ   #0,D1
MOVE.B  mt_SongPos(PC),D0
MOVE.B  (A2,D0.W),D1
ASL.L   #8,D1
ASL.L   #2,D1
CLR.W   mt_DMACONtemp

LEA \$DFF0A0,A5
LEA mt_chan1temp(PC),A6
BSR.S   mt_PlayVoice
LEA \$DFF0B0,A5
LEA mt_chan2temp(PC),A6
BSR.S   mt_PlayVoice
LEA \$DFF0C0,A5
LEA mt_chan3temp(PC),A6
BSR.S   mt_PlayVoice
LEA \$DFF0D0,A5
LEA mt_chan4temp(PC),A6
BSR.S   mt_PlayVoice
BRA mt_SetDMA

mt_PlayVoice
TST.L   (A6)
BNE.S   mt_plvskip
BSR mt_PerNop
mt_plvskip
MOVE.L  (A0,D1.L),(A6)
MOVEQ   #0,D2
MOVE.B  n_cmd(A6),D2
AND.B   #\$F0,D2
LSR.B   #4,D2
MOVE.B  (A6),D0
AND.B   #\$F0,D0
OR.B    D0,D2
TST.B   D2
BEQ mt_SetRegs
MOVEQ   #0,D3
LEA mt_SampleStarts(PC),A1
MOVE    D2,D4
SUBQ.L  #1,D2
ASL.L   #2,D2
MULU    #30,D4
MOVE.L  (A1,D2.L),n_start(A6)
MOVE.W  (A3,D4.L),n_length(A6)
MOVE.W  (A3,D4.L),n_reallength(A6)
MOVE.B  2(A3,D4.L),n_finetune(A6)
MOVE.B  3(A3,D4.L),n_volume(A6)
MOVE.W  4(A3,D4.L),D3 ; Get repeat
TST.W   D3
BEQ.S   mt_NoLoop
MOVE.L  n_start(A6),D2  ; Get start
ASL.W   #1,D3
MOVE.L  D2,n_loopstart(A6)
MOVE.L  D2,n_wavestart(A6)
MOVE.W  4(A3,D4.L),D0   ; Get repeat
MOVE.W  D0,n_length(A6)
MOVE.W  6(A3,D4.L),n_replen(A6) ; Save replen
MOVEQ   #0,D0
MOVE.B  n_volume(A6),D0
MOVE.W  D0,8(A5)    ; Set volume
BRA.S   mt_SetRegs

mt_NoLoop
MOVE.L  n_start(A6),D2
MOVE.L  D2,n_loopstart(A6)
MOVE.L  D2,n_wavestart(A6)
MOVE.W  6(A3,D4.L),n_replen(A6) ; Save replen
MOVEQ   #0,D0
MOVE.B  n_volume(A6),D0
MOVE.W  D0,8(A5)    ; Set volume
mt_SetRegs
MOVE.W  (A6),D0
AND.W   #\$0FFF,D0
BEQ mt_CheckMoreEfx ; If no note
MOVE.W  2(A6),D0
AND.W   #\$0FF0,D0
CMP.W   #\$0E50,D0
BEQ.S   mt_DoSetFineTune
MOVE.B  2(A6),D0
AND.B   #\$0F,D0
CMP.B   #3,D0   ; TonePortamento
BEQ.S   mt_ChkTonePorta
CMP.B   #5,D0
BEQ.S   mt_ChkTonePorta
CMP.B   #9,D0   ; Sample Offset
BNE.S   mt_SetPeriod
BSR mt_CheckMoreEfx
BRA.S   mt_SetPeriod

mt_DoSetFineTune
BSR mt_SetFineTune
BRA.S   mt_SetPeriod

mt_ChkTonePorta
BSR mt_SetTonePorta
BRA mt_CheckMoreEfx

mt_SetPeriod
MOVEM.L D0-D1/A0-A1,-(SP)
MOVE.W  (A6),D1
AND.W   #\$0FFF,D1
LEA mt_PeriodTable(PC),A1
MOVEQ   #0,D0
MOVEQ   #35,D2
mt_ftuloop
CMP.W   (A1,D0.W),D1
BHS.S   mt_ftufound
DBRA    D2,mt_ftuloop
mt_ftufound
MOVEQ   #0,D1
MOVE.B  n_finetune(A6),D1
MULU    #36*2,D1
MOVE.W  (A1,D0.W),n_period(A6)
MOVEM.L (SP)+,D0-D1/A0-A1

MOVE.W  2(A6),D0
AND.W   #\$0FF0,D0
CMP.W   #\$0ED0,D0 ; Notedelay
BEQ mt_CheckMoreEfx

;   MOVE.W  n_dmabit(A6),\$DFF096
BTST    #2,n_wavecontrol(A6)
BNE.S   mt_vibnoc
CLR.B   n_viBRAtopos(A6)
mt_vibnoc
BTST    #6,n_wavecontrol(A6)
BNE.S   mt_trenoc
CLR.B   n_tremolopos(A6)
mt_trenoc
MOVE.L  n_start(A6),(A5)    ; Set start
MOVE.W  n_length(A6),4(A5)  ; Set length
;   MOVE.W  n_period(A6),6(A5)  ; Set period
MOVE.W  n_dmabit(A6),D0
OR.W    D0,mt_DMACONtemp
BRA mt_CheckMoreEfx

mt_SetDMA
MOVE.W  mt_DMACONtemp(PC),D0
BSR mt_PlaySamples      ; this does the magic
LEA \$DFF000,A5
LEA mt_chan1temp(PC),A6
MOVE.L  n_loopstart(A6),\$A0(A5)
MOVE.W  n_replen(A6),\$A4(A5)
LEA mt_chan2temp(PC),A6
MOVE.L  n_loopstart(A6),\$B0(A5)
MOVE.W  n_replen(A6),\$B4(A5)
LEA mt_chan3temp(PC),A6
MOVE.L  n_loopstart(A6),\$C0(A5)
MOVE.W  n_replen(A6),\$C4(A5)
LEA mt_chan4temp(PC),A6
MOVE.L  n_loopstart(A6),\$D0(A5)
MOVE.W  n_replen(A6),\$D4(A5)

mt_dskip
MOVE.B  mt_PattDelTime,D0
BEQ.S   mt_dskc
MOVE.B  D0,mt_PattDelTime2
CLR.B   mt_PattDelTime
mt_dskc TST.B   mt_PattDelTime2
BEQ.S   mt_dska
SUBQ.B  #1,mt_PattDelTime2
BEQ.S   mt_dska
SUB.W   #16,mt_PatternPos
mt_dska TST.B   mt_PBreakFlag
BEQ.S   mt_nnpysk
SF  mt_PBreakFlag
MOVEQ   #0,D0
MOVE.B  mt_PBreakPos(PC),D0
CLR.B   mt_PBreakPos
LSL.W   #4,D0
MOVE.W  D0,mt_PatternPos
mt_nnpysk
CMP.W   #1024,mt_PatternPos
BLO.S   mt_NoNewPosYet
mt_NextPosition
MOVEQ   #0,D0
MOVE.B  mt_PBreakPos(PC),D0
LSL.W   #4,D0
MOVE.W  D0,mt_PatternPos
CLR.B   mt_PBreakPos
CLR.B   mt_PosJumpFlag
AND.B   #\$7F,mt_SongPos
MOVE.B  mt_SongPos(PC),D1
MOVE.L  mt_SongDataPtr(PC),A0
CMP.B   950(A0),D1
BLO.S   mt_NoNewPosYet
CLR.B   mt_SongPos
mt_NoNewPosYet
TST.B   mt_PosJumpFlag
BNE.S   mt_NextPosition
mt_exit MOVEM.L (SP)+,D0-D4/A0-A6
RTS

;
; busywait-fixed by Delirium Softdesign.
;
; the old routine wasted about 2*10 rasterlines, this routine needs 2-8 lines
; (depending on the module). It was tested on an A500/A3000/A4000 and seems to
; play all modules ok. BTW, using this new technique it should be no problem
; to fix the busywait-loops of almost every other replay !
;
; known bugs:
;
;  sometimes when a module starts playing and the first note is played on
;  a channel, the routine needs ~100 rasterlines (in the mt_Wait2 loop).
;  perhaps this is a dma problem ?
;
; kunath@informatik.tu-muenchen.de (Peter Kunath)
;

mt_PlaySamples
movem.l d0-d2/a5-a6,-(sp)
lea \$DFF000,a5
move.w  d0,d2

move.b  \$06(a5),d0      ; wait until end of line
;   move.w  #\$0ff,\$180(a5)
mt_Wait1
cmp.b   \$06(a5),d0      ; the wait should be enough even on
beq.s   mt_Wait1        ; an A4000 running DBLPAL screenmode
mt_MaxPer0
btst    #0,d2
beq.s   mt_MaxPer1
move.w  #1,\$A6(a5)      ; max. speed
mt_MaxPer1
btst    #1,d2
beq.s   mt_MaxPer2
move.w  #1,\$B6(a5)      ; max. speed
mt_MaxPer2
btst    #2,d2
beq.s   mt_MaxPer3
move.w  #1,\$C6(a5)      ; max. speed
mt_MaxPer3
btst    #3,d2
beq.s   mt_MaxPer4
move.w  #1,\$D6(a5)      ; max. speed
mt_MaxPer4
move.w  \$02(a5),d0      ; get active channels
and.w   d2,d0
move.w  d0,d1
lsl.w   #7,d0
move.w  d0,\$9C(a5)      ; stop channels
move.w  d1,\$96(a5)
;   move.w  #\$f00,\$180(a5)
mt_Wait2
move.w  \$1E(a5),d1      ; wait until all channels are stopped
and.w   d0,d1
cmp.w   d0,d1
bne.s   mt_Wait2

move.w  \$02(a5),d0      ; get active channels
not.w   d0
and.w   d2,d0
move.w  d0,d1
lsl.w   #7,d0
move.w  d0,\$9C(a5)
or.w    #\$8000,d1
move.w  d1,\$96(a5)      ; start channels
;   move.w  #\$0f0,\$180(a5)
mt_Wait3
move.w  \$1E(a5),d1      ; wait until all channels are running
and.w   d0,d1
cmp.w   d0,d1
bne.s   mt_Wait3
move.b  \$06(a5),d0      ; wait until end of line
;   move.w  #\$00f,\$180(a5)
mt_Wait4
cmp.b   \$06(a5),d0      ; the wait should be enough even on
beq.s   mt_Wait4        ; an A4000 running DBLPAL screenmode
mt_SetPer0
btst    #0,d2
beq.s   mt_SetPer1
lea mt_chan1temp(pc),a6
move.w  n_period(a6),\$A6(a5)
mt_SetPer1
btst    #1,d2
beq.s   mt_SetPer2
lea mt_chan2temp(pc),a6
move.w  n_period(a6),\$B6(a5)
mt_SetPer2
btst    #2,d2
beq.s   mt_SetPer3
lea mt_chan3temp(pc),a6
move.w  n_period(a6),\$C6(a5)
mt_SetPer3
btst    #3,d2
beq.s   mt_SetPer4
lea mt_chan4temp(pc),a6
move.w  n_period(a6),\$D6(a5)
mt_SetPer4
;   move.w  #\$000,\$180(a5)
movem.l (sp)+,d0-d2/a5-a6
rts

mt_CheckEfx
BSR mt_UpdateFunk
MOVE.W  n_cmd(A6),D0
AND.W   #\$0FFF,D0
BEQ.S   mt_PerNop
MOVE.B  n_cmd(A6),D0
AND.B   #\$0F,D0
BEQ.S   mt_Arpeggio
CMP.B   #1,D0
BEQ mt_PortaUp
CMP.B   #2,D0
CMP.B   #3,D0
BEQ mt_TonePortamento
CMP.B   #4,D0
BEQ mt_ViBRAto
CMP.B   #5,D0
BEQ mt_TonePlusVolSlide
CMP.B   #6,D0
BEQ mt_ViBRAtoPlusVolSlide
CMP.B   #\$E,D0
BEQ mt_E_Commands
SetBack MOVE.W  n_period(A6),6(A5)
CMP.B   #7,D0
BEQ mt_Tremolo
CMP.B   #\$A,D0
BEQ mt_VolumeSlide
mt_Return
RTS

mt_PerNop
MOVE.W  n_period(A6),6(A5)
RTS

mt_Arpeggio
MOVEQ   #0,D0
MOVE.B  mt_counter(PC),D0
DIVS    #3,D0
SWAP    D0
CMP.W   #0,D0
BEQ.S   mt_Arpeggio2
CMP.W   #2,D0
BEQ.S   mt_Arpeggio1
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
LSR.B   #4,D0
BRA.S   mt_Arpeggio3

mt_Arpeggio1
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
AND.B   #15,D0
BRA.S   mt_Arpeggio3

mt_Arpeggio2
MOVE.W  n_period(A6),D2
BRA.S   mt_Arpeggio4

mt_Arpeggio3
ASL.W   #1,D0
MOVEQ   #0,D1
MOVE.B  n_finetune(A6),D1
MULU    #36*2,D1
LEA mt_PeriodTable(PC),A0
MOVEQ   #0,D1
MOVE.W  n_period(A6),D1
MOVEQ   #35,D3
mt_arploop
MOVE.W  (A0,D0.W),D2
CMP.W   (A0),D1
BHS.S   mt_Arpeggio4
DBRA    D3,mt_arploop
RTS

mt_Arpeggio4
MOVE.W  D2,6(A5)
RTS

mt_FinePortaUp
TST.B   mt_counter
BNE.S   mt_Return
mt_PortaUp
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
SUB.W   D0,n_period(A6)
MOVE.W  n_period(A6),D0
AND.W   #\$0FFF,D0
CMP.W   #113,D0
BPL.S   mt_PortaUskip
AND.W   #\$F000,n_period(A6)
OR.W    #113,n_period(A6)
mt_PortaUskip
MOVE.W  n_period(A6),D0
AND.W   #\$0FFF,D0
MOVE.W  D0,6(A5)
RTS

TST.B   mt_counter
BNE mt_Return
CLR.W   D0
MOVE.B  n_cmdlo(A6),D0
MOVE.W  n_period(A6),D0
AND.W   #\$0FFF,D0
CMP.W   #856,D0
AND.W   #\$F000,n_period(A6)
OR.W    #856,n_period(A6)
MOVE.W  n_period(A6),D0
AND.W   #\$0FFF,D0
MOVE.W  D0,6(A5)
RTS

mt_SetTonePorta
MOVE.L  A0,-(SP)
MOVE.W  (A6),D2
AND.W   #\$0FFF,D2
MOVEQ   #0,D0
MOVE.B  n_finetune(A6),D0
MULU    #36*2,D0
LEA mt_PeriodTable(PC),A0
MOVEQ   #0,D0
mt_StpLoop
CMP.W   (A0,D0.W),D2
BHS.S   mt_StpFound
CMP.W   #36*2,D0
BLO.S   mt_StpLoop
MOVEQ   #35*2,D0
mt_StpFound
MOVE.B  n_finetune(A6),D2
AND.B   #8,D2
BEQ.S   mt_StpGoss
TST.W   D0
BEQ.S   mt_StpGoss
SUBQ.W  #2,D0
mt_StpGoss
MOVE.W  (A0,D0.W),D2
MOVE.L  (SP)+,A0
MOVE.W  D2,n_wantedperiod(A6)
MOVE.W  n_period(A6),D0
CLR.B   n_toneportdirec(A6)
CMP.W   D0,D2
BEQ.S   mt_ClearTonePorta
BGE mt_Return
MOVE.B  #1,n_toneportdirec(A6)
RTS

mt_ClearTonePorta
CLR.W   n_wantedperiod(A6)
RTS

mt_TonePortamento
MOVE.B  n_cmdlo(A6),D0
BEQ.S   mt_TonePortNoChange
MOVE.B  D0,n_toneportspeed(A6)
CLR.B   n_cmdlo(A6)
mt_TonePortNoChange
TST.W   n_wantedperiod(A6)
BEQ mt_Return
MOVEQ   #0,D0
MOVE.B  n_toneportspeed(A6),D0
TST.B   n_toneportdirec(A6)
BNE.S   mt_TonePortaUp
MOVE.W  n_wantedperiod(A6),D0
CMP.W   n_period(A6),D0
BGT.S   mt_TonePortaSetPer
MOVE.W  n_wantedperiod(A6),n_period(A6)
CLR.W   n_wantedperiod(A6)
BRA.S   mt_TonePortaSetPer

mt_TonePortaUp
SUB.W   D0,n_period(A6)
MOVE.W  n_wantedperiod(A6),D0
CMP.W   n_period(A6),D0
BLT.S   mt_TonePortaSetPer
MOVE.W  n_wantedperiod(A6),n_period(A6)
CLR.W   n_wantedperiod(A6)

mt_TonePortaSetPer
MOVE.W  n_period(A6),D2
MOVE.B  n_glissfunk(A6),D0
AND.B   #\$0F,D0
BEQ.S   mt_GlissSkip
MOVEQ   #0,D0
MOVE.B  n_finetune(A6),D0
MULU    #36*2,D0
LEA mt_PeriodTable(PC),A0
MOVEQ   #0,D0
mt_GlissLoop
CMP.W   (A0,D0.W),D2
BHS.S   mt_GlissFound
CMP.W   #36*2,D0
BLO.S   mt_GlissLoop
MOVEQ   #35*2,D0
mt_GlissFound
MOVE.W  (A0,D0.W),D2
mt_GlissSkip
MOVE.W  D2,6(A5) ; Set period
RTS

mt_ViBRAto
MOVE.B  n_cmdlo(A6),D0
BEQ.S   mt_ViBRAto2
MOVE.B  n_viBRAtocmd(A6),D2
AND.B   #\$0F,D0
BEQ.S   mt_vibskip
AND.B   #\$F0,D2
OR.B    D0,D2
mt_vibskip
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$F0,D0
BEQ.S   mt_vibskip2
AND.B   #\$0F,D2
OR.B    D0,D2
mt_vibskip2
MOVE.B  D2,n_viBRAtocmd(A6)
mt_ViBRAto2
MOVE.B  n_viBRAtopos(A6),D0
LEA mt_ViBRAtoTable(PC),A4
LSR.W   #2,D0
AND.W   #\$001F,D0
MOVEQ   #0,D2
MOVE.B  n_wavecontrol(A6),D2
AND.B   #\$03,D2
BEQ.S   mt_vib_sine
LSL.B   #3,D0
CMP.B   #1,D2
BEQ.S   mt_vib_rampdown
MOVE.B  #255,D2
BRA.S   mt_vib_set
mt_vib_rampdown
TST.B   n_viBRAtopos(A6)
BPL.S   mt_vib_rampdown2
MOVE.B  #255,D2
SUB.B   D0,D2
BRA.S   mt_vib_set
mt_vib_rampdown2
MOVE.B  D0,D2
BRA.S   mt_vib_set
mt_vib_sine
MOVE.B  (A4,D0.W),D2
mt_vib_set
MOVE.B  n_viBRAtocmd(A6),D0
AND.W   #15,D0
MULU    D0,D2
LSR.W   #7,D2
MOVE.W  n_period(A6),D0
TST.B   n_viBRAtopos(A6)
BMI.S   mt_ViBRAtoNeg
BRA.S   mt_ViBRAto3
mt_ViBRAtoNeg
SUB.W   D2,D0
mt_ViBRAto3
MOVE.W  D0,6(A5)
MOVE.B  n_viBRAtocmd(A6),D0
LSR.W   #2,D0
AND.W   #\$003C,D0
RTS

mt_TonePlusVolSlide
BSR mt_TonePortNoChange
BRA mt_VolumeSlide

mt_ViBRAtoPlusVolSlide
BSR.S   mt_ViBRAto2
BRA mt_VolumeSlide

mt_Tremolo
MOVE.B  n_cmdlo(A6),D0
BEQ.S   mt_Tremolo2
MOVE.B  n_tremolocmd(A6),D2
AND.B   #\$0F,D0
BEQ.S   mt_treskip
AND.B   #\$F0,D2
OR.B    D0,D2
mt_treskip
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$F0,D0
BEQ.S   mt_treskip2
AND.B   #\$0F,D2
OR.B    D0,D2
mt_treskip2
MOVE.B  D2,n_tremolocmd(A6)
mt_Tremolo2
MOVE.B  n_tremolopos(A6),D0
LEA mt_ViBRAtoTable(PC),A4
LSR.W   #2,D0
AND.W   #\$001F,D0
MOVEQ   #0,D2
MOVE.B  n_wavecontrol(A6),D2
LSR.B   #4,D2
AND.B   #\$03,D2
BEQ.S   mt_tre_sine
LSL.B   #3,D0
CMP.B   #1,D2
BEQ.S   mt_tre_rampdown
MOVE.B  #255,D2
BRA.S   mt_tre_set
mt_tre_rampdown
TST.B   n_viBRAtopos(A6)
BPL.S   mt_tre_rampdown2
MOVE.B  #255,D2
SUB.B   D0,D2
BRA.S   mt_tre_set
mt_tre_rampdown2
MOVE.B  D0,D2
BRA.S   mt_tre_set
mt_tre_sine
MOVE.B  (A4,D0.W),D2
mt_tre_set
MOVE.B  n_tremolocmd(A6),D0
AND.W   #15,D0
MULU    D0,D2
LSR.W   #6,D2
MOVEQ   #0,D0
MOVE.B  n_volume(A6),D0
TST.B   n_tremolopos(A6)
BMI.S   mt_TremoloNeg
BRA.S   mt_Tremolo3
mt_TremoloNeg
SUB.W   D2,D0
mt_Tremolo3
BPL.S   mt_TremoloSkip
CLR.W   D0
mt_TremoloSkip
CMP.W   #\$40,D0
BLS.S   mt_TremoloOk
MOVE.W  #\$40,D0
mt_TremoloOk
MOVE.W  D0,8(A5)
MOVE.B  n_tremolocmd(A6),D0
LSR.W   #2,D0
AND.W   #\$003C,D0
RTS

mt_SampleOffset
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
BEQ.S   mt_sononew
MOVE.B  D0,n_sampleoffset(A6)
mt_sononew
MOVE.B  n_sampleoffset(A6),D0
LSL.W   #7,D0
CMP.W   n_length(A6),D0
BGE.S   mt_sofskip
SUB.W   D0,n_length(A6)
LSL.W   #1,D0
RTS
mt_sofskip
MOVE.W  #\$0001,n_length(A6)
RTS

mt_VolumeSlide
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
LSR.B   #4,D0
TST.B   D0
BEQ.S   mt_VolSlideDown
mt_VolSlideUp
CMP.B   #\$40,n_volume(A6)
BMI.S   mt_vsuskip
MOVE.B  #\$40,n_volume(A6)
mt_vsuskip
MOVE.B  n_volume(A6),D0
MOVE.W  D0,8(A5)
RTS

mt_VolSlideDown
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
mt_VolSlideDown2
SUB.B   D0,n_volume(A6)
BPL.S   mt_vsdskip
CLR.B   n_volume(A6)
mt_vsdskip
MOVE.B  n_volume(A6),D0
MOVE.W  D0,8(A5)
RTS

mt_PositionJump
MOVE.B  n_cmdlo(A6),D0
SUBQ.B  #1,D0
MOVE.B  D0,mt_SongPos
mt_pj2  CLR.B   mt_PBreakPos
ST  mt_PosJumpFlag
RTS

mt_VolumeChange
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
CMP.B   #\$40,D0
BLS.S   mt_VolumeOk
MOVEQ   #\$40,D0
mt_VolumeOk
MOVE.B  D0,n_volume(A6)
MOVE.W  D0,8(A5)
RTS

mt_PatternBreak
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
MOVE.L  D0,D2
LSR.B   #4,D0
MULU    #10,D0
AND.B   #\$0F,D2
CMP.B   #63,D0
BHI.S   mt_pj2
MOVE.B  D0,mt_PBreakPos
ST  mt_PosJumpFlag
RTS

mt_SetSpeed
MOVEQ   #0,D0
MOVE.B  3(A6),D0
BEQ mt_end
CMP.B   #32,D0
BHS SetTempo
CLR.B   mt_counter
MOVE.B  D0,mt_speed
RTS

mt_CheckMoreEfx
BSR mt_UpdateFunk
MOVE.B  2(A6),D0
AND.B   #\$0F,D0
CMP.B   #\$9,D0
BEQ mt_SampleOffset
CMP.B   #\$B,D0
BEQ mt_PositionJump
CMP.B   #\$D,D0
BEQ.S   mt_PatternBreak
CMP.B   #\$E,D0
BEQ.S   mt_E_Commands
CMP.B   #\$F,D0
BEQ.S   mt_SetSpeed
CMP.B   #\$C,D0
BEQ mt_VolumeChange
BRA mt_PerNop

mt_E_Commands
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$F0,D0
LSR.B   #4,D0
BEQ.S   mt_FilterOnOff
CMP.B   #1,D0
BEQ mt_FinePortaUp
CMP.B   #2,D0
CMP.B   #3,D0
BEQ.S   mt_SetGlissControl
CMP.B   #4,D0
BEQ mt_SetViBRAtoControl
CMP.B   #5,D0
BEQ mt_SetFineTune
CMP.B   #6,D0
BEQ mt_JumpLoop
CMP.B   #7,D0
BEQ mt_SetTremoloControl
CMP.B   #9,D0
BEQ mt_RetrigNote
CMP.B   #\$A,D0
BEQ mt_VolumeFineUp
CMP.B   #\$B,D0
BEQ mt_VolumeFineDown
CMP.B   #\$C,D0
BEQ mt_NoteCut
CMP.B   #\$D,D0
BEQ mt_NoteDelay
CMP.B   #\$E,D0
BEQ mt_PatternDelay
CMP.B   #\$F,D0
BEQ mt_FunkIt
RTS

mt_FilterOnOff
MOVE.B  n_cmdlo(A6),D0
AND.B   #1,D0
ASL.B   #1,D0
AND.B   #\$FD,\$BFE001
OR.B    D0,\$BFE001
RTS

mt_SetGlissControl
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
AND.B   #\$F0,n_glissfunk(A6)
OR.B    D0,n_glissfunk(A6)
RTS

mt_SetViBRAtoControl
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
AND.B   #\$F0,n_wavecontrol(A6)
OR.B    D0,n_wavecontrol(A6)
RTS

mt_SetFineTune
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
MOVE.B  D0,n_finetune(A6)
RTS

mt_JumpLoop
TST.B   mt_counter
BNE mt_Return
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
BEQ.S   mt_SetLoop
TST.B   n_loopcount(A6)
BEQ.S   mt_jumpcnt
SUBQ.B  #1,n_loopcount(A6)
BEQ mt_Return
mt_jmploop  MOVE.B  n_pattpos(A6),mt_PBreakPos
ST  mt_PBreakFlag
RTS

mt_jumpcnt
MOVE.B  D0,n_loopcount(A6)
BRA.S   mt_jmploop

mt_SetLoop
MOVE.W  mt_PatternPos(PC),D0
LSR.W   #4,D0
MOVE.B  D0,n_pattpos(A6)
RTS

mt_SetTremoloControl
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
LSL.B   #4,D0
AND.B   #\$0F,n_wavecontrol(A6)
OR.B    D0,n_wavecontrol(A6)
RTS

mt_RetrigNote
MOVE.L  D1,-(SP)
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
BEQ.S   mt_rtnend
MOVEQ   #0,D1
MOVE.B  mt_counter(PC),D1
BNE.S   mt_rtnskp
MOVE.W  (A6),D1
AND.W   #\$0FFF,D1
BNE.S   mt_rtnend
MOVEQ   #0,D1
MOVE.B  mt_counter(PC),D1
mt_rtnskp
DIVU    D0,D1
SWAP    D1
TST.W   D1
BNE.S   mt_rtnend
mt_DoRetrig
;   MOVE.W  n_dmabit(A6),\$DFF096    ; Channel DMA off
MOVE.L  n_start(A6),(A5)    ; Set sampledata pointer
MOVE.W  n_length(A6),4(A5)  ; Set length
MOVE.W  n_dmabit(A6),D0
BSR mt_PlaySamples      ; this does the magic
MOVE.L  n_loopstart(A6),(A5)
MOVE.L  n_replen(A6),4(A5)
mt_rtnend
MOVE.L  (SP)+,D1
RTS

mt_VolumeFineUp
TST.B   mt_counter
BNE mt_Return
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$F,D0
BRA mt_VolSlideUp

mt_VolumeFineDown
TST.B   mt_counter
BNE mt_Return
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
BRA mt_VolSlideDown2

mt_NoteCut
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
CMP.B   mt_counter(PC),D0
BNE mt_Return
CLR.B   n_volume(A6)
MOVE.W  #0,8(A5)
RTS

mt_NoteDelay
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
CMP.B   mt_counter,D0
BNE mt_Return
MOVE.W  (A6),D0
BEQ mt_Return
MOVE.L  D1,-(SP)
BRA mt_DoRetrig

mt_PatternDelay
TST.B   mt_counter
BNE mt_Return
MOVEQ   #0,D0
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
TST.B   mt_PattDelTime2
BNE mt_Return
MOVE.B  D0,mt_PattDelTime
RTS

mt_FunkIt
TST.B   mt_counter
BNE mt_Return
MOVE.B  n_cmdlo(A6),D0
AND.B   #\$0F,D0
LSL.B   #4,D0
AND.B   #\$0F,n_glissfunk(A6)
OR.B    D0,n_glissfunk(A6)
TST.B   D0
BEQ mt_Return
mt_UpdateFunk
MOVEM.L A0/D1,-(SP)
MOVEQ   #0,D0
MOVE.B  n_glissfunk(A6),D0
LSR.B   #4,D0
BEQ.S   mt_funkend
LEA mt_FunkTable(PC),A0
MOVE.B  (A0,D0.W),D0
BTST    #7,n_funkoffset(A6)
BEQ.S   mt_funkend
CLR.B   n_funkoffset(A6)

MOVE.L  n_loopstart(A6),D0
MOVEQ   #0,D1
MOVE.W  n_replen(A6),D1
MOVE.L  n_wavestart(A6),A0
CMP.L   D0,A0
BLO.S   mt_funkok
MOVE.L  n_loopstart(A6),A0
mt_funkok
MOVE.L  A0,n_wavestart(A6)
MOVEQ   #-1,D0
SUB.B   (A0),D0
MOVE.B  D0,(A0)
mt_funkend
MOVEM.L (SP)+,A0/D1
RTS

mt_FunkTable dc.b 0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128

mt_ViBRAtoTable
dc.b   0, 24, 49, 74, 97,120,141,161
dc.b 180,197,212,224,235,244,250,253
dc.b 255,253,250,244,235,224,212,197
dc.b 180,161,141,120, 97, 74, 49, 24

mt_PeriodTable
; Tuning 0, Normal
dc.w    856,808,762,720,678,640,604,570,538,508,480,453
dc.w    428,404,381,360,339,320,302,285,269,254,240,226
dc.w    214,202,190,180,170,160,151,143,135,127,120,113
; Tuning 1
dc.w    850,802,757,715,674,637,601,567,535,505,477,450
dc.w    425,401,379,357,337,318,300,284,268,253,239,225
dc.w    213,201,189,179,169,159,150,142,134,126,119,113
; Tuning 2
dc.w    844,796,752,709,670,632,597,563,532,502,474,447
dc.w    422,398,376,355,335,316,298,282,266,251,237,224
dc.w    211,199,188,177,167,158,149,141,133,125,118,112
; Tuning 3
dc.w    838,791,746,704,665,628,592,559,528,498,470,444
dc.w    419,395,373,352,332,314,296,280,264,249,235,222
dc.w    209,198,187,176,166,157,148,140,132,125,118,111
; Tuning 4
dc.w    832,785,741,699,660,623,588,555,524,495,467,441
dc.w    416,392,370,350,330,312,294,278,262,247,233,220
dc.w    208,196,185,175,165,156,147,139,131,124,117,110
; Tuning 5
dc.w    826,779,736,694,655,619,584,551,520,491,463,437
dc.w    413,390,368,347,328,309,292,276,260,245,232,219
dc.w    206,195,184,174,164,155,146,138,130,123,116,109
; Tuning 6
dc.w    820,774,730,689,651,614,580,547,516,487,460,434
dc.w    410,387,365,345,325,307,290,274,258,244,230,217
dc.w    205,193,183,172,163,154,145,137,129,122,115,109
; Tuning 7
dc.w    814,768,725,684,646,610,575,543,513,484,457,431
dc.w    407,384,363,342,323,305,288,272,256,242,228,216
dc.w    204,192,181,171,161,152,144,136,128,121,114,108
; Tuning -8
dc.w    907,856,808,762,720,678,640,604,570,538,508,480
dc.w    453,428,404,381,360,339,320,302,285,269,254,240
dc.w    226,214,202,190,180,170,160,151,143,135,127,120
; Tuning -7
dc.w    900,850,802,757,715,675,636,601,567,535,505,477
dc.w    450,425,401,379,357,337,318,300,284,268,253,238
dc.w    225,212,200,189,179,169,159,150,142,134,126,119
; Tuning -6
dc.w    894,844,796,752,709,670,632,597,563,532,502,474
dc.w    447,422,398,376,355,335,316,298,282,266,251,237
dc.w    223,211,199,188,177,167,158,149,141,133,125,118
; Tuning -5
dc.w    887,838,791,746,704,665,628,592,559,528,498,470
dc.w    444,419,395,373,352,332,314,296,280,264,249,235
dc.w    222,209,198,187,176,166,157,148,140,132,125,118
; Tuning -4
dc.w    881,832,785,741,699,660,623,588,555,524,494,467
dc.w    441,416,392,370,350,330,312,294,278,262,247,233
dc.w    220,208,196,185,175,165,156,147,139,131,123,117
; Tuning -3
dc.w    875,826,779,736,694,655,619,584,551,520,491,463
dc.w    437,413,390,368,347,328,309,292,276,260,245,232
dc.w    219,206,195,184,174,164,155,146,138,130,123,116
; Tuning -2
dc.w    868,820,774,730,689,651,614,580,547,516,487,460
dc.w    434,410,387,365,345,325,307,290,274,258,244,230
dc.w    217,205,193,183,172,163,154,145,137,129,122,115
; Tuning -1
dc.w    862,814,768,725,684,646,610,575,543,513,484,457
dc.w    431,407,384,363,342,323,305,288,272,256,242,228
dc.w    216,203,192,181,171,161,152,144,136,128,121,114

mt_chan1temp    dc.l    0,0,0,0,0,\$00010000,0,  0,0,0,0
mt_chan2temp    dc.l    0,0,0,0,0,\$00020000,0,  0,0,0,0
mt_chan3temp    dc.l    0,0,0,0,0,\$00040000,0,  0,0,0,0
mt_chan4temp    dc.l    0,0,0,0,0,\$00080000,0,  0,0,0,0

mt_SampleStarts dc.l    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dc.l    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

mt_SongDataPtr  dc.l 0
mt_speed    dc.b 6
mt_counter  dc.b 0
mt_SongPos  dc.b 0
mt_PBreakPos    dc.b 0
mt_PosJumpFlag  dc.b 0
mt_PBreakFlag   dc.b 0
mt_PattDelTime  dc.b 0
mt_PattDelTime2 dc.b 0
mt_Enable   dc.b 0
mt_PatternPos   dc.w 0
mt_DMACONtemp   dc.w 0

;------------------------------------------------------------------------------

;------------------------------------------------------------------------------

Gamefield       incbin  "Work:MyProjects/Game/GameFieldStuff/level1.gamefield"
Gamefield2      incbin  "Work:MyProjects/Game/GameFieldStuff/level2.gamefield"
Gamefield3      incbin  "Work:MyProjects/Game/GameFieldStuff/level3.gamefield"

Coords1         incbin  "Work:MyProjects/Game/Coords/Coords4"
Coords2         incbin  "Work:MyProjects/Game/Coords/3Coords2"
Coords3         incbin  "Work:MyProjects/Game/Coords/3Coords3"
even

Fontti          incbin  "Work:MyProjects/Game/BPL/Font"

gfxname         dc.b    "graphics.liBRAry",0
intuiname       dc.b    "intuition.liBRAry",0
dosname         dc.b    "dos.liBRAry",0

vertname        dc.b    "Music interrupt",0

xwars           dc.b    "A?JOURNEY?TO?HOME",0
codingby        dc.b    "CODING?BY?MARKUS?KETOLA",0
musicby         dc.b    "MUSIC?BY?VARIOUS?PEOPLE",0
titlemusicby    dc.b    "TITLE?MUSIC?BY?CHIPPER",0
ingamemusicby   dc.b    "IN?GAME?MUSIC?BY?MERLIN?M",0
endmusicby      dc.b    "END?MUSIC?BY?HEATBEAT",0

press           dc.b    "PRESS?JOYSTICK?BUTTON?TO?PLAY",0
gameover        dc.b    "GAME?OVER",0
pressjoy        dc.b    "PRESS?JOYSTICK?BUTTON",0
udidit          dc.b    "YOU?DID?IT",0
leftmouse       dc.b    "PRESS?LEFT?MOUSEBUTTON?TO?EXIT",0
usejoy          dc.b    "USE?JOYSTICK?TO",0
type            dc.b    "TYPE?YOUR?INITIALS",0
even

section Muuttujat,DATA

intuibase       dc.l    0
gfxbase         dc.l    0
dosbase         dc.l    0
ptbase          dc.l    0

;------------------------------------------------------------------------------
; Räjähdystietue
; WORD  Kehissä 0/1
; WORD   x
; WORD   y
; WORD   viive
; LONG   Pointteri grafiikkadataan. Tämä on pelkkä lisäysarvo
Explosions       ds.b   12*20
dc.w   -1

; ExpVanhaSij0 rakenne
; LONG  ClearScreen-osoite
; LONG   Vanha sijainti -osoite
; WORD   BLITSIZE

ExpVanhaSij0     ds.b   10*20
ExpVanhaSij1     ds.b   10*20

;------------------------------------------------------------------------------
; Monsterin räjähdystietue
;------------------------------------------------------------------------------
; WORD Kehissä 0/1
; WORD x
; WORD y
; WORD viive
; LONG Pointteri grafiikkadataan, pelkkä lisäysarvo

Monster_explosion   ds.b    12

MExp_VanhaSij0      ds.b    10
MExp_VanhaSij1      ds.b    10

;------------------------------------------------------------------------------
; VanhaSijX:n rakenne: LONG,LONG,WORD

VanhaSij1           ds.w    max_bobs+(4*max_bobs)
VanhaSij2           ds.w    max_bobs+(4*max_bobs)

;------------------------------------------------------------------------------
; Rakenne: LONG,WORD
; LONG: Pointteri Coordinaatteihin, WORD: ON/OFF (1=ON, 0=OFF)
; WORD kestävyys, LONG pointteri bob-dataan, LONG pointteri mask-dataan
; Tässä versiossa kaikkien wordien pitää olla ykkösiä aluksi!

PTRsAndONOFF        ds.b    16*max_bobs

;------------------------------------------------------------------------------
; Rakenne: LONG,LONG: ClearScreen(osoite),Vanhasijainti(osoite)

VanhaESij1          ds.l    (AmountEBullets+1)*2
VanhaESij2          ds.l    (AmountEBullets+1)*2
;------------------------------------------------------------------------------
; Rakenne WORD,WORD=x,y. Jos x=-1,niin laaki ei ole liikenteessä (=vapaa)
; Aluksi kaikkien x:ien pitää olla -1!!

EnemyLaakit         ds.w    (AmountEBullets+1)*2

;------------------------------------------------------------------------------
; (0,0,0)=Laaki kehissä/ei kehissä,x,y)

Laakit              ds.w    (AmountBullets+1)*3
dc.w    -1

;------------------------------------------------------------------------------
; Monster-tietue
;
; WORD MX
; WORD MY
; WORD Kestävyys
; WORD Laaki liikkeelä
; LONG Bullet X
; LONG Bullet Y
; WORD Laaki liikkeellä
; LONG Bullet X
; LONG Bullet Y
; WORD Laaki liikkeellä
; LONG Bullet X
; LONG Bullet Y
; LONG BobData

Monster ds.b    68

;------------------------------------------------------------------------------
; Unit rakenne.
; WORD Liikkellä 0/1        0
; LONG UnitX                2
; LONG UnitY                6
; WORD Laaki liikkeellä     10
; LONG Bullet X             12
; LONG Bullet Y             16
; LONG UnitBob              28
; LONG ExplodedUnit         36
; WORD Kestävyys            44
; WORD Liikkuvako           46 Jos 0, niin liikkuu vain 1.:set 16 pikseliä
;--------------------------
;                       48
Units           ds.b    48*5
UnitsVanhaSij0  ds.b    10*5
UnitsVanhaSij1  ds.b    10*5
UnitsVBSij0     ds.b    10*5
UnitsVBSij1     ds.b    10*5

; UnitLiikkeellä, unit x, unit y, laaki liikkeellä, bullet X, bullet Y,
; UnitClearScr, UnitVanhaSij, UnitBulletClearScr, UnitBulletVanhaSij,
;

;------------------------------------------------------------------------------
; Asteroids-tietue: Liikkeellä-merkki, x,y,speed, Kestävyys
;
; Tässä laitetaan 28 asteroidia
;

Asteroids       ds.w    5*28
VanhaAstSij0    ds.w    28+(4*28)
VanhaAstSij1    ds.w    28+(4*28)

;------------------------------------------------------------------------------
; Monsterille vanhasijaintistuff
MonstVanhaSij0  ds.b    10
MonstVanhaSij1  ds.b    10
MonstBVanhaSij0 ds.b    30
MonstBVanhaSij1 ds.b    30

;------------------------------------------------------------------------------
ScrollOffset    dc.l    (256+16+16)*4*32
LaakiPT         dc.l    0       ; Missä kohtaa laakeja ollaan menossa

Exp_PT          dc.l    0           ;
VanhaExpSij     dc.l    0
MExp_vanhasij   dc.l    0

UnitsVanhaSij   dc.l    0
UnitsVBSij      dc.l    0

VanhaAstSij     dc.l    0
VanhaSij        dc.l    0       ; Vihollisten vanha sijainti
VanhaESij       dc.l    0       ; Vihollisten laakien vanha sijainti

MonsterVanhaSij dc.l    0
MonstBVanhaSij  dc.l    0

coolfield       dc.l    0

x               dc.w    128
y               dc.w    235
MX              dc.w    32
MY              dc.w    -64
DX              dc.w    1

Nr_of_asteroids dc.w    0

LineN           dc.l    256     ; Blo(c)kin y-paikka
Bl_paikka       dc.l    0       ; Blo(c)kin x-paikka
pt_toCoolF      dc.l    0       ; 2048
pt_toClear      dc.l    0
Coords          dc.l    0
BitMap1         dc.l    0
BitMap2         dc.l    0
ClearScreen     dc.l    0       ; Pelkästään scrollaava alue
ShowScreen      dc.l    0
DrawScreen      dc.l    0
AttackWavePointer dc.l  0
monster         dc.l   0

outfile         dc.l    0

Random          dc.w    0
Pisteet         dc.w    0

wbenchmsg       dc.l    0
oldview         dc.l    0
process         dc.l    0
processor       dc.w    0
chiprev         dc.b    0

level           dc.b    1

LastCBFrames    dc.b    0
Kumpainen       dc.b    0
LameFrame       dc.b    0
Frame           dc.b    0
NPohjassa       dc.b    0
AmEnemies       dc.b    0
MovingEBullets  dc.b    0       ; Liikkeellä olevien EnemyBullettien määrä
energia         dc.b    16

gameOver        dc.b    0

DoLastCoordBobFrames    dc.b 0
CoordBobsRunning        dc.b 0      ; Ovatko koordinaativalmiit bobit liikkeellä
nr_of_bobs              dc.b 0
Asteroids_on_screen     dc.b 0
AsteroidsRunning        dc.b 0
LastAsteroidFrames      dc.b 3
OwnBulletsOnScreen      dc.b 0
NrOfOwnBullets          dc.b 0
MonsterKehissa          dc.b 0
Monster_destroyed       dc.b 0
MExpFinished            dc.b 0
LastMExpFrames          dc.b 0

phase                   dc.b    0
delay                   dc.b    0
kierros                 dc.b    0

even

viive           dc.b  0
letterstyped    dc.b    0
currentchar     dc.b    'A'
small_font      dc.b    0
even
bitmap          dc.l    0
pt_Font         dc.l    0

hiscoretable
dc.l    Nimi1
dc.w    12345
dc.l    Nimi2
dc.w    2345
dc.l    Nimi3
dc.w    345
dc.l    Nimi4
dc.w    45
dc.l    Nimi5
dc.w    5

Nimi1               dc.b    "ABC",0
Nimi2               dc.b    "DEF",0
Nimi3               dc.b    "GHI",0
Nimi4               dc.b    "JKL",0
Nimi5               dc.b    "MNO",0

Nimi                dc.b    "   ",0,0,0,0,0,0,0,0,0
Luku                dc.b    0,0,0,0,0,0
LevelTXT            dc.b    "LEVEL?0",0,0

Number              dc.b     0,0,0,0,0
even

; Vertical blanking -keskeytyksen strukture

Vert_str:       dc.l    0           ; Käyttis asettaa
dc.l    0           ;
dc.b    2           ; Nodetyyppi=NT_INTERRUPT
dc.b    0           ; Priotiteetti
dc.l    vertname
dc.l    0           ; Kesk.rut.lle tuleva tieto
dc.l    Keskeytysrutiini ; Kesk. alkuosoite

section ChipData,DATA,CHIP

Coolfield       ds.b    5120*4
dc.l    999     ; Loppumerrki
Coolfield2       ds.b    5120*4
dc.l       999
Coolfield3       ds.b    5120*4
dc.l       999

Dummy           dc.l    0

;EsBob          incbin  "Work:MyProjects/Game/BPL/NewEs.bob"
RengasBob       incbin  "Work:MyProjects/Game/BPL/Rengas.bob"

;UfoBob         incbin  "Work:MyProjects/Game/BPL/Ufo.bob"
ShipBob         incbin  "Work:MyProjects/Game/BPL/alus.bob"
WBob            incbin  "Work:MyProjects/Game/BPL/w.bob"
;ThreeShipBob   incbin  "Work:MyProjects/Game/BPL/3-osainen_alus.bob"

Bob             incbin  "Work:MyProjects/Game/BPL/es.bob"
EnBulletBob     incbin  "Work:MyProjects/Game/BPL/newEnemyBullet.bob"
Blocks          incbin  "Work:MyProjects/Game/BPL/4BPLBlocks"
Unit            incbin  "Work:MyProjects/Game/BPL/Unit.bob"
ExplodedUnit    incbin  "Work:MyProjects/Game/BPL/ExplodedUnit.bob"
AsteroidBob     incbin  "Work:MyProjects/Game/BPL/NewAsteroid.bob"
Explosion       incbin  "Work:MyProjects/Game/BPL/Explosion8Frames"
MonsterBob      incbin  "Work:MyProjects/Game/BPL/Monster_draft_smaller.bob"
MonsterBullet   incbin  "Work:MyProjects/Game/BPL/Monster_bullet.bob"
MonsterExplosionBob incbin "Work:MyProjects/Game/BPL/Monster_explosion_smaller_2.bo"
Monster2Bob     incbin  "Work:MyProjects/Game/BPL/Monster2_draft_smaller.bob"
Monster3Bob     incbin  "Work:MyProjects/Game/BPL/Monster3_draft_smaller.bob"

Score           incbin  "Work:MyProjects/Game/BPL/NewScore"

Numbers         incbin  "Work:MyProjects/Game/BPL/NewNumbers"

even

CopperLista
dc.w    \$00e0
high1   dc.w    \$0000
dc.w    \$00e2
low1    dc.w    \$0000
dc.w    \$00e4
high2   dc.w    \$0000
dc.w    \$00e6
low2    dc.w    \$0000
dc.w    \$00e8
high3   dc.w    \$0000
dc.w    \$00ea
low3    dc.w    \$0000
dc.w    \$00ec
high4   dc.w    \$0000
dc.w    \$00ee
low4    dc.w    \$0000
dc.w    \$0100,\$4200
dc.w    \$0102,\$0000
dc.w    \$0108,\$0060
dc.w    \$010a,\$0060
dc.w    \$0092,\$0048
dc.w    \$0094,\$00c0
dc.w    \$008e,\$2c81
dc.w    \$0090,\$2ca1

dc.w    \$0120
s0_high dc.w    \$0000
dc.w    \$0122
s0_low: dc.w    \$0000
dc.w    \$0124
s1_high dc.w    \$0000
dc.w    \$0126
s1_low: dc.w    \$0000
dc.w    \$0128
s2_high dc.w    \$0000
dc.w    \$012a
s2_low  dc.w    \$0000
empty   dc.w    \$012c
dc.w    \$0000
dc.w    \$012e
dc.w    \$0000
dc.w    \$0130
dc.w    \$0000
dc.w    \$0132
dc.w    \$0000
dc.w    \$0134
dc.w    \$0000
dc.w    \$0136
dc.w    \$0000
dc.w    \$0138
dc.w    \$0000
dc.w    \$013a
dc.w    \$0000
dc.w    \$013c,\$0000
dc.w    \$013e,\$0000

Colours
dc.w    \$0182,\$0000
dc.w    \$0184,\$0000
dc.w    \$0186,\$0000
dc.w    \$0188,\$0000
dc.w    \$018a,\$0000
dc.w    \$018c,\$0000
dc.w    \$018e,\$0000
dc.w    \$0190,\$0000
dc.w    \$0192,\$0000
dc.w    \$0194,\$0000
dc.w    \$0196,\$0000
dc.w    \$0198,\$0000
dc.w    \$019a,\$0000
dc.w    \$019c,\$0000
dc.w    \$019e,\$0000

; Energiapalkin värit

dc.w    \$3101,\$ff00,\$01aa,\$0ff0
dc.w    \$3201,\$ff00,\$01aa,\$0cf0
dc.w    \$3301,\$ff00,\$01aa,\$09f0
dc.w    \$3401,\$ff00,\$01aa,\$06f0
dc.w    \$3501,\$ff00,\$01aa,\$03f0
dc.w    \$3601,\$ff00,\$01aa,\$00f0
dc.w    \$3701,\$ff00,\$01aa,\$00f3
dc.w    \$3801,\$ff00,\$01aa,\$00f6
dc.w    \$3901,\$ff00,\$01aa,\$00f9
dc.w    \$3a01,\$ff00,\$01aa,\$00fc
dc.w    \$3b01,\$ff00,\$01aa,\$00ff
dc.w    \$3c01,\$ff00,\$01aa,\$00cf
dc.w    \$3d01,\$ff00,\$01aa,\$009f
dc.w    \$3e01,\$ff00,\$01aa,\$006f
dc.w    \$3f01,\$ff00,\$01aa,\$003f
dc.w    \$4001,\$ff00,\$01aa,\$000f

;           dc.w    \$4101,\$ff00,\$01aa,\$0fff

dc.w    \$ffff,\$fffe

SPR2    dc.l    \$00000000
dc.l    \$e0000000,\$e0000000,\$e0000000,\$e0000000
dc.l    \$e0000000,\$e0000000,\$e0000000,\$e0000000
dc.l    \$e0000000,\$e0000000,\$e0000000,\$e0000000
dc.l    \$e0000000,\$e0000000,\$e0000000,\$e0000000
dc.l    \$00000000

; Aluksi oma sprite-alus, sitten spritelaakit (30)
SPR1            dc.w    \$0000,\$0000,\$0100,\$0000,\$4284,\$0180,\$A28A,\$6186,\$A44A,\$63C6,\$A44A,\$63C6,\$A92A,\$66E6,\$AAAA,\$65E6,\$B29A,\$6DF6
dc.w    \$B45A,\$6BF6,\$B55A,\$6BF6,\$B55A,\$6AF6,\$B45A,\$6BF6,\$F7DE,\$2872,\$1010,\$0FF0,\$1FF0,\$0010,\$0000,\$0000

SPR0            dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000

dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000

dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000
dc.w    \$0000,\$0000,\$2000,\$0000,\$5000,\$3000,\$5000,\$3000,\$5000,\$3000,\$8800,\$7800,\$8800,\$7800,\$8800,\$7800,\$7000,\$7000

dc.w    \$0000,\$0000

;mt_data        incbin  "ram:thinktwiceiii.mod"

end

```
Posted in Mathematics, Programming

## Generating the Cantor’s Set with Computer

The Cantor’s set is somewhat fascinating fractal, when one gets to more familiar with it.

The basic idea is to handle real number interval [0,1]. This is divided to three parts of same width removing the middle part. The remaining parts are again divided to three parts of same width removing always the middle part. This is continued infinitely.

The Cantor’s set consists of the points that are left in this process.

In the language of the set theory the Cantor’s set can be expressed as follows:

The union tells what doesn’t belong to the set.

I have used this formula to implement the Cantor’s set in my program. The idea is to examine the union interval and draw a pixel, when the point does belong to the set.

Below is a picture from the program’s output:

Here’s the Java program in full:

```import java.awt.*;
import javax.swing.*;
import java.awt.event.WindowEvent;
import java.lang.Math;

public class Cantor {

private JFrame frame;
private CantorPanel panel;

public Cantor() {
frame = new JFrame("The Cantor's Set");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initialize();
frame.pack();
frame.setVisible(true);
}

private void initialize() {
panel = new CantorPanel();
}

public static void main(String args[]) {
new Cantor();
}
}

class CantorPanel extends JPanel {

public CantorPanel() {

setBackground(Color.lightGray);
setPreferredSize(new Dimension(1024,100));
}

public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;

drawCantor(g, 7);
}

public void drawCantor(Graphics g, int maxIter) {

int y = 17;

for (int m = 1; m < maxIter + 1; m++) {

for (int x = 0; x < 1024; x++) {

if (belongsToSet(m,x) == true) g.drawOval(x,y,1,1);
}
y = y + 10;
}
}

public boolean belongsToSet(int m, double x) {

double line = 1024;
double x1,x2;

for(int mm = 1; mm < m ; mm++) {

for (int k = 0; k < (int)((Math.pow(3,(mm-1))) - 1 + 1); k++) {

x1 = (3.0*k + 1) / Math.pow(3.0,mm);
x2 = (3.0*k + 2) / Math.pow(3.0,mm);

if ((x > x1 * line) && (x < x2 * line)) return false;

}

}
return true;
}

}
```

Because of the calculation precision with “big” number of iterations drawing accuracy isn’t very good.

The program is free for personal and educational use.