c3ab4004ad
Signed-off-by: Gwenhael Le Moine <gwenhael.le.moine@gmail.com>
739 lines
No EOL
18 KiB
C
739 lines
No EOL
18 KiB
C
/*
|
||
* Copyright (C) 1995 Sebastien Carlier
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <memory.h>
|
||
#include <malloc.h>
|
||
#include <string.h>
|
||
#include "emu48.h"
|
||
|
||
/* Modules :
|
||
* 0 IO RAM
|
||
* 1 RAM
|
||
* 2 bank switcher
|
||
* 3 PORT 1
|
||
* 4 PORT 2
|
||
* 5 ROM
|
||
*/
|
||
|
||
/* ucfg value :
|
||
* 0 configured
|
||
* 1 unconfigured
|
||
* 2 got size only
|
||
*/
|
||
|
||
#define PORT1DEF "port1"
|
||
|
||
char PORT1[100] = PORT1DEF;
|
||
|
||
void setport1(const char *newstring)
|
||
{
|
||
if (newstring)
|
||
{
|
||
if (*newstring)
|
||
strcpy(PORT1, newstring);
|
||
else
|
||
strcpy(PORT1, PORT1DEF);
|
||
}
|
||
}
|
||
|
||
int readport1(const char *portname)
|
||
{
|
||
/* CARDSTATUS: P2W P1W P2C P1C */
|
||
long i, s;
|
||
unsigned char c;
|
||
FILE *in = fopen(PORT1, "rb");
|
||
if (in!=NULL)
|
||
{
|
||
fseek(in, 0, SEEK_END);
|
||
s = ftell(in) * 2;
|
||
fseek(in, 0, SEEK_SET);
|
||
#ifdef DOSX286
|
||
port1 = (char*)_halloc(262144L,1);
|
||
#else
|
||
port1 = (char*)malloc(262144L);
|
||
#endif
|
||
if (port1!=NULL) {
|
||
for (i=0; i<s;) {
|
||
c = (char)fgetc(in);
|
||
port1[i++] = (char)(c&0xf);
|
||
port1[i++] = (char)((c>>4)&0xf);
|
||
}
|
||
data[3] = port1;
|
||
CARDSTATUS |= 0xA;
|
||
if (s!=262144L) memset(port1, 0, 16);
|
||
}
|
||
else display_warning("Not enough memory for port1");
|
||
fclose(in);
|
||
return 0;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
int load()
|
||
{
|
||
FILE *in;
|
||
long i, s;
|
||
unsigned char c;
|
||
int swap;
|
||
|
||
if (load_state) {
|
||
in = fopen("saturn", "rb");
|
||
if (in != NULL) {
|
||
fread(A, 16, 1, in);
|
||
fread(B, 16, 1, in);
|
||
fread(C, 16, 1, in);
|
||
fread(D, 16, 1, in);
|
||
fread(R0, 16, 1, in);
|
||
fread(R1, 16, 1, in);
|
||
fread(R2, 16, 1, in);
|
||
fread(R3, 16, 1, in);
|
||
fread(R4, 16, 1, in);
|
||
if (!pc) fread(&pc, 4, 1, in); else fseek(in, 4, SEEK_CUR);
|
||
fread(&d0, 4, 1, in);
|
||
fread(&d1, 4, 1, in);
|
||
fread(&OUT, 4, 1, in);
|
||
fread(&IN, 4, 1, in);
|
||
fread(ST, 4, 1, in);
|
||
HST = (char)fgetc(in);
|
||
if (!P) P = (char)fgetc(in); else fseek(in, 1, SEEK_CUR);
|
||
CARRY = fgetc(in);
|
||
MODE = fgetc(in);
|
||
INTP = fgetc(in);
|
||
INTE = fgetc(in);
|
||
INTD = fgetc(in);
|
||
SHUTDN = fgetc(in);
|
||
fread(rstk, 32, 1, in);
|
||
rstkp = fgetc(in);
|
||
for (i=0; i<5; i++) {
|
||
ucfg[i] = fgetc(in);
|
||
fread(&base[i], 4, 1, in);
|
||
fread(&size[i], 4, 1, in);
|
||
}
|
||
fread(ioram, 64, 1, in);
|
||
t1 = fgetc(in);
|
||
fread(&t2, 4, 1, in);
|
||
fread(&crc, 4, 1, in);
|
||
fread(&display, sizeof(display_t), 1, in);
|
||
fclose(in);
|
||
}
|
||
}
|
||
|
||
#ifdef DOSX286
|
||
rom = (char*)_halloc(1048576L,1);
|
||
#else
|
||
rom = (char*)malloc(1048576L);
|
||
#endif
|
||
|
||
if (rom==NULL) display_error("Not enough memory for rom.\n");
|
||
in = fopen("rom", "rb");
|
||
if (in==NULL) {
|
||
free(rom);
|
||
display_error("The rom dump file 'rom' is missing.\n");
|
||
}
|
||
fseek(in,0,SEEK_END);
|
||
s = ftell(in)*2;
|
||
fseek(in,0,SEEK_SET);
|
||
c = (char)fgetc(in);
|
||
switch (c) {
|
||
case 0x32: swap = 0; break;
|
||
case 0x23: swap = 1; break;
|
||
default: swap = 0; break;
|
||
}
|
||
ungetc(c, in);
|
||
if (!swap)
|
||
for (i=0; i<s;) {
|
||
c = (char)fgetc(in);
|
||
rom[i++] = (char)(c&0xf);
|
||
rom[i++] = (char)((c>>4)&0xf);
|
||
}
|
||
else
|
||
for (i=0; i<s;) {
|
||
c = (char)fgetc(in);
|
||
rom[i++] = (char)((c>>4)&0xf);
|
||
rom[i++] = (char)(c&0xf);
|
||
}
|
||
fclose(in);
|
||
data[5] = rom;
|
||
|
||
#ifdef DOSX286
|
||
ram = (char*)_halloc(262144L,1);
|
||
#else
|
||
ram = (char*)malloc(262144L);
|
||
#endif
|
||
if (ram==NULL) display_error("Not enough memory for ram.\n");
|
||
in = fopen("ram", "rb");
|
||
if (in!=NULL) {
|
||
c = (char)fgetc(in);
|
||
switch (c) {
|
||
case 0x3F: swap = 0; break;
|
||
case 0xF3: swap = 1; break;
|
||
default: swap = 0; break;
|
||
}
|
||
ungetc(c, in);
|
||
if (!swap)
|
||
for (i=0; i<262144L;) {
|
||
c = (char)fgetc(in);
|
||
ram[i++] = (char)(c&0xf);
|
||
ram[i++] = (char)((c>>4)&0xf);
|
||
}
|
||
else
|
||
for (i=0; i<262144L;) {
|
||
c = (char)fgetc(in);
|
||
ram[i++] = (char)((c>>4)&0xf);
|
||
ram[i++] = (char)(c&0xf);
|
||
}
|
||
fclose(in);
|
||
}
|
||
data[1] = ram;
|
||
|
||
readport1(PORT1);
|
||
/* CARDSTATUS: P2W P1W P2C P1C */
|
||
in = fopen("port2", "rb");
|
||
if (in!=NULL) {
|
||
fseek(in, 0, SEEK_END);
|
||
s = ftell(in) * 2;
|
||
fseek(in, 0, SEEK_SET);
|
||
#ifdef DOSX286
|
||
port2 = (char*)_halloc(262144L,1);
|
||
#else
|
||
port2 = (char*)malloc(262144L);
|
||
#endif
|
||
if (port2!=NULL) {
|
||
for (i=0; i<s;) {
|
||
c = (char)fgetc(in);
|
||
port2[i++] = (char)(c&0xf);
|
||
port2[i++] = (char)((c>>4)&0xf);
|
||
}
|
||
data[4] = port2;
|
||
CARDSTATUS |= 0x5;
|
||
} else display_warning("Not enough memory for port2");
|
||
fclose(in);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
int save() {
|
||
FILE *out;
|
||
long i;
|
||
|
||
out = fopen("ram", "wb");
|
||
if (out==NULL) return 1;
|
||
for (i=0; i<262144L; i+=2) fputc(ram[i]|(ram[i+1]<<4), out);
|
||
fclose(out);
|
||
|
||
if (CARDSTATUS&2) bank_save(port1,PORT1,bank1);
|
||
|
||
if (CARDSTATUS&1) bank_save(port2,"port2",bank2);
|
||
|
||
out = fopen("saturn", "wb");
|
||
fwrite(A, 16, 1, out);
|
||
fwrite(B, 16, 1, out);
|
||
fwrite(C, 16, 1, out);
|
||
fwrite(D, 16, 1, out);
|
||
fwrite(R0, 16, 1, out);
|
||
fwrite(R1, 16, 1, out);
|
||
fwrite(R2, 16, 1, out);
|
||
fwrite(R3, 16, 1, out);
|
||
fwrite(R4, 16, 1, out);
|
||
fwrite(&pc, 4, 1, out);
|
||
fwrite(&d0, 4, 1, out);
|
||
fwrite(&d1, 4, 1, out);
|
||
fwrite(&OUT, 4, 1, out);
|
||
fwrite(&IN, 4, 1, out);
|
||
fwrite(ST, 4, 1, out);
|
||
fputc(HST, out);
|
||
fputc(P, out);
|
||
fputc(CARRY, out);
|
||
fputc(MODE, out);
|
||
fputc(INTP, out);
|
||
fputc(INTE, out);
|
||
fputc(INTD, out);
|
||
fputc(SHUTDN, out);
|
||
fwrite(rstk, 32, 1, out);
|
||
fputc(rstkp, out);
|
||
for (i=0; i<5; i++) {
|
||
fputc(ucfg[i], out);
|
||
fwrite(&base[i], 4, 1, out);
|
||
fwrite(&size[i], 4, 1, out);
|
||
}
|
||
fwrite(ioram, 64, 1, out);
|
||
fputc((int)t1, out);
|
||
fwrite(&t2, 4, 1, out);
|
||
fwrite(&crc, 4, 1, out);
|
||
fwrite(&display, sizeof(display_t), 1, out);
|
||
fclose(out);
|
||
|
||
return 0;
|
||
}
|
||
|
||
void bank_save(char *mem, char *bn, int bank) {
|
||
char name[12];
|
||
FILE *out;
|
||
long i;
|
||
|
||
if (bank)
|
||
sprintf(name,"%s.%i",bn,bank);
|
||
else
|
||
strcpy(name, bn);
|
||
out = fopen(name, "rb");
|
||
if (out==NULL) return;
|
||
fclose(out);
|
||
out = fopen(name, "wb");
|
||
if (out==NULL) {
|
||
printf("Failed to write %s\n", name);
|
||
return;
|
||
}
|
||
for (i=0; i<262144L; i+=2) fputc(mem[i]|(mem[i+1]<<4), out);
|
||
fclose(out);
|
||
return;
|
||
}
|
||
|
||
void bank_load(char *mem, char *bn, int bank) {
|
||
char name[12], c;
|
||
FILE *in;
|
||
long i, s;
|
||
|
||
if (bank)
|
||
sprintf(name,"%s.%i",bn,bank);
|
||
else
|
||
strcpy(name, bn);
|
||
in = fopen(name, "rb");
|
||
if (in==NULL) {
|
||
printf("Failed to read %s\n", name);
|
||
return;
|
||
}
|
||
fseek(in, 0, SEEK_END);
|
||
s = ftell(in) * 2;
|
||
fseek(in, 0, SEEK_SET);
|
||
for (i=0; i<s;) {
|
||
c = (char)fgetc(in);
|
||
mem[i++] = (char)(c&0xf);
|
||
mem[i++] = (char)((c>>4)&0xf);
|
||
}
|
||
fclose(in);
|
||
return;
|
||
}
|
||
|
||
void bank_switch(int bank) {
|
||
|
||
if (bank<32) /* port 1 */ {
|
||
if (bank1 == bank) return;
|
||
bank_save(port1,PORT1,bank1);
|
||
bank1 = bank;
|
||
bank_load(port1,PORT1,bank1);
|
||
} else {
|
||
bank -= 32;
|
||
if (bank2 == bank) return;
|
||
bank_save(port2,"port2",bank2);
|
||
bank2 = bank;
|
||
bank_load(port2,"port2",bank2);
|
||
}
|
||
return;
|
||
}
|
||
|
||
/******** IO RAM ********/
|
||
|
||
char ioram[64] = {
|
||
0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0xC,0x0,
|
||
0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
|
||
0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0,
|
||
0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xf, 0xf,0xf,0xf,0xf, 0xf,0xf,0xf,0xf
|
||
};
|
||
|
||
char read_io(long d) {
|
||
char c;
|
||
|
||
switch (d) {
|
||
case 0x04: c = (char)(crc); break;
|
||
case 0x05: c = (char)(crc>>4); break;
|
||
case 0x06: c = (char)(crc>>8); break;
|
||
case 0x07: c = (char)(crc>>12); break;
|
||
case 0x0F: c = CARDSTATUS; break;
|
||
case 0x14: return ioram[d];
|
||
case 0x15: ioram[0x11]&=0xe; return ioram[d];
|
||
case 0x16: /**/
|
||
case 0x17: /**/ return 3;
|
||
case 0x18: /**/
|
||
case 0x19: /**/ display_warning("Nibbles #118/#119 read.");
|
||
case 0x20: /**/
|
||
case 0x21: /**/
|
||
case 0x22: /**/
|
||
case 0x23: /**/
|
||
case 0x24: /**/
|
||
case 0x25: /**/
|
||
case 0x26: /**/
|
||
case 0x27: /**/ return 3;
|
||
case 0x28: c = (char)display.lcounter; break;
|
||
case 0x29: c = (char)(display.lcounter>>4); break;
|
||
case 0x30: /**/
|
||
case 0x31: /**/
|
||
case 0x32: /**/
|
||
case 0x33: /**/
|
||
case 0x34: /**/ c = 3; break;
|
||
case 0x37: c = (char)(t1); break;
|
||
case 0x38: c = (char)(t2); break;
|
||
case 0x39: c = (char)(t2>>4); break;
|
||
case 0x3A: c = (char)(t2>>8); break;
|
||
case 0x3B: c = (char)(t2>>12); break;
|
||
case 0x3C: c = (char)(t2>>16); break;
|
||
case 0x3D: c = (char)(t2>>20); break;
|
||
case 0x3E: c = (char)(t2>>24); break;
|
||
case 0x3F: c = (char)(t2>>28); break;
|
||
default:
|
||
return ioram[d];
|
||
}
|
||
return (char)(c&0xf);
|
||
}
|
||
|
||
void write_io(long d, char c) {
|
||
|
||
switch (d) {
|
||
|
||
/* 00100 = NS:DISPIO
|
||
* 00100 @ Display bit offset and DON [DON OFF2 OFF1 OFF0]
|
||
* 00100 @ 3 nibs for display offset (scrolling), DON=Display ON
|
||
*/
|
||
case 0x00:
|
||
if (display.boffset!=(c&7)) {
|
||
display.touched = 1;
|
||
display.boffset = c&7;
|
||
}
|
||
if (display.dispon!=(c>>3)) {
|
||
display.touched = 1;
|
||
display.dispon = c>>3;
|
||
}
|
||
break;
|
||
|
||
/* 00101 = NS:CONTRLSB
|
||
* 00101 @ Contrast Control [CON3 CON2 CON1 CON0]
|
||
* 00101 @ Higher value = darker screen
|
||
*/
|
||
case 0x01:
|
||
if ((display.contrast&0xf)!=c) {
|
||
display.contrast &= 0x10;
|
||
display.contrast |= c;
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
|
||
/* 00102 = NS:DISPTEST
|
||
* 00102 @ Display test [VDIG LID TRIM CON4] [LRT LRTD LRTC BIN]
|
||
* 00102 @ Normally zeros
|
||
*/
|
||
case 0x02:
|
||
if ((display.contrast>>4)!=(c&1)) {
|
||
display.contrast &= 0x0f;
|
||
display.contrast |= (c<<4)&0x10;
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
case 0x03:
|
||
/*display.noscan = (c>>3)&1;*/
|
||
/*display.touched = 1;*/
|
||
break;
|
||
|
||
/* 00104 = HP:CRC
|
||
* 00104 @ 16 bit hardware CRC (104-107) (X^16+X^12+X^5+1)
|
||
* 00104 @ crc = ( crc >> 4 ) ^ ( ( ( crc ^ nib ) & 0x000F ) * 0x1081 );
|
||
*/
|
||
case 0x04: crc=crc&0xfff0;crc|=(c); return;
|
||
case 0x05: crc=crc&0xff0f;crc|=(c<<4); return;
|
||
case 0x06: crc=crc&0xf0ff;crc|=(c<<8); return;
|
||
case 0x07: crc=crc&0x0fff;crc|=(c<<12); return;
|
||
|
||
/* 00108 = NS:POWERSTATUS
|
||
* 00108 @ Low power registers (108-109)
|
||
* 00108 @ [LB2 LB1 LB0 VLBI] (read only)
|
||
* 00108 @ LowBat(2) LowBat(1) LowBat(S) VeryLowBat
|
||
*/
|
||
case 0x08:
|
||
return;
|
||
|
||
/* 00109 = NS:POWERCTRL
|
||
* 00109 @ [ELBI EVLBI GRST RST] (read/write)
|
||
*/
|
||
case 0x09:
|
||
break;
|
||
|
||
/* 0010A = NS:MODE
|
||
* 0010A @ Mode Register (read-only)
|
||
*/
|
||
case 0x0A:
|
||
break;
|
||
|
||
/* 0010B = HP:ANNCTRL
|
||
* 0010B @ Annunciator control [LA4 LA3 LA2 LA1] = [ alarm alpha -> <- ]
|
||
*/
|
||
case 0x0B:
|
||
case 0x0C:
|
||
ioram[d] = c; display_ann(); return;
|
||
|
||
/* 0010D = NS:BAU
|
||
* 0010D @ Serial baud rate [UCK BD2 BD1 BD0] (bit 3 is read-only)
|
||
* 0010D @ 3 bits = {1200 1920 2400 3840 4800 7680 9600 15360}
|
||
*/
|
||
case 0x0D:
|
||
c &= 7;
|
||
break;
|
||
|
||
/* 0010E = NS:CARDCTRL
|
||
* 0010E @ [ECDT RCDT SMP SWINT] (read/write)
|
||
* 0010E @ Enable Card Det., Run Card Det., Set Module Pulled, Software interrupt
|
||
*/
|
||
case 0x0E:
|
||
if (c&1) INTERRUPT("SW");
|
||
if (c&2) { ioram[0x19] = 2; HST|=MP; INTERRUPT("MP"); }
|
||
if (c&8)
|
||
if (c&4) ioram[0x0F] = 0;
|
||
break;
|
||
|
||
/* 0010F = NS:CARDSTATUS
|
||
* 0010F @ [P2W P1W P2C P1C] (read-only) Port 2 writable .. Port 1 inserted
|
||
*/
|
||
case 0x0F:
|
||
return;
|
||
|
||
/* 00110 = HP:IOC
|
||
* 00110 @ Serial I/O Control [SON ETBE ERBF ERBZ]
|
||
* 00110 @ Serial On, Interrupt On Recv.Buf.Empty, Full, Buzy
|
||
*/
|
||
case 0x10:
|
||
break;
|
||
|
||
/* 00111 = HP:RCS
|
||
* 00111 @ Serial Receive Control/Status [RX RER RBZ RBF] (bit 3 is read-only)
|
||
*/
|
||
case 0x11:
|
||
c &= 7;
|
||
c |= ioram[0x11]&8;
|
||
break;
|
||
|
||
/* 00112 = HP:TCS
|
||
* 00112 @ Serial Transmit Control/Status [BRK LPB TBZ TBF]
|
||
*/
|
||
case 0x12:
|
||
break;
|
||
|
||
/* 00113 = HP:CRER
|
||
* 00113 @ Serial Clear RER (writing anything clears RER bit)
|
||
*/
|
||
case 0x13:
|
||
ioram[0x11]&=0xB;
|
||
return;
|
||
|
||
/* 00114 = HP:RBR
|
||
* 00114 @ Serial Receive Buffer Register (Reading clears RBF bit)
|
||
* 00114 @ [RX RER RBZ RBF]
|
||
*/
|
||
case 0x14:
|
||
case 0x15:
|
||
return;
|
||
|
||
/* 00116 = HP:TBR
|
||
* 00116 @ Serial Transmit Buffer Register (Writing sets TBF bit)
|
||
*/
|
||
case 0x016: break;
|
||
case 0x017:
|
||
ioram[0x12] |= 1;
|
||
break;
|
||
|
||
/* 00118 = NS:SRR
|
||
* 00118 @ Service Request Register (read-only)
|
||
* 00118 @ [ISQR TSQR USRQ VSRQ] [KDN NINT2 NINT LSRQ]
|
||
*/
|
||
case 0x18:
|
||
case 0x19:
|
||
return;
|
||
|
||
/* 0011A = HP:IRC
|
||
* 0011A @ IR Control Register [IRI EIRU EIRI IRE] (bit 3 is read-only)
|
||
* 0011A @ IR Input, Enable IR UART mode, Enable IR Interrupt, IR Event
|
||
*/
|
||
case 0x1A:
|
||
c &= 7;
|
||
c |= ioram[0x1A]&8;
|
||
break;
|
||
|
||
/* 0011B = NS:BASENIBOFF
|
||
* 0011B @ Used as addressto get BASENIB from 11F to the 5th nibble
|
||
*/
|
||
case 0x1B:
|
||
return;
|
||
|
||
/* 0011C = NS:LCR
|
||
* 0011C @ Led Control Register [LED ELBE LBZ LBF] (Setting LED is draining)
|
||
*/
|
||
case 0x1C:
|
||
break;
|
||
|
||
/* 0011D = NS:LBR
|
||
* 0011D @ Led Buffer Register [0 0 0 LBO] (bits 1-3 read zero)
|
||
*/
|
||
case 0x1D:
|
||
c &= 1;
|
||
break;
|
||
|
||
/* 0011E = NS:SCRATCHPAD
|
||
* 0011E @ Scratch pad (11F is BASEIB, 7 or F for base memory)
|
||
*/
|
||
case 0x1E:
|
||
break;
|
||
|
||
/* 0011F = NS:BASENIB
|
||
*/
|
||
case 0x1F:
|
||
break;
|
||
|
||
/* 00120 = NS:DISPADDR
|
||
* 00120 @ Display Start Address (write only)
|
||
* 00120 @ bit 0 is ignored (display must start on byte boundary)
|
||
*/
|
||
case 0x20:
|
||
if ((display.start1&0x0000F)!=c) {
|
||
display.start1 = (display.start1&0xFFFF0)|(c&0xE);
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
case 0x21:
|
||
if (((display.start1&0x000F0)>>4)!=c) {
|
||
display.start1=(display.start1&0xFFF0F)|(c<<4);
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
case 0x22:
|
||
if (((display.start1&0x00F00)>>8)!=c) {
|
||
display.start1=(display.start1&0xFF0FF)|(c<<8);
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
case 0x23:
|
||
if (((display.start1&0x0F000)>>12)!=c) {
|
||
display.start1=(display.start1&0xF0FFF)|(c<<12);
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
case 0x24:
|
||
if (((display.start1&0xF0000)>>16)!=c) {
|
||
display.start1=(display.start1&0x0FFFF)|(c<<16);
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
|
||
/* 00125 = NS:LINEOFFS
|
||
* 00125 @ Display Line offset (write only) (no of bytes skipped after each line)
|
||
* 00125 @ MSG sign extended
|
||
*/
|
||
case 0x25: c &= 0xe;
|
||
case 0x26:
|
||
case 0x27:
|
||
ioram[d] = c;
|
||
display.loffset = (int)Npack(ioram+0x25, 3);
|
||
if (display.loffset&0x800) display.loffset = display.loffset - 0x1000;
|
||
display.touched = 1;
|
||
return;
|
||
|
||
/* 00128 = NS:LINECOUNT
|
||
* 00128 @ Display Line Counter and miscellaneous (28-29)
|
||
* 00128 @ [LC3 LC2 LC1 LC0] [DA19 M32 LC5 LC4]
|
||
* 00128 @ Line counter 6 bits -> max = 2^6-1 = 63 = disp height
|
||
* 00128 @ Normally has 55 -> Menu starts at display row 56
|
||
*/
|
||
case 0x28:
|
||
if ((display.lcntsave&0xf)!=c) {
|
||
display.lcntsave=(display.lcntsave&0x30)|c;
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
case 0x29:
|
||
if ((display.lcntsave&0x30)!=((c&3)<<4)) {
|
||
display.lcntsave=(display.lcntsave&0x0f)|((c&3)<<4);
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
|
||
case 0x2A:
|
||
case 0x2B:
|
||
case 0x2C:
|
||
case 0x2D:
|
||
return;
|
||
|
||
/* 0012E = NS:TIMER1CTRL
|
||
* 0012E @ TIMER1 Control [SRQ WKE INT XTRA]
|
||
*/
|
||
case 0x2E:
|
||
c &= 0xE;
|
||
break;
|
||
|
||
/* 0012F = NS:TIMER2CTRL
|
||
* 0012F @ TIMER2 Control [SRQ WKE INT RUN]
|
||
*/
|
||
case 0x2F:
|
||
break;
|
||
|
||
/* 00130 = NS:MENUADDR
|
||
* 00130 @ Display Secondary Start Address (write only) (30-34)
|
||
* 00130 @ Menu Display Address, no line offsets
|
||
*/
|
||
case 0x30:
|
||
if ((display.start2&0x0000F)!=c) {
|
||
display.start2=(display.start2&0xFFFF0)|(c&0xE);
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
case 0x31:
|
||
if (((display.start2&0x000F0)>>4)!=c) {
|
||
display.start2=(display.start2&0xFFF0F)|(c<<4);
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
case 0x32:
|
||
if (((display.start2&0x00F00)>>8)!=c) {
|
||
display.start2=(display.start2&0xFF0FF)|(c<<8);
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
case 0x33:
|
||
if (((display.start2&0x0F000)>>12)!=c) {
|
||
display.start2=(display.start2&0xF0FFF)|(c<<12);
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
case 0x34:
|
||
if (((display.start2&0xF0000)>>16)!=c) {
|
||
display.start2=(display.start2&0x0FFFF)|(c<<16);
|
||
display.touched = 1;
|
||
}
|
||
break;
|
||
|
||
case 0x35:
|
||
case 0x36:
|
||
return;
|
||
|
||
/* 00137 = HP:TIMER1
|
||
* 00137 @ Decremented 16 times/s
|
||
*/
|
||
case 0x37:
|
||
t1 = c;
|
||
break;
|
||
|
||
/* 00138 = HP:TIMER2
|
||
* 00138 @ hardware timer (38-3F), decremented 8192 times/s
|
||
*/
|
||
case 0x38: t2=(t2&0xFFFFFFF0)|c; break;
|
||
case 0x39: t2=(t2&0xFFFFFF0F)|(c<<4); break;
|
||
case 0x3A: t2=(t2&0xFFFFF0FF)|(c<<8); break;
|
||
case 0x3B: t2=(t2&0xFFFF0FFF)|(c<<12); break;
|
||
case 0x3C: t2=(t2&0xFFF0FFFF)|(c<<16); break;
|
||
case 0x3D: t2=(t2&0xFF0FFFFF)|(c<<20); break;
|
||
case 0x3E: t2=(t2&0xF0FFFFFF)|(c<<24); break;
|
||
case 0x3F: t2=(t2&0x0FFFFFFF)|(c<<28); break;
|
||
default: return;
|
||
}
|
||
ioram[d] = c;
|
||
return;
|
||
}
|
||
|