blob: c9faa30aa8c88281b33f6a28020d38fd4ea89f51 [file] [log] [blame]
// Libthomson - C wrapper for Thomson MO/TO monitor and hardware
// Copyright 2012-2013, Adrien Destugues <pulkomandy@pulkomandy.tk>
//
// This file is distributed under the terms of the MIT licence.
// You need the GCC-6809 compiler based on lwtools to use this file.
// http://www.boxofdoom.net/2011/09/22/how-to-compile-gcc-for-the-6809-processor-gcc6809/
#pragma once
// 5 : MO5 / 8: TO8
#ifndef PLATFORM
#error "make TARGET=TO8 or make TARGET=MO5"
#endif
///////////////////////////////////////
// THOMSON.H
///////////////////////////////////////
/* MONITOR ZERO-PAGE */
struct Monitor {
unsigned char TERMIN[0x18];
unsigned char STATUS;
unsigned char TABPT;
unsigned char RANG;
unsigned char COLN;
unsigned char TOPTAB;
unsigned char TOPRAN;
unsigned char BOTTAB;
unsigned char BOTRAN;
unsigned int SCRPT;
unsigned int STADR;
unsigned int ENDDR;
unsigned int BLOCZ;
unsigned char FORME;
unsigned char ATRANG;
unsigned char COLOUR;
unsigned char PAGFLG;
unsigned char SCROLS;
unsigned char CURSFL;
unsigned char COPCHR;
unsigned char EFCMPT;
unsigned char ITCMPT;
unsigned int PLOTX;
unsigned int PLOTY;
unsigned char CHDRAW;
unsigned char KEY;
unsigned char CMPKB;
unsigned char _unused1;
unsigned char TEMPO;
unsigned char _unused2;
unsigned char DUREE;
unsigned char WAVE;
unsigned int OCTAVE;
unsigned char K7DATA;
unsigned char K7LENG;
unsigned char PROPC;
unsigned char PRSTA;
unsigned int TEMP;
unsigned int SAVEST;
unsigned char DKOPC;
unsigned char DKDRV;
unsigned int DKTRK;
unsigned char DKSEC;
unsigned char DKNUM;
unsigned char DKSTA;
unsigned int DKBUF;
unsigned char DKTRACK[8];
unsigned char SEQUCE;
unsigned char US1;
unsigned char ACCENT;
unsigned char SS2GET;
unsigned char SS3GET;
unsigned int SWIPT;
unsigned char _unused3;
unsigned int TIMEPT;
unsigned char SEMIRQ;
unsigned int IRQPT;
unsigned char _unused4;
unsigned int FIRQPT;
unsigned char _unused5;
unsigned int SIMUL;
unsigned char _unused6;
unsigned int CHRPTR;
unsigned char _unused7;
unsigned int USERAF;
unsigned char _unused8;
unsigned int GENPTR;
unsigned char _unused9;
unsigned char LATCLV;
unsigned char GRCODE;
unsigned char DECALG;
unsigned char _unusedA[6];
unsigned char DEFDST;
unsigned char DKFLG;
};
_Static_assert(sizeof(Monitor) == 0x80, "Problem with struct packing, Monitor Zero-Page has wrong size.");
void printhex(unsigned char i);
extern unsigned char mark[];
/* HARDWARE */
#define FDC_STATUS (*(volatile unsigned char*)(FDCBASE))
////////////////////////////////////////
// MO5.H
////////////////////////////////////////
#if PLATFORM == 5
/*****************************************************************************
* MOx CODE
****************************************************************************/
volatile Monitor* monitor = (volatile Monitor*)0x2000;
#define FDCBASE 0xA7D0
/* MONITOR ENTRY POINTS */
static inline void MENU() {
asm(" SWI \n"
" FCB 0"
);
}
static inline void PUTC(unsigned char car) {
asm(" swi \n"
" fcb 2"
::"B" (car)
);
}
static inline void FRM0() {
asm(" SWI \n"
" FCB 4"
);
}
static inline void FRM1() {
asm(" SWI \n"
" FCB 6"
);
}
static inline void BEEP() {
asm(" SWI \n"
" FCB 8"
);
}
// TODO GETC and KTST return values in B,A and Z-flag. How to get these
// back in C ?
static inline void DRAW(int x, int y) {
asm(" SWI \n"
" FCB 0xE"
:: "X" (x), "Y" (y)
);
}
static inline void PLOT(int x, int y) {
asm(" SWI \n"
" FCB 0x10"
:: "X" (x), "Y" (y)
);
}
static inline void CHPL(int x, int y) {
asm(" SWI \n"
" FCB 0x12"
:: "X" (x), "Y" (y)
);
}
// TODO GETP returns in B, LPIN in flag C, GETL flag C and regs XY
// GETS and JOYS in A
enum Note {
DO = 0,
DOs = 1,
RE = 2,
REs = 3,
MI = 4,
FA = 5,
FAs = 6,
SO = 7,
SOs = 8,
LA = 9,
LAs = 9,
SI = 10,
UT = 11,
// TODO what happens with other values ?
};
static inline void NOTE(enum Note note)
{
asm(" SWI \n"
" FCB 0x1E"
:: "B" (note)
);
}
/* FLOPPY DRIVE MONITOR ROM */
// NOTE DKOPC was split into several commands to make it easier to use from
// C code.
static inline void write(unsigned char track, unsigned char sector, unsigned char* buffer) {
DKTRK = (unsigned char)track;
DKSEC = (unsigned char)sector;
DKOPC = 8;
DKBUF = (unsigned int)buffer;
asm(" swi \n"
" fcb 0x26"
);
}
static inline void read(unsigned char track, unsigned char sector, unsigned char* output)
{
for(;;)
{
DKTRK = (unsigned char)track;
DKSEC = (unsigned char)sector;
DKOPC = 2;
DKBUF = (unsigned int)output;
asm(" swi \n"
" fcb 0x26"
);
if (DKSTA == 0x44 || DKSTA == 0) return; // Sector read ok!
printhex(DKSTA);
}
}
static inline void BOOT() {
asm(" SWI \n"
" FCB 0x28"
);
}
#else
/*****************************************************************************
* TOx CODE
****************************************************************************/
/* MONITOR ENTRY POINTS */
#define mon_putc(car) { \
asm("JSR \t0xE803 \t; TO8 PUTC\n"\
::"B" ((unsigned char) (car))\
); \
}
volatile Monitor* monitor = (volatile Monitor*)0x6000;
#define write(track, sector, buffer) {\
DKTRK = (unsigned char)track;\
DKSEC = (unsigned char)sector;\
DKOPC = 8;\
DKBUF = (unsigned int)buffer;\
\
asm("JSR \t 0xE004 \t; TO8 DKCONT\n"\
); \
}
/* FLOPPY DRIVE MONITOR ROM */
inline void read(unsigned char track, unsigned char sector,
unsigned char* output)
{
for(;;)
{
DKTRK = (unsigned char)track;
DKSEC = (unsigned char)sector;
DKOPC = 2;
DKBUF = (unsigned int)output;
asm("JSR \t 0xE004 \t \n"); \
if (DKSTA == 0x44 || DKSTA == 0) return; // Sector read ok!
printhex(DKSTA);
}
}
#endif