Added Blocks
This commit is contained in:
parent
31098a6e6b
commit
40ad25b725
BIN
Blocks/BLOCKS.COM
Normal file
BIN
Blocks/BLOCKS.COM
Normal file
Binary file not shown.
BIN
Blocks/CC.COM
Normal file
BIN
Blocks/CC.COM
Normal file
Binary file not shown.
BIN
Blocks/CCOPT.COM
Normal file
BIN
Blocks/CCOPT.COM
Normal file
Binary file not shown.
BIN
Blocks/HEXTOCOM.COM
Normal file
BIN
Blocks/HEXTOCOM.COM
Normal file
Binary file not shown.
34
Blocks/README.md
Normal file
34
Blocks/README.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Blocks
|
||||||
|
|
||||||
|
This is a clon (more or less) of SameGame, a tile-matching puzzle video game, originally released under the name Chain Shot! in 1985 by Kuniaki Moribe (Morisuke).
|
||||||
|
|
||||||
|
The goal of the game is to remove all the blocks of the board.
|
||||||
|
|
||||||
|
Copyright (c) 1999-2018 Miguel García / FloppySoftware
|
||||||
|
|
||||||
|
The file ``kslib.h`` has been modified for VT100 compatibility (insted of VT52) by me (Anna Christina Naß <acn@acn.wtf>.
|
||||||
|
|
||||||
|
Original Repository: https://github.com/MiguelVis/RetroProjects
|
||||||
|
Website: http://www.floppysoftware.es/blocks.html?path=cpm_projects|blocks
|
||||||
|
|
||||||
|
The file ``BLOCKS.COM`` is the compiled game file.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
Move the cursor using Q, O, P and A as shown on the screen.
|
||||||
|
|
||||||
|
## Compile:
|
||||||
|
|
||||||
|
To compile, use MESCC, "Mike's Enhanced Small C Compiler".
|
||||||
|
See: http://www.floppysoftware.es/mescc.html?path=cpm_projects|mescc
|
||||||
|
|
||||||
|
I provide the files neccessary to compile Blocks, using:
|
||||||
|
|
||||||
|
CC BLOCKS
|
||||||
|
CCOPT BLOCKS
|
||||||
|
ZSM BLOCKS
|
||||||
|
HEXTOCOM BLOCKS
|
||||||
|
|
||||||
|
## License:
|
||||||
|
|
||||||
|
GPL Version 2, see copying.txt - valid for MESCC and Blocks.
|
BIN
Blocks/ZSM.COM
Normal file
BIN
Blocks/ZSM.COM
Normal file
Binary file not shown.
866
Blocks/blocks.c
Normal file
866
Blocks/blocks.c
Normal file
@ -0,0 +1,866 @@
|
|||||||
|
/* BLOCKS!
|
||||||
|
|
||||||
|
Game from Floppy Software for MESCC - Mike's Enhanced Small C Compiler.
|
||||||
|
|
||||||
|
Copyright (c) 2012 Miguel I. Garcia Lopez, Valencia, Spain.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
Revisions:
|
||||||
|
|
||||||
|
02 Jul 2012 : Generic CP/M version 1.0 for 24x80 VT52 screen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <mescc.h> /* MESCC header & runtime */
|
||||||
|
#include <string.h> /* We need strlen() */
|
||||||
|
#include <ctype.h> /* We need toupper() */
|
||||||
|
#include <sprintf.h> /* We need sprintf() */
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WORD
|
||||||
|
#define WORD unsigned int
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <kslib.h> /* Screen output for CP/M */
|
||||||
|
#include <kslibfun.h> /* More functions for kslib */
|
||||||
|
|
||||||
|
/* GAME DEFS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BOARD_ROW 6 /* Screen position for board */
|
||||||
|
#define BOARD_COL 25 /* id */
|
||||||
|
|
||||||
|
#define BORDER_ROW 5 /* Screen position for border */
|
||||||
|
#define BORDER_COL 24 /* id */
|
||||||
|
|
||||||
|
#define BOARD_ROWS 10 /* Board rows */
|
||||||
|
#define BOARD_COLS 10 /* Board columns */
|
||||||
|
|
||||||
|
#define BLOCK_COLS 3 /* Block size */
|
||||||
|
#define BLOCK_ROWS 1 /* id */
|
||||||
|
|
||||||
|
#define BLOCK_EMPTY ' ' /* Value if block is empty */
|
||||||
|
|
||||||
|
#define LEVEL_ROW 2 /* Screen position for level info - used to show blocks killed */
|
||||||
|
#define LEVEL_COL 2 /* id */
|
||||||
|
|
||||||
|
#define SCORE_ROW 2 /* Screen position for score info */
|
||||||
|
#define SCORE_COL 73 /* id */
|
||||||
|
|
||||||
|
#define K_UP 'Q' /* Key up */
|
||||||
|
#define K_DOWN 'A' /* Key down */
|
||||||
|
#define K_LEFT 'O' /* Key left */
|
||||||
|
#define K_RIGHT 'P' /* Key right */
|
||||||
|
#define K_EXIT 'X' /* Key exit */
|
||||||
|
#define K_SELECT 'S' /* Key select */
|
||||||
|
#define K_KILL 'K' /* Key kill */
|
||||||
|
#define K_GRAV_UP '1' /* Key gravity up */
|
||||||
|
#define K_GRAV_LEFT '2' /* Key gravity left */
|
||||||
|
#define K_GRAV_RIGHT '3' /* Key gravity right */
|
||||||
|
#define K_GRAV_DOWN '4' /* Key gravity down */
|
||||||
|
|
||||||
|
/* VARIABLES
|
||||||
|
*/
|
||||||
|
|
||||||
|
WORD board[BOARD_ROWS]; /* Array for blocks values <<char *board[] -- MESCC things>> */
|
||||||
|
WORD board_sel[BOARD_ROWS]; /* Array for blocks selections <<id>> */
|
||||||
|
|
||||||
|
int score, /* Score */
|
||||||
|
blocks, /* Blocks remaining */
|
||||||
|
randindex, /* Random number used for generate blocks values */
|
||||||
|
selected, /* Number of blocks selected */
|
||||||
|
add_to_score, /* How much can I add to score if I kill selected blocks */
|
||||||
|
automode, /* Non zero if automode is selected */
|
||||||
|
ChkPlsCtr, /* CheckPlease variable */
|
||||||
|
ChkPlsMul, /* id */
|
||||||
|
ChkPlsVal; /* id */
|
||||||
|
|
||||||
|
/* MAIN FUNCTION
|
||||||
|
*/
|
||||||
|
|
||||||
|
main(argc, argv)
|
||||||
|
int argc, argv[];
|
||||||
|
{
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
/* SETUP KSLIB ENVIRONMENT
|
||||||
|
*/
|
||||||
|
|
||||||
|
KbdScrStart();
|
||||||
|
|
||||||
|
/* SETUP SOME THINGS
|
||||||
|
*/
|
||||||
|
|
||||||
|
board[0]="1234567890"; board_sel[0]="1234567890";
|
||||||
|
board[1]="1234567890"; board_sel[1]="1234567890";
|
||||||
|
board[2]="1234567890"; board_sel[2]="1234567890";
|
||||||
|
board[3]="1234567890"; board_sel[3]="1234567890";
|
||||||
|
board[4]="1234567890"; board_sel[4]="1234567890";
|
||||||
|
board[5]="1234567890"; board_sel[5]="1234567890";
|
||||||
|
board[6]="1234567890"; board_sel[6]="1234567890";
|
||||||
|
board[7]="1234567890"; board_sel[7]="1234567890";
|
||||||
|
board[8]="1234567890"; board_sel[8]="1234567890";
|
||||||
|
board[9]="1234567890"; board_sel[9]="1234567890";
|
||||||
|
|
||||||
|
/* PLAY THE GAME, PLEASE
|
||||||
|
*/
|
||||||
|
|
||||||
|
while((opt=Menu()))
|
||||||
|
{
|
||||||
|
if(opt==1)
|
||||||
|
Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GAME IS OVER - BEST TO CLEAN THE SCREEN
|
||||||
|
*/
|
||||||
|
|
||||||
|
ScrClr(); ScrCurOn();
|
||||||
|
|
||||||
|
/* WE SAY GOOD BYE TO KSLIB ENVIRONMENT & WE SAY HELLO TO CP/M
|
||||||
|
*/
|
||||||
|
|
||||||
|
KbdScrEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MENU - RETURN 0 IF WE WANT TO END GAME, 1 IF WE WANT TO PLAY GAME, OR 2 IF WE WANT TO RETURN TO MENU
|
||||||
|
*/
|
||||||
|
|
||||||
|
Menu()
|
||||||
|
{
|
||||||
|
ScrClr(); ScrCurOff();
|
||||||
|
|
||||||
|
ScrTitle(0, "BLOCKS");
|
||||||
|
ScrTitle(1, "v1.0");
|
||||||
|
ScrTitle(3, "(c) 2012 FLOPPY SOFTWARE");
|
||||||
|
|
||||||
|
ScrOutStrRC( 6, 25, "1 : PLAY GAME IN NORMAL MODE");
|
||||||
|
ScrOutStrRC( 8, 25, "2 : PLAY GAME IN AUTOMATIC MODE");
|
||||||
|
ScrOutStrRC(10, 25, "3 : SHOW HELP");
|
||||||
|
|
||||||
|
ScrOutStrRC(12, 25, "X : EXIT GAME");
|
||||||
|
|
||||||
|
ScrTitle(SCR_ROWS-2, "SELECT YOUR CHOICE");
|
||||||
|
|
||||||
|
randindex=0; /* This is used to generate a random number */
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
while(!KbdChk())
|
||||||
|
{
|
||||||
|
if(++randindex==BOARD_ROWS*BOARD_COLS)
|
||||||
|
randindex=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(toupper(KbdIn()))
|
||||||
|
{
|
||||||
|
case '1' : automode=0; return 1;
|
||||||
|
case '2' : automode=1; return 1;
|
||||||
|
case '3' : Help(); return 2;
|
||||||
|
case 'X' : return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HELP -- SHOW HELP
|
||||||
|
*/
|
||||||
|
|
||||||
|
Help()
|
||||||
|
{
|
||||||
|
ScrClr();
|
||||||
|
|
||||||
|
ScrTitle( 0, "BLOCKS");
|
||||||
|
|
||||||
|
ScrTitle( 2, "The object of the game is to remove all the");
|
||||||
|
ScrTitle( 3, "blocks of the board.");
|
||||||
|
ScrTitle( 5, "You can select just one block, or a group of");
|
||||||
|
ScrTitle( 6, "blocks of the same type.");
|
||||||
|
ScrTitle( 8, "Then, if you are in the normal mode, you can place all");
|
||||||
|
ScrTitle( 9, "the blocks against a side (top, bottom, left or right).");
|
||||||
|
ScrTitle(11, "If you are in the automatic mode, the blocks rows will be");
|
||||||
|
ScrTitle(12, "placed on the bottom side of the board, and the columns");
|
||||||
|
ScrTitle(13, "will be placed on the middle of the board.");
|
||||||
|
ScrTitle(15, "The partial score is the square of the number of");
|
||||||
|
ScrTitle(16, "blocks selected.");
|
||||||
|
ScrTitle(18, "The special block 'X', multiplies that result by 10.");
|
||||||
|
ScrTitle(20, "Good luck!");
|
||||||
|
ScrTitle(22, "PRESS ANY KEY");
|
||||||
|
|
||||||
|
KbdIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PLAY THE GAME, PLEASE
|
||||||
|
*/
|
||||||
|
|
||||||
|
Play()
|
||||||
|
{
|
||||||
|
int row, col, run, val, key;
|
||||||
|
|
||||||
|
/* SETUP VARIABLES & BOARD
|
||||||
|
*/
|
||||||
|
|
||||||
|
row=col=selected=score=0; run=1;
|
||||||
|
|
||||||
|
blocks=BOARD_ROWS*BOARD_COLS;
|
||||||
|
|
||||||
|
SetupBoard();
|
||||||
|
|
||||||
|
/* DRAW SCREEN
|
||||||
|
*/
|
||||||
|
|
||||||
|
ScrClr();
|
||||||
|
|
||||||
|
ScrBox(0, 0, SCR_ROWS-1, SCR_COLS, NULL); ScrTitle(0, "| BLOCKS |");
|
||||||
|
|
||||||
|
ScrOutStrRC(LEVEL_ROW, LEVEL_COL, "BLOCKS"); PrintBlocks();
|
||||||
|
|
||||||
|
ScrOutStrRC(SCORE_ROW, SCORE_COL, "SCORE"); PrintScore();
|
||||||
|
|
||||||
|
|
||||||
|
ScrBox(BORDER_ROW, BORDER_COL, BOARD_ROWS*BLOCK_ROWS+2, BOARD_COLS*BLOCK_COLS+2, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
PaintBoard();
|
||||||
|
|
||||||
|
|
||||||
|
if(!automode)
|
||||||
|
{
|
||||||
|
scrTitle(BORDER_ROW-1, "1");
|
||||||
|
|
||||||
|
ScrTitle(BORDER_ROW+BOARD_ROWS+2, "4");
|
||||||
|
|
||||||
|
ScrOutStrRC(BORDER_ROW+5, BORDER_COL-2, "2");
|
||||||
|
|
||||||
|
ScrOutStrRC(BORDER_ROW+5, BORDER_COL+BOARD_COLS*BLOCK_COLS+3, "3");
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrOutStrRC(BORDER_ROW+3, 7, " Q");
|
||||||
|
ScrOutStrRC(BORDER_ROW+4, 7, " |");
|
||||||
|
ScrOutStrRC(BORDER_ROW+5, 7, "O --x-- P");
|
||||||
|
ScrOutStrRC(BORDER_ROW+6, 7, " |");
|
||||||
|
ScrOutStrRC(BORDER_ROW+7, 7, " A");
|
||||||
|
|
||||||
|
ScrOutStrRC(BORDER_ROW+4, BORDER_COL+BOARD_COLS*BLOCK_COLS+8, "S> SELECT BLOCKS");
|
||||||
|
ScrOutStrRC(BORDER_ROW+5, BORDER_COL+BOARD_COLS*BLOCK_COLS+8, "K> KILL BLOCKS");
|
||||||
|
ScrOutStrRC(BORDER_ROW+6, BORDER_COL+BOARD_COLS*BLOCK_COLS+8, "X> EXIT");
|
||||||
|
|
||||||
|
/* PLAY GAME
|
||||||
|
*/
|
||||||
|
|
||||||
|
while(run)
|
||||||
|
{
|
||||||
|
/* DRAW CURSOR
|
||||||
|
*/
|
||||||
|
|
||||||
|
ScrSetRC(BOARD_ROW+row*BLOCK_ROWS, BOARD_COL+col*BLOCK_COLS+1); ScrCurOn();
|
||||||
|
|
||||||
|
/* USER ACTION
|
||||||
|
*/
|
||||||
|
|
||||||
|
key=toupper(KbdIn());
|
||||||
|
|
||||||
|
ScrCurOff();
|
||||||
|
|
||||||
|
switch(key)
|
||||||
|
{
|
||||||
|
case K_UP: if(row) --row;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_DOWN: if(++row==BOARD_ROWS) --row;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_LEFT: if(col) --col;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_RIGHT: if(++col==BOARD_COLS) -- col;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_SELECT: /* CHECK FOR VALID BLOCKS
|
||||||
|
*/
|
||||||
|
|
||||||
|
val=GetBlock(row, col);
|
||||||
|
|
||||||
|
if(val==BLOCK_EMPTY || val=='X')
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* CHECK IF ALREADY SELECTED
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(TstSelBlock(row, col))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* UNSELECT PREVIOUS SELECTION
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(selected)
|
||||||
|
{
|
||||||
|
/* HEY! TOO MUCH WORK IF ONLY 1 SELECTED */
|
||||||
|
|
||||||
|
UnSelAllBlocks();
|
||||||
|
PaintBoard();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SELECT
|
||||||
|
*/
|
||||||
|
|
||||||
|
selected=CheckPlease(row, col);
|
||||||
|
|
||||||
|
add_to_score=selected*selected*ChkPlsMul;
|
||||||
|
|
||||||
|
PrintSelec();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_KILL: if(selected)
|
||||||
|
{
|
||||||
|
/* HEY! TOO MUCH WORK IF ONLY 1 SELECTED */
|
||||||
|
|
||||||
|
KillSelBlocks();
|
||||||
|
|
||||||
|
score+=add_to_score;
|
||||||
|
|
||||||
|
PrintScore();
|
||||||
|
|
||||||
|
blocks-=selected; PrintBlocks();
|
||||||
|
|
||||||
|
selected=add_to_score=0;
|
||||||
|
|
||||||
|
PrintSelec();
|
||||||
|
|
||||||
|
if(!blocks)
|
||||||
|
{
|
||||||
|
GameOver(); run=0;
|
||||||
|
}
|
||||||
|
else if(automode)
|
||||||
|
{
|
||||||
|
DoAutoMode(); PaintBoard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_GRAV_UP: if(automode)
|
||||||
|
break;
|
||||||
|
|
||||||
|
GravityUp();
|
||||||
|
|
||||||
|
if(selected)
|
||||||
|
{
|
||||||
|
UnSelAllBlocks(); selected=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaintBoard();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_GRAV_DOWN:
|
||||||
|
if(automode)
|
||||||
|
break;
|
||||||
|
|
||||||
|
GravityDown();
|
||||||
|
|
||||||
|
if(selected)
|
||||||
|
{
|
||||||
|
UnSelAllBlocks(); selected=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaintBoard();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_GRAV_LEFT:
|
||||||
|
if(automode)
|
||||||
|
break;
|
||||||
|
|
||||||
|
GravityLeft();
|
||||||
|
|
||||||
|
if(selected)
|
||||||
|
{
|
||||||
|
UnSelAllBlocks(); selected=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaintBoard();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_GRAV_RIGHT:
|
||||||
|
if(automode)
|
||||||
|
break;
|
||||||
|
|
||||||
|
GravityRight();
|
||||||
|
|
||||||
|
if(selected)
|
||||||
|
{
|
||||||
|
UnSelAllBlocks(); selected=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PaintBoard();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_EXIT :
|
||||||
|
PrintMsg("ARE YOU SURE Y/N?");
|
||||||
|
|
||||||
|
if(toupper(KbdIn())=='Y')
|
||||||
|
run=0;
|
||||||
|
else
|
||||||
|
PrintMsg("");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GAME IS OVER
|
||||||
|
*/
|
||||||
|
|
||||||
|
GameOver()
|
||||||
|
{
|
||||||
|
ScrTitle(BORDER_ROW+4, "*** GAME OVER ***");
|
||||||
|
|
||||||
|
PrintMsg("PRESS ANY KEY");
|
||||||
|
|
||||||
|
KbdIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SETUP BOARD
|
||||||
|
*/
|
||||||
|
|
||||||
|
SetupBoard()
|
||||||
|
{
|
||||||
|
int r, c; unsigned char *values;
|
||||||
|
|
||||||
|
/* 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 (width 100) */
|
||||||
|
values="4321242333123432411123443444432111234332222343331214422444441243444132222311114242423111133222441111";
|
||||||
|
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
{
|
||||||
|
for(c=0; c!=BOARD_COLS; ++c)
|
||||||
|
{
|
||||||
|
SetBlock(r, c, values[randindex]);
|
||||||
|
|
||||||
|
UnSelBlock(r, c);
|
||||||
|
|
||||||
|
if(++randindex==BOARD_ROWS*BOARD_COLS)
|
||||||
|
randindex=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(randindex<25)
|
||||||
|
SetBlock(2, 5, 'X');
|
||||||
|
else if(randindex<50)
|
||||||
|
SetBlock(9, 4, 'X');
|
||||||
|
else if(randindex<75)
|
||||||
|
SetBlock(4, 8, 'X');
|
||||||
|
else
|
||||||
|
SetBlock(7, 3, 'X');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SET BLOCK WITH VALUE
|
||||||
|
*/
|
||||||
|
|
||||||
|
SetBlock(row, col, value)
|
||||||
|
int row, col, value;
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
ptr=board[row];
|
||||||
|
|
||||||
|
ptr[col]=value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GET BLOCK VALUE
|
||||||
|
*/
|
||||||
|
|
||||||
|
GetBlock(row, col)
|
||||||
|
int row, col;
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
ptr=board[row];
|
||||||
|
|
||||||
|
return ptr[col];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SELECT BLOCK
|
||||||
|
*/
|
||||||
|
|
||||||
|
SelBlock(row, col)
|
||||||
|
int row, col;
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
ptr=board_sel[row];
|
||||||
|
|
||||||
|
ptr[col]=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UNSELECT BLOCK
|
||||||
|
*/
|
||||||
|
|
||||||
|
UnSelBlock(row, col)
|
||||||
|
int row, col;
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
ptr=board_sel[row];
|
||||||
|
|
||||||
|
ptr[col]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UNSELECT ALL BLOCKS
|
||||||
|
*/
|
||||||
|
|
||||||
|
UnSelAllBlocks()
|
||||||
|
{
|
||||||
|
int r, c;
|
||||||
|
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
for(c=0; c!=BOARD_COLS; ++c)
|
||||||
|
UnSelBlock(r, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TEST IF A BLOCK IS SELECTED
|
||||||
|
*/
|
||||||
|
|
||||||
|
TstSelBlock(row, col)
|
||||||
|
int row, col;
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
ptr=board_sel[row];
|
||||||
|
|
||||||
|
return ptr[col];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* KILL SELECTED BLOCKS
|
||||||
|
*/
|
||||||
|
|
||||||
|
KillSelBlocks()
|
||||||
|
{
|
||||||
|
int r, c;
|
||||||
|
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
{
|
||||||
|
for(c=0; c!=BOARD_COLS; ++c)
|
||||||
|
{
|
||||||
|
if(TstSelBlock(r, c))
|
||||||
|
{
|
||||||
|
SetBlock(r, c, BLOCK_EMPTY);
|
||||||
|
UnSelBlock(r, c);
|
||||||
|
PaintBlock(r, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PAINT BLOCK
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaintBlock(row, col)
|
||||||
|
int row, col;
|
||||||
|
{
|
||||||
|
int selected;
|
||||||
|
|
||||||
|
ScrSetRC(BOARD_ROW+row*BLOCK_ROWS, BOARD_COL+col*BLOCK_COLS);
|
||||||
|
|
||||||
|
ScrOut((selected=TstSelBlock(row, col)) ? ':' : ' ');
|
||||||
|
|
||||||
|
switch(GetBlock(row, col))
|
||||||
|
{
|
||||||
|
case '1' : ScrOut('$'); break;
|
||||||
|
case '2' : ScrOut('O'); break;
|
||||||
|
case '3' : ScrOut('+'); break;
|
||||||
|
case '4' : ScrOut('#'); break;
|
||||||
|
case 'X' : ScrOut('X'); break;
|
||||||
|
case BLOCK_EMPTY : ScrOut(' '); break;
|
||||||
|
default : ScrOut('?'); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrOut(selected ? ':' : ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PAINT ALL BLOCKS
|
||||||
|
*/
|
||||||
|
|
||||||
|
PaintBoard()
|
||||||
|
{
|
||||||
|
int r, c;
|
||||||
|
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
for(c=0; c!=BOARD_COLS; ++c)
|
||||||
|
PaintBlock(r, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CHECK WHAT BLOCKS CAN BE SELECTED - SETUP THREE VARIABLES
|
||||||
|
*/
|
||||||
|
|
||||||
|
CheckPlease(row, col)
|
||||||
|
int row, col;
|
||||||
|
{
|
||||||
|
ChkPlsCtr=0; ChkPlsMul=1; ChkPlsVal=GetBlock(row, col);
|
||||||
|
|
||||||
|
ChkPls2(row, col);
|
||||||
|
|
||||||
|
return ChkPlsCtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChkPls2(row, col)
|
||||||
|
int row, col;
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
|
||||||
|
SelBlock(row, col); PaintBlock(row, col);
|
||||||
|
|
||||||
|
if(GetBlock(row, col)=='X')
|
||||||
|
ChkPlsMul=10;
|
||||||
|
|
||||||
|
if(row)
|
||||||
|
{
|
||||||
|
if(((val=GetBlock(row-1, col))==ChkPlsVal || val=='X') && (!TstSelBlock(row-1, col)))
|
||||||
|
ChkPls2(row-1, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(col<(BOARD_COLS-1))
|
||||||
|
{
|
||||||
|
if(((val=GetBlock(row, col+1))==ChkPlsVal || val=='X') && (!TstSelBlock(row, col+1)))
|
||||||
|
ChkPls2(row, col+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(row<(BOARD_ROWS-1))
|
||||||
|
{
|
||||||
|
if(((val=GetBlock(row+1, col))==ChkPlsVal || val=='X') && (!TstSelBlock(row+1, col)))
|
||||||
|
ChkPls2(row+1, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(col)
|
||||||
|
{
|
||||||
|
if(((val=GetBlock(row, col-1))==ChkPlsVal || val=='X') && (!TstSelBlock(row, col-1)))
|
||||||
|
ChkPls2(row, col-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
++ChkPlsCtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GRAVITY DOWN (BOARD BOTTOM)
|
||||||
|
*/
|
||||||
|
|
||||||
|
GravityDown()
|
||||||
|
{
|
||||||
|
int r, c, i, blk, row[BOARD_ROWS];
|
||||||
|
|
||||||
|
for(c=0; c!=BOARD_COLS; ++c)
|
||||||
|
{
|
||||||
|
for((r=i=BOARD_ROWS-1); r!=-1; --r)
|
||||||
|
{
|
||||||
|
if((blk=GetBlock(r, c))!=BLOCK_EMPTY)
|
||||||
|
row[i--]=blk;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(i!=-1)
|
||||||
|
row[i--]=BLOCK_EMPTY;
|
||||||
|
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
SetBlock(r, c, row[r]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GRAVITY UP (WE PUT BLOCKS ON BOARD TOP)
|
||||||
|
*/
|
||||||
|
|
||||||
|
GravityUp()
|
||||||
|
{
|
||||||
|
int r, c, i, blk, row[BOARD_ROWS];
|
||||||
|
|
||||||
|
for(c=0; c!=BOARD_COLS; ++c)
|
||||||
|
{
|
||||||
|
for((r=i=0); r!=BOARD_ROWS; ++r)
|
||||||
|
{
|
||||||
|
if((blk=GetBlock(r, c))!=BLOCK_EMPTY)
|
||||||
|
row[i++]=blk;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(i!=BOARD_ROWS)
|
||||||
|
row[i++]=BLOCK_EMPTY;
|
||||||
|
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
SetBlock(r, c, row[r]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GRAVITY LEFT (WE PUT BLOCKS ON BOARD LEFT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
GravityLeft()
|
||||||
|
{
|
||||||
|
int r, c, i, blk, col[BOARD_ROWS];
|
||||||
|
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
{
|
||||||
|
for((c=i=0); c!=BOARD_COLS; ++c)
|
||||||
|
{
|
||||||
|
if((blk=GetBlock(r, c))!=BLOCK_EMPTY)
|
||||||
|
col[i++]=blk;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(i!=BOARD_COLS)
|
||||||
|
col[i++]=BLOCK_EMPTY;
|
||||||
|
|
||||||
|
for(c=0; c!=BOARD_COLS; ++c)
|
||||||
|
SetBlock(r, c, col[c]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GRAVITY RIGHT (WE PUT BLOCKS ON BOARD RIGHT)
|
||||||
|
*/
|
||||||
|
|
||||||
|
GravityRight()
|
||||||
|
{
|
||||||
|
int r, c, i, blk, col[BOARD_ROWS];
|
||||||
|
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
{
|
||||||
|
for((c=i=BOARD_COLS-1); c!=-1; --c)
|
||||||
|
{
|
||||||
|
if((blk=GetBlock(r, c))!=BLOCK_EMPTY)
|
||||||
|
col[i--]=blk;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(i!=-1)
|
||||||
|
col[i--]=BLOCK_EMPTY;
|
||||||
|
|
||||||
|
for(c=0; c!=BOARD_COLS; ++c)
|
||||||
|
SetBlock(r, c, col[c]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AUTOMATIC MODE (WE PUT BLOKS FIRST ON BOARD BOTTOM, THEN WE CENTER THE COLUMNS)
|
||||||
|
*/
|
||||||
|
|
||||||
|
DoAutoMode()
|
||||||
|
{
|
||||||
|
int r, c, i, pos, cols;
|
||||||
|
|
||||||
|
GravityDown();
|
||||||
|
|
||||||
|
/* COPY NON EMPTY COLUMNS TO THE LEFT
|
||||||
|
*/
|
||||||
|
|
||||||
|
for(i=c=0; c!=BOARD_COLS; ++c)
|
||||||
|
{
|
||||||
|
if(GetBlock(BOARD_ROWS-1, c) != BLOCK_EMPTY)
|
||||||
|
{
|
||||||
|
if(i!=c)
|
||||||
|
{
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
SetBlock(r, i, GetBlock(r, c));
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DO NOTHING IF ALL COLUMNS ARE NON EMPTY
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(i==BOARD_COLS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* CALCULATE WHERE TO PUT THE COLUMNS
|
||||||
|
*/
|
||||||
|
|
||||||
|
pos=(BOARD_COLS-i)/2;
|
||||||
|
|
||||||
|
/* COPY COLUMNS WITHOUT OVERLAP
|
||||||
|
*/
|
||||||
|
|
||||||
|
cols=i;
|
||||||
|
|
||||||
|
for(c=pos+i-1; i!=-1; --c)
|
||||||
|
{
|
||||||
|
--i;
|
||||||
|
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
SetBlock(r, c, GetBlock(r, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EMPTY COLUMNS TO THE LEFT
|
||||||
|
*/
|
||||||
|
|
||||||
|
for(c=0; c!=pos; ++c)
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
SetBlock(r, c, BLOCK_EMPTY);
|
||||||
|
|
||||||
|
/* EMPTY COLUMNS TO THE RIGHT
|
||||||
|
*/
|
||||||
|
|
||||||
|
for(c=pos+cols; c!=BOARD_COLS; ++c)
|
||||||
|
for(r=0; r!=BOARD_ROWS; ++r)
|
||||||
|
SetBlock(r, c, BLOCK_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PRINT HOW MANY BLOCKS ARE REMAINING
|
||||||
|
*/
|
||||||
|
|
||||||
|
PrintBlocks()
|
||||||
|
{
|
||||||
|
char str[6];
|
||||||
|
|
||||||
|
sprintf(str, "%d ", blocks);
|
||||||
|
|
||||||
|
ScrOutStrRC(LEVEL_ROW+1, LEVEL_COL, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PRINT SCORE
|
||||||
|
*/
|
||||||
|
|
||||||
|
PrintScore()
|
||||||
|
{
|
||||||
|
char str[6];
|
||||||
|
|
||||||
|
sprintf(str, "%5d", score);
|
||||||
|
|
||||||
|
ScrOutStrRC(SCORE_ROW+1, SCORE_COL, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PRINT SELECTION INFO.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PrintSelec()
|
||||||
|
{
|
||||||
|
char str[7];
|
||||||
|
|
||||||
|
sprintf(str, "x%d ", selected);
|
||||||
|
|
||||||
|
ScrOutStrRC(LEVEL_ROW+3, LEVEL_COL, str);
|
||||||
|
|
||||||
|
sprintf(str, "%5d+", add_to_score);
|
||||||
|
|
||||||
|
ScrOutStrRC(SCORE_ROW+3, SCORE_COL-1, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PRINT TEXT STRING (MESSAGE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
PrintMsg(str)
|
||||||
|
char *str;
|
||||||
|
{
|
||||||
|
ScrSetRC(SCR_ROWS-4, 2);
|
||||||
|
ScrOutRpt(' ', SCR_COLS-4);
|
||||||
|
|
||||||
|
ScrTitle(SCR_ROWS-4, str);
|
||||||
|
}
|
203
Blocks/ctype.h
Normal file
203
Blocks/ctype.h
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/**
|
||||||
|
* @file ctype.h
|
||||||
|
* @brief Character tests and conversion functions.
|
||||||
|
* @author Miguel I. Garcia Lopez / FloppySoftware
|
||||||
|
*
|
||||||
|
* Character tests and conversion functions, for MESCC (Mike's Enhanced
|
||||||
|
* Small C Compiler for Z80 & CP/M).
|
||||||
|
*
|
||||||
|
* Revisions:
|
||||||
|
* - 19 Dec 2000 : Last revision.
|
||||||
|
* - 16 Apr 2007 : GPL'd.
|
||||||
|
* - 15 Aug 2016 : Documented. GPL v3.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2016 Miguel I. Garcia Lopez / FloppySoftware.
|
||||||
|
*
|
||||||
|
* Licensed under the GNU General Public License v3.
|
||||||
|
*
|
||||||
|
* http://www.floppysoftware.es
|
||||||
|
* floppysoftware@gmail.com
|
||||||
|
*/
|
||||||
|
#ifndef CTYPE_H
|
||||||
|
|
||||||
|
#define CTYPE_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int isalpha(char ch)
|
||||||
|
* @brief Test if ch is a letter.
|
||||||
|
* @param ch - character to test
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
|
||||||
|
isalpha
|
||||||
|
ld a,l
|
||||||
|
ld hl,0
|
||||||
|
cp 'A'
|
||||||
|
ret c
|
||||||
|
cp 'Z'+1
|
||||||
|
jr c,isalpha1
|
||||||
|
cp 'a'
|
||||||
|
ret c
|
||||||
|
cp 'z'+1
|
||||||
|
ret nc
|
||||||
|
isalpha1
|
||||||
|
inc l
|
||||||
|
ret
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int isdigit(char ch)
|
||||||
|
* @brief Test if ch is a decimal digit.
|
||||||
|
* @param ch - character to test
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
|
||||||
|
isdigit
|
||||||
|
ld a,l
|
||||||
|
ld hl,0
|
||||||
|
cp '0'
|
||||||
|
ret c
|
||||||
|
cp '9'+1
|
||||||
|
ret nc
|
||||||
|
inc l
|
||||||
|
ret
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int isxdigit(char ch)
|
||||||
|
* @brief Test if ch is an hexadecimal digit.
|
||||||
|
* @param ch - character to test
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
|
||||||
|
isxdigit
|
||||||
|
LD C,L
|
||||||
|
CALL isdigit
|
||||||
|
RET C
|
||||||
|
LD HL,0
|
||||||
|
LD A,C
|
||||||
|
CP 'A'
|
||||||
|
RET C
|
||||||
|
CP 'G'
|
||||||
|
JR C,isxdigit1
|
||||||
|
CP 'a'
|
||||||
|
RET C
|
||||||
|
CP 'g'
|
||||||
|
RET NC
|
||||||
|
isxdigit1
|
||||||
|
INC L
|
||||||
|
RET
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int isalnum(char ch)
|
||||||
|
* @brief Test if ch is a letter or a decimal digit.
|
||||||
|
* @param ch - character to test
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
|
||||||
|
isalnum
|
||||||
|
LD C,L
|
||||||
|
CALL isdigit
|
||||||
|
RET C
|
||||||
|
LD L,C
|
||||||
|
JP isalpha
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int isupper(char ch)
|
||||||
|
* @brief Test if ch is a letter in uppercase.
|
||||||
|
* @param ch - character to test
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
|
||||||
|
isupper
|
||||||
|
ld a,l
|
||||||
|
ld hl,0
|
||||||
|
cp 'A'
|
||||||
|
ret c
|
||||||
|
cp 'Z'+1
|
||||||
|
ret nc
|
||||||
|
inc l
|
||||||
|
ret
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int islower(char ch)
|
||||||
|
* @brief Test if ch is a letter in lowercase.
|
||||||
|
* @param ch - character to test
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
|
||||||
|
islower
|
||||||
|
ld a,l
|
||||||
|
ld hl,0
|
||||||
|
cp 'a'
|
||||||
|
ret c
|
||||||
|
cp 'z'+1
|
||||||
|
ret nc
|
||||||
|
inc l
|
||||||
|
ret
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int toupper(char ch)
|
||||||
|
* @brief Convert letter to uppercase.
|
||||||
|
*
|
||||||
|
* If ch is not a letter in lowercase, returns ch unchanged.
|
||||||
|
*
|
||||||
|
* @param ch - character to convert
|
||||||
|
* @return ch in uppercase
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
|
||||||
|
toupper
|
||||||
|
ld a,l
|
||||||
|
cp 'a'
|
||||||
|
ret c
|
||||||
|
cp 'z'+1
|
||||||
|
ret nc
|
||||||
|
sub 20h
|
||||||
|
ld l,a
|
||||||
|
ret
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int tolower(char ch)
|
||||||
|
* @brief Convert letter to lowercase.
|
||||||
|
*
|
||||||
|
* If ch is not a letter in uppercase, returns ch unchanged.
|
||||||
|
*
|
||||||
|
* @param ch - character to convert
|
||||||
|
* @return ch in lowercase
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
|
||||||
|
tolower
|
||||||
|
ld a,l
|
||||||
|
cp 'A'
|
||||||
|
ret c
|
||||||
|
cp 'Z'+1
|
||||||
|
ret nc
|
||||||
|
add 20h
|
||||||
|
ld l,a
|
||||||
|
ret
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
158
Blocks/kslib.h
Normal file
158
Blocks/kslib.h
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/* kslib.h
|
||||||
|
|
||||||
|
Keyboard & screen functions library for CP/M & MESCC - Mike's Enhanced Small C Compiler.
|
||||||
|
|
||||||
|
Copyright (c) 2012 Miguel I. Garcia Lopez, Valencia, Spain.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
Revisions:
|
||||||
|
|
||||||
|
02 Jul 2012 : Version 1.0 for 24x80 VT52 screen.
|
||||||
|
10 Mar 2020 : Version 1.1 for 24x80 VT100 screen.
|
||||||
|
|
||||||
|
Functions:
|
||||||
|
|
||||||
|
int KbdScrStart(void)
|
||||||
|
int KbdScrEnd(void)
|
||||||
|
int KbdIn(void)
|
||||||
|
int KbdChk(void)
|
||||||
|
int KbdStat(void)
|
||||||
|
void ScrOut(ch)
|
||||||
|
void ScrOutStr(str)
|
||||||
|
void ScrSetRC(row, col)
|
||||||
|
void ScrCurOn(void)
|
||||||
|
void ScrCurOff(void)
|
||||||
|
void ScrClr(void)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SCR_ROWS 24
|
||||||
|
#define SCR_COLS 80
|
||||||
|
|
||||||
|
#asm
|
||||||
|
|
||||||
|
xDirConInSt:
|
||||||
|
jp 0
|
||||||
|
xDirConIn:
|
||||||
|
jp 0
|
||||||
|
xDirConOut:
|
||||||
|
jp 0
|
||||||
|
|
||||||
|
KbdScrStart:
|
||||||
|
ld hl,(1)
|
||||||
|
inc hl
|
||||||
|
inc hl
|
||||||
|
inc hl ;HL = JP CONST (BIOS VECTOR)
|
||||||
|
ld de,xDirConInSt
|
||||||
|
ld bc,9
|
||||||
|
ldir
|
||||||
|
ld hl,0 ;Success
|
||||||
|
ret
|
||||||
|
|
||||||
|
KbdScrEnd:
|
||||||
|
ld hl,0 ;Success
|
||||||
|
ret
|
||||||
|
|
||||||
|
KbdIn:
|
||||||
|
call xDirConIn
|
||||||
|
KbdIn2:
|
||||||
|
ld h,0
|
||||||
|
ld l,a
|
||||||
|
ret
|
||||||
|
|
||||||
|
KbdChk:
|
||||||
|
call xDirConInSt
|
||||||
|
ld h,0
|
||||||
|
ld l,a
|
||||||
|
ret
|
||||||
|
|
||||||
|
KbdStat:
|
||||||
|
call xDirConInSt
|
||||||
|
or a
|
||||||
|
jr nz,KbdIn
|
||||||
|
jr KbdIn2
|
||||||
|
|
||||||
|
ScrOut:
|
||||||
|
ld c,l
|
||||||
|
jp xDirConOut
|
||||||
|
|
||||||
|
ScrOutStr:
|
||||||
|
ld a,(hl)
|
||||||
|
or a
|
||||||
|
ret z
|
||||||
|
push hl
|
||||||
|
ld c,a
|
||||||
|
call xDirConOut
|
||||||
|
pop hl
|
||||||
|
inc hl
|
||||||
|
jr ScrOutStr
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
ScrSetRC(row, col)
|
||||||
|
int row, col;
|
||||||
|
{
|
||||||
|
char str[9];
|
||||||
|
sprintf(str, "%c[%d;%dH", 27, row+1, col+1);
|
||||||
|
ScrOutStr(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
#asm
|
||||||
|
|
||||||
|
ScrCurOn:
|
||||||
|
call xScrEsc
|
||||||
|
ld c,'['
|
||||||
|
call xDirConOut
|
||||||
|
ld c,'?'
|
||||||
|
call xDirConOut
|
||||||
|
ld c,'2'
|
||||||
|
call xDirConOut
|
||||||
|
ld c,'5'
|
||||||
|
call xDirConOut
|
||||||
|
ld c,'h'
|
||||||
|
jp xDirConOut
|
||||||
|
|
||||||
|
ScrCurOff:
|
||||||
|
call xScrEsc
|
||||||
|
ld c,'['
|
||||||
|
call xDirConOut
|
||||||
|
ld c,'?'
|
||||||
|
call xDirConOut
|
||||||
|
ld c,'2'
|
||||||
|
call xDirConOut
|
||||||
|
ld c,'5'
|
||||||
|
call xDirConOut
|
||||||
|
ld c,'l'
|
||||||
|
jp xDirConOut
|
||||||
|
|
||||||
|
ScrClr:
|
||||||
|
call xScrEsc
|
||||||
|
ld c,'['
|
||||||
|
call xDirConOut
|
||||||
|
ld c,'2'
|
||||||
|
call xDirConOut
|
||||||
|
ld c,'J'
|
||||||
|
call xDirConOut
|
||||||
|
call xScrEsc
|
||||||
|
ld c,'['
|
||||||
|
call xDirConOut
|
||||||
|
ld c,'H'
|
||||||
|
jp xDirConOut
|
||||||
|
|
||||||
|
xScrEsc:
|
||||||
|
ld c,27
|
||||||
|
jp xDirConOut
|
||||||
|
|
||||||
|
#endasm
|
72
Blocks/kslibfun.h
Normal file
72
Blocks/kslibfun.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* kslibfun.h
|
||||||
|
|
||||||
|
More functions for kslib.h for CP/M and MESCC - Mike's Enhanced Small C Compiler.
|
||||||
|
|
||||||
|
Copyright (c) 2012 Miguel I. Garcia Lopez, Valencia, Spain.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
Revisions:
|
||||||
|
|
||||||
|
02 Jul 2012 : Version 1.0.
|
||||||
|
|
||||||
|
Functions:
|
||||||
|
|
||||||
|
ScrOutRpt(ch, times)
|
||||||
|
ScrOutStrRC(row, col, str)
|
||||||
|
ScrBox(row, col, rows, cols, fill)
|
||||||
|
ScrTitle(row, str)
|
||||||
|
*/
|
||||||
|
|
||||||
|
ScrOutRpt(ch, times)
|
||||||
|
int ch, times;
|
||||||
|
{
|
||||||
|
while(times--)
|
||||||
|
ScrOut(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrOutStrRC(row, col, str)
|
||||||
|
int row, col; char *str;
|
||||||
|
{
|
||||||
|
ScrSetRC(row, col); ScrOutStr(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrBox(row, col, rows, cols, fill)
|
||||||
|
int row, col, rows, cols, fill;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ScrSetRC(row++, col); ScrOut('+');
|
||||||
|
ScrOutRpt('-', cols-2);
|
||||||
|
ScrOut('+');
|
||||||
|
|
||||||
|
for(i=rows-2; i; --i)
|
||||||
|
{
|
||||||
|
ScrSetRC(row, col); ScrOut('|');
|
||||||
|
if(fill!=NULL)
|
||||||
|
ScrOutRpt(fill, cols-2);
|
||||||
|
ScrSetRC(row++, col+cols-1); ScrOut('|');
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrSetRC(row, col); ScrOut('+');
|
||||||
|
ScrOutRpt('-', cols-2);
|
||||||
|
ScrOut('+');
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrTitle(row, str)
|
||||||
|
int row; char *str;
|
||||||
|
{
|
||||||
|
ScrOutStrRC(row, (SCR_COLS-strlen(str))/2, str);
|
||||||
|
}
|
945
Blocks/mescc.h
Normal file
945
Blocks/mescc.h
Normal file
@ -0,0 +1,945 @@
|
|||||||
|
/**
|
||||||
|
* @file mescc.h
|
||||||
|
* @brief Runtime library.
|
||||||
|
* @author Miguel I. Garcia Lopez / FloppySoftware
|
||||||
|
*
|
||||||
|
* Runtime library for MESCC (Mike's Enhanced
|
||||||
|
* Small C Compiler for Z80 & CP/M).
|
||||||
|
*
|
||||||
|
* This library file must be included first!
|
||||||
|
*
|
||||||
|
* Need following EQU's (generated by the compiler):
|
||||||
|
* - ccSTACKSIZE : Stack size in bytes.
|
||||||
|
*
|
||||||
|
* Supports following #defs:
|
||||||
|
* - #define CC_STDIO Support for stdin, stdout & stderr.
|
||||||
|
* - #define CC_REDIR Support for stdin & stdout redirection
|
||||||
|
* in command line (needs CC_STDIO).
|
||||||
|
* - #define CC_NO_MUL To exclude MULTIPLICATION code.
|
||||||
|
* - #define CC_NO_DIV To exclude DIVISION & MODULUS code.
|
||||||
|
* - #define CC_NO_SWITCH To exclude SWITCH code.
|
||||||
|
* - #define CC_NO_ARGS To exclude ARGC & ARGV code.
|
||||||
|
* - #define CC_NO_ORG To exclude ORG 0100H code.
|
||||||
|
*
|
||||||
|
* Sets the following #defines:
|
||||||
|
*
|
||||||
|
* - BYTE
|
||||||
|
* - WORD
|
||||||
|
* - BOOL
|
||||||
|
* - NULL
|
||||||
|
* - TRUE
|
||||||
|
* - FALSE
|
||||||
|
* - SIZEOF_CHAR
|
||||||
|
* - SIZEOF_INT
|
||||||
|
* - SIZEOF_PTR
|
||||||
|
*
|
||||||
|
* Revisions:
|
||||||
|
* - 16 Jan 2001 : Last revision.
|
||||||
|
* - 23 Mar 2007 : Expand ccladr1 and ccladr2 for more speed.
|
||||||
|
* - 16 Apr 2007 : GPL'd.
|
||||||
|
* - 26 Aug 2012 : Added standard defs.
|
||||||
|
* - 08 Dec 2014 : Minor changes.
|
||||||
|
* - 09 Dec 2014 : Added support for stdin, stdout & stderr with CC_STDIO.
|
||||||
|
* - 12 Dec 2014 : Added support for stdin & stdout redirection in command line with CC_REDIR.
|
||||||
|
* - 16 Jan 2015 : Added SIZEOF_??? definitions.
|
||||||
|
* - 16 Feb 2015 : Modified / added code in cctmpw, ccxpb2, ccxpb, ccxpb3, ccxpw2
|
||||||
|
* ccxpw, ccxpw3, ccladr2sv, ccladr2, ccladr1sv, ccladr1,
|
||||||
|
* to avoid use of IX register.
|
||||||
|
* - 20 Mar 2015 : Added support for CC_NO_MUL, CC_NO_DIV, CC_NO_SWITCH, CC_NO_ARGS.
|
||||||
|
* - 12 Apr 2015 : Removed ccDEFARGS code.
|
||||||
|
* - 14 Jul 2015 : Modified code for << and >>, because a shift of 0 positions,
|
||||||
|
* resulted in a wrong value (they assumed a shift > 0) - ie: 128 >> 0 resulted in 0.
|
||||||
|
* - 19 Oct 2015 : Improved multiplication algorithm (ccmul & ccumul).
|
||||||
|
* - 05 Nov 2015 : Modified ccsxt.
|
||||||
|
* - 30 Nov 2015 : Added support for atexit().
|
||||||
|
* - 24 Jan 2016 : Added support for CC_NO_ORG.
|
||||||
|
* - 10 Dec 2016 : Documented. GPL v3.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2016 Miguel I. Garcia Lopez / FloppySoftware.
|
||||||
|
*
|
||||||
|
* Licensed under the GNU General Public License v3.
|
||||||
|
*
|
||||||
|
* http://www.floppysoftware.es
|
||||||
|
* floppysoftware@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* STANDARD DEFs
|
||||||
|
-------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BYTE unsigned char
|
||||||
|
#define WORD unsigned int
|
||||||
|
#define BOOL char
|
||||||
|
#define NULL 0
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
#define SIZEOF_CHAR 1 /* [unsigned] char */
|
||||||
|
#define SIZEOF_INT 2 /* [unsigned] int */
|
||||||
|
#define SIZEOF_PTR 2 /* pointer */
|
||||||
|
|
||||||
|
/* RUNTIME CODE
|
||||||
|
------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CC_NO_ORG
|
||||||
|
|
||||||
|
#asm
|
||||||
|
; Start at TPA
|
||||||
|
|
||||||
|
ORG 0100H
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#asm
|
||||||
|
; Runtime address
|
||||||
|
|
||||||
|
ccrtadr:
|
||||||
|
|
||||||
|
; Set stack under BDOS (xx00h)
|
||||||
|
|
||||||
|
LD HL,(6)
|
||||||
|
LD L,0
|
||||||
|
LD SP,HL
|
||||||
|
|
||||||
|
; Leave space for stack and init. variables
|
||||||
|
|
||||||
|
LD DE,ccSTACKSIZE
|
||||||
|
OR A
|
||||||
|
SBC HL,DE
|
||||||
|
DEC HL
|
||||||
|
LD (ccfreelast),HL
|
||||||
|
LD DE,ccfreemem
|
||||||
|
LD (ccfreefirst),DE
|
||||||
|
OR A
|
||||||
|
SBC HL,DE
|
||||||
|
INC HL
|
||||||
|
LD (ccfreebytes),HL
|
||||||
|
JR NC,ccargs
|
||||||
|
|
||||||
|
; Error, no memory for stack
|
||||||
|
|
||||||
|
LD C,9
|
||||||
|
LD DE,ccerrstack
|
||||||
|
CALL 5
|
||||||
|
JP 0
|
||||||
|
|
||||||
|
ccerrstack
|
||||||
|
DEFB 'Runtime Error - No stack$'
|
||||||
|
|
||||||
|
; Setup command line arguments
|
||||||
|
|
||||||
|
ccargs
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#ifndef CC_NO_ARGS
|
||||||
|
|
||||||
|
#asm
|
||||||
|
; Copy command line
|
||||||
|
|
||||||
|
LD HL,81H
|
||||||
|
LD DE,ccmdbuf
|
||||||
|
LD BC,127
|
||||||
|
LDIR
|
||||||
|
|
||||||
|
LD A,(80H)
|
||||||
|
LD B,0
|
||||||
|
LD C,A
|
||||||
|
LD HL,ccmdbuf
|
||||||
|
ADD HL,BC
|
||||||
|
LD (HL),0
|
||||||
|
|
||||||
|
; Init. argc & argv
|
||||||
|
|
||||||
|
LD DE,cchptr
|
||||||
|
LD HL,ccmdbuf - 1
|
||||||
|
LD BC,1
|
||||||
|
ccspc
|
||||||
|
INC HL
|
||||||
|
LD A,(HL)
|
||||||
|
OR A
|
||||||
|
JR Z,ccarg
|
||||||
|
CP ' '
|
||||||
|
JR Z,ccspc
|
||||||
|
LD A,L
|
||||||
|
LD (DE),A
|
||||||
|
LD A,H
|
||||||
|
INC DE
|
||||||
|
LD (DE),A
|
||||||
|
INC DE
|
||||||
|
INC C
|
||||||
|
ccpar
|
||||||
|
INC HL
|
||||||
|
LD A,(HL)
|
||||||
|
OR A
|
||||||
|
JR Z,ccarg
|
||||||
|
CP ' '
|
||||||
|
JR NZ,ccpar
|
||||||
|
LD (HL),0
|
||||||
|
JR ccspc
|
||||||
|
|
||||||
|
ccarg
|
||||||
|
LD HL,cchptr - 2
|
||||||
|
PUSH BC ;argc
|
||||||
|
PUSH HL ;argv
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CC_REDIR
|
||||||
|
|
||||||
|
#asm
|
||||||
|
CALL redir ;FIXME - Check errors
|
||||||
|
POP DE
|
||||||
|
POP BC
|
||||||
|
PUSH HL ;argc
|
||||||
|
PUSH DE ;argv
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#asm
|
||||||
|
|
||||||
|
; Execute program
|
||||||
|
|
||||||
|
CALL main
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void exit(int code)
|
||||||
|
* @brief Exit to CP/M.
|
||||||
|
*
|
||||||
|
* FixMe: Return code is lost!
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
|
||||||
|
; Exit to CP/M
|
||||||
|
|
||||||
|
exit
|
||||||
|
NOP ; Patch for atexit() -- 3 bytes.
|
||||||
|
NOP
|
||||||
|
NOP
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#ifdef CC_STDIO
|
||||||
|
|
||||||
|
BYTE *stdin, *stdout, *stderr; /* Sorry, no available FILE here */
|
||||||
|
|
||||||
|
#asm
|
||||||
|
LD HL,(stdin)
|
||||||
|
CALL ccflush
|
||||||
|
LD HL,(stdout)
|
||||||
|
CALL ccflush
|
||||||
|
|
||||||
|
JP 0
|
||||||
|
|
||||||
|
ccflush
|
||||||
|
LD A,H
|
||||||
|
OR L
|
||||||
|
RET Z
|
||||||
|
PUSH HL
|
||||||
|
CALL fclose
|
||||||
|
POP BC
|
||||||
|
RET
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#asm
|
||||||
|
JP 0
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#asm
|
||||||
|
|
||||||
|
; Variables for memory functions
|
||||||
|
|
||||||
|
ccfreefirst
|
||||||
|
DEFW 0 ;Adr. first free byte
|
||||||
|
ccfreelast
|
||||||
|
DEFW 0 ;Adr. last free byte
|
||||||
|
ccfreebytes
|
||||||
|
DEFW 0 ;Number of free bytes
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#ifndef CC_NO_ARGS
|
||||||
|
|
||||||
|
#asm
|
||||||
|
; Variables for command line arguments
|
||||||
|
|
||||||
|
ccmdbuf
|
||||||
|
DEFS 128 ;Command line buffer
|
||||||
|
|
||||||
|
DEFW ccNULL ;Pointers table for argv
|
||||||
|
cchptr
|
||||||
|
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
|
||||||
|
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
|
||||||
|
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
|
||||||
|
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
|
||||||
|
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
|
||||||
|
|
||||||
|
ccNULL
|
||||||
|
DEFB 0 ;Null pointer
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#asm
|
||||||
|
|
||||||
|
; Basic routines
|
||||||
|
|
||||||
|
; Call formats to access locals:
|
||||||
|
;
|
||||||
|
; Format 1: CALL routine
|
||||||
|
; DEFB SpOffset
|
||||||
|
;
|
||||||
|
; Format 2: CALL routine
|
||||||
|
; DEFW SpOffset
|
||||||
|
|
||||||
|
; HL = unsigned char from local (format 2)
|
||||||
|
|
||||||
|
ccxgb2
|
||||||
|
CALL ccladr2
|
||||||
|
JR ccxgb3
|
||||||
|
|
||||||
|
; HL = unsigned char from local (format 1)
|
||||||
|
|
||||||
|
ccxgb
|
||||||
|
CALL ccladr1
|
||||||
|
ccxgb3
|
||||||
|
LD L,(HL)
|
||||||
|
LD H,0
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = signed char from local (format 2)
|
||||||
|
|
||||||
|
ccxgc2
|
||||||
|
CALL ccladr2
|
||||||
|
JR ccgc
|
||||||
|
|
||||||
|
; HL = signed char from local (format 1)
|
||||||
|
|
||||||
|
ccxgc
|
||||||
|
CALL ccladr1
|
||||||
|
|
||||||
|
; HL = signed char from (HL)
|
||||||
|
|
||||||
|
ccgc
|
||||||
|
LD A,(HL)
|
||||||
|
|
||||||
|
; HL = signed char from A
|
||||||
|
|
||||||
|
ccsxt
|
||||||
|
LD L,A
|
||||||
|
RLCA
|
||||||
|
SBC A
|
||||||
|
LD H,A
|
||||||
|
RET
|
||||||
|
|
||||||
|
; LD H,0
|
||||||
|
; LD L,A
|
||||||
|
; AND 128
|
||||||
|
; RET Z
|
||||||
|
; DEC H
|
||||||
|
; RET
|
||||||
|
|
||||||
|
; HL = word from local (format 2)
|
||||||
|
|
||||||
|
ccxgw2
|
||||||
|
CALL ccladr2
|
||||||
|
JR ccgw
|
||||||
|
|
||||||
|
; HL = word from local (format 1)
|
||||||
|
|
||||||
|
ccxgw
|
||||||
|
CALL ccladr1
|
||||||
|
|
||||||
|
; HL = word from (HL)
|
||||||
|
|
||||||
|
ccgw
|
||||||
|
LD A,(HL)
|
||||||
|
INC HL
|
||||||
|
LD H,(HL)
|
||||||
|
LD L,A
|
||||||
|
RET
|
||||||
|
|
||||||
|
; char local = HL (format 2)
|
||||||
|
|
||||||
|
ccxpb2
|
||||||
|
CALL ccladr2sv
|
||||||
|
JR ccxpb3
|
||||||
|
|
||||||
|
; char local = HL (format 1)
|
||||||
|
|
||||||
|
ccxpb
|
||||||
|
CALL ccladr1sv
|
||||||
|
ccxpb3
|
||||||
|
LD DE,(cctmpw)
|
||||||
|
LD (HL),E
|
||||||
|
EX DE,HL
|
||||||
|
RET
|
||||||
|
|
||||||
|
; int/ptr local = HL (format 2)
|
||||||
|
|
||||||
|
ccxpw2
|
||||||
|
CALL ccladr2sv
|
||||||
|
JR ccxpw3
|
||||||
|
|
||||||
|
; int/ptr local = HL (format 1)
|
||||||
|
|
||||||
|
ccxpw
|
||||||
|
CALL ccladr1sv
|
||||||
|
ccxpw3
|
||||||
|
LD DE,(cctmpw)
|
||||||
|
LD (HL),E
|
||||||
|
INC HL
|
||||||
|
LD (HL),D
|
||||||
|
EX DE,HL
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Copy 1 word from HL to (DE)
|
||||||
|
|
||||||
|
ccpw
|
||||||
|
LD A,L
|
||||||
|
LD (DE),A
|
||||||
|
INC DE
|
||||||
|
LD A,H
|
||||||
|
LD (DE),A
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Calc. local adress
|
||||||
|
|
||||||
|
cctmpw DEFW 0
|
||||||
|
|
||||||
|
ccladr2sv
|
||||||
|
LD (cctmpw),HL
|
||||||
|
|
||||||
|
ccladr2
|
||||||
|
POP DE
|
||||||
|
POP HL
|
||||||
|
LD C,(HL)
|
||||||
|
INC HL
|
||||||
|
LD B,(HL)
|
||||||
|
INC HL
|
||||||
|
PUSH HL
|
||||||
|
PUSH DE
|
||||||
|
LD HL,4
|
||||||
|
ADD HL,BC
|
||||||
|
ADD HL,SP
|
||||||
|
RET
|
||||||
|
|
||||||
|
ccladr1sv
|
||||||
|
LD (cctmpw),HL
|
||||||
|
|
||||||
|
ccladr1
|
||||||
|
POP DE
|
||||||
|
POP HL
|
||||||
|
LD B,0
|
||||||
|
LD C,(HL)
|
||||||
|
INC HL
|
||||||
|
PUSH HL
|
||||||
|
PUSH DE
|
||||||
|
LD HL,4
|
||||||
|
ADD HL,BC
|
||||||
|
ADD HL,SP
|
||||||
|
RET
|
||||||
|
|
||||||
|
; OR HL = HL | DE
|
||||||
|
|
||||||
|
ccor
|
||||||
|
LD A,L
|
||||||
|
OR E
|
||||||
|
LD L,A
|
||||||
|
LD A,H
|
||||||
|
OR D
|
||||||
|
LD H,A
|
||||||
|
RET
|
||||||
|
|
||||||
|
; XOR HL = HL ^ DE
|
||||||
|
|
||||||
|
ccxor
|
||||||
|
LD A,L
|
||||||
|
XOR E
|
||||||
|
LD L,A
|
||||||
|
LD A,H
|
||||||
|
XOR D
|
||||||
|
LD H,A
|
||||||
|
RET
|
||||||
|
|
||||||
|
; AND HL = HL & DE
|
||||||
|
|
||||||
|
ccand
|
||||||
|
LD A,L
|
||||||
|
AND E
|
||||||
|
LD L,A
|
||||||
|
LD A,H
|
||||||
|
AND D
|
||||||
|
LD H,A
|
||||||
|
RET
|
||||||
|
|
||||||
|
; LOGIC OR HL = DE || HL
|
||||||
|
|
||||||
|
cclgor
|
||||||
|
LD A,H
|
||||||
|
OR L
|
||||||
|
OR D
|
||||||
|
OR E
|
||||||
|
LD L,A
|
||||||
|
RET
|
||||||
|
|
||||||
|
;LD A,H
|
||||||
|
;OR L
|
||||||
|
;RET NZ
|
||||||
|
;LD A,D
|
||||||
|
;OR E
|
||||||
|
;RET Z
|
||||||
|
;INC L
|
||||||
|
;RET
|
||||||
|
|
||||||
|
; LOGIC AND HL = DE && HL
|
||||||
|
|
||||||
|
cclgand
|
||||||
|
LD A,H
|
||||||
|
OR L
|
||||||
|
RET Z
|
||||||
|
LD A,D
|
||||||
|
OR E
|
||||||
|
RET NZ
|
||||||
|
JP ccfalse
|
||||||
|
|
||||||
|
; HL = HL == DE
|
||||||
|
|
||||||
|
cceq
|
||||||
|
OR A
|
||||||
|
SBC HL,DE
|
||||||
|
|
||||||
|
; LOGIC NOT HL = !HL
|
||||||
|
|
||||||
|
cclgnot
|
||||||
|
LD A,H
|
||||||
|
OR L
|
||||||
|
JP NZ,ccfalse
|
||||||
|
INC L
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = HL != DE
|
||||||
|
|
||||||
|
ccne
|
||||||
|
OR A
|
||||||
|
SBC HL,DE
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = DE > HL (SIGNED)
|
||||||
|
|
||||||
|
ccgt
|
||||||
|
EX DE,HL
|
||||||
|
|
||||||
|
; HL = DE < HL (SIGNED)
|
||||||
|
|
||||||
|
cclt
|
||||||
|
CALL cccmp
|
||||||
|
RET C
|
||||||
|
DEC L
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = DE <= HL (SIGNED)
|
||||||
|
|
||||||
|
ccle
|
||||||
|
CALL cccmp
|
||||||
|
RET Z
|
||||||
|
RET C
|
||||||
|
DEC L
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = DE >= HL (SIGNED)
|
||||||
|
|
||||||
|
ccge
|
||||||
|
CALL cccmp
|
||||||
|
RET NC
|
||||||
|
DEC L
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Compare DE with HL, and return: (SIGNED)
|
||||||
|
;
|
||||||
|
; CARRY if DE < HL
|
||||||
|
; ZERO if DE == HL
|
||||||
|
; HL = 1
|
||||||
|
|
||||||
|
cccmp
|
||||||
|
LD A,E
|
||||||
|
SUB L
|
||||||
|
LD E,A
|
||||||
|
LD A,D
|
||||||
|
SBC H
|
||||||
|
LD HL,1
|
||||||
|
JP M,cccmp1
|
||||||
|
OR E
|
||||||
|
RET
|
||||||
|
|
||||||
|
cccmp1
|
||||||
|
OR E
|
||||||
|
SCF
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = DE <= HL (UNSIGNED)
|
||||||
|
|
||||||
|
ccule
|
||||||
|
CALL ccucmp
|
||||||
|
RET Z
|
||||||
|
RET C
|
||||||
|
DEC L
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = DE >= HL (UNSIGNED)
|
||||||
|
|
||||||
|
ccuge
|
||||||
|
CALL ccucmp
|
||||||
|
RET NC
|
||||||
|
DEC L
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = DE > HL (UNSIGNED)
|
||||||
|
|
||||||
|
ccugt
|
||||||
|
EX DE,HL
|
||||||
|
|
||||||
|
; HL = DE < HL (UNSIGNED)
|
||||||
|
|
||||||
|
ccult
|
||||||
|
CALL ccucmp
|
||||||
|
RET C
|
||||||
|
DEC L
|
||||||
|
RET
|
||||||
|
|
||||||
|
; Compare DE with HL, and return: (UNSIGNED)
|
||||||
|
;
|
||||||
|
; CARRY if DE < HL
|
||||||
|
; ZERO if DE == HL
|
||||||
|
; HL = 1
|
||||||
|
|
||||||
|
ccucmp
|
||||||
|
LD A,D
|
||||||
|
CP H
|
||||||
|
JR NZ,ccucmp1
|
||||||
|
LD A,E
|
||||||
|
CP L
|
||||||
|
|
||||||
|
ccucmp1
|
||||||
|
LD HL,1
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = DE >> HL (UNSIGNED)
|
||||||
|
|
||||||
|
ccuasr
|
||||||
|
EX DE,HL
|
||||||
|
LD A,E
|
||||||
|
ccuasr1
|
||||||
|
OR A
|
||||||
|
RET Z
|
||||||
|
DEC A
|
||||||
|
SRL H
|
||||||
|
RR L
|
||||||
|
JR ccuasr1
|
||||||
|
|
||||||
|
; HL = DE >> HL (ARITMETIC)
|
||||||
|
|
||||||
|
ccasr
|
||||||
|
EX DE,HL
|
||||||
|
LD A,E
|
||||||
|
ccasr1
|
||||||
|
OR A
|
||||||
|
RET Z
|
||||||
|
DEC A
|
||||||
|
SRA H
|
||||||
|
RR L
|
||||||
|
JR ccasr1
|
||||||
|
|
||||||
|
; HL = DE << HL (UNSIGNED)
|
||||||
|
|
||||||
|
ccuasl
|
||||||
|
|
||||||
|
; HL = DE << HL (ARITMETIC)
|
||||||
|
|
||||||
|
ccasl
|
||||||
|
EX DE,HL
|
||||||
|
LD A,E
|
||||||
|
ccasl1
|
||||||
|
OR A
|
||||||
|
RET Z
|
||||||
|
DEC A
|
||||||
|
ADD HL,HL
|
||||||
|
JR ccasl1
|
||||||
|
|
||||||
|
; HL = DE - HL
|
||||||
|
|
||||||
|
ccsub
|
||||||
|
EX DE,HL
|
||||||
|
OR A
|
||||||
|
SBC HL,DE
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = ~HL (1 COMPLEMENT)
|
||||||
|
|
||||||
|
cccom
|
||||||
|
LD A,H
|
||||||
|
CPL
|
||||||
|
LD H,A
|
||||||
|
LD A,L
|
||||||
|
CPL
|
||||||
|
LD L,A
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = -HL (2 COMPLEMENT)
|
||||||
|
|
||||||
|
ccneg
|
||||||
|
LD A,H
|
||||||
|
CPL
|
||||||
|
LD H,A
|
||||||
|
LD A,L
|
||||||
|
CPL
|
||||||
|
LD L,A
|
||||||
|
INC HL
|
||||||
|
RET
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#ifndef CC_NO_MUL
|
||||||
|
|
||||||
|
#asm
|
||||||
|
|
||||||
|
; HL = DE * HL (UNSIGNED)
|
||||||
|
|
||||||
|
ccumul
|
||||||
|
|
||||||
|
; HL = DE * HL (SIGNED)
|
||||||
|
|
||||||
|
ccmul
|
||||||
|
LD A,H
|
||||||
|
LD C,L
|
||||||
|
LD HL,0
|
||||||
|
LD B,16
|
||||||
|
ccmul0
|
||||||
|
ADD HL,HL
|
||||||
|
SLA C
|
||||||
|
RL A
|
||||||
|
JR NC,ccmul1
|
||||||
|
ADD HL,DE
|
||||||
|
ccmul1
|
||||||
|
DJNZ ccmul0
|
||||||
|
RET
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CC_NO_DIV
|
||||||
|
|
||||||
|
#asm
|
||||||
|
|
||||||
|
; HL = DE % HL (SIGNED)
|
||||||
|
|
||||||
|
ccmod
|
||||||
|
CALL ccdiv
|
||||||
|
EX DE,HL
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = DE / HL (SIGNED)
|
||||||
|
; DE = DE % HL (SIGNED)
|
||||||
|
|
||||||
|
ccdiv
|
||||||
|
LD B,H
|
||||||
|
LD C,L
|
||||||
|
LD A,D
|
||||||
|
XOR B
|
||||||
|
PUSH AF
|
||||||
|
LD A,D
|
||||||
|
OR A
|
||||||
|
CALL M,ccdivdeneg
|
||||||
|
LD A,B
|
||||||
|
OR A
|
||||||
|
|
||||||
|
JP P,ccdiv0
|
||||||
|
|
||||||
|
LD A,B
|
||||||
|
CPL
|
||||||
|
LD B,A
|
||||||
|
LD A,C
|
||||||
|
CPL
|
||||||
|
LD C,A
|
||||||
|
INC BC
|
||||||
|
|
||||||
|
ccdiv0
|
||||||
|
EX DE,HL
|
||||||
|
LD DE,0
|
||||||
|
LD A,16
|
||||||
|
|
||||||
|
ccdiv1
|
||||||
|
PUSH AF
|
||||||
|
|
||||||
|
ADD HL,HL
|
||||||
|
|
||||||
|
RL E
|
||||||
|
RL D
|
||||||
|
LD A,D
|
||||||
|
OR E
|
||||||
|
|
||||||
|
JR Z,ccdiv2
|
||||||
|
|
||||||
|
LD A,E
|
||||||
|
SUB C
|
||||||
|
LD A,D
|
||||||
|
SBC B
|
||||||
|
|
||||||
|
JP M,ccdiv2
|
||||||
|
LD A,L
|
||||||
|
OR 1
|
||||||
|
LD L,A
|
||||||
|
LD A,E
|
||||||
|
SUB C
|
||||||
|
LD E,A
|
||||||
|
LD A,D
|
||||||
|
SBC B
|
||||||
|
LD D,A
|
||||||
|
|
||||||
|
ccdiv2
|
||||||
|
POP AF
|
||||||
|
DEC A
|
||||||
|
JR NZ,ccdiv1
|
||||||
|
POP AF
|
||||||
|
RET P
|
||||||
|
|
||||||
|
CALL ccneg
|
||||||
|
|
||||||
|
ccdivdeneg
|
||||||
|
LD A,D
|
||||||
|
CPL
|
||||||
|
LD D,A
|
||||||
|
LD A,E
|
||||||
|
CPL
|
||||||
|
LD E,A
|
||||||
|
INC DE
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = DE % HL (UNSIGNED)
|
||||||
|
|
||||||
|
ccumod
|
||||||
|
CALL ccudiv
|
||||||
|
EX DE,HL
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = DE / HL (UNSIGNED)
|
||||||
|
; DE = DE % HL (UNSIGNED)
|
||||||
|
|
||||||
|
ccudiv
|
||||||
|
LD (ccudiv_tmp),HL
|
||||||
|
LD HL,ccudiv_cnt
|
||||||
|
LD (HL),17
|
||||||
|
LD BC,0
|
||||||
|
PUSH BC
|
||||||
|
XOR A
|
||||||
|
|
||||||
|
ccudiv0
|
||||||
|
RL E
|
||||||
|
RL D
|
||||||
|
DEC (HL)
|
||||||
|
POP HL
|
||||||
|
JR Z,ccudiv2
|
||||||
|
LD A,0
|
||||||
|
ADC 0
|
||||||
|
ADD HL,HL
|
||||||
|
LD B,H
|
||||||
|
ADD L
|
||||||
|
LD HL,(ccudiv_tmp)
|
||||||
|
SUB L
|
||||||
|
LD C,A
|
||||||
|
LD A,B
|
||||||
|
SBC H
|
||||||
|
LD B,A
|
||||||
|
PUSH BC
|
||||||
|
JR NC,ccudiv1
|
||||||
|
ADD HL,BC
|
||||||
|
EX (SP),HL
|
||||||
|
|
||||||
|
ccudiv1
|
||||||
|
LD HL,ccudiv_cnt
|
||||||
|
CCF
|
||||||
|
JR ccudiv0
|
||||||
|
|
||||||
|
ccudiv2
|
||||||
|
EX DE,HL
|
||||||
|
RET
|
||||||
|
|
||||||
|
ccudiv_tmp
|
||||||
|
DEFW 0
|
||||||
|
ccudiv_cnt
|
||||||
|
DEFB 0
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CC_NO_SWITCH
|
||||||
|
|
||||||
|
#asm
|
||||||
|
|
||||||
|
; Switch, on entry:
|
||||||
|
;
|
||||||
|
; DE = Table address
|
||||||
|
; HL = Where to go if value was not found in table
|
||||||
|
; B = Number of entries in table
|
||||||
|
|
||||||
|
ccswtch
|
||||||
|
EX (SP),HL
|
||||||
|
EX DE,HL
|
||||||
|
|
||||||
|
ccswch1
|
||||||
|
LD A,E
|
||||||
|
CP (HL)
|
||||||
|
INC HL
|
||||||
|
JR NZ,ccswch2
|
||||||
|
LD A,D
|
||||||
|
CP (HL)
|
||||||
|
JR NZ,ccswch2
|
||||||
|
INC HL
|
||||||
|
LD E,(HL)
|
||||||
|
INC HL
|
||||||
|
LD D,(HL)
|
||||||
|
EX DE,HL
|
||||||
|
POP BC
|
||||||
|
JP (HL)
|
||||||
|
|
||||||
|
ccswch2
|
||||||
|
INC HL
|
||||||
|
INC HL
|
||||||
|
INC HL
|
||||||
|
DJNZ ccswch1
|
||||||
|
EX (SP),HL
|
||||||
|
POP BC
|
||||||
|
JP (HL)
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#asm
|
||||||
|
|
||||||
|
; HL = TRUE
|
||||||
|
|
||||||
|
cctrue
|
||||||
|
LD L,1
|
||||||
|
RET
|
||||||
|
|
||||||
|
; HL = FALSE
|
||||||
|
|
||||||
|
ccfalse
|
||||||
|
LD HL,0
|
||||||
|
RET
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
|
104
Blocks/sprintf.h
Normal file
104
Blocks/sprintf.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* @file sprintf.h
|
||||||
|
* @brief Library for sprintf() function.
|
||||||
|
* @author Miguel I. Garcia Lopez / FloppySoftware
|
||||||
|
*
|
||||||
|
* Implementation of sprintf() function, for MESCC (Mike's Enhanced
|
||||||
|
* Small C Compiler for Z80 & CP/M).
|
||||||
|
*
|
||||||
|
* Revisions:
|
||||||
|
* - 20 Oct 2000 : Last revision.
|
||||||
|
* - 16 Apr 2007 : GPL'd.
|
||||||
|
* - 14 Apr 2015 : Ammended a bad closed comment.
|
||||||
|
* - 25 Aug 2016 : Documented. GPL v3.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2016 Miguel I. Garcia Lopez / FloppySoftware.
|
||||||
|
*
|
||||||
|
* Licensed under the GNU General Public License v3.
|
||||||
|
*
|
||||||
|
* http://www.floppysoftware.es
|
||||||
|
* floppysoftware@gmail.com
|
||||||
|
*/
|
||||||
|
#ifndef SPRINTF_H
|
||||||
|
|
||||||
|
#define SPRINTF_H
|
||||||
|
|
||||||
|
// Dependencies
|
||||||
|
// ------------
|
||||||
|
|
||||||
|
#ifndef XPRINTF_H
|
||||||
|
#include <xprintf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int sprintf(char *dst, char *fmt, arg1, arg2, ...)
|
||||||
|
* @brief Formatted output to memory.
|
||||||
|
*
|
||||||
|
* See the documentation for xprintf.h to learn about the string format.
|
||||||
|
*
|
||||||
|
* @param dst - destination
|
||||||
|
* @param fmt - string format
|
||||||
|
* @param arg1 - argument #1
|
||||||
|
* @param arg? - argument #?
|
||||||
|
* @return number or characters written, or -1 on failure (currently always #).
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
|
||||||
|
sprintf:
|
||||||
|
ADD HL,HL
|
||||||
|
ADD HL,SP ;HL=Adr. fmt
|
||||||
|
|
||||||
|
LD DE,xspfout
|
||||||
|
PUSH DE
|
||||||
|
LD DE,xspfend
|
||||||
|
PUSH DE
|
||||||
|
PUSH HL
|
||||||
|
|
||||||
|
INC HL
|
||||||
|
INC HL ;HL=Adr. dst
|
||||||
|
LD A,(HL)
|
||||||
|
INC HL
|
||||||
|
LD H,(HL)
|
||||||
|
LD L,A
|
||||||
|
LD (xspfout+2),HL
|
||||||
|
|
||||||
|
CALL xprintf
|
||||||
|
|
||||||
|
POP BC
|
||||||
|
POP BC
|
||||||
|
POP BC
|
||||||
|
|
||||||
|
RET
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
// int xspfout(char ch) : output ch to memory; return 0 on success, !=0 on failure (currently always returns 0).
|
||||||
|
|
||||||
|
#asm
|
||||||
|
|
||||||
|
xspfout:
|
||||||
|
LD A,L
|
||||||
|
LD HL,0 ;Adr.
|
||||||
|
LD (HL),A
|
||||||
|
|
||||||
|
INC HL
|
||||||
|
LD (xspfout+2),HL
|
||||||
|
|
||||||
|
LD HL,0
|
||||||
|
|
||||||
|
RET
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
// void xspfend(void) : end formatted output; writes a trailing zero byte.
|
||||||
|
|
||||||
|
#asm
|
||||||
|
|
||||||
|
xspfend:
|
||||||
|
LD HL,(xspfout+2)
|
||||||
|
LD (HL),0
|
||||||
|
RET
|
||||||
|
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
249
Blocks/string.h
Normal file
249
Blocks/string.h
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/**
|
||||||
|
* @file string.h
|
||||||
|
* @brief String functions.
|
||||||
|
* @author Miguel I. Garcia Lopez / FloppySoftware
|
||||||
|
*
|
||||||
|
* String functions, for MESCC (Mike's Enhanced
|
||||||
|
* Small C Compiler for Z80 & CP/M).
|
||||||
|
*
|
||||||
|
* Revisions:
|
||||||
|
* - 19 Mar 2001 : Last revision.
|
||||||
|
* - 16 Apr 2007 : GPL'd.
|
||||||
|
* - 15 Aug 2016 : Documented. GPL v3.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2016 Miguel I. Garcia Lopez / FloppySoftware.
|
||||||
|
*
|
||||||
|
* Licensed under the GNU General Public License v3.
|
||||||
|
*
|
||||||
|
* http://www.floppysoftware.es
|
||||||
|
* floppysoftware@gmail.com
|
||||||
|
*/
|
||||||
|
#ifndef STRING_H
|
||||||
|
|
||||||
|
#define STRING_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int strlen(char *str)
|
||||||
|
* @brief Return string length.
|
||||||
|
* @param str - string
|
||||||
|
* @return length in characters
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
strlen:
|
||||||
|
LD D,H
|
||||||
|
LD E,L
|
||||||
|
LD BC,0FFFFH
|
||||||
|
XOR A
|
||||||
|
CPIR
|
||||||
|
OR A
|
||||||
|
SBC HL,DE
|
||||||
|
DEC HL
|
||||||
|
RET
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn char *strcpy(char *dst, char *src)
|
||||||
|
* @brief Copy string.
|
||||||
|
* @param dst - destination string
|
||||||
|
* @param src - source string
|
||||||
|
* @return pointer to dst
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
strcpy:
|
||||||
|
POP BC
|
||||||
|
POP HL
|
||||||
|
POP DE
|
||||||
|
PUSH DE
|
||||||
|
PUSH HL
|
||||||
|
PUSH BC
|
||||||
|
|
||||||
|
PUSH DE
|
||||||
|
|
||||||
|
strcpy2:
|
||||||
|
LD A,(HL)
|
||||||
|
LD (DE),A
|
||||||
|
INC HL
|
||||||
|
INC DE
|
||||||
|
OR A
|
||||||
|
JR NZ,strcpy2
|
||||||
|
POP HL
|
||||||
|
RET
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn char *strcat(char *dst, char *src)
|
||||||
|
* @brief Copy string at the end of another string.
|
||||||
|
* @param dst - destination string
|
||||||
|
* @param src - source string
|
||||||
|
* @return pointer to dst
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
strcat:
|
||||||
|
POP BC
|
||||||
|
POP HL
|
||||||
|
POP DE
|
||||||
|
PUSH DE
|
||||||
|
PUSH HL
|
||||||
|
PUSH BC
|
||||||
|
|
||||||
|
PUSH DE
|
||||||
|
|
||||||
|
strcat2
|
||||||
|
LD A,(DE)
|
||||||
|
OR A
|
||||||
|
JR Z,strcpy2
|
||||||
|
INC DE
|
||||||
|
JR strcat2
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int strcmp(char *str1, char *str2)
|
||||||
|
* @brief Compare two strings.
|
||||||
|
* @param str1 - a string
|
||||||
|
* @param str2 - a string
|
||||||
|
* @return <0 on str1 < str2; =0 on str1 == str2; >0 on str1 > str2
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
strcmp
|
||||||
|
POP BC
|
||||||
|
POP HL
|
||||||
|
POP DE
|
||||||
|
PUSH DE
|
||||||
|
PUSH HL
|
||||||
|
PUSH BC
|
||||||
|
strcmp1
|
||||||
|
LD A,(DE)
|
||||||
|
CP (HL)
|
||||||
|
JR NZ,strcmp2
|
||||||
|
|
||||||
|
OR A
|
||||||
|
JR Z,strcmp2
|
||||||
|
|
||||||
|
INC DE
|
||||||
|
INC HL
|
||||||
|
JR strcmp1
|
||||||
|
|
||||||
|
strcmp2
|
||||||
|
LD HL,0
|
||||||
|
RET Z
|
||||||
|
JR NC,strcmp3
|
||||||
|
DEC HL
|
||||||
|
RET
|
||||||
|
strcmp3
|
||||||
|
INC L
|
||||||
|
RET
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn char *strchr(char *str, char ch)
|
||||||
|
* @brief Search a character in a string.
|
||||||
|
* @param str - the string where to search
|
||||||
|
* @param ch - the character to find
|
||||||
|
* @return pointer to ch in the string, or NULL on failure
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
strchr
|
||||||
|
POP BC
|
||||||
|
POP DE
|
||||||
|
POP HL
|
||||||
|
PUSH HL
|
||||||
|
PUSH DE
|
||||||
|
PUSH BC
|
||||||
|
|
||||||
|
|
||||||
|
strchr2
|
||||||
|
LD A,(HL)
|
||||||
|
CP E
|
||||||
|
RET Z
|
||||||
|
|
||||||
|
INC HL
|
||||||
|
OR A
|
||||||
|
JR NZ,strchr2
|
||||||
|
|
||||||
|
LD H,A
|
||||||
|
LD L,A
|
||||||
|
RET
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn char *strupr(char *str)
|
||||||
|
* @brief Convert a string to upper case.
|
||||||
|
* @param str - a string
|
||||||
|
* @return pointer to str
|
||||||
|
*/
|
||||||
|
#asm
|
||||||
|
strupr
|
||||||
|
POP BC
|
||||||
|
POP HL
|
||||||
|
PUSH HL
|
||||||
|
PUSH BC
|
||||||
|
|
||||||
|
PUSH HL
|
||||||
|
|
||||||
|
strupr1
|
||||||
|
LD A,(HL)
|
||||||
|
OR A
|
||||||
|
JR Z,strupr3
|
||||||
|
|
||||||
|
CP 'a'
|
||||||
|
JR C,strupr2
|
||||||
|
CP 'z'+1
|
||||||
|
JR NC,strupr2
|
||||||
|
SUB 32
|
||||||
|
LD (HL),A
|
||||||
|
|
||||||
|
strupr2
|
||||||
|
INC HL
|
||||||
|
JR strupr1
|
||||||
|
|
||||||
|
strupr3
|
||||||
|
POP HL
|
||||||
|
RET
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int atoi(char *s)
|
||||||
|
* @brief Convert string to a integer.
|
||||||
|
*
|
||||||
|
* This function parses a string, interpreting its content as
|
||||||
|
* a decimal integer number, until the end of the string, or
|
||||||
|
* a non decimal digit:
|
||||||
|
*
|
||||||
|
* [+|-][[0..9]...][ZERO|NON_DECIMAL_DIGIT]
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* - "-256" == -256
|
||||||
|
* - "64" == 64
|
||||||
|
* - "1024 bytes" == 1024
|
||||||
|
* - "what?" == 0
|
||||||
|
*
|
||||||
|
* @param s - a string
|
||||||
|
* @return integer value
|
||||||
|
*/
|
||||||
|
atoi(s)
|
||||||
|
char *s;
|
||||||
|
{
|
||||||
|
int sign, val;
|
||||||
|
|
||||||
|
if(*s == '+')
|
||||||
|
{
|
||||||
|
++s; sign = 1;
|
||||||
|
}
|
||||||
|
else if(*s == '-')
|
||||||
|
{
|
||||||
|
++s; sign = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sign = 1;
|
||||||
|
|
||||||
|
val=0;
|
||||||
|
|
||||||
|
while(*s >= '0' && *s <= '9')
|
||||||
|
val = val * 10 + (*s++ - '0');
|
||||||
|
|
||||||
|
return val * sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
365
Blocks/xprintf.h
Normal file
365
Blocks/xprintf.h
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
/**
|
||||||
|
* @file xprintf.h
|
||||||
|
* @brief Support library for formatted output.
|
||||||
|
* @author Miguel I. Garcia Lopez / FloppySoftware
|
||||||
|
*
|
||||||
|
* Support library for formatted output,
|
||||||
|
* for MESCC (Mike's Enhanced Small C Compiler for Z80 & CP/M).
|
||||||
|
*
|
||||||
|
* All functions with formatted output like printf(), fprintf()
|
||||||
|
* and sprintf() call some private functions in this order:
|
||||||
|
* - pf_sf()
|
||||||
|
* - pf_s()
|
||||||
|
* - pf_out()
|
||||||
|
*
|
||||||
|
* Revisions:
|
||||||
|
* - 19 Mar 2001 : Last revision.
|
||||||
|
* - 16 Apr 2007 : GPL'd.
|
||||||
|
* - 09 Dec 2016 : Documented. Optimized. GPL v3.
|
||||||
|
* - 02 Aug 2017 : Output '%%' as '%'.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1999-2016 Miguel I. Garcia Lopez / FloppySoftware.
|
||||||
|
*
|
||||||
|
* Licensed under the GNU General Public License v3.
|
||||||
|
*
|
||||||
|
* http://www.floppysoftware.es
|
||||||
|
* floppysoftware@gmail.com
|
||||||
|
*/
|
||||||
|
#ifndef XPRINTF_H
|
||||||
|
|
||||||
|
#define XPRINTF_H
|
||||||
|
|
||||||
|
// Dependencies
|
||||||
|
// ------------
|
||||||
|
|
||||||
|
#ifndef STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Private globals
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
BYTE xpf_err; // True on error
|
||||||
|
|
||||||
|
extern WORD xpf_out; // Output function
|
||||||
|
extern WORD xpf_end; // End function
|
||||||
|
|
||||||
|
int xpf_fw; // Field width
|
||||||
|
BYTE xpf_fa; // Field alignment: 0=left, 1=right
|
||||||
|
BYTE xpf_fz; // True on zero filling
|
||||||
|
|
||||||
|
int xpf_cnt; // # of characters sent
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn int xprintf(WORD funout, WORD funend, WORD adrpars)
|
||||||
|
* @brief Formatted output.
|
||||||
|
*
|
||||||
|
* This function performs formatted output. It is used
|
||||||
|
* by printf(), fprintf() and sprintf() functions.
|
||||||
|
*
|
||||||
|
* The format is indicated in the string as follows:
|
||||||
|
*
|
||||||
|
* %[-][0][w]t
|
||||||
|
*
|
||||||
|
* | - : Left align (default: right align).
|
||||||
|
* | 0 : Zero filling on right align.
|
||||||
|
* | w : Width for alignment. If the specified width
|
||||||
|
* | is lower than the argument length, output is
|
||||||
|
* | done without aligment. Care with sprinf()!
|
||||||
|
* | t : d = Signed decimal integer.
|
||||||
|
* | u = Unsigned decimal integer.
|
||||||
|
* | x = Hexadecimal integer.
|
||||||
|
* | s = String.
|
||||||
|
* | c = Character.
|
||||||
|
*
|
||||||
|
* The pair %% outputs a single %.
|
||||||
|
*
|
||||||
|
* @param funout - function to output a character
|
||||||
|
* @param funend - function to end output
|
||||||
|
* @param adrpars - arguments addresses
|
||||||
|
* @return # of characters sent on sucess, -1 on failure
|
||||||
|
*/
|
||||||
|
xprintf(funout, funend, adrpars)
|
||||||
|
WORD funout, funend;
|
||||||
|
WORD *adrpars;
|
||||||
|
{
|
||||||
|
WORD *parg; // Pointer to arguments
|
||||||
|
char *pfor; // Pointer to formatted string
|
||||||
|
int ivalue;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
xpf_out = funout;
|
||||||
|
xpf_end = funend;
|
||||||
|
|
||||||
|
pfor = *adrpars;
|
||||||
|
parg = --adrpars;
|
||||||
|
|
||||||
|
xpf_err = xpf_cnt = 0;
|
||||||
|
|
||||||
|
// Loop
|
||||||
|
while((ch = *pfor++))
|
||||||
|
{
|
||||||
|
if(ch == '%')
|
||||||
|
{
|
||||||
|
// Character %
|
||||||
|
if(*pfor == '%')
|
||||||
|
{
|
||||||
|
pf_out(ch);
|
||||||
|
++pfor;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Align
|
||||||
|
if(*pfor == '-')
|
||||||
|
{
|
||||||
|
xpf_fa = 0; // Left align
|
||||||
|
++pfor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
xpf_fa = 1; // Right align
|
||||||
|
|
||||||
|
// Zero filling
|
||||||
|
if(*pfor == '0')
|
||||||
|
{
|
||||||
|
xpf_fz = 1; // Zero filling
|
||||||
|
++pfor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
xpf_fz = 0;
|
||||||
|
|
||||||
|
// Width
|
||||||
|
xpf_fw = 0;
|
||||||
|
|
||||||
|
while(*pfor >= '0' && *pfor <= '9')
|
||||||
|
xpf_fw = xpf_fw * 10 + (*pfor++) - '0';
|
||||||
|
|
||||||
|
// Type
|
||||||
|
switch(ch = *pfor++)
|
||||||
|
{
|
||||||
|
case 'd' :
|
||||||
|
ivalue = *parg--;
|
||||||
|
pf_dec(ivalue);
|
||||||
|
break;
|
||||||
|
case 'u' :
|
||||||
|
ivalue = *parg--;
|
||||||
|
pf_udec(ivalue);
|
||||||
|
break;
|
||||||
|
case 'x' :
|
||||||
|
ivalue = *parg--;
|
||||||
|
pf_hex(ivalue);
|
||||||
|
break;
|
||||||
|
case 'c' :
|
||||||
|
pf_cf(*parg--);
|
||||||
|
break;
|
||||||
|
case 's' :
|
||||||
|
pf_sf(*parg--);
|
||||||
|
break;
|
||||||
|
case '\0' :
|
||||||
|
--pfor;
|
||||||
|
// P'abajo
|
||||||
|
default :
|
||||||
|
pf_out('!');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pf_out(ch);
|
||||||
|
|
||||||
|
if(xpf_err)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pf_end();
|
||||||
|
|
||||||
|
return xpf_err ? -1 : xpf_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void pf_sf(char *s) : output formatted string.
|
||||||
|
|
||||||
|
pf_sf(s)
|
||||||
|
char *s;
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char fill;
|
||||||
|
|
||||||
|
if(xpf_fw)
|
||||||
|
{
|
||||||
|
if((len = strlen(s)) < xpf_fw)
|
||||||
|
{
|
||||||
|
xpf_fw = xpf_fw-len;
|
||||||
|
|
||||||
|
if(xpf_fa)
|
||||||
|
{
|
||||||
|
// Left align
|
||||||
|
fill = (xpf_fz ? '0' : ' ');
|
||||||
|
|
||||||
|
while(xpf_fw--)
|
||||||
|
pf_out(fill);
|
||||||
|
pf_s(s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Right align
|
||||||
|
pf_s(s);
|
||||||
|
|
||||||
|
while(xpf_fw--)
|
||||||
|
pf_out(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pf_s(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void pf_cf(char c) : output formatted character.
|
||||||
|
|
||||||
|
pf_cf(c)
|
||||||
|
char c;
|
||||||
|
{
|
||||||
|
char tmp[2];
|
||||||
|
|
||||||
|
tmp[0] = c; tmp[1] = '\0';
|
||||||
|
|
||||||
|
pf_sf(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char xpf_dst[7]; // Buffer for numbers
|
||||||
|
unsigned char *xpf_dpt; // Buffer pointer
|
||||||
|
|
||||||
|
// void pf_dec(int i) : output signed decimal integer.
|
||||||
|
|
||||||
|
pf_dec(i)
|
||||||
|
int i;
|
||||||
|
{
|
||||||
|
xpf_dpt = xpf_dst;
|
||||||
|
|
||||||
|
if(i < 0)
|
||||||
|
{
|
||||||
|
*xpf_dpt++ = '-'; i = -i;
|
||||||
|
}
|
||||||
|
|
||||||
|
pf_dec2(i);
|
||||||
|
|
||||||
|
*xpf_dpt = '\0';
|
||||||
|
|
||||||
|
pf_sf(xpf_dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void pf_dec2(int i) : helper for pf_dec().
|
||||||
|
|
||||||
|
pf_dec2(i)
|
||||||
|
int i;
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if(n = i / 10)
|
||||||
|
pf_dec2(n);
|
||||||
|
|
||||||
|
*xpf_dpt++ = i % 10 + '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// void pf_udec(unsigned int i) : output unsigned decimal integer.
|
||||||
|
|
||||||
|
pf_udec(i)
|
||||||
|
unsigned i;
|
||||||
|
{
|
||||||
|
xpf_dpt = xpf_dst;
|
||||||
|
|
||||||
|
pf_udec2(i);
|
||||||
|
|
||||||
|
*xpf_dpt = '\0';
|
||||||
|
|
||||||
|
pf_sf(xpf_dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void pf_udec2(unsigned int i) : helper for pf_udec().
|
||||||
|
|
||||||
|
pf_udec2(i)
|
||||||
|
unsigned i;
|
||||||
|
{
|
||||||
|
unsigned n;
|
||||||
|
|
||||||
|
if(n = i / 10)
|
||||||
|
pf_udec2(n);
|
||||||
|
|
||||||
|
*xpf_dpt++ = i % 10 + '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// void pf_hex(unsigned int i) : output hexadecimal integer.
|
||||||
|
|
||||||
|
pf_hex(i)
|
||||||
|
unsigned i;
|
||||||
|
{
|
||||||
|
xpf_dpt = xpf_dst;
|
||||||
|
|
||||||
|
pf_hex2(i);
|
||||||
|
|
||||||
|
*xpf_dpt = '\0';
|
||||||
|
|
||||||
|
pf_sf(xpf_dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void pf_hex2(unsigned int i) : helper for pf_hex().
|
||||||
|
|
||||||
|
pf_hex2(i)
|
||||||
|
unsigned i;
|
||||||
|
{
|
||||||
|
unsigned n;
|
||||||
|
|
||||||
|
if(n = i / 16)
|
||||||
|
pf_hex2(n);
|
||||||
|
|
||||||
|
i %= 16;
|
||||||
|
|
||||||
|
*xpf_dpt++ = i < 10 ? '0' + i : 'A' + i - 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void pf_s(char *s) : output string.
|
||||||
|
|
||||||
|
pf_s(s)
|
||||||
|
char *s;
|
||||||
|
{
|
||||||
|
while(*s)
|
||||||
|
pf_out(*s++);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void pf_out(char c) : output character.
|
||||||
|
|
||||||
|
#asm
|
||||||
|
pf_out:
|
||||||
|
PUSH HL
|
||||||
|
DEFB 0CDH
|
||||||
|
xpf_out:
|
||||||
|
DEFW 0
|
||||||
|
POP BC
|
||||||
|
|
||||||
|
EX DE,HL
|
||||||
|
|
||||||
|
LD HL,(xpf_cnt)
|
||||||
|
INC HL
|
||||||
|
LD (xpf_cnt),HL
|
||||||
|
|
||||||
|
LD A,D
|
||||||
|
OR E
|
||||||
|
RET Z
|
||||||
|
;; LD A,255
|
||||||
|
LD (xpf_err),A
|
||||||
|
RET
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
// void pf_end(void) : end output.
|
||||||
|
|
||||||
|
#asm
|
||||||
|
pf_end:
|
||||||
|
DEFB 0C3H
|
||||||
|
xpf_end:
|
||||||
|
DEFW 0
|
||||||
|
#endasm
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -26,6 +26,7 @@ See this repository: https://git.imzadi.de/acn/backgammon-vt100
|
|||||||
* [Cpmtris](cpmtris/)
|
* [Cpmtris](cpmtris/)
|
||||||
* [Sokoban](Sokoban/)
|
* [Sokoban](Sokoban/)
|
||||||
* [Battleships](Battleships/)
|
* [Battleships](Battleships/)
|
||||||
|
* [Blocks](Blocks/)
|
||||||
|
|
||||||
## More Games on the Interwebs
|
## More Games on the Interwebs
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user