@@ -39,29 +39,263 @@
unsigned char RA;
// Pointers for the arrays, images and sprites on 0xB2 page
-unsigned int StoryPalette = 0x8000; // 1160 [145][8]
-unsigned int MinionSprites = 0x8000 + 1160; // 2464 [2][4][308]
-unsigned int BananaPic = 0x8000 + 3624; // 67 [67]
-unsigned int Bricks = 0x8000 + 3691; // 76 [2][38]
-unsigned int MenuText = 0x8000 + 3767; // 264 [4][66]
-unsigned int GameWorm = 0x8000 + 4031; // 64 [2][32]
-unsigned int MenuWorm = 0x8000 + 4095; // 112 [2][56]
-unsigned int HeartPic = 0x8000 + 4207; // 77 [77]
-unsigned int EndText = 0x8000 + 4284; // 93 [93]
-unsigned int ReadyText = 0x8000 + 4377; // 121 [121]
-unsigned int QuitText = 0x8000 + 4498; // 122 [122]
-unsigned int Digits = 0x8000 + 4620; // 160 [10][16]
-unsigned int PX = 0x8000 + 4780; // 400 [2][MaxWorm=200]
-unsigned int PY = 0x8000 + 5180; // 400 [2][MaxWorm=200]
+static const unsigned int StoryPalette = 0x8000; // 1160 [145][8]
+static const unsigned int MinionSprites = 0x8000 + 1160; // 2464 [2][4][308]
+static const unsigned int BananaPic = 0x8000 + 3624; // 67 [67]
+static const unsigned int Bricks = 0x8000 + 3691; // 76 [2][38]
+static const unsigned int MenuText = 0x8000 + 3767; // 264 [4][66]
+static const unsigned int GameWorm = 0x8000 + 4031; // 64 [2][32]
+static const unsigned int MenuWorm = 0x8000 + 4095; // 112 [2][56]
+static const unsigned int HeartPic = 0x8000 + 4207; // 77 [77]
+static const unsigned int EndText = 0x8000 + 4284; // 93 [93]
+static const unsigned int ReadyText = 0x8000 + 4377; // 121 [121]
+static const unsigned int QuitText = 0x8000 + 4498; // 122 [122]
+static const unsigned int Digits = 0x8000 + 4620; // 160 [10][16]
+static const unsigned int PX = 0x8000 + 4780; // 400 [2][MaxWorm=200]
+static const unsigned int PY = 0x8000 + 5180; // 400 [2][MaxWorm=200]
// Music
unsigned char Volume = 50, VolumeInc = 1, MusicPtr;
static unsigned char Music[] = { 37, 12, 45, 12, 37, 12, 45, 12, 37, 12, 45, 6, 37, 31,
41, 12, 41, 12, 41, 12, 41, 12, 37, 12, 45, 6, 37, 31 };
+#ifdef Z88DK_USES_SDCC
+void Set_EXOS_Var(unsigned char Variable, unsigned char Value) __naked
+{
+ (void) Variable;
+ (void) Value;
+ __asm__ (
+ "ld hl, #2\n"
+ "add hl, sp\n"
+ "ld c, (hl)\n"
+ "inc hl\n"
+ "ld d, (hl)\n"
+ "ld b, #1\n"
+ "rst 0x30\n"
+ ".byte 16\n"
+ "ret\n"
+ );
+}
+
+unsigned char Ask_EXOS_Var(unsigned char Variable) __naked
+{
+ (void) Variable;
+ __asm__ (
+ "ld hl, #2\n"
+ "add hl, sp\n"
+ "ld c, (hl)\n"
+ "ld b, #0\n"
+ "rst 0x30\n"
+ ".byte 16\n"
+ "ld l, d\n"
+ "ret\n"
+ );
+}
+
+/* joystick status (1=right, 2=left, 4=down, 8=up, 16=fire) */
+
+unsigned char Get_Joy(unsigned char Channel, unsigned char Joy_number) __naked
+{
+ (void) Channel;
+ (void) Joy_number;
+ __asm__ (
+ "ld hl, #2\n"
+ "add hl, sp\n"
+ "ld a, (hl)\n"
+ "inc hl\n"
+ "ld c, (hl)\n"
+ "ld b, #9\n"
+ "rst 0x30\n"
+ ".byte 11\n"
+ "ld l, c\n"
+ "ret\n"
+ );
+}
+
+#define Out(port_, value_) { static __sfr __at (port_) tmp_; tmp_ = (value_); }
+#define Peek(addr_) *((unsigned char *) (addr_))
+#define Poke(addr_, value_) *((unsigned char *) (addr_)) = (value_)
+
+void Open_Channel(unsigned char Channel, unsigned int FileNamePtr) __naked
+{
+ (void) Channel;
+ (void) FileNamePtr;
+ __asm__ (
+ "ld hl, #2\n"
+ "add hl, sp\n"
+ "ld a, (hl)\n"
+ "inc hl\n"
+ "ld e, (hl)\n"
+ "inc hl\n"
+ "ld d, (hl)\n"
+ "rst 0x30\n"
+ ".byte 1\n"
+ "ret\n"
+ );
+}
+
+void Close_Channel(unsigned char Channel) __naked
+{
+ (void) Channel;
+ __asm__ (
+ "ld hl, #2\n"
+ "add hl, sp\n"
+ "ld a, (hl)\n"
+ "rst 0x30\n"
+ ".byte 3\n"
+ "ret\n"
+ );
+}
+
+unsigned char Channel_Status(unsigned char Channel) __naked
+{
+ (void) Channel;
+ __asm__ (
+ "ld hl, #2\n"
+ "add hl, sp\n"
+ "ld a, (hl)\n"
+ "rst 0x30\n"
+ ".byte 9\n"
+ "ld l, c\n"
+ "ret\n"
+ );
+}
+
+void Get_Block(unsigned char Channel, unsigned int Bytes, unsigned int BufPtr) __naked
+{
+ (void) Channel;
+ (void) Bytes;
+ (void) BufPtr;
+ __asm__ (
+ "ld hl, #2\n"
+ "add hl, sp\n"
+ "ld a, (hl)\n"
+ "inc hl\n"
+ "ld c, (hl)\n"
+ "inc hl\n"
+ "ld b, (hl)\n"
+ "inc hl\n"
+ "ld e, (hl)\n"
+ "inc hl\n"
+ "ld d, (hl)\n"
+ "rst 0x30\n"
+ ".byte 6\n"
+ "ret\n"
+ );
+}
+
+unsigned char Write_Block(unsigned char Channel, unsigned int Bytes, unsigned int BufPtr) __naked
+{
+ (void) Channel;
+ (void) Bytes;
+ (void) BufPtr;
+ __asm__ (
+ "ld hl, #2\n"
+ "add hl, sp\n"
+ "ld a, (hl)\n"
+ "inc hl\n"
+ "ld c, (hl)\n"
+ "inc hl\n"
+ "ld b, (hl)\n"
+ "inc hl\n"
+ "ld e, (hl)\n"
+ "inc hl\n"
+ "ld d, (hl)\n"
+ "rst 0x30\n"
+ ".byte 8\n"
+ "ld l, a\n"
+ "ret\n"
+ );
+}
+
+void CopyMem(unsigned int From, unsigned int To, unsigned int Count) __z88dk_callee __naked
+{
+ (void) From;
+ (void) To;
+ (void) Count;
+ __asm__ (
+ "pop af\n"
+ "pop hl\n"
+ "pop de\n"
+ "pop bc\n"
+ "push af\n"
+ "ldir\n"
+ "ret\n"
+ );
+}
+
+void FillMem(unsigned int From, unsigned int Count, unsigned char Value) __z88dk_callee __naked
+{
+ (void) From;
+ (void) Count;
+ (void) Value;
+ __asm__ (
+ "pop hl\n"
+ "pop de\n"
+ "pop bc\n"
+ "dec sp\n"
+ "pop af\n"
+ "push hl\n"
+ "ld l, e\n"
+ "ld h, d\n"
+ "ld (hl), a\n"
+ "cpi\n"
+ "ret po\n"
+ "ex de, hl\n"
+ "ldir\n"
+ "ret\n"
+ );
+}
+
+unsigned char Rnd_0_127() __naked
+{
+ __asm__ (
+ "00001$:\n"
+ "ld hl, #0x7fff\n"
+ "ld a, r\n"
+ "xor a, l\n"
+ "add hl, hl\n"
+ "xor a, h\n"
+ "ld l, a\n"
+ "xor a, h\n"
+ "ld h, a\n"
+ "ld (__sdcc_local_00001 + 1), hl\n"
+ "and a, #0x7f\n"
+ "ld l, a\n"
+ "ret\n"
+ );
+}
+
+unsigned char Get_Segment() __naked
+{
+ __asm__ (
+ "rst 0x30\n"
+ ".byte 24\n"
+ "cp a, #1\n"
+ "ld a, c\n"
+ "ld (_SegNum), a\n"
+ "ld l, #0\n"
+ "rl l\n"
+ "ret\n"
+ );
+}
+
+void Free_Segment(unsigned char Segment_Num) __naked
+{
+ (void) Segment_Num;
+ __asm__ (
+ "ld hl, #2\n"
+ "add hl, sp\n"
+ "ld c, (hl)\n"
+ "rst 0x30\n"
+ ".byte 25\n"
+ "ret\n"
+ );
+}
+#else
void Set_EXOS_Var(unsigned char Variable, unsigned char Value)
{
#asm
ld HL,2
@@ -302,8 +536,30 @@
rst 30h
defb 25
#endasm
}
+#endif
+
+static unsigned char Last_IRQ_Cnt = 0;
+
+void Timer_Init()
+{
+ Out(0xB2, 0xFF);
+ Last_IRQ_Cnt = Peek(0xBFEC);
+ Out(0xB2, DataSeg);
+}
+
+void Timer_Wait(unsigned char n)
+{
+ volatile unsigned char *p = (unsigned char *) 0xBFEC;
+ unsigned char t;
+
+ Out(0xB2, 0xFF);
+ while ((unsigned char) ((t = *p) - Last_IRQ_Cnt) < n)
+ ;
+ Last_IRQ_Cnt = t;
+ Out(0xB2, DataSeg);
+}
unsigned char Get_VideoSegments()
{
unsigned char OK;
@@ -451,9 +707,9 @@
void Box16B(unsigned char Screen, unsigned char X_in_bytes, unsigned char Y,
unsigned char XSize_in_bytes, unsigned char YSize, unsigned char Colour)
{
- unsigned char i, j, Value;
+ unsigned char /* i, */ j, Value;
Get_Address(Screen, Y);
VideoOfs += (X_in_bytes + 0xC000);
Value = (Colour & 1) * 12 + (Colour & 2) * 96 + ((Colour & 4) / 4) * 3 + (Colour & 8) * 6;
@@ -498,9 +754,9 @@
unsigned char GetPixel16(unsigned char Screen, unsigned char X, unsigned char Y)
{
Get_Address(Screen, Y);
VideoOfs += (X / 2 + 0xC000);
- return Peek(VideoOfs) && ((X % 2) ? 85 : 170);
+ return Peek(VideoOfs) & ((X % 2) ? 85 : 170);
}
void GetPic16B(unsigned char Screen, unsigned int X_in_bytes, unsigned int Y,
unsigned char XSize_in_bytes, unsigned char YSize, unsigned int Address)
@@ -618,9 +874,9 @@
if (Pic.PixelLines || (y == 0)) {
Get_Block(40, 8, (unsigned int) &Buf[8]);
if ((Block == 3) && (y == 0)) CopyMem((unsigned int) &Buf[8], StoryPalette + 144 * 8, 8);
if (Block < 5) {
- Buf[0] = Pic.PixelLines ? 255 : 256 - Pic.Lines;
+ Buf[0] = Pic.PixelLines ? 255 : (unsigned char) (256 - Pic.Lines);
Buf[1] = Pic.VideoMode;
Buf[2] = 10;
Buf[3] = 52;
Buf[4] = VideoOfs % 256;
@@ -762,17 +1018,17 @@
static unsigned char Video[] = { 6, 'V', 'I', 'D', 'E', 'O', ':' };
static unsigned char Snd[] = { 6, 'S', 'O', 'U', 'N', 'D', ':' };
static unsigned char Error[] = { 15, 'N', 'o', 't', ' ', 'e', 'n', 'o', 'u', 'g', 'h', ' ', 'R', 'A', 'M', '.' };
- Out(0xB2, DataSeg);
Out(0xB3, 255);
SaveLPTAddr = Peek(0xFFF4) + Peek(0xFFF5) * 256 + 16384;
if (Get_VideoSegments() == 0) {
Print(0, (unsigned int) &Error[0]);
GetKey(1);
Term();
return;
}
+ Out(0xB2, DataSeg);
Set_EXOS_Var(7, 255); // Click
Set_EXOS_Var(8, 255); // Stop
Set_EXOS_Var(10, 1); // Key rate
@@ -934,8 +1190,9 @@
Poke(PX, 153); Poke(PY, 93);
Poke(PX + MaxWorm, 9); Poke(PY + MaxWorm, 32);
Bananas = 0; Bananas_to_eat = 10;
Track();
+ Timer_Init();
do {
GetKey(0);
if ((Key == 27) || (Key == 3)) if (Quit()) GameEnd = 1;
if (Key == 'n') GameEnd = 2;
@@ -1076,8 +1333,9 @@
if (PY1 > PY2) Box16(6, PX2, PY2, 6, 2, 0);
}
}
}
+ Timer_Wait(2);
} while (GameEnd == 0);
if (GameEnd == 2) Level++;
// All levels are completed