mirror of
https://github.com/stevenhowes/CTheEscape.git
synced 2026-05-27 00:03:27 +01:00
446 lines
9.6 KiB
C
446 lines
9.6 KiB
C
#include <stdio.h>
|
|
#include "swis.h"
|
|
#include <kernel.h>
|
|
|
|
// SWI Registers
|
|
extern _kernel_swi_regs inreg;
|
|
extern _kernel_swi_regs outreg;
|
|
|
|
extern unsigned char *buffer;
|
|
extern unsigned char *fontbuffer;
|
|
extern unsigned char *tilebuffer;
|
|
|
|
char tilenamebuffer[4];
|
|
char letternamebuffer[2];
|
|
|
|
int screen = 1;
|
|
int tilecache[256];
|
|
int lettercache[256];
|
|
|
|
extern void screen_nobuffer();
|
|
// Loads sprite file into buffer
|
|
void load_sprites(char* filename, unsigned char **buffername)
|
|
{
|
|
int length;
|
|
|
|
// Attempt to get file info
|
|
inreg.r[0] = 5;
|
|
inreg.r[1] = (int) filename;
|
|
_kernel_swi(OS_File,&inreg,&outreg);
|
|
|
|
// Length will be in R4 if it exists
|
|
length = outreg.r[4];
|
|
|
|
// If it's <1 it's fil not found
|
|
if(outreg.r[0] < 1)
|
|
{
|
|
printf("Sprite file %s not found, object type is %i and size is %i\n",filename,outreg.r[0],outreg.r[4]);
|
|
exit(0);
|
|
}
|
|
|
|
// Stops us trying to mallocsomething mad if file is too big.
|
|
if(length > 200000)
|
|
{
|
|
screen_nobuffer();
|
|
printf("Sprite file %s seems unreasonably large at %i bytes, object type is %i\n",filename, length, outreg.r[0]);
|
|
exit(0);
|
|
}
|
|
|
|
// Attempt malloc, die if we cant
|
|
*buffername = (unsigned char *) malloc(length + 4);
|
|
|
|
if(buffername==NULL)
|
|
{
|
|
screen_nobuffer();
|
|
printf("Couldn't malloc %i bytes for sprite buffer\n",length);
|
|
exit(0);
|
|
}
|
|
|
|
// Store size and other info as required for SpriteOp 9 to init sprite area
|
|
*(unsigned int *)*buffername = length + 4;
|
|
*(unsigned int *)(*buffername + 4) = 16;
|
|
inreg.r[0] = 256+9;
|
|
inreg.r[1] = (unsigned int) *buffername;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
|
|
// Load sprite file into buffer
|
|
inreg.r[0] = 256+10;
|
|
inreg.r[1] = (int) *buffername;
|
|
inreg.r[2] = (int) filename;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
}
|
|
|
|
void display_mode(int mode)
|
|
{
|
|
int pitch;
|
|
int height=256; // TODO: This shouldn't be here!
|
|
|
|
// OS_ScreenMode doesn't seem to work in 3.10
|
|
inreg.r[0] = 22;
|
|
_kernel_swi(OS_WriteC,&inreg,&outreg);
|
|
inreg.r[0] = mode;
|
|
_kernel_swi(OS_WriteC,&inreg,&outreg);
|
|
|
|
// The SDL library does this if double buffering is enabled - seems
|
|
// to be what makes it work - although other examples dont have this
|
|
inreg.r[0] = -1;
|
|
inreg.r[1] = 6;
|
|
_kernel_swi(OS_ReadModeVariable, &inreg, &outreg);
|
|
pitch = outreg.r[2];
|
|
|
|
inreg.r[0] = 2; /* Screen area */
|
|
_kernel_swi(OS_ReadDynamicArea, &inreg, &outreg);
|
|
inreg.r[1] = (pitch * height * 2) - outreg.r[1];
|
|
if (_kernel_swi(OS_ChangeDynamicArea, &inreg, &outreg) != NULL)
|
|
{
|
|
screen_nobuffer();
|
|
while(1)
|
|
printf("Couldn't OS_ChangeDynamicArea\n");
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
void draw_dotted_line(int x1,int y1,int x2,int y2)
|
|
{
|
|
inreg.r[0] = 4 + 16;
|
|
inreg.r[1] = x1;
|
|
inreg.r[2] = y1;
|
|
_kernel_swi(OS_Plot,&inreg,&outreg);
|
|
inreg.r[0] = 5 + 16;
|
|
inreg.r[1] = x2;
|
|
inreg.r[2] = y2;
|
|
_kernel_swi(OS_Plot,&inreg,&outreg);
|
|
}
|
|
|
|
void draw_line(int x1,int y1,int x2,int y2)
|
|
{
|
|
inreg.r[0] = 4;
|
|
inreg.r[1] = x1;
|
|
inreg.r[2] = y1;
|
|
_kernel_swi(OS_Plot,&inreg,&outreg);
|
|
inreg.r[0] = 5;
|
|
inreg.r[1] = x2;
|
|
inreg.r[2] = y2;
|
|
_kernel_swi(OS_Plot,&inreg,&outreg);
|
|
}
|
|
|
|
void draw_rectangle(int x1,int y1,int x2,int y2)
|
|
{
|
|
draw_line(x1,y1,x1,y2);
|
|
draw_line(x1,y1,x2,y1);
|
|
draw_line(x2,y2,x2,y1);
|
|
draw_line(x2,y2,x1,y2);
|
|
}
|
|
|
|
void draw_sprite(char* spritename,int x, int y)
|
|
{
|
|
// SpriteOp 34 to put sprite at a location
|
|
inreg.r[0] = 256+34;
|
|
inreg.r[1] = (int) buffer;
|
|
inreg.r[2] = (int) spritename;
|
|
inreg.r[3] = x;
|
|
inreg.r[4] = y;
|
|
inreg.r[5] = 8; // GCOL dest=source and sprite mask
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
}
|
|
|
|
void draw_sprite_flippedhv(char* spritename,int x, int y)
|
|
{
|
|
// SpriteOp 32
|
|
inreg.r[0] = 256+33;
|
|
inreg.r[1] = (int) buffer;
|
|
inreg.r[2] = (int) spritename;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
|
|
// SpriteOp 47
|
|
inreg.r[0] = 256+47;
|
|
inreg.r[1] = (int) buffer;
|
|
inreg.r[2] = (int) spritename;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
|
|
draw_sprite(spritename,x,y);
|
|
|
|
// SpriteOp 47
|
|
inreg.r[0] = 256+47;
|
|
inreg.r[1] = (int) buffer;
|
|
inreg.r[2] = (int) spritename;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
|
|
// SpriteOp 32
|
|
inreg.r[0] = 256+33;
|
|
inreg.r[1] = (int) buffer;
|
|
inreg.r[2] = (int) spritename;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
|
|
}
|
|
|
|
void draw_sprite_flippedh(char* spritename,int x, int y)
|
|
{
|
|
// SpriteOp 32
|
|
inreg.r[0] = 256+33;
|
|
inreg.r[1] = (int) buffer;
|
|
inreg.r[2] = (int) spritename;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
|
|
draw_sprite(spritename,x,y);
|
|
|
|
// SpriteOp 32
|
|
inreg.r[0] = 256+33;
|
|
inreg.r[1] = (int) buffer;
|
|
inreg.r[2] = (int) spritename;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
|
|
}
|
|
|
|
void draw_sprite_flippedv(char* spritename,int x, int y)
|
|
{
|
|
// SpriteOp 47
|
|
inreg.r[0] = 256+47;
|
|
inreg.r[1] = (int) buffer;
|
|
inreg.r[2] = (int) spritename;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
|
|
draw_sprite(spritename,x,y);
|
|
|
|
// SpriteOp 47
|
|
inreg.r[0] = 256+47;
|
|
inreg.r[1] = (int) buffer;
|
|
inreg.r[2] = (int) spritename;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
|
|
}
|
|
|
|
int get_letter_address(int letternumber)
|
|
{
|
|
if(lettercache[letternumber] > 0)
|
|
return lettercache[letternumber];
|
|
|
|
sprintf(letternamebuffer,"%c",letternumber);
|
|
inreg.r[0] = 256+24;
|
|
inreg.r[1] = (int) fontbuffer;
|
|
inreg.r[2] = (int) letternamebuffer;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
|
|
// For now, if we get an invalid character just display an X
|
|
// to make it really obvious
|
|
if(outreg.r[2] == inreg.r[2])
|
|
get_letter_address((int)'X');
|
|
|
|
lettercache[letternumber] = outreg.r[2];
|
|
|
|
return lettercache[letternumber];
|
|
}
|
|
|
|
void draw_letter(int letter,int x, int y)
|
|
{
|
|
int address = get_letter_address(letter);
|
|
// SpriteOp 34 to put sprite at a location
|
|
inreg.r[0] = 512+34;
|
|
inreg.r[1] = (int) fontbuffer;
|
|
inreg.r[2] = address;
|
|
inreg.r[3] = x;
|
|
inreg.r[4] = y;
|
|
inreg.r[5] = 8;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
}
|
|
|
|
int get_tile_address(int tilenumber)
|
|
{
|
|
if(tilecache[tilenumber] > 0)
|
|
return tilecache[tilenumber];
|
|
|
|
sprintf(tilenamebuffer,"%i",tilenumber);
|
|
inreg.r[0] = 256+24;
|
|
inreg.r[1] = (int) tilebuffer;
|
|
inreg.r[2] = (int)tilenamebuffer;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
|
|
// Show default tile if not found
|
|
if(outreg.r[2] == inreg.r[2])
|
|
{
|
|
get_tile_address(0);
|
|
}
|
|
|
|
// Caching 0 seems to make it shit itself?
|
|
if(tilenumber > 0)
|
|
tilecache[tilenumber] = outreg.r[2];
|
|
|
|
return outreg.r[2];
|
|
}
|
|
|
|
void draw_tile(int tilenumber,int x, int y)
|
|
{
|
|
int address = get_tile_address(tilenumber);
|
|
|
|
// SpriteOp 34 to put sprite at a location
|
|
inreg.r[0] = 512+34;
|
|
inreg.r[1] = (int) tilebuffer; // unused because pointers are in use now
|
|
inreg.r[2] = address;
|
|
inreg.r[3] = x;
|
|
inreg.r[4] = y;
|
|
inreg.r[5] = 0;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
}
|
|
|
|
void draw_tile_trans(int tilenumber,int x, int y)
|
|
{
|
|
int address = get_tile_address(tilenumber);
|
|
|
|
// SpriteOp 34 to put sprite at a location
|
|
inreg.r[0] = 512+34;
|
|
inreg.r[1] = (int) tilebuffer;
|
|
inreg.r[2] = address;
|
|
inreg.r[3] = x;
|
|
inreg.r[4] = y;
|
|
inreg.r[5] = 8;
|
|
_kernel_swi(OS_SpriteOp,&inreg,&outreg);
|
|
}
|
|
|
|
void draw_spritetext(char* text, int x, int y)
|
|
{
|
|
int currentx;
|
|
int currenty;
|
|
int i;
|
|
|
|
currentx = x;
|
|
currenty = y;
|
|
for(i = 0; i < strlen(text); i++)
|
|
{
|
|
if((text[i] != ' ') && (text[i] != '\n') && (text[i] != '~'))
|
|
draw_letter(text[i],currentx,currenty);
|
|
|
|
switch (text[i])
|
|
{
|
|
case 't':
|
|
case 'i':
|
|
case '.':
|
|
case ',':
|
|
case 'y':
|
|
case ':':
|
|
currentx += 12 + 4;
|
|
break;
|
|
case '\'':
|
|
currentx += 8 + 4;
|
|
break;
|
|
case 'm':
|
|
currentx += 22 + 4;
|
|
break;
|
|
case 'q':
|
|
case 'w':
|
|
currentx += 20 + 4;
|
|
break;
|
|
case ' ':
|
|
case '(':
|
|
case ')':
|
|
currentx += 8 + 4;
|
|
break;
|
|
case '=':
|
|
currentx += 22 + 2;
|
|
break;
|
|
case '{':
|
|
case '}':
|
|
case ']':
|
|
currentx += 26;
|
|
break;
|
|
case '~':
|
|
currentx -= 2;
|
|
break;
|
|
default:
|
|
currentx += 16 + 4;
|
|
}
|
|
|
|
if(text[i] == '\n')
|
|
{
|
|
currentx = x;
|
|
currenty -= 36;
|
|
}
|
|
}
|
|
}
|
|
|
|
void draw_text(char* text, int x, int y, int fonthandle)
|
|
{
|
|
inreg.r[0] = fonthandle;
|
|
inreg.r[1] = (int) text;
|
|
inreg.r[2] = 1 << 4;
|
|
inreg.r[3] = x;
|
|
inreg.r[4] = y;
|
|
inreg.r[5] = 0;
|
|
inreg.r[6] = 0;
|
|
inreg.r[7] = 0;
|
|
_kernel_swi(Font_Paint,&inreg,&outreg);
|
|
}
|
|
|
|
int font_find(char* font, int height, int width)
|
|
{
|
|
inreg.r[0] = 0;
|
|
inreg.r[1] = (int) font;
|
|
inreg.r[2] = height*16;
|
|
inreg.r[3] = width*16;
|
|
inreg.r[4] = 0;
|
|
inreg.r[5] = 0;
|
|
_kernel_swi(Font_FindFont,&inreg,&outreg);
|
|
|
|
return outreg.r[0];
|
|
}
|
|
|
|
void font_colour(int fg, int bg, int fonthandle)
|
|
{
|
|
inreg.r[0] = fonthandle;
|
|
inreg.r[1] = bg;
|
|
inreg.r[2] = fg;
|
|
inreg.r[3] = 14;
|
|
_kernel_swi(ColourTrans_SetFontColours, &inreg, &outreg);
|
|
}
|
|
|
|
void graphics_colour(int setcolour)
|
|
{
|
|
inreg.r[0] = setcolour;
|
|
inreg.r[1] = -1;
|
|
inreg.r[2] = 0;
|
|
_kernel_swi(ColourTrans_ReturnColourNumberForMode,&inreg,&outreg);
|
|
inreg.r[0] = 0;
|
|
inreg.r[1] = outreg.r[0];
|
|
_kernel_swi(OS_SetColour,&inreg,&outreg);
|
|
}
|
|
void screen_flipbuffer()
|
|
{
|
|
// Hardware
|
|
inreg.r[0] = 113;
|
|
inreg.r[1] = screen+1;
|
|
_kernel_swi(OS_Byte,&inreg,&outreg);
|
|
|
|
screen ^= 1;
|
|
|
|
// Drivers
|
|
inreg.r[0] = 112;
|
|
inreg.r[1] = screen+1;
|
|
_kernel_swi(OS_Byte,&inreg,&outreg);
|
|
|
|
inreg.r[0] = 19;
|
|
_kernel_swi(OS_Byte,&inreg,&outreg);
|
|
|
|
}
|
|
|
|
void screen_nobuffer()
|
|
{
|
|
// Hardware
|
|
inreg.r[0] = 113;
|
|
inreg.r[1] = 1;
|
|
_kernel_swi(OS_Byte,&inreg,&outreg);
|
|
|
|
// Drivers
|
|
inreg.r[0] = 112;
|
|
inreg.r[1] = 1;
|
|
_kernel_swi(OS_Byte,&inreg,&outreg);
|
|
|
|
inreg.r[0] = 19;
|
|
_kernel_swi(OS_Byte,&inreg,&outreg);
|
|
|
|
}
|
|
|
|
void screen_clear()
|
|
{
|
|
inreg.r[0] = 12;
|
|
_kernel_swi(OS_WriteC,&inreg,&outreg);
|
|
}
|