Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions assets/data/programs.json
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,15 @@
"machineType": "VIC44",
"ram": "RAM_UNEXPANDED"
},
{
"name": "VIC44K",
"displayName": "VIC 44K",
"filePath": "",
"fileType": "ROM",
"iconPath": "screenshots/V/VIC44/VIC44.png",
"machineType": "VIC44K",
"ram": "RAM_UNEXPANDED"
},
{
"name": "Whack-E",
"filePath": "https://archive.org/download/tosec-20161111-commodore-vic-20_20170305/TOSEC.2016.11.11.Commodore.VIC20.AlphaBot.zip/TOSEC.2016.11.11.Commodore.VIC20.AlphaBot%2FCommodore%20VIC20%20-%20Games%20-%20%5BPRG%5D%2FWhack-E%20%282009%29%28McCrea%2C%20Steve%29.zip",
Expand Down
Binary file added assets/roms/vic_44k_basic.rom
Binary file not shown.
Binary file added assets/roms/vic_44k_kernal.rom
Binary file not shown.
2 changes: 2 additions & 0 deletions core/src/main/java/emu/jvic/JVic.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ private void applyTvConfig(AppConfigItem appConfigItem, String tv) {
case "VIC44":
appConfigItem.setMachineType("VIC44");
break;
case "VIC44K":
appConfigItem.setMachineType("VIC44K");
default:
break;
}
Expand Down
42 changes: 42 additions & 0 deletions core/src/main/java/emu/jvic/JVicRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,48 @@ public MachineInputProcessor getMachineInputProcessor() {
return (machineScreen != null? machineScreen.getMachineInputProcessor() : null);
}

public byte[] loadKernalRom(MachineType machineType) {
byte[] kernalRom = null;

switch (machineType) {
case NTSC:
kernalRom = Gdx.files.internal("roms/kernal_ntsc.rom").readBytes();
break;
case PAL:
kernalRom = Gdx.files.internal("roms/kernal_pal.rom").readBytes();
break;
case VIC44:
kernalRom = Gdx.files.internal("roms/vic_44_kernal.rom").readBytes();
break;
case VIC44K:
kernalRom = Gdx.files.internal("roms/vic_44k_kernal.rom").readBytes();
break;
}

return kernalRom;
}

public byte[] loadBasicRom(MachineType machineType) {
byte[] basicRom = null;

switch (machineType) {
case NTSC:
basicRom = Gdx.files.internal("roms/basic.rom").readBytes();
break;
case PAL:
basicRom = Gdx.files.internal("roms/basic.rom").readBytes();
break;
case VIC44:
basicRom = Gdx.files.internal("roms/vic_44_basic.rom").readBytes();
break;
case VIC44K:
basicRom = Gdx.files.internal("roms/vic_44k_basic.rom").readBytes();
break;
}

return basicRom;
}

public abstract void start(AppConfigItem appConfigItem);

public abstract void reset();
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/java/emu/jvic/Machine.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import emu.jvic.sound.libgdx.GdxSoundGenerator;
import emu.jvic.video.Vic;
import emu.jvic.video.Vic44;
import emu.jvic.video.Vic44k;
import emu.jvic.video.Vic6560;
import emu.jvic.video.Vic6561;

Expand Down Expand Up @@ -138,6 +139,8 @@ public Callable<Queue<char[]>> init(
// Create the VIC chip and configure it as per the current TV type.
if (machineType.isVIC44()) {
vic = new Vic44(pixelData, machineType, snapshot);
} else if (machineType.isVIC44K()) {
vic = new Vic44k(pixelData, machineType, snapshot);
} else if (machineType.isNTSC()) {
vic = new Vic6560(pixelData, machineType, snapshot);
} else {
Expand Down
1 change: 1 addition & 0 deletions core/src/main/java/emu/jvic/MachineScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ public MachineScreen(JVic jvic, JVicRunner jvicRunner, DialogHandler dialogHandl
createScreenResourcesForMachineType(MachineType.PAL);
createScreenResourcesForMachineType(MachineType.NTSC);
createScreenResourcesForMachineType(MachineType.VIC44);
createScreenResourcesForMachineType(MachineType.VIC44K);

warpSpeedIcon = new Texture("png/warp_speed_icon.png");
cameraIcon = new Texture("png/camera_icon.png");
Expand Down
8 changes: 7 additions & 1 deletion core/src/main/java/emu/jvic/MachineType.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ public enum MachineType {

NTSC(1022727, 260, 263, 199, 252, 49, 8, 60),

VIC44(1108405, 568, 312, 440, 272, 103, 31, 50);
VIC44(1108405, 568, 312, 440, 272, 103, 31, 50),

VIC44K(1108405, 568, 312, 440, 272, 103, 31, 50);

private int cyclesPerSecond;
private int totalScreenWidth;
Expand Down Expand Up @@ -147,4 +149,8 @@ public boolean isNTSC() {
public boolean isVIC44() {
return equals(VIC44);
}

public boolean isVIC44K() {
return equals(VIC44K);
}
}
253 changes: 153 additions & 100 deletions core/src/main/java/emu/jvic/memory/Vic20Memory.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,111 +75,164 @@ public Vic20Memory(Cpu6502 cpu, Vic vic, Via6522 via1, Via6522 via2, int ramExpa
*/
private void initVicMemory(Vic vic, Via6522 via1, Via6522 via2, byte[] basicRom, byte[] kernalRom, byte[] charRom) {

// This 1K of RAM is always present.
mapChipToMemory(new VicBusRamChip(), 0x0000, 0x03FF);

// The next 3K of memory may have RAM or may be unconnected.
mapChipToMemory((ramExpansion & RAM_1) != 0 ? new RamChip() : new UnconnectedMemory(), 0x0400, 0x07FF);
mapChipToMemory((ramExpansion & RAM_2) != 0 ? new RamChip() : new UnconnectedMemory(), 0x0800, 0x0BFF);
mapChipToMemory((ramExpansion & RAM_3) != 0 ? new RamChip() : new UnconnectedMemory(), 0x0C00, 0x0FFF);

// This 4K of RAM is always present.
mapChipToMemory(new VicBusRamChip(), 0x1000, 0x1FFF);

// The next three 8K blocks may have RAM or may be unconnected.
mapChipToMemory((ramExpansion & BLK_1) != 0 ? new RamChip() : new UnconnectedMemory(), 0x2000, 0x3FFF);
mapChipToMemory((ramExpansion & BLK_2) != 0 ? new RamChip() : new UnconnectedMemory(), 0x4000, 0x5FFF);
mapChipToMemory((ramExpansion & BLK_3) != 0 ? new RamChip() : new UnconnectedMemory(), 0x6000, 0x7FFF);

mapChipToMemory(new VicBusRomChip(), 0x8000, 0x8FFF, charRom);

if (machineType.isVIC44K()) {
initVic44KMemory(vic, via1, via2);

} else {
// This 1K of RAM is always present.
mapChipToMemory(new VicBusRamChip(), 0x0000, 0x03FF);

// The next 3K of memory may have RAM or may be unconnected.
mapChipToMemory((ramExpansion & RAM_1) != 0 ? new RamChip() : new UnconnectedMemory(), 0x0400, 0x07FF);
mapChipToMemory((ramExpansion & RAM_2) != 0 ? new RamChip() : new UnconnectedMemory(), 0x0800, 0x0BFF);
mapChipToMemory((ramExpansion & RAM_3) != 0 ? new RamChip() : new UnconnectedMemory(), 0x0C00, 0x0FFF);

// This 4K of RAM is always present.
mapChipToMemory(new VicBusRamChip(), 0x1000, 0x1FFF);

// The next three 8K blocks may have RAM or may be unconnected.
mapChipToMemory((ramExpansion & BLK_1) != 0 ? new RamChip() : new UnconnectedMemory(), 0x2000, 0x3FFF);
mapChipToMemory((ramExpansion & BLK_2) != 0 ? new RamChip() : new UnconnectedMemory(), 0x4000, 0x5FFF);
mapChipToMemory((ramExpansion & BLK_3) != 0 ? new RamChip() : new UnconnectedMemory(), 0x6000, 0x7FFF);

mapChipToMemory(new VicBusRomChip(), 0x8000, 0x8FFF, charRom);

// These are the standard locations for the VIC, VIA1 and VIA2 chips.
mapChipToMemory(vic, 0x9000, 0x900F);
mapChipToMemory(via1, 0x9110, 0x911F);
mapChipToMemory(via2, 0x9120, 0x912F);

// The rest of the $9XXX address space, other than colour RAM, is not fully
// decoded. Every address in that range is going to select at least one of
// the VIC, VIA1 or VIA2 chips though, but sometimes it will select 2 or 3
// of them at once!! So we emulate this behaviour below.
NotFullyDecodedMemory vicVia1 = new NotFullyDecodedMemory(new MemoryMappedChip[] { vic, via1 });
NotFullyDecodedMemory vicVia2 = new NotFullyDecodedMemory(new MemoryMappedChip[] { vic, via2 });
NotFullyDecodedMemory via1Via2 = new NotFullyDecodedMemory(new MemoryMappedChip[] { via1, via2 });
NotFullyDecodedMemory vicVia1Via2 = new NotFullyDecodedMemory(new MemoryMappedChip[] { vic, via1, via2 });

mapChipToMemory(vicVia1, 0x9010, 0x901F);
mapChipToMemory(vicVia2, 0x9020, 0x902F);
mapChipToMemory(vicVia1Via2, 0x9030, 0x903F);
mapChipToMemory(vic, 0x9040, 0x904F);
mapChipToMemory(vicVia1, 0x9050, 0x905F);
mapChipToMemory(vicVia2, 0x9060, 0x906F);
mapChipToMemory(vicVia1Via2, 0x9070, 0x907F);
mapChipToMemory(vic, 0x9080, 0x908F);
mapChipToMemory(vicVia1, 0x9090, 0x909F);
mapChipToMemory(vicVia2, 0x90A0, 0x90AF);
mapChipToMemory(vicVia1Via2, 0x90B0, 0x90BF);
mapChipToMemory(vic, 0x90C0, 0x90CF);
mapChipToMemory(vicVia1, 0x90D0, 0x90DF);
mapChipToMemory(vicVia2, 0x90E0, 0x90EF);
mapChipToMemory(vicVia1Via2, 0x90F0, 0x90FF);

mapChipToMemory(vic, 0x9100, 0x910F); // Unconnected VIC address bus space.
mapChipToMemory(via1Via2, 0x9130, 0x913F);
mapChipToMemory(vic, 0x9140, 0x914F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9150, 0x915F);
mapChipToMemory(via2, 0x9160, 0x916F);
mapChipToMemory(via1Via2, 0x9170, 0x917F);
mapChipToMemory(vic, 0x9180, 0x918F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9190, 0x919F);
mapChipToMemory(via2, 0x91A0, 0x91AF);
mapChipToMemory(via1Via2, 0x91B0, 0x91BF);
mapChipToMemory(vic, 0x91C0, 0x91CF); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x91D0, 0x91DF);
mapChipToMemory(via2, 0x91E0, 0x91EF);
mapChipToMemory(via1Via2, 0x91F0, 0x91FF);
mapChipToMemory(vic, 0x9200, 0x920F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9210, 0x921F);
mapChipToMemory(via2, 0x9220, 0x922F);
mapChipToMemory(via1Via2, 0x9230, 0x923F);
mapChipToMemory(vic, 0x9240, 0x924F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9250, 0x925F);
mapChipToMemory(via2, 0x9260, 0x926F);
mapChipToMemory(via1Via2, 0x9270, 0x927F);
mapChipToMemory(vic, 0x9280, 0x928F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9290, 0x929F);
mapChipToMemory(via2, 0x92A0, 0x92AF);
mapChipToMemory(via1Via2, 0x92B0, 0x92BF);
mapChipToMemory(vic, 0x92C0, 0x92CF); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x92D0, 0x92DF);
mapChipToMemory(via2, 0x92E0, 0x92EF);
mapChipToMemory(via1Via2, 0x92F0, 0x92FF);
mapChipToMemory(vic, 0x9300, 0x930F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9310, 0x931F);
mapChipToMemory(via2, 0x9320, 0x932F);
mapChipToMemory(via1Via2, 0x9330, 0x933F);
mapChipToMemory(vic, 0x9340, 0x934F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9350, 0x935F);
mapChipToMemory(via2, 0x9360, 0x936F);
mapChipToMemory(via1Via2, 0x9370, 0x937F);
mapChipToMemory(vic, 0x9380, 0x938F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9390, 0x939F);
mapChipToMemory(via2, 0x93A0, 0x93AF);
mapChipToMemory(via1Via2, 0x93B0, 0x93BF);
mapChipToMemory(vic, 0x93C0, 0x93CF); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x93D0, 0x93DF);
mapChipToMemory(via2, 0x93E0, 0x93EF);
mapChipToMemory(via1Via2, 0x93F0, 0x93FF);

// The colour RAM lives at this spot by default.
mapChipToMemory(new NibbleRamChip(), 0x9400, 0x97FF);

mapChipToMemory(vic, 0x9800, 0x9FFF); // Unconnected VIC address bus space.

// It is possible to connect RAM in this block, even though it would normally be
// a cartridge ROM.
mapChipToMemory((ramExpansion & BLK_5) != 0 ? new RamChip() : new UnconnectedMemory(), 0xA000, 0xBFFF);
}

mapChipToMemory(new RomChip(), 0xC000, 0xDFFF, basicRom);
mapChipToMemory(new RomChip(), 0xE000, 0xFFFF, kernalRom);

if (machineType.isVIC44() || machineType.isVIC44K()) {
vic.setCharRom(charRom);
}
}

/**
* Initialises the memory for the VIC44K machine.
*
* @param vic The VIC chip to map to memory.
* @param via1 The VIA #1 chip to map to memory.
* @param via2 The VIA #2 chip to map to memory.
*/
private void initVic44KMemory(Vic vic, Via6522 via1, Via6522 via2) {
// All Expansion RAM in the VIC44K (BLK5/BLK1/BLK2/BLK3)
mapChipToMemory(new RamChip(), 0x0000, 0x7FFF);

mapChipToMemory(new VicBusRamChip(), 0x8000, 0xB7FF);

mapChipToMemory(new NibbleRamChip(), 0xB800, 0xBBFF);

// These are the standard locations for the VIC, VIA1 and VIA2 chips.
mapChipToMemory(vic, 0x9000, 0x900F);
mapChipToMemory(via1, 0x9110, 0x911F);
mapChipToMemory(via2, 0x9120, 0x912F);

// The rest of the $9XXX address space, other than colour RAM, is not fully
// decoded. Every address in that range is going to select at least one of
// the VIC, VIA1 or VIA2 chips though, but sometimes it will select 2 or 3
// of them at once!! So we emulate this behaviour below.
mapChipToMemory(vic, 0xBC00, 0xBC0F);
mapChipToMemory(via1, 0xBD10, 0xBD1F);
mapChipToMemory(via2, 0xBD20, 0xBD2F);

NotFullyDecodedMemory vicVia1 = new NotFullyDecodedMemory(new MemoryMappedChip[] { vic, via1 });
NotFullyDecodedMemory vicVia2 = new NotFullyDecodedMemory(new MemoryMappedChip[] { vic, via2 });
NotFullyDecodedMemory via1Via2 = new NotFullyDecodedMemory(new MemoryMappedChip[] { via1, via2 });
NotFullyDecodedMemory vicVia1Via2 = new NotFullyDecodedMemory(new MemoryMappedChip[] { vic, via1, via2 });

mapChipToMemory(vicVia1, 0x9010, 0x901F);
mapChipToMemory(vicVia2, 0x9020, 0x902F);
mapChipToMemory(vicVia1Via2, 0x9030, 0x903F);
mapChipToMemory(vic, 0x9040, 0x904F);
mapChipToMemory(vicVia1, 0x9050, 0x905F);
mapChipToMemory(vicVia2, 0x9060, 0x906F);
mapChipToMemory(vicVia1Via2, 0x9070, 0x907F);
mapChipToMemory(vic, 0x9080, 0x908F);
mapChipToMemory(vicVia1, 0x9090, 0x909F);
mapChipToMemory(vicVia2, 0x90A0, 0x90AF);
mapChipToMemory(vicVia1Via2, 0x90B0, 0x90BF);
mapChipToMemory(vic, 0x90C0, 0x90CF);
mapChipToMemory(vicVia1, 0x90D0, 0x90DF);
mapChipToMemory(vicVia2, 0x90E0, 0x90EF);
mapChipToMemory(vicVia1Via2, 0x90F0, 0x90FF);
mapChipToMemory(vic, 0x9100, 0x910F); // Unconnected VIC address bus space.
mapChipToMemory(via1Via2, 0x9130, 0x913F);
mapChipToMemory(vic, 0x9140, 0x914F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9150, 0x915F);
mapChipToMemory(via2, 0x9160, 0x916F);
mapChipToMemory(via1Via2, 0x9170, 0x917F);
mapChipToMemory(vic, 0x9180, 0x918F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9190, 0x919F);
mapChipToMemory(via2, 0x91A0, 0x91AF);
mapChipToMemory(via1Via2, 0x91B0, 0x91BF);
mapChipToMemory(vic, 0x91C0, 0x91CF); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x91D0, 0x91DF);
mapChipToMemory(via2, 0x91E0, 0x91EF);
mapChipToMemory(via1Via2, 0x91F0, 0x91FF);
mapChipToMemory(vic, 0x9200, 0x920F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9210, 0x921F);
mapChipToMemory(via2, 0x9220, 0x922F);
mapChipToMemory(via1Via2, 0x9230, 0x923F);
mapChipToMemory(vic, 0x9240, 0x924F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9250, 0x925F);
mapChipToMemory(via2, 0x9260, 0x926F);
mapChipToMemory(via1Via2, 0x9270, 0x927F);
mapChipToMemory(vic, 0x9280, 0x928F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9290, 0x929F);
mapChipToMemory(via2, 0x92A0, 0x92AF);
mapChipToMemory(via1Via2, 0x92B0, 0x92BF);
mapChipToMemory(vic, 0x92C0, 0x92CF); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x92D0, 0x92DF);
mapChipToMemory(via2, 0x92E0, 0x92EF);
mapChipToMemory(via1Via2, 0x92F0, 0x92FF);
mapChipToMemory(vic, 0x9300, 0x930F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9310, 0x931F);
mapChipToMemory(via2, 0x9320, 0x932F);
mapChipToMemory(via1Via2, 0x9330, 0x933F);
mapChipToMemory(vic, 0x9340, 0x934F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9350, 0x935F);
mapChipToMemory(via2, 0x9360, 0x936F);
mapChipToMemory(via1Via2, 0x9370, 0x937F);
mapChipToMemory(vic, 0x9380, 0x938F); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x9390, 0x939F);
mapChipToMemory(via2, 0x93A0, 0x93AF);
mapChipToMemory(via1Via2, 0x93B0, 0x93BF);
mapChipToMemory(vic, 0x93C0, 0x93CF); // Unconnected VIC address bus space.
mapChipToMemory(via1, 0x93D0, 0x93DF);
mapChipToMemory(via2, 0x93E0, 0x93EF);
mapChipToMemory(via1Via2, 0x93F0, 0x93FF);

// The colour RAM lives at this spot by default.
mapChipToMemory(new NibbleRamChip(), 0x9400, 0x97FF);

mapChipToMemory(vic, 0x9800, 0x9FFF); // Unconnected VIC address bus space.

// It is possible to connect RAM in this block, even though it would normally be
// a cartridge ROM.
mapChipToMemory((ramExpansion & BLK_5) != 0 ? new RamChip() : new UnconnectedMemory(), 0xA000, 0xBFFF);

mapChipToMemory(new RomChip(), 0xC000, 0xDFFF, basicRom);
mapChipToMemory(new RomChip(), 0xE000, 0xFFFF, kernalRom);

for (int i=0xBC00; i<=0xBFFF; i++) {
boolean isVic = ((i & 0xFF00) == 0xBC00);
boolean isVia1 = ((i & 0x0030) == 0x0010);
boolean isVia2 = ((i & 0x0030) == 0x0020);

if (isVic && !isVia1 && !isVia2) mapChipToMemory(vic, i, i);
if (isVic && isVia1 && !isVia2) mapChipToMemory(vicVia1, i, i);
if (isVic && !isVia1 && isVia2) mapChipToMemory(vicVia2, i, i);
if (isVic && isVia1 && isVia2) mapChipToMemory(vicVia1Via2, i, i);
if (!isVic && isVia1 && !isVia2) mapChipToMemory(via1, i, i);
if (!isVic && !isVia1 && isVia2) mapChipToMemory(via2, i, i);
if (!isVic && isVia1 && isVia2) mapChipToMemory(via1Via2, i, i);

// TODO: Does this need vic bus version of unconnected memory?
if (!isVic && !isVia1 && !isVia2) mapChipToMemory(new UnconnectedMemory(), i, i);
}
}

/**
Expand Down
Loading
Loading