Compare commits

..

10 Commits

Author SHA1 Message Date
0xmac
0db7573a04 Fixed VRAM random value fill overhead 2024-12-02 14:06:56 +01:00
0xmac
f129aae3a3 Added SFML event handler 2024-12-02 14:06:29 +01:00
0xmac
b35d280f12 Added memory manager 2024-12-02 14:06:20 +01:00
0xmac
0227bc634f Added main c file 2024-12-02 14:06:05 +01:00
0xmac
a3fa133480 Added config.h 2024-12-02 14:05:49 +01:00
0xmac
99db648885 Added testbinaries 2024-12-02 14:05:38 +01:00
0xmac
a38cfc1cba Added -O2 Optimisation 2024-12-02 14:05:26 +01:00
0xmac
3389ed1172 Renamed variables 2024-12-02 10:39:58 +01:00
0xmac
623bec2127 Removed unused functions 2024-12-02 10:39:18 +01:00
0xmac
a5e914de4b Changed keyboard register to mem map 2024-12-02 10:37:30 +01:00
12 changed files with 355 additions and 120 deletions

View File

@ -11,8 +11,8 @@ clean:
ls7emulator:
cd src
$(CC) ls7emulator.c -o ls7emulator $(CFLAGS)
$(CC) ls7emulator.c -o ls7emulator $(CFLAGS) -O2
rm ../bin -rf
mkdir ../bin
cd ../bin

18
src/config.h Normal file
View File

@ -0,0 +1,18 @@
#include <stdint.h>
#include <SFML/System.h>
#include <SFML/Graphics.h>
#define NOP 0xEA /* CPU NoOp */
#define PAGESIZE 0x1F /* Pagesize of extra addressing of devices */
#define VIDADDRS 0xBE00 /* Video Address */
#define VIAADDRS 0xBF80 /* VIA Address */
#define KBDADDRS 0xBD00 /* Keyboard Register */
#define RAMSIZE 0x7FFF /* RAM Page Size */
#define RAMLOC 0x0000 /* ROM Page Location */
#define ROMSIZE 0x3FFF /* ROM Page Size */
#define ROMLOC 0xC000 /* ROM Page Location */
#define BACKCOLOR sfBlack

View File

@ -4,12 +4,9 @@
* Modified by Gabriel Weingardt *
*****************************************************/
#include <stdio.h>
#include <stdint.h>
#include "memory.h"
//externally supplied functions
extern uint8_t read6502(uint16_t address);
extern void write6502(uint16_t address, uint8_t value);
//6502 defines
#define FLAG_CARRY 0x01
@ -724,28 +721,6 @@ void irq6502() {
pc = (uint16_t)read6502(0xFFFE) | ((uint16_t)read6502(0xFFFF) << 8);
}
uint8_t callexternal = 0;
void (*loopexternal)();
void exec6502(uint32_t tickcount) {
clockgoal6502 += tickcount;
while (clockticks6502 < clockgoal6502) {
opcode = read6502(pc++);
penaltyop = 0;
penaltyaddr = 0;
(*addrtable[opcode])();
(*optable[opcode])();
clockticks6502 += ticktable[opcode];
if (penaltyop && penaltyaddr) clockticks6502++;
if (callexternal) (*loopexternal)();
}
}
void step6502() {
opcode = read6502(pc++);
@ -758,12 +733,4 @@ void step6502() {
if (penaltyop && penaltyaddr) clockticks6502++;
clockgoal6502 = clockticks6502;
if (callexternal) (*loopexternal)();
}
void hookexternal(void *funcptr) {
if (funcptr != (void *)NULL) {
loopexternal = funcptr;
callexternal = 1;
} else callexternal = 0;
}

66
src/events.c Normal file
View File

@ -0,0 +1,66 @@
#include <stdint.h>
#include <SFML/Graphics/RenderWindow.h>
#include <SFML/System.h>
#include <SFML/Graphics.h>
#include <SFML/Window.h>
extern float displayScale;
extern void resetSystem();
extern void irq6502();
extern void nmi6502();
extern void updateRenderStates();
extern void scanKeyboard();
static sfKeyCode currentKey = sfKeyUnknown;
void pollEvents(sfRenderWindow *window){
sfEvent event;
while (sfRenderWindow_pollEvent(window, &event)) {
switch (event.type){
case sfEvtClosed:
sfRenderWindow_close(window);
break;
case sfEvtResized:
sfRenderWindow_setView(window, sfView_createFromRect((sfFloatRect){0, 0, event.size.width, event.size.height}));
break;
case sfEvtKeyPressed:
switch (event.key.code){
case sfKeyEscape:
sfRenderWindow_close(window);
break;
case sfKeyF2:
if (displayScale > 1) displayScale--;
updateRenderStates();
break;
case sfKeyF3:
displayScale++;
updateRenderStates();
break;
case sfKeyF5:
resetSystem();
break;
case sfKeyF12:
irq6502();
break;
case sfKeyF11:
nmi6502();
break;
default:
currentKey = event.key.code;
break;
}
break;
case sfEvtKeyReleased:
currentKey = sfKeyUnknown;
break;
default: break;
}
}
}

View File

@ -2,10 +2,10 @@
#include <SFML/Window.h>
extern uint8_t systemRegister;
extern uint8_t keyboardResult;
extern sfKeyCode currentKey;
static uint8_t keyboardResult;
static sfKeyCode scanMatrix[48] = {
const static sfKeyCode scanMatrix[48] = {
sfKeyNum1, sfKeyNum2, sfKeyNum3, sfKeyNum4, sfKeyNum5, sfKeyNum6, sfKeyNum7, sfKeyNum8,
sfKeyQ, sfKeyW, sfKeyE, sfKeyR, sfKeyT, sfKeyY, sfKeyU, sfKeyI,
sfKeyA, sfKeyS, sfKeyD, sfKeyF, sfKeyG, sfKeyH, sfKeyJ, sfKeyK,
@ -15,11 +15,11 @@ static sfKeyCode scanMatrix[48] = {
};
void scanKeyboard(const sfKeyCode key){
void scanKeyboard(){
keyboardResult = 0;
for (int i = 0; i < 8; i++) {
if (key == scanMatrix[i + (((systemRegister & 0x07) % 6) * 8)]){
if (currentKey == scanMatrix[i + (((systemRegister & 0x07) % 6) * 8)]){
keyboardResult |= (0x80 >> i);
}
}

88
src/ls7emulator.c Normal file
View File

@ -0,0 +1,88 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <SFML/System.h>
#include <SFML/Graphics.h>
#include <SFML/Window.h>
#include "ls7emulator.h"
#include "config.h"
#include "events.c"
#include "cpu.c"
#include "memory.c"
#include "video.c"
#include "keyboard.c"
void openFile(const char *inputFile){
FILE *file = fopen(inputFile, "rb");
if (file != NULL){
fseek(file, 0, SEEK_END);
long filelen = ftell(file);
rewind(file);
fread(rom, filelen, 1, file);
printf("Loaded File\n");
} else {
printf("Error while opening file\n");
exit(1);
}
fclose(file);
}
void resetSystem(){
initVideo();
updateVideo();
reset6502();
}
void updateRenderStates(){
renderStates.transform = sfTransform_Identity;
sfTransform_scale(&renderStates.transform, displayScale, displayScale);
}
void drawScreen(){
sfRenderWindow_drawVertexArray(window, renderArray, &renderStates);
}
int main(int argc, char *argv[]){
window = sfRenderWindow_create((sfVideoMode){800, 600, 24}, "LS7 Emulator", sfResize | sfClose, NULL);
sfRenderWindow_setVerticalSyncEnabled(window, sfFalse);
sfRenderWindow_setFramerateLimit(window, 60);
sfRenderWindow_setKeyRepeatEnabled(window, sfFalse);
renderStates = sfRenderStates_default();
sfTransform_scale(&renderStates.transform, 2, 2);
if (argc == 2) { openFile(argv[1]); }
else {
printf("Please specify a input file\n");
exit(1);
}
resetSystem();
while (sfRenderWindow_isOpen(window)){
pollEvents(window);
for (int i = 0; i < 4096 * 16; i++) step6502();
irq6502();
sfRenderWindow_clear(window, BACKCOLOR);
updateVideo();
drawScreen();
sfRenderWindow_display(window);
}
sfRenderWindow_destroy(window);
return 0;
}

13
src/ls7emulator.h Normal file
View File

@ -0,0 +1,13 @@
#include <SFML/System.h>
#include <SFML/Graphics.h>
#include <stdint.h>
/* Display Scale used for VertexArray */
static float displayScale = 2;
static sfVertexArray *renderArray;
static sfRenderWindow *window;
static sfRenderStates renderStates;

64
src/memory.c Normal file
View File

@ -0,0 +1,64 @@
#include <stdint.h>
#include "memory.h"
uint8_t read6502(uint16_t address){
switch (address){
case RAMLOC ... RAMLOC + RAMSIZE:
return ram[address - RAMLOC];
break;
case ROMLOC ... ROMLOC + ROMSIZE:
return rom[address - ROMLOC];
break;
case VIDADDRS ... VIDADDRS + PAGESIZE:
if ((address - VIDADDRS) % 4 == 3) return readVideo();
else return 0;
break;
case 0xBD00:
scanKeyboard();
return keyboardResult;
break;
default:
return NOP;
break;
}
}
void write6502(uint16_t address, uint8_t value){
switch (address){
case RAMLOC ... RAMLOC + RAMSIZE:
ram[address - RAMLOC] = value;
break;
case ROMLOC ... ROMLOC + ROMSIZE:
rom[address - ROMLOC] = value;
break;
case VIDADDRS ... VIDADDRS + PAGESIZE:
switch ((address - VIDADDRS) % 4){
case 0: /* Video X Register */
videoX = value;
break;
case 1: /* Video Y Register */
videoY = value;
break;
case 2: /* Video M Register */
videoMode = value;
break;
case 3: /* Video A Register */
videoA = value;
writeVideo();
break;
}
break;
case 0xBC00:
systemRegister = value;
break;
default:
break;
}
}

21
src/memory.h Normal file
View File

@ -0,0 +1,21 @@
#include <stdint.h>
#include "config.h"
extern void scanKeyboard();
extern void writeVideo();
extern uint8_t readVideo();
extern uint8_t videoX;
extern uint8_t videoY;
extern uint8_t videoMode;
extern uint8_t videoA;
static int8_t ram[RAMSIZE + 1];
static int8_t rom[ROMSIZE + 1];
static uint8_t systemRegister;
static uint8_t keyboardResult;
uint8_t read6502(uint16_t address);
void write6502(uint16_t address, uint8_t value);

View File

@ -8,108 +8,106 @@
/* Public Variables */
extern sfVertexArray *renderArray;
int8_t videoModified;
int8_t videoMode;
/* Hardware-like Registers */
uint8_t videoX;
uint8_t videoY;
uint8_t videoMode;
uint8_t videoA;
/* Private Variables */
static uint8_t video_row;
static uint8_t video_value;
static uint8_t video_colorValue;
static sfColor video_displayColor;
static sfColor video_foreColor;
static sfColor video_backColor;
static uint8_t videoRow;
static uint8_t videoValue;
static uint8_t videoColorValue;
static sfColor videoDisplayColor;
static sfColor videoForeColor;
static sfColor videoBackColor;
const sfColor video_upperPalette = (sfColor){ 64, 64, 64 };
const static sfColor videoUpperPalette = (sfColor){ 64, 64, 64 };
static sfColor *video_colorIndex[16] = {
&sfBlack, // 0x0
&sfRed, // 0x1
&sfGreen, // 0x2
&sfYellow, // 0x3
&sfBlue, // 0x4
&sfMagenta, // 0x5
&sfCyan, // 0x6
&(sfColor){ 96, 96, 96 }, // 0x7
&(sfColor){ 162, 162, 162 },// 0x8
&sfRed, // 0x9
&sfGreen, // 0xA
&sfYellow, // 0xB
&sfBlue, // 0xC
&sfMagenta, // 0xD
&sfCyan, // 0xE
&sfWhite, // 0xF
static sfColor *videoColorIndex[] = {
&sfBlack, &sfRed, &sfGreen, &sfYellow, &sfBlue, &sfMagenta, &sfCyan, &sfWhite//&(sfColor){ 96, 96, 96 } ,
/*&(sfColor){ 0, 0, 0 },
&(sfColor){ 0xFF, 0, 0 },
&(sfColor){ 0, 0xFF, 0 },
&(sfColor){ 0xFF, 0xFF, 0 },
&(sfColor){ 0, 0, 0xFF },
&(sfColor){ 0xFF, 0, 0xFF },
&(sfColor){ 0, 0xFF, 0xFF },
&(sfColor){ 0xFF, 0xFF, 0xFF },*/
};
static uint8_t videoMemory[0x7FFF];
static uint8_t video_memory[0x8000]; // Empty Memory with 32k space
void writeVideo(){
videoMemory[videoX + (videoY * 128)] = videoA;
videoModified = 1;
}
uint8_t readVideo(){
return videoMemory[videoX + (videoY * 128)];
}
void initVideo(){
renderArray = sfVertexArray_create();
sfVertexArray_setPrimitiveType(renderArray, sfQuads);
videoModified = 1;
videoMode = 0;
videoMode = 0x01;
for (int i = 0x8; i < 0xF; i++){
//*video_colorIndex[i] = sfColor_add(*video_colorIndex[i], video_upperPalette);
}
for (int i = 0; i < 0x8000; i++){
video_memory[i] = rand();
}
for (int i = 0; i < 0x7FFF; i++) videoMemory[i] = rand();
}
void updateVideo(){
sfVertexArray_clear(renderArray);
sfVertexArray_setPrimitiveType(renderArray, sfQuads);
videoModified = 0;
for (int y = 0; y < 256; y++){
video_row = (int8_t)(y & 0x7);
if (videoModified){
sfVertexArray_clear(renderArray);
for (int x = 0; x < 48; x++){
for (uint8_t y = 0; y < 255; y++){
videoRow = (int8_t)(y & 0x7);
if (videoMode == 1){
/*
* Text Address Format
* 0bRRR1111AAAAAAAA
*
* R = row pins
* A = address
*/
for (uint8_t x = 0; x < 48; x++){
// Get text index value
video_value = video_memory[(((y & 0xF8) >> 3) << 7) | x];
// Index the value in font location
video_value = video_memory[(video_row | 0b1111000) + (video_value * 128)];
video_colorValue = video_memory[(((y & 0xF8) >> 3) << 7) + (x | 0x40)];
}
else {
video_value = video_memory[(y * 128) + x];
video_colorValue = video_memory[(y * 128) + (x | 0x40)];
}
// Snipping out the upper 8 colors
//video_colorValue &= 0x77;
video_foreColor = *video_colorIndex[(video_colorValue & 0x0F)];
video_backColor = *video_colorIndex[((video_colorValue & 0xF0) >> 4)];
for (int i = 0; i < 8; i++){
if (video_value & (128 >> i)){
video_displayColor = video_foreColor;
} else {
video_displayColor = video_backColor;
if ((videoMode & 0x01) == 0){
/*
* Text Address Format
* 0bRRR1111AAAAAAAA
*
* R = row pins
* A = address
*/
// Get text index value
videoValue = videoMemory[(((y & 0xF8) >> 3) << 7) | x];
// Index the value in font location
videoValue = videoMemory[(videoRow | 0b1111000) + (videoValue * 128)];
videoColorValue = videoMemory[(((y & 0xF8) >> 3) << 7) + (x | 0x40)];
}
else {
videoValue = videoMemory[(y * 128) + x];
videoColorValue = videoMemory[(y * 128) + (x | 0x40)];
}
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i, y }, video_displayColor});
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i + 1, y }, video_displayColor});
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i + 1, y + 1 }, video_displayColor});
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i, y + 1 }, video_displayColor});
// Snipping out the upper 8 colors
videoColorValue &= 0x77;
videoForeColor = *videoColorIndex[(videoColorValue & 0x0F)];
videoBackColor = *videoColorIndex[((videoColorValue & 0xF0) >> 4)];
for (uint8_t i = 0; i < 8; i++){
if (videoValue & (128 >> i)) videoDisplayColor = videoBackColor;
else videoDisplayColor = videoForeColor;
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i, y }, videoDisplayColor});
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i + 1, y }, videoDisplayColor});
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i + 1, y + 1 }, videoDisplayColor});
sfVertexArray_append(renderArray, (sfVertex){ (sfVector2f){ (x * 8) + i, y + 1 }, videoDisplayColor});
}
}
}
videoModified = 0;
}
}

BIN
testbins/2048.bin Normal file

Binary file not shown.

BIN
testbins/typewriter.bin Normal file

Binary file not shown.