Skip to content

Commit 2569df1

Browse files
committed
v2.1
Added bitmap VGA mode File choosers now use system defaults Bug Fixes
1 parent 0a31e29 commit 2569df1

File tree

10 files changed

+207
-88
lines changed

10 files changed

+207
-88
lines changed

.vscode/launch.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
55
"version": "0.2.0",
66
"configurations": [
7+
{
8+
"type": "java",
9+
"name": "Launch LCD",
10+
"request": "launch",
11+
"mainClass": "LCD",
12+
"projectName": "Java-6502-Emulator_cdf032ed"
13+
},
714
{
815
"type": "java",
916
"name": "Launch GPU",

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
# Java 6502 Emulator
22

33

4-
## Update: v2.0 is here!
5-
Whoa! Almost a year after the last update it's back and better than ever! The emulator now includes a character-driven GPU (bitmap modes in development) and SO MUCH customizability!
4+
## Update: v2.1 is here!
5+
Whoa! Almost a year after the last update it's back and better than ever! The emulator now includes a GPU (with Ben's bitmap and a custom character mode) and SO MUCH customizability!
66
You can now hide and show the LCD and GPU windows with the buttons at the top right!
77
You can now customize the address ranges of the VIA and GPU!
88
The GPU's resolution and array size is _whatever you want it to be_!
99
The fonts actually work now!
10+
The file choosers aren't the old Java ones!
1011
And **COLORS!!**
1112

1213
Store the configs in our fancy new .pref files!
1314
These configuration settings are stored in your AppData or Application Support folder on Windows/Mac respectively. It generates a defaults.pref file on startup every time if you want to go back to the default settings. (options.pref is loaded on startup.)
1415

15-
(The GPU Mode setting doesn't do anything yet, but that will allow me to implement more fun modes in the future.)
16-
1716
Enjoy the new features!
1817
-Dylan
1918

@@ -48,3 +47,4 @@ You can load ```.bin``` files into RAM or ROM using the File Pickers in the top
4847
![Screenshot 0](screenshots/screenshot0.png?raw=true)
4948
![Screenshot 1](screenshots/screenshot1.png?raw=true)
5049
![Screenshot 2](screenshots/screenshot2.png?raw=true)
50+
![Screenshot 3](screenshots/screenshot3.png?raw=true)

screenshots/screenshot3.png

591 KB
Loading

src/CPU.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ void clock() {
352352
ClocksPerSecond = EaterEmulator.clocks/((System.currentTimeMillis()-startTime)/1000);
353353

354354
EaterEmulator.clocks++;
355+
355356
cycles--;
356357
}
357358

src/DisplayPanel.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ public void paintComponent(Graphics g) {
5959

6060
//Title
6161
g.setFont(new Font("Calibri Bold", 50, 50));
62-
g.drawString("Ben Eater 6502 Emulator", 40, 50);
62+
g.drawString("BE6502 Emulator", 40, 50);
6363

6464
//Version
6565
g.setFont(courierNewBold);
66-
g.drawString("v"+EaterEmulator.versionString, 7, 1033);
66+
g.drawString("v"+EaterEmulator.versionString+" (c) Dylan Speiser", 7, 1033);
6767

6868
//Clocks
6969
g.drawString("Clocks: "+EaterEmulator.clocks, 40, 80);
@@ -146,6 +146,9 @@ public void resetGraphics() {
146146
public void actionPerformed(ActionEvent e) {
147147
if (e.getSource().equals(t)) {
148148
EaterEmulator.running = true;
149+
150+
EaterEmulator.cpu.cycles = 0;
151+
149152

150153
ramPageString = EaterEmulator.ram.RAMString.substring(ramPage*960,(ramPage+1)*960);
151154
EaterEmulator.ROMopenButton.setBounds(rightAlignHelper-150, 15, 125, 25);

src/EaterEmulator.java

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@
88
import javax.swing.*;
99

1010
public class EaterEmulator extends JFrame implements ActionListener {
11-
public static EaterEmulator emu;
12-
public static String versionString = "2.0";
11+
public static String versionString = "2.1";
1312
public static boolean debug = false;
1413

1514
//Swing Things
1615
JPanel p = new JPanel();
1716
JPanel header = new JPanel();
18-
public static JFileChooser fc = new JFileChooser();
17+
public static FileDialog fc = new java.awt.FileDialog((java.awt.Frame) null);
1918
public static JButton ROMopenButton = new JButton("Open ROM File");
2019
public static JButton RAMopenButton = new JButton("Open RAM File");
2120

@@ -30,27 +29,29 @@ public class EaterEmulator extends JFrame implements ActionListener {
3029
public static int clocks = 0;
3130
public static boolean haltFlag = true;
3231
public static boolean slowerClock = false;
32+
public static boolean running = false;
3333

3434
//Emulator Things
35+
public static EaterEmulator emu;
3536
public static RAM ram = new RAM();
3637
public static ROM rom = new ROM();
3738
public static LCD lcd = new LCD();
3839
public static VIA via = new VIA();
3940
public static Bus bus = new Bus();
4041
public static CPU cpu = new CPU();
41-
public static GPU gpu = new GPU(ram);
42-
42+
public static GPU gpu = new GPU(ram,false);
4343
public static DisplayPanel GraphicsPanel = new DisplayPanel();
44-
45-
//Options
4644
public static OptionsPane options = new OptionsPane();
47-
48-
public static boolean running = false;
4945

5046
public EaterEmulator() {
5147
//Swing Stuff:
5248
System.setProperty("sun.java2d.opengl", "true");
5349
this.setSize(1920,1080);
50+
try {
51+
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
52+
}catch(Exception ex) {
53+
ex.printStackTrace();
54+
}
5455

5556
//Open .bin file button
5657
ROMopenButton.setVisible(true);
@@ -86,8 +87,8 @@ public EaterEmulator() {
8687
GraphicsPanel.add(optionsButton);
8788

8889
//file chooser
89-
fc.setVisible(true);
90-
fc.setCurrentDirectory(new File(options.data.defaultFileChooserDirectory));
90+
fc.setDirectory(options.data.defaultFileChooserDirectory);
91+
fc.setVisible(false);
9192

9293
//Clock thread setup
9394
clockThread = new Thread(() -> {
@@ -121,22 +122,24 @@ public EaterEmulator() {
121122
@Override
122123
public void actionPerformed(ActionEvent e) {
123124
if (e.getSource().equals(ROMopenButton)) {
124-
fc.setSelectedFile(new File(""));
125-
int returnVal = fc.showOpenDialog(this);
125+
fc.setFile("");
126+
fc.setMode(FileDialog.LOAD);
127+
fc.setVisible(true);
126128

127-
if (returnVal == JFileChooser.APPROVE_OPTION) {
128-
rom.setROMArray(ROMLoader.readROM(fc.getSelectedFile()));
129-
}
129+
if (fc.getFile() != null)
130+
rom.setROMArray(ROMLoader.readROM(new File(fc.getDirectory()+fc.getFile())));
131+
130132
GraphicsPanel.requestFocus();
131133
GraphicsPanel.romPageString = EaterEmulator.rom.ROMString.substring(GraphicsPanel.romPage*960,(GraphicsPanel.romPage+1)*960);
132134
cpu.reset();
133135
} else if (e.getSource().equals(RAMopenButton)) {
134-
fc.setSelectedFile(new File(""));
135-
int returnVal = fc.showOpenDialog(this);
136+
fc.setFile("");
137+
fc.setMode(FileDialog.LOAD);
138+
fc.setVisible(true);
139+
140+
if (fc.getFile() != null)
141+
ram.setRAMArray(ROMLoader.readROM(new File(fc.getDirectory()+fc.getFile())));
136142

137-
if (returnVal == JFileChooser.APPROVE_OPTION) {
138-
ram.setRAMArray(ROMLoader.readROM(fc.getSelectedFile()));
139-
}
140143
GraphicsPanel.requestFocus();
141144
GraphicsPanel.ramPageString = EaterEmulator.ram.RAMString.substring(GraphicsPanel.ramPage*960,(GraphicsPanel.ramPage+1)*960);
142145
cpu.reset();

src/GPU.java

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import java.io.File;
77
import java.io.InputStream;
88
import java.net.URISyntaxException;
9-
109
import javax.imageio.ImageIO;
1110
import java.nio.file.*;
1211
import java.util.Scanner;
@@ -15,16 +14,22 @@
1514

1615
public class GPU extends JFrame implements ActionListener {
1716
GPUPanel p = new GPUPanel();
17+
1818
Timer t;
1919
Scanner s;
2020

21+
boolean scanned = false;
22+
2123
public static int VRAM_START_ADDRESS = 0x6000;
2224

2325
public static int n_cols = 80;
2426
public static int n_rows = 60;
2527

26-
public static int width = 640;
27-
public static int height = 480;
28+
public static int width = 100;
29+
public static int height = 75;
30+
31+
public static int gpuMode = 1;
32+
public static int GPUPixelScale = 8;
2833

2934
int charWidth;
3035
int charHeight;
@@ -39,8 +44,9 @@ public class GPU extends JFrame implements ActionListener {
3944

4045
RAM vram;
4146

42-
public GPU(RAM vram) {
43-
this.setSize(width,height);
47+
public GPU(RAM vram,boolean isVisible) {
48+
this.setSize(GPUPixelScale*width,GPUPixelScale*height);
49+
4450
t = new Timer(16,this);
4551
t.start();
4652

@@ -107,18 +113,18 @@ public GPU(RAM vram) {
107113
this.setTitle("GPU");
108114
this.setContentPane(p);
109115
this.setAlwaysOnTop(true);
110-
this.setVisible(false);
116+
this.setVisible(isVisible);
111117
this.setDefaultCloseOperation(HIDE_ON_CLOSE);
112118
this.setResizable(false);
113119
}
114120

115-
public GPU() {
116-
this(new RAM());
121+
public GPU(boolean isVisible) {
122+
this(new RAM(),isVisible);
117123
}
118124

119125
@SuppressWarnings("unused")
120126
public static void main(String[] args) {
121-
GPU gpu = new GPU();
127+
GPU gpu = new GPU(true);
122128
gpu.setVisible(true);
123129

124130
@SuppressWarnings("resource")
@@ -144,11 +150,13 @@ public static void main(String[] args) {
144150

145151
System.out.println("Read "+newData.length+" bytes.");
146152

147-
System.arraycopy(newData, 0, newRAMArray, GPU.VRAM_START_ADDRESS, Math.min(newData.length,newRAMArray.length));
153+
System.arraycopy(newData, 0, newRAMArray, (gpuMode == 1 | gpuMode == 2) ? 0 : (GPU.VRAM_START_ADDRESS), Math.min(newData.length,newRAMArray.length));
148154

149155
gpu.vram.setRAMArray(newRAMArray);
150156

151-
//System.out.println(ROMLoader.ROMString(gpu.vram.getRAMArray(),40,false));
157+
gpu.scanned = true;
158+
// System.out.println(ROMLoader.ROMString(gpu.vram.getRAMArray(),40,false));
159+
// System.exit(0);
152160
}
153161
}
154162

@@ -162,22 +170,66 @@ public GPUPanel() {
162170
}
163171

164172
public void paintComponent(Graphics g) {
165-
g.setColor(Color.BLACK);
166-
g.fillRect(0, 0, p.getWidth(), p.getHeight());
167-
168-
g.setColor(Color.white);
169-
170-
for (int i = 0; i<n_rows; i++) {
171-
for (int j = 0; j<n_cols; j++) {
172-
int index = i*n_cols + j;
173-
int character = Byte.toUnsignedInt(vram.read((short)(VRAM_START_ADDRESS+index)));
174-
175-
g.drawImage(charImages[character],j*effectiveCharWidth,i*effectiveCharHeight,effectiveCharWidth,effectiveCharHeight,this);
176-
if (debug) {
177-
System.out.println("Painted Char #"+character+" @ index "+index+" ("+j*charWidth+","+i*charHeight+")");
173+
if (this.isVisible()) {
174+
g.setColor(Color.BLACK);
175+
g.fillRect(0, 0, p.getWidth(), p.getHeight());
176+
177+
g.setColor(Color.white);
178+
179+
if (gpuMode == 0) {
180+
//Speiser Character Mode
181+
for (int i = 0; i<n_rows; i++) {
182+
for (int j = 0; j<n_cols; j++) {
183+
int index = i*n_cols + j;
184+
int character = Byte.toUnsignedInt(vram.read((short)(VRAM_START_ADDRESS+index)));
185+
186+
g.drawImage(charImages[character],j*effectiveCharWidth,i*effectiveCharHeight,effectiveCharWidth,effectiveCharHeight,this);
187+
if (debug) {
188+
System.out.println("Painted Char #"+character+" @ index "+index+" ("+j*charWidth+","+i*charHeight+")");
189+
}
190+
}
191+
}
192+
} else if (gpuMode == 1 || gpuMode == 2) {
193+
//Eater Bitmap Mode
194+
int nextPowerOf2 = (int)Math.pow(2,((int)Math.ceil(Math.log(width)/Math.log(2))));
195+
for (int i = 0; i<height; i++) {
196+
for (int j = 0; j<width; j++) {
197+
int index = j+nextPowerOf2*i;
198+
199+
/*
200+
System.out.println(" i: "+Integer.toBinaryString(i)+
201+
" j: "+Integer.toBinaryString(j)+
202+
" i (shifted): "+Integer.toBinaryString((i >> 3))+
203+
" j (shifted): "+Integer.toBinaryString((j >> 1))+
204+
" index: "+Integer.toBinaryString(index));
205+
*/
206+
207+
byte pixelData = vram.read( (short) Math.min((((gpuMode == 1 || gpuMode == 2) && debug == true) ? 0 : VRAM_START_ADDRESS)+index,vram.getRAMArray().length-1) );
208+
//pixelData = 0b001010;
209+
210+
byte red = (byte)((pixelData & 0b00110000) >> 4);
211+
byte green = (byte)((pixelData & 0b00001100) >> 2);
212+
byte blue = (byte)((pixelData & 0b00000011) >> 0);
213+
214+
Color c = Color.decode("#"+
215+
Integer.toHexString(red*5)+Integer.toHexString(red*5)+
216+
Integer.toHexString(green*5)+Integer.toHexString(green*5)+
217+
Integer.toHexString(blue*5)+Integer.toHexString(blue*5)
218+
);
219+
220+
if (scanned) {
221+
System.out.println("PixelData: "+ROMLoader.byteToHexString(pixelData)+" Color "+c.toString()+" @ ("+i+","+j+"), Index "+Integer.toHexString(index));
222+
System.out.println("PixelData "+Integer.toBinaryString(pixelData)+" R:"+Integer.toBinaryString(red)+" G:"+Integer.toBinaryString(green)+" B:"+Integer.toBinaryString(blue));
223+
System.out.println("NextPowerOf2: "+nextPowerOf2);
224+
}
225+
226+
g.setColor(c);
227+
228+
g.fillRect(GPUPixelScale*j, GPUPixelScale*i, GPUPixelScale, GPUPixelScale);
229+
}
178230
}
179-
}
180-
}
231+
}
232+
}
181233
}
182234
}
183235

src/LCD.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,13 @@ public LCD() {
5353
this.setTitle("LCD");
5454
this.setContentPane(p);
5555
this.setAlwaysOnTop(true);
56-
this.setVisible(true);
56+
this.setVisible(false);
5757
this.setDefaultCloseOperation(HIDE_ON_CLOSE);
5858
}
5959

6060
public static void main(String[] args) {
6161
LCD lcd = new LCD();
62+
lcd.setVisible(true);
6263

6364
@SuppressWarnings("resource")
6465
Scanner scan = new Scanner(System.in);

src/OptionsData.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ public class OptionsData implements Serializable {
1313
int GPUHeight = GPU.height;
1414
int GPUCols = GPU.n_cols;
1515
int GPURows = GPU.n_rows;
16-
int GPUBufferBegin = 0x4000;
17-
int GPUMode = 0; //GPU Modes (planned): 0=Character, 1=Bitmap Mono, 2=Character w/ Color, 3=Bitmap w/ Color
16+
int GPUBufferBegin = 0x2000;
17+
int GPUMode = GPU.gpuMode;
18+
int GPUBitmapPixelScale = GPU.GPUPixelScale;
1819
Color bgColor = Color.blue;
1920
Color fgColor = Color.white;
2021

@@ -27,6 +28,7 @@ public String toString() {
2728
"GPU Buffer Address: 0x"+Integer.toHexString(GPUBufferBegin)+"\n"+
2829
"GPU Character Dimentsions: "+GPUCols+"x"+GPURows+"\n"+
2930
"GPU Mode: "+GPUMode+"\n"+
31+
"GPU Bitmap Pixel Scale: "+GPUBitmapPixelScale+"\n"+
3032
"Background Color: "+bgColor.toString()+"\n"+
3133
"Foreground Color: "+fgColor.toString()+"\n";
3234
}

0 commit comments

Comments
 (0)