/* orionix.cpp - Main file of OrioniX emulator (20-Oct-2006) Copyright (c) 1994-2006, Alexander Shabarshin (alexander@shabarshin.com) This file is part of OrioniX (testing emulator of computer ORION). OrioniX 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 of the License, or (at your option) any later version. OrioniX 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 OrioniX; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "orionix.h" #include "unigraf.h" //#define DEBUG /* some logs */ //#define DEBUG_MORE /* more logs */ UniGraf *ug = NULL; Orion::Orion(int pmem,char *code) : Processor8080() { #ifdef DEBUG printf("Orion::Orion(%i,%s)\n",pmem,code?code:"NULL"); #endif int i,j,k; page_mem=pmem; if(page_mem<4) error(3); for(i=0;i<4;i++) page[i]=i; memory=new SH_BYTE[page_mem*PAGE_SIZE]; if(memory==NULL) error(2); memset(memory,0,page_mem*PAGE_SIZE); start = SH_FALSE; load("MONITOR2.BIN",0xF800); PC = 0xF800; SP = 0xB000; if(page_mem>=20) { for(i=0;i<4;i++) page[i]=16+i; for(i=0;i<65536;i+=16) put(i,0xFF); load("ROMDISK.BIN",0); if(code && *code) { #if 0 for(i=0;i<4;i++) page[i]=20+i; load("ROMDISK.BIN",0); for(i=LOADADR;i<65536;i+=16) put(i,0xFF); #endif char *po = strrchr(code,'.'); if(po!=NULL) { for(i=LOADADR;i<65536;i+=16) put(i,0xFF); if(!strcmp(po,".bru")||!strcmp(po,".BRU")) { #ifdef DEBUG printf("Orion::Orion : load BRU\n"); #endif load(code,LOADADR); } if(!strcmp(po,".rko")||!strcmp(po,".RKO")) { #ifdef DEBUG printf("Orion::Orion : load RKO\n"); #endif unsigned char head[77]; FILE *f = fopen(code,"rb"); if(f==NULL) error(1); fread(head,1,77,f); i = head[73]*256 + head[74]; j = head[75]*256 + head[76]; k = j-i; for(i=0;i %li\n",size); #endif return (int)size; } int Orion::save(char *s,SH_WORD adr,SH_WORD len) { #ifdef DEBUG printf("Orion::save(%s,#%4.4X,#%4.4X)\n",s,adr,len); #endif FILE *file=fopen(s,"wb"); if(file==NULL) error(1); long ll,size; size=len; for(ll=0;ll %li\n",size); #endif return (int)size; } /* Structure of ORION screen ========================= In monochrome mode: structure is the same as in SPECIALIST 1st page of screen is used as RAM In color mode: color is taken from 1st page of screen 16 colors - the same color for 1 byte (8 pixels) D7 D6 Background color D5 (if main page bit = 0) D4 ---- D3 D2 Foreground color D1 (if main page bit = 1) D0 4 colors - color of each pixel is set separately Main page 0 Page 1 1 0 green 0 1 red 0 0 black 1 1 blue (in palette 2 other colors are used) */ SH_BIT Orion::perif(SH_WORD a,SH_BIT f,SH_BYTE *b) { #ifdef DEBUG_MORE printf("Orion::perif(#%4.4X,%i,0x%8.8X)\n",a,f,(int)b); #endif auto int i,j,c,k,x,y; if(!start) return SH_FALSE; if((a>>PAGE_BITS)<3) return SH_FALSE; if(f==PERIF_W && a>=ascr && a>6)&((c&0x80)>>7)) { case 0: color=0x0; break; case 1: color=0x4; break; case 2: color=0x2; break; case 3: color=0x1; break; }; c<<=1; break; case 5: switch(((j&0x80)>>6)&((c&0x80)>>7)) { case 0: color=0x0; break; case 1: color=0x4; break; case 2: color=0x2; break; case 3: color=0x1; break; }; c<<=1; break; case 6: if(j&0x80) color=c&0x0F; else color=c>>4; break; case 7: if(j&0x80) color=c&0x0F; else color=c>>4; break; } if(ug) ug->SetScreenPixel(x+i,y,color); j<<=1; } return SH_TRUE; } if(a>=0xF000) { if(a>=0xF000 && a<0xF400) { // system RAM if(f==PERIF_R) *b = memory[(3<=0xF400 && a<0xF500) { // F400 - 580VV55 (RK-keyboard) switch(a&3) { case 0: // port A if(f==PERIF_W) kb_a=*b; break; case 1: // port B if(f==PERIF_R) *b=keyRK()&0xFF; break; case 2: // port C if(f==PERIF_R) *b=(keyRK()&0xF000)>>8; if(f==PERIF_W) rus_lat=(*b&8)>>3; break; case 3: break; } return SH_TRUE; } if(a>=0xF500 && a<0xF600) { // F500 - 580VV55 (ROM-disk) // port A - data from ROM-disk // port B - low byte of address in ROM-disk // порт C - high byte of address in ROM-disk switch(a&3) { case 0: // port A if(f==PERIF_R) { for(i=0;i<4;i++) page[i]=16+i; rom_a = get((rom_c<<8)|rom_b); for(i=0;i<4;i++) page[i]=i; *b = rom_a; // printf("ROM1 #%2.2X #%2.2X #%2.2X\n",rom_a,rom_b,rom_c); } break; case 1: // port B if(f==PERIF_W) rom_b=*b; break; case 2: // port C if(f==PERIF_W) rom_c=*b; break; case 3: break; } return SH_TRUE; } if(a>=0xF600 && a<0xF700) { // F600 - 580VV55 (ROM-disk-2) switch(a&3) { case 0: // port A if(f==PERIF_R) { for(i=0;i<4;i++) page[i]=20+i; rom_a = get((rom2_c<<8)|rom2_b); for(i=0;i<4;i++) page[i]=i; *b = rom2_a; // printf("ROM2 #%2.2X #%2.2X #%2.2X\n",rom2_a,rom2_b,rom2_c); } break; case 1: // port B if(f==PERIF_W) rom2_b=*b; break; case 2: // port C if(f==PERIF_W) rom2_c=*b; break; case 3: break; } return SH_TRUE; } if(a>=0xF700 && a<0xF800) { // F700 - additional devices return SH_TRUE; } if(a>=0xF800 && f==PERIF_R) { // F800 - monitor ROM *b = memory[(3<=0xF800 && a<0xF900 && f==PERIF_W) { // F800 - color mode // D0 - 0 - palette 1 // 1 - palette 2 // D1 - 0 - 16 colors // 1 - 4 colors // D2 - 0 - monochrome mode // 1 - color mode // // 00 - monochrome green on black // 01 - monochrome yellow on blue // 02 - no image // 03 - no image // 04 - 4 colors, palette 1 // 05 - 4 colors, palette 2 // 06,07 - 16 colors fcolors = *b; return SH_TRUE; } if(a==0xF900 && a<0xFA00 && f==PERIF_W) { // F900 - memory pages managment // (F000-FFFF never switched) // D1 D0 // 0 0 - page 0 (main) // 0 1 - page 1 // 1 0 - page 2 (not for 128K) // 1 1 - page 3 (not for 128K) fpages = *b & 3; k = fpages<<2; page[0] = k; page[1] = k+1; page[2] = k+2; page[3] = k+3; return SH_TRUE; } if(a==0xFA00 && a<0xFB00 && f==PERIF_W) { // FA00 - switch screens // D1 D0 // 0 0 - screen 1 ( C000-EFFF ) // 0 1 - screen 2 ( 8000-AFFF ) // 1 0 - screen 3 ( 4000-6FFF ) // 1 1 - screen 4 ( 0000-2FFF ) fscreens = *b; pscr = 3 - fscreens; ascr = pscr * 0x4000; return SH_TRUE; } } return SH_FALSE; } SH_BYTE Orion::get(SH_WORD a) // read from memory { #ifdef DEBUG_MORE printf("Orion::get(#%4.4X)\n",a); #endif SH_BYTE by; if(!perif(a,PERIF_R,&by)) by=memory[(page[a>>PAGE_BITS]< #%2.2X\n",by); #endif return by; } void Orion::put(SH_WORD a,SH_BYTE b) // write to memory { #ifdef DEBUG_MORE printf("Orion::put(#%4.4X,#%2.2X)\n",a,b); #endif SH_BYTE by = b; if(!perif(a,PERIF_W,&by)) memory[(page[a>>PAGE_BITS]< %i\n",oka); #endif return oka; } SH_BYTE Orion::inp(SH_BYTE p) // read from port { SH_BYTE data = 0xFF; #ifdef DEBUG_MORE printf("Orion::inp -> #%2.2X\n",data); #endif return data; } void Orion::outp(SH_BYTE p,SH_BYTE b) // write to port { #ifdef DEBUG_MORE printf("Orion::outp(#%2.2X,#%2.2X)\n",p,b); #endif int k; switch(p) { case 0xF8: fcolors = b; break; case 0xF9: fpages = b & 3; k = fpages<<2; page[0] = k; page[1] = k+1; page[2] = k+2; page[3] = k+3; break; case 0xFA: fscreens = b; pscr = 3 - fscreens; ascr = pscr * 0x4000; break; } } int Orion::keyRK(void) { #ifdef DEBUG_MORE printf("Orion::keyRK()\n"); #endif int i,j,k,o,oo,kba; // F1...F5 and Arrows // Diag.Arrow - Home // PS - Ctrl+J // RUS/LAT - Ctrl+Shift // AR2 - Alt // STR - PgUp // SS - Shift // US - Ctrl static unsigned char keyboard[2][8][8] = { { // lat {0x47,0x49,0x38,0x3B,0x3C,0x3D,0x3E,0x3F}, // A0 {0x0F,0x00,0x1C,0x0E,0x4B,0x48,0x4D,0x50}, // A1 {0x0B,0x02,0x03,0x04,0x05,0x06,0x07,0x08}, // A2 {0x09,0x0A,0x27,0x0D,0x33,0x0C,0x34,0x35}, // A3 {0x28,0x1E,0x30,0x2E,0x20,0x12,0x21,0x22}, // A4 {0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18}, // A5 {0x19,0x10,0x13,0x1F,0x14,0x16,0x2F,0x11}, // A6 {0x2D,0x15,0x2C,0x1A,0x2B,0x1B,0x29,0x39}, // A7 }, { // rus {0x47,0x49,0x38,0x3B,0x3C,0x3D,0x3E,0x3F}, // A0 {0x0F,0x00,0x1C,0x0E,0x4B,0x48,0x4D,0x50}, // A1 {0x0B,0x02,0x03,0x04,0x05,0x06,0x07,0x08}, // A2 {0x09,0x0A,0x27,0x0D,0x33,0x0C,0x34,0x35}, // A3 {0x28,0x1E,0x30,0x2E,0x20,0x12,0x21,0x22}, // A4 {0x23,0x17,0x22,0x25,0x26,0x32,0x31,0x18}, // A5 {0x19,0x10,0x13,0x1F,0x14,0x16,0x2F,0x11}, // A6 {0x2D,0x15,0x2C,0x1A,0x2B,0x1B,0x29,0x39}, // A7 } }; if(kb_a==0xFF) return 0xFF; kba = kb_a; oo = 0; for(i=0;i<8;i++) { k = kba&1; kba>>=1; if(k) continue; o = 1; for(j=0;j<8;j++,o<<=1) { k = keyboard[rus_lat][i][j]; if(k==0) // Ctrl-J { if(ug->KeyPressed(0x1D) && ug->KeyPressed(0x24)) oo|=o; } if(ug->KeyPressed(k)) oo|=o; } } oo=(~oo)&0xFF; if(ug->KeyPressed(0x2A)) oo|=0x2000; if(ug->KeyPressed(0x1D)) oo|=0x4000; if(ug->KeyPressed(0x1D) && ug->KeyPressed(0x36)) oo|=0x8000; #ifdef DEBUG if(oo!=0xFF && oo!=key) printf("Orion::keyRK -> #%4.4X\n",oo); k = ug->WhatKey(); if(k) printf("Orion::keyRK -> scancode 0x%2.2X (%i)\n",k,k); #endif key = oo&0xFF; return key; } int main(int argc,char **argv) { char prog[32] = ""; if(argc>1) strcpy(prog,argv[1]); ug = new UniGraf(UG256_640x480,1); if(ug==NULL) return -1; if(!ug->Screen(ORCOL,ORROW)) printf("SCREEN ERROR!\n"); int level0 = 0x00; int level1 = 0x15<<2; int level2 = 0x2A<<2; int level3 = 0x3F<<2; ug->SetPalette(0x0,level0,level0,level0); ug->SetPalette(0x1,level0,level0,level2); ug->SetPalette(0x2,level0,level2,level0); ug->SetPalette(0x3,level0,level2,level2); ug->SetPalette(0x4,level2,level0,level0); ug->SetPalette(0x5,level2,level0,level2); ug->SetPalette(0x6,level2,level1,level0); ug->SetPalette(0x7,level2,level2,level2); ug->SetPalette(0x8,level1,level1,level1); ug->SetPalette(0x9,level0,level0,level3); ug->SetPalette(0xA,level0,level3,level0); ug->SetPalette(0xB,level0,level3,level3); ug->SetPalette(0xC,level3,level0,level0); ug->SetPalette(0xD,level3,level0,level3); ug->SetPalette(0xE,level3,level3,level0); ug->SetPalette(0xF,level3,level3,level3); ug->Update(); Orion o(24,prog); while(!o.HALT) { o.step(10000); ug->Update(); if(ug->KeyPressed(0x01)) break; } delete ug; return 0; }