262 lines
6.6 KiB
C
262 lines
6.6 KiB
C
/*
|
|
* Copyright (c) 2024 Scott Duensing, scott@kangaroopunch.com
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
|
|
#ifndef WITHOUT_TEXT
|
|
|
|
|
|
#ifndef F256LIB_AMALGAMATED_BUILD
|
|
#include "f_text.h"
|
|
#include "f_math.h"
|
|
#endif
|
|
|
|
|
|
//***FIX*** IIgs colors aren't as useful as EGA colors.
|
|
colorT textColors[16] = {
|
|
{ 0x00, 0x00, 0x00 }, // 0 Black
|
|
{ 0xdd, 0x00, 0x33 }, // 1 Deep Red
|
|
{ 0x00, 0x00, 0x99 }, // 2 Dark Blue
|
|
{ 0xdd, 0x22, 0xdd }, // 3 Purple
|
|
{ 0x00, 0x77, 0x22 }, // 4 Dark Green
|
|
{ 0x55, 0x55, 0x55 }, // 5 Dark Gray
|
|
{ 0x22, 0x22, 0xff }, // 6 Medium Blue
|
|
{ 0x66, 0xaa, 0xff }, // 7 Light Blue
|
|
{ 0x88, 0x55, 0x00 }, // 8 Brown
|
|
{ 0xff, 0x66, 0x00 }, // 9 Orange
|
|
{ 0xaa, 0xaa, 0xaa }, // A Light Gray
|
|
{ 0xff, 0x99, 0x88 }, // B Pink
|
|
{ 0x00, 0xdd, 0x00 }, // C Light Green
|
|
{ 0xff, 0xff, 0x00 }, // D Yellow
|
|
{ 0x55, 0xff, 0x99 }, // E Aquamarine
|
|
{ 0xff, 0xff, 0xff } // F White
|
|
};
|
|
|
|
|
|
static byte _MAX_COL = 80;
|
|
static byte _MAX_ROW = 30;
|
|
static byte _row = 0;
|
|
static byte _col = 0;
|
|
static byte _fcolor = 15;
|
|
static byte _bcolor = 0;
|
|
static byte _ccolor = 240;
|
|
|
|
|
|
// Clear screen to current text attributes.
|
|
void textClear(void) {
|
|
byte mmu = PEEK(MMU_IO_CTRL); // Get current MMU state.
|
|
int16_t i;
|
|
int16_t count = mathUnsignedMultiply(_MAX_COL, _MAX_ROW);
|
|
volatile byte *vram = (byte *)TEXT_MATRIX;
|
|
|
|
POKE(MMU_IO_CTRL, MMU_IO_TEXT); // Swap I/O page 2 into bank 6.
|
|
for (i=0; i<count; i++) *vram++ = 32;
|
|
|
|
POKE(MMU_IO_CTRL, MMU_IO_COLOR); // Swap I/O page 3 into bank 6.
|
|
vram = (byte *)TEXT_MATRIX;
|
|
for (i=0; i<count; i++) *vram++ = _ccolor;
|
|
|
|
POKE(MMU_IO_CTRL, mmu); // Restore MMU state.
|
|
|
|
textGotoXY(0, 0);
|
|
}
|
|
|
|
|
|
void textDefineBackgroundColor(byte slot, byte r, byte g, byte b) {
|
|
byte *write;
|
|
|
|
write = (byte *)VKY_TXT_BGLUT + mathUnsignedMultiply(slot, 4);
|
|
*write++ = b;
|
|
*write++ = g;
|
|
*write++ = r;
|
|
*write++ = 0xff;
|
|
}
|
|
|
|
|
|
void textDefineForegroundColor(byte slot, byte r, byte g, byte b) {
|
|
byte *write;
|
|
|
|
write = (byte *)VKY_TXT_FGLUT + mathUnsignedMultiply(slot, 4);
|
|
*write++ = b;
|
|
*write++ = g;
|
|
*write++ = r;
|
|
*write++ = 0xff;
|
|
}
|
|
|
|
|
|
void textEnableBackgroundColors(bool b) {
|
|
POKE(VKY_MSTR_CTRL_1, (PEEK(VKY_MSTR_CTRL_1) & 0xef) | (b << 4));
|
|
}
|
|
|
|
|
|
void textGetXY(byte *x, byte *y) {
|
|
*x = _col;
|
|
*y = _row;
|
|
}
|
|
|
|
|
|
// Move cursor.
|
|
void textGotoXY(byte x, byte y) {
|
|
_col = x;
|
|
POKE(VKY_CRSR_X_L, _col); // Set cursor X position.
|
|
POKE(VKY_CRSR_X_H, 0);
|
|
|
|
_row = y;
|
|
POKE(VKY_CRSR_Y_L, _row); // Set cursor Y position.
|
|
POKE(VKY_CRSR_Y_H, 0);
|
|
}
|
|
|
|
|
|
// Print a string to the screen.
|
|
void textPrint(char *message) {
|
|
int16_t x = 0;
|
|
int16_t i = 0;
|
|
int16_t j = 0;
|
|
int16_t m = 0;
|
|
byte mmu = PEEK(MMU_IO_CTRL); // Get current MMU state.
|
|
volatile byte *vram = (byte *)mathUnsignedAddition(TEXT_MATRIX, mathUnsignedMultiply(_MAX_COL, _row));
|
|
volatile byte *save = 0;
|
|
|
|
while (message[x] != 0) {
|
|
switch (message[x]) {
|
|
default:
|
|
POKE(MMU_IO_CTRL, MMU_IO_COLOR); // Swap I/O page 3 into bank 6.
|
|
vram[_col] = _ccolor;
|
|
POKE(MMU_IO_CTRL, MMU_IO_TEXT); // Swap I/O page 2 into bank 6.
|
|
vram[_col] = message[x];
|
|
_col++;
|
|
if (_col != _MAX_COL) break;
|
|
// Fall through.
|
|
case 10:
|
|
case 13:
|
|
_col = 0;
|
|
_row++;
|
|
if (_row == _MAX_ROW) {
|
|
// Scroll contents up one line.
|
|
vram = (byte *)TEXT_MATRIX;
|
|
m = _MAX_COL * (_MAX_ROW - 1); // mathUnsignedMultiply(_MAX_COL, (_MAX_ROW - 1)); // It REALLY doesn't like using the copro for this.
|
|
POKE(MMU_IO_CTRL, MMU_IO_COLOR); // Swap I/O page 3 into bank 6.
|
|
for (j=0; j<2; j++) { // Twice - first is the text, second is color.
|
|
for (i = 0; i < m; i++) {
|
|
vram[i] = vram[i + _MAX_COL];
|
|
}
|
|
POKE(MMU_IO_CTRL, MMU_IO_TEXT); // Swap I/O page 2 into bank 6.
|
|
}
|
|
// Clear bottom line.
|
|
vram += i;
|
|
save = vram;
|
|
POKE(MMU_IO_CTRL, MMU_IO_COLOR); // Swap I/O page 3 into bank 6.
|
|
for (i = 0; i < _MAX_COL; i++) *vram++ = _ccolor;
|
|
POKE(MMU_IO_CTRL, MMU_IO_TEXT); // Swap I/O page 2 into bank 6.
|
|
vram = save;
|
|
for (i = 0; i < _MAX_COL; i++) *vram++ = 32;
|
|
// Set up on bottom line.
|
|
_row--;
|
|
vram = (byte *)mathUnsignedAddition(TEXT_MATRIX, (_MAX_ROW - 1));
|
|
} else {
|
|
vram += _MAX_COL;
|
|
}
|
|
break;
|
|
}
|
|
x++;
|
|
}
|
|
|
|
POKE(MMU_IO_CTRL, mmu); // Restore MMU state.
|
|
|
|
textGotoXY(_col, _row);
|
|
}
|
|
|
|
|
|
void textPrintInt(int32_t value){
|
|
if (value < 0) {
|
|
textPrint("-");
|
|
value = -value;
|
|
}
|
|
textPrintUInt(value);
|
|
}
|
|
|
|
|
|
void textPrintUInt(uint32_t value){
|
|
char c[2];
|
|
|
|
if (value > 9) {
|
|
if (value > 65535) {
|
|
textPrintUInt(value / 10); // Can't use the coprocessor for uint32.
|
|
} else {
|
|
textPrintUInt(mathUnsignedDivision(value, 10));
|
|
}
|
|
}
|
|
|
|
c[0] = '0' + (value % 10);
|
|
c[1] = 0;
|
|
textPrint(c);
|
|
}
|
|
|
|
|
|
void textReset(void) {
|
|
byte x;
|
|
|
|
_fcolor = 15;
|
|
_bcolor = 0;
|
|
_ccolor = 240;
|
|
|
|
// Make font taller for us blind people.
|
|
textSetDouble(false, true);
|
|
|
|
// No cursor by default.
|
|
textSetCursor(0);
|
|
|
|
// Set up default text colors.
|
|
for (x=0; x<TEXTCOLORS_COUNT; x++) {
|
|
textDefineForegroundColor(x, textColors[x].r, textColors[x].g, textColors[x].b);
|
|
textDefineBackgroundColor(x, textColors[x].r, textColors[x].g, textColors[x].b);
|
|
}
|
|
|
|
textClear();
|
|
}
|
|
|
|
|
|
void textSetColor(byte f, byte b) {
|
|
_fcolor = f;
|
|
_bcolor = b;
|
|
_ccolor = (f << 4) + b;
|
|
}
|
|
|
|
|
|
void textSetCursor(byte c) {
|
|
if (c == 0) {
|
|
POKE(VKY_CRSR_CTRL, 0); // No cursor.
|
|
} else {
|
|
POKE(VKY_CRSR_CTRL, 3); // Enable cursor, 1/2s flash.
|
|
POKE(VKY_CRSR_CHAR, c); // Set cursor shape. (199 = Checkerboard)
|
|
}
|
|
}
|
|
|
|
|
|
void textSetDouble(bool x, bool y) {
|
|
POKE(VKY_MSTR_CTRL_1, (PEEK(VKY_MSTR_CTRL_1) & 0xf9) | (x << 1) | (y << 2));
|
|
|
|
_MAX_COL = x ? 40 : 80;
|
|
_MAX_ROW = y ? 30 : 60;
|
|
}
|
|
|
|
|
|
#endif
|