1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-26 12:49:21 +00:00

Implemented support for controlling output file extension using #pragma extension("xxx"), property "extension" in the target platform file or command-line option -oext. Closes #446

This commit is contained in:
jespergravgaard 2020-05-17 23:33:18 +02:00
parent c2993e4d82
commit 2faaae5d93
43 changed files with 2453 additions and 2319 deletions

View File

@ -45,16 +45,19 @@ public class KickC implements Callable<Integer> {
@CommandLine.Option(names = {"-odir"}, description = "Path to the output folder, where the compiler places all generated files. By default the folder of the output file is used.")
private Path outputDir = null;
@CommandLine.Option(names = {"-a"}, description = "Assemble the output file using KickAssembler. Produces a .prg file.")
@CommandLine.Option(names = {"-oext"}, description = "Override the output file extension. The default is specified in the target platform / linker configuration.")
private String outputExtension = null;
@CommandLine.Option(names = {"-a"}, description = "Assemble the output file using KickAssembler. Produces a binary file.")
private boolean assemble = false;
@CommandLine.Option(names = {"-e"}, description = "Execute the assembled prg file using VICE. Implicitly assembles the output.")
@CommandLine.Option(names = {"-e"}, description = "Execute the assembled binary file using an appropriate emulator. The emulator chosen depends on the target platform.")
private boolean execute = false;
@CommandLine.Option(names = {"-emu"}, description = "Execute the assembled program file by passing it to the named emulator. Implicitly assembles the output.")
private String emulator = null;
@CommandLine.Option(names = {"-d"}, description = "Debug the assembled prg file using C64Debugger. Implicitly assembles the output.")
@CommandLine.Option(names = {"-d"}, description = "Debug the assembled binary file using C64Debugger. Implicitly assembles the output.")
private boolean debug = false;
@CommandLine.Option(names = {"-D"}, parameterConsumer = DefineConsumer.class, description = "Define macro to value (1 if no value given).")
@ -243,6 +246,11 @@ public class KickC implements Callable<Integer> {
program.getTargetPlatform().setLinkScriptFile(SourceLoader.loadFile(linkScript, currentPath, program.getTargetPlatformPaths()));
}
// Update output file extension
if(outputExtension != null) {
program.getTargetPlatform().setOutFileExtension(outputExtension);
}
// Update CPU
if(cpu != null) {
TargetCpu targetCpu = TargetCpu.getTargetCpu(cpu, false);
@ -400,8 +408,8 @@ public class KickC implements Callable<Integer> {
}
// Assemble the asm-file if instructed
String prgFileName = outputFileNameBase + ".prg";
Path prgPath = outputDir.resolve(prgFileName);
String outputBinaryFileName = outputFileNameBase + "." + program.getTargetPlatform().getOutFileExtension();
Path outputBinaryFilePath = outputDir.resolve(outputBinaryFileName);
// Find emulator - if set by #pragma
if(emulator == null) {
@ -415,10 +423,21 @@ public class KickC implements Callable<Integer> {
if(assemble || emulator != null) {
Path kasmLogPath = outputDir.resolve(outputFileNameBase + ".klog");
System.out.println("Assembling to " + prgPath.toString());
String[] assembleCommand = {asmPath.toString(), "-log", kasmLogPath.toString(), "-o", prgPath.toString(), "-vicesymbols", "-showmem", "-debugdump"};
System.out.println("Assembling to " + outputBinaryFilePath.toString());
List<String> assembleCommand = new ArrayList<>();
assembleCommand.add(asmPath.toString());
assembleCommand.add("-log");
assembleCommand.add(kasmLogPath.toString());
final String linkScriptBody = program.getTargetPlatform().getLinkScriptBody();
if(!linkScriptBody.contains(".file") && !linkScriptBody.contains(".disk")) {
assembleCommand.add("-o");
assembleCommand.add(outputBinaryFilePath.toString());
}
assembleCommand.add("-vicesymbols");
assembleCommand.add("-showmem");
assembleCommand.add("-debugdump");
if(verbose) {
System.out.print("Assembling command: java -jar kickassembler-5.9.jar ");
System.out.print("Assembling command: java -jar KickAss.jar ");
for(String cmd : assembleCommand) {
System.out.print(cmd + " ");
}
@ -431,7 +450,7 @@ public class KickC implements Callable<Integer> {
int kasmResult = -1;
try {
CharToPetsciiConverter.setCurrentEncoding("screencode_mixed");
kasmResult = KickAssembler.main2(assembleCommand);
kasmResult = KickAssembler.main2(assembleCommand.toArray(new String[0]));
} catch(Throwable e) {
throw new CompileError("KickAssembling file failed! ", e);
} finally {
@ -442,7 +461,7 @@ public class KickC implements Callable<Integer> {
}
}
// Execute the prg-file if instructed
// Execute the binary file if instructed
if(emulator != null) {
// Find commandline options for the emulator
@ -458,8 +477,8 @@ public class KickC implements Callable<Integer> {
emuOptions = "-moncommands " + viceSymbolsPath.toAbsolutePath().toString() + " ";
}
System.out.println("Executing " + prgPath + " using " + emulator);
String executeCommand = emulator + " " + emuOptions + prgPath.toAbsolutePath().toString();
System.out.println("Executing " + outputBinaryFilePath + " using " + emulator);
String executeCommand = emulator + " " + emuOptions + outputBinaryFilePath.toAbsolutePath().toString();
if(verbose) {
System.out.println("Executing command: " + executeCommand);
}

View File

@ -1,6 +1,8 @@
package dk.camelot64.kickc.model;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Map;
/**
@ -26,6 +28,9 @@ public class TargetPlatform {
/** The command to use for starting an emulator. */
private String emulatorCommand;
/** The output file extension. */
private String outFileExtension;
/** A number of preprocessor macro defines. */
private Map<String, String> defines = null;
@ -57,6 +62,19 @@ public class TargetPlatform {
this.linkScriptFile = linkScriptFile;
}
public String getLinkScriptBody() {
final File linkScriptFile = getLinkScriptFile();
if(linkScriptFile == null)
throw new InternalError("No link script found! Cannot link program.");
String linkScriptBody = null;
try {
linkScriptBody = new String(Files.readAllBytes(linkScriptFile.toPath()));
} catch(IOException e) {
throw new CompileError("Cannot read link script file " + linkScriptFile.getAbsolutePath(), e);
}
return linkScriptBody;
}
public String getEmulatorCommand() {
return emulatorCommand;
}
@ -65,6 +83,14 @@ public class TargetPlatform {
this.emulatorCommand = emulatorCommand;
}
public String getOutFileExtension() {
return outFileExtension;
}
public void setOutFileExtension(String outFileExtension) {
this.outFileExtension = outFileExtension;
}
public Map<String, String> getDefines() {
return defines;
}

View File

@ -34,25 +34,38 @@ public class CTargetPlatformParser {
final JsonReader jsonReader = Json.createReader(new BufferedInputStream(new FileInputStream(platformFile)));
final JsonObject platformJson = jsonReader.readObject();
TargetPlatform targetPlatform = new TargetPlatform(platformName);
final String cpuName = platformJson.getString("cpu", null);
if(cpuName != null)
targetPlatform.setCpu(TargetCpu.getTargetCpu(cpuName, false));
final String linkScriptName = platformJson.getString("link", null);
if(linkScriptName != null)
targetPlatform.setLinkScriptFile(SourceLoader.loadFile(linkScriptName, currentFolder, platformSearchPaths));
final String emulatorCommand = platformJson.getString("emulator", null);
if(emulatorCommand != null)
targetPlatform.setEmulatorCommand(emulatorCommand);
final JsonObject defines = platformJson.getJsonObject("defines");
if(defines != null) {
final Set<String> macroNames = defines.keySet();
final LinkedHashMap<String, String> macros = new LinkedHashMap<>();
for(String macroName : macroNames) {
final JsonValue jsonValue = defines.get(macroName);
final String macroBody = jsonValue.toString();
macros.put(macroName, macroBody);
{
final String cpuName = platformJson.getString("cpu", null);
if(cpuName != null)
targetPlatform.setCpu(TargetCpu.getTargetCpu(cpuName, false));
}
{
final String linkScriptName = platformJson.getString("link", null);
if(linkScriptName != null)
targetPlatform.setLinkScriptFile(SourceLoader.loadFile(linkScriptName, currentFolder, platformSearchPaths));
}
{
final String emulatorCommand = platformJson.getString("emulator", null);
if(emulatorCommand != null)
targetPlatform.setEmulatorCommand(emulatorCommand);
}
{
final String outExtension = platformJson.getString("extension", null);
if(outExtension != null)
targetPlatform.setOutFileExtension(outExtension);
}
{
final JsonObject defines = platformJson.getJsonObject("defines");
if(defines != null) {
final Set<String> macroNames = defines.keySet();
final LinkedHashMap<String, String> macros = new LinkedHashMap<>();
for(String macroName : macroNames) {
final JsonValue jsonValue = defines.get(macroName);
final String macroBody = jsonValue.toString();
macros.put(macroName, macroBody);
}
targetPlatform.setDefines(macros);
}
targetPlatform.setDefines(macros);
}
return targetPlatform;
} catch(CompileError | IOException | JsonParsingException e) {

View File

@ -66,6 +66,7 @@ RESERVE:'reserve' ;
PC:'pc';
TARGET:'target';
LINK:'link';
EXTENSION:'extension';
EMULATOR:'emulator';
CPU:'cpu';
CODESEG:'code_seg';

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -41,125 +41,126 @@ RESERVE=40
PC=41
TARGET=42
LINK=43
EMULATOR=44
CPU=45
CODESEG=46
DATASEG=47
ENCODING=48
CONST=49
EXTERN=50
EXPORT=51
ALIGN=52
INLINE=53
VOLATILE=54
STATIC=55
INTERRUPT=56
REGISTER=57
ADDRESS=58
ADDRESS_ZEROPAGE=59
ADDRESS_MAINMEM=60
FORM_SSA=61
FORM_MA=62
INTRINSIC=63
CALLING=64
CALLINGCONVENTION=65
VARMODEL=66
IF=67
ELSE=68
WHILE=69
DO=70
FOR=71
SWITCH=72
RETURN=73
BREAK=74
CONTINUE=75
ASM=76
DEFAULT=77
CASE=78
STRUCT=79
ENUM=80
SIZEOF=81
TYPEID=82
DEFINED=83
KICKASM=84
RESOURCE=85
USES=86
CLOBBERS=87
BYTES=88
CYCLES=89
LOGIC_NOT=90
SIGNEDNESS=91
SIMPLETYPE=92
BOOLEAN=93
KICKASM_BODY=94
IMPORT=95
INCLUDE=96
PRAGMA=97
DEFINE=98
DEFINE_CONTINUE=99
UNDEF=100
IFDEF=101
IFNDEF=102
IFIF=103
ELIF=104
IFELSE=105
ENDIF=106
NUMBER=107
NUMFLOAT=108
BINFLOAT=109
DECFLOAT=110
HEXFLOAT=111
NUMINT=112
BININTEGER=113
DECINTEGER=114
HEXINTEGER=115
NAME=116
STRING=117
CHAR=118
WS=119
COMMENT_LINE=120
COMMENT_BLOCK=121
ASM_BYTE=122
ASM_MNEMONIC=123
ASM_IMM=124
ASM_COLON=125
ASM_COMMA=126
ASM_PAR_BEGIN=127
ASM_PAR_END=128
ASM_BRACKET_BEGIN=129
ASM_BRACKET_END=130
ASM_DOT=131
ASM_SHIFT_LEFT=132
ASM_SHIFT_RIGHT=133
ASM_PLUS=134
ASM_MINUS=135
ASM_LESS_THAN=136
ASM_GREATER_THAN=137
ASM_MULTIPLY=138
ASM_DIVIDE=139
ASM_CURLY_BEGIN=140
ASM_CURLY_END=141
ASM_NUMBER=142
ASM_NUMFLOAT=143
ASM_BINFLOAT=144
ASM_DECFLOAT=145
ASM_HEXFLOAT=146
ASM_NUMINT=147
ASM_BININTEGER=148
ASM_DECINTEGER=149
ASM_HEXINTEGER=150
ASM_CHAR=151
ASM_MULTI_REL=152
ASM_MULTI_NAME=153
ASM_NAME=154
ASM_WS=155
ASM_COMMENT_LINE=156
ASM_COMMENT_BLOCK=157
IMPORT_SYSTEMFILE=158
IMPORT_LOCALFILE=159
IMPORT_WS=160
IMPORT_COMMENT_LINE=161
IMPORT_COMMENT_BLOCK=162
EXTENSION=44
EMULATOR=45
CPU=46
CODESEG=47
DATASEG=48
ENCODING=49
CONST=50
EXTERN=51
EXPORT=52
ALIGN=53
INLINE=54
VOLATILE=55
STATIC=56
INTERRUPT=57
REGISTER=58
ADDRESS=59
ADDRESS_ZEROPAGE=60
ADDRESS_MAINMEM=61
FORM_SSA=62
FORM_MA=63
INTRINSIC=64
CALLING=65
CALLINGCONVENTION=66
VARMODEL=67
IF=68
ELSE=69
WHILE=70
DO=71
FOR=72
SWITCH=73
RETURN=74
BREAK=75
CONTINUE=76
ASM=77
DEFAULT=78
CASE=79
STRUCT=80
ENUM=81
SIZEOF=82
TYPEID=83
DEFINED=84
KICKASM=85
RESOURCE=86
USES=87
CLOBBERS=88
BYTES=89
CYCLES=90
LOGIC_NOT=91
SIGNEDNESS=92
SIMPLETYPE=93
BOOLEAN=94
KICKASM_BODY=95
IMPORT=96
INCLUDE=97
PRAGMA=98
DEFINE=99
DEFINE_CONTINUE=100
UNDEF=101
IFDEF=102
IFNDEF=103
IFIF=104
ELIF=105
IFELSE=106
ENDIF=107
NUMBER=108
NUMFLOAT=109
BINFLOAT=110
DECFLOAT=111
HEXFLOAT=112
NUMINT=113
BININTEGER=114
DECINTEGER=115
HEXINTEGER=116
NAME=117
STRING=118
CHAR=119
WS=120
COMMENT_LINE=121
COMMENT_BLOCK=122
ASM_BYTE=123
ASM_MNEMONIC=124
ASM_IMM=125
ASM_COLON=126
ASM_COMMA=127
ASM_PAR_BEGIN=128
ASM_PAR_END=129
ASM_BRACKET_BEGIN=130
ASM_BRACKET_END=131
ASM_DOT=132
ASM_SHIFT_LEFT=133
ASM_SHIFT_RIGHT=134
ASM_PLUS=135
ASM_MINUS=136
ASM_LESS_THAN=137
ASM_GREATER_THAN=138
ASM_MULTIPLY=139
ASM_DIVIDE=140
ASM_CURLY_BEGIN=141
ASM_CURLY_END=142
ASM_NUMBER=143
ASM_NUMFLOAT=144
ASM_BINFLOAT=145
ASM_DECFLOAT=146
ASM_HEXFLOAT=147
ASM_NUMINT=148
ASM_BININTEGER=149
ASM_DECINTEGER=150
ASM_HEXINTEGER=151
ASM_CHAR=152
ASM_MULTI_REL=153
ASM_MULTI_NAME=154
ASM_NAME=155
ASM_WS=156
ASM_COMMENT_LINE=157
ASM_COMMENT_BLOCK=158
IMPORT_SYSTEMFILE=159
IMPORT_LOCALFILE=160
IMPORT_WS=161
IMPORT_COMMENT_LINE=162
IMPORT_COMMENT_BLOCK=163
';'=8
'..'=11
'...'=12
@ -184,62 +185,63 @@ IMPORT_COMMENT_BLOCK=162
'pc'=41
'target'=42
'link'=43
'emulator'=44
'cpu'=45
'code_seg'=46
'data_seg'=47
'encoding'=48
'const'=49
'extern'=50
'export'=51
'align'=52
'inline'=53
'volatile'=54
'static'=55
'interrupt'=56
'register'=57
'__address'=58
'__zp'=59
'__mem'=60
'__ssa'=61
'__ma'=62
'__intrinsic'=63
'calling'=64
'var_model'=66
'if'=67
'else'=68
'while'=69
'do'=70
'for'=71
'switch'=72
'return'=73
'break'=74
'continue'=75
'asm'=76
'default'=77
'case'=78
'struct'=79
'enum'=80
'sizeof'=81
'typeid'=82
'defined'=83
'kickasm'=84
'resource'=85
'uses'=86
'clobbers'=87
'bytes'=88
'cycles'=89
'!'=90
'#import'=95
'#include'=96
'#pragma'=97
'#define'=98
'#undef'=100
'#ifdef'=101
'#ifndef'=102
'#if'=103
'#elif'=104
'#else'=105
'#endif'=106
'.byte'=122
'#'=124
'extension'=44
'emulator'=45
'cpu'=46
'code_seg'=47
'data_seg'=48
'encoding'=49
'const'=50
'extern'=51
'export'=52
'align'=53
'inline'=54
'volatile'=55
'static'=56
'interrupt'=57
'register'=58
'__address'=59
'__zp'=60
'__mem'=61
'__ssa'=62
'__ma'=63
'__intrinsic'=64
'calling'=65
'var_model'=67
'if'=68
'else'=69
'while'=70
'do'=71
'for'=72
'switch'=73
'return'=74
'break'=75
'continue'=76
'asm'=77
'default'=78
'case'=79
'struct'=80
'enum'=81
'sizeof'=82
'typeid'=83
'defined'=84
'kickasm'=85
'resource'=86
'uses'=87
'clobbers'=88
'bytes'=89
'cycles'=90
'!'=91
'#import'=96
'#include'=97
'#pragma'=98
'#define'=99
'#undef'=101
'#ifdef'=102
'#ifndef'=103
'#if'=104
'#elif'=105
'#else'=106
'#endif'=107
'.byte'=123
'#'=125

View File

@ -149,6 +149,7 @@ globalDirective
: (PRAGMA TARGET) PAR_BEGIN NAME PAR_END #globalDirectivePlatform
| (PRAGMA CPU) PAR_BEGIN NAME PAR_END #globalDirectiveCpu
| (PRAGMA LINK) PAR_BEGIN STRING PAR_END #globalDirectiveLinkScript
| (PRAGMA EXTENSION) PAR_BEGIN STRING PAR_END #globalDirectiveExtension
| (PRAGMA EMULATOR) PAR_BEGIN STRING PAR_END #globalDirectiveEmulator
| (PRAGMA RESERVE) PAR_BEGIN NUMBER ( COMMA NUMBER )* PAR_END #globalDirectiveReserve
| (PRAGMA PC) PAR_BEGIN NUMBER PAR_END #globalDirectivePc

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -41,125 +41,126 @@ RESERVE=40
PC=41
TARGET=42
LINK=43
EMULATOR=44
CPU=45
CODESEG=46
DATASEG=47
ENCODING=48
CONST=49
EXTERN=50
EXPORT=51
ALIGN=52
INLINE=53
VOLATILE=54
STATIC=55
INTERRUPT=56
REGISTER=57
ADDRESS=58
ADDRESS_ZEROPAGE=59
ADDRESS_MAINMEM=60
FORM_SSA=61
FORM_MA=62
INTRINSIC=63
CALLING=64
CALLINGCONVENTION=65
VARMODEL=66
IF=67
ELSE=68
WHILE=69
DO=70
FOR=71
SWITCH=72
RETURN=73
BREAK=74
CONTINUE=75
ASM=76
DEFAULT=77
CASE=78
STRUCT=79
ENUM=80
SIZEOF=81
TYPEID=82
DEFINED=83
KICKASM=84
RESOURCE=85
USES=86
CLOBBERS=87
BYTES=88
CYCLES=89
LOGIC_NOT=90
SIGNEDNESS=91
SIMPLETYPE=92
BOOLEAN=93
KICKASM_BODY=94
IMPORT=95
INCLUDE=96
PRAGMA=97
DEFINE=98
DEFINE_CONTINUE=99
UNDEF=100
IFDEF=101
IFNDEF=102
IFIF=103
ELIF=104
IFELSE=105
ENDIF=106
NUMBER=107
NUMFLOAT=108
BINFLOAT=109
DECFLOAT=110
HEXFLOAT=111
NUMINT=112
BININTEGER=113
DECINTEGER=114
HEXINTEGER=115
NAME=116
STRING=117
CHAR=118
WS=119
COMMENT_LINE=120
COMMENT_BLOCK=121
ASM_BYTE=122
ASM_MNEMONIC=123
ASM_IMM=124
ASM_COLON=125
ASM_COMMA=126
ASM_PAR_BEGIN=127
ASM_PAR_END=128
ASM_BRACKET_BEGIN=129
ASM_BRACKET_END=130
ASM_DOT=131
ASM_SHIFT_LEFT=132
ASM_SHIFT_RIGHT=133
ASM_PLUS=134
ASM_MINUS=135
ASM_LESS_THAN=136
ASM_GREATER_THAN=137
ASM_MULTIPLY=138
ASM_DIVIDE=139
ASM_CURLY_BEGIN=140
ASM_CURLY_END=141
ASM_NUMBER=142
ASM_NUMFLOAT=143
ASM_BINFLOAT=144
ASM_DECFLOAT=145
ASM_HEXFLOAT=146
ASM_NUMINT=147
ASM_BININTEGER=148
ASM_DECINTEGER=149
ASM_HEXINTEGER=150
ASM_CHAR=151
ASM_MULTI_REL=152
ASM_MULTI_NAME=153
ASM_NAME=154
ASM_WS=155
ASM_COMMENT_LINE=156
ASM_COMMENT_BLOCK=157
IMPORT_SYSTEMFILE=158
IMPORT_LOCALFILE=159
IMPORT_WS=160
IMPORT_COMMENT_LINE=161
IMPORT_COMMENT_BLOCK=162
EXTENSION=44
EMULATOR=45
CPU=46
CODESEG=47
DATASEG=48
ENCODING=49
CONST=50
EXTERN=51
EXPORT=52
ALIGN=53
INLINE=54
VOLATILE=55
STATIC=56
INTERRUPT=57
REGISTER=58
ADDRESS=59
ADDRESS_ZEROPAGE=60
ADDRESS_MAINMEM=61
FORM_SSA=62
FORM_MA=63
INTRINSIC=64
CALLING=65
CALLINGCONVENTION=66
VARMODEL=67
IF=68
ELSE=69
WHILE=70
DO=71
FOR=72
SWITCH=73
RETURN=74
BREAK=75
CONTINUE=76
ASM=77
DEFAULT=78
CASE=79
STRUCT=80
ENUM=81
SIZEOF=82
TYPEID=83
DEFINED=84
KICKASM=85
RESOURCE=86
USES=87
CLOBBERS=88
BYTES=89
CYCLES=90
LOGIC_NOT=91
SIGNEDNESS=92
SIMPLETYPE=93
BOOLEAN=94
KICKASM_BODY=95
IMPORT=96
INCLUDE=97
PRAGMA=98
DEFINE=99
DEFINE_CONTINUE=100
UNDEF=101
IFDEF=102
IFNDEF=103
IFIF=104
ELIF=105
IFELSE=106
ENDIF=107
NUMBER=108
NUMFLOAT=109
BINFLOAT=110
DECFLOAT=111
HEXFLOAT=112
NUMINT=113
BININTEGER=114
DECINTEGER=115
HEXINTEGER=116
NAME=117
STRING=118
CHAR=119
WS=120
COMMENT_LINE=121
COMMENT_BLOCK=122
ASM_BYTE=123
ASM_MNEMONIC=124
ASM_IMM=125
ASM_COLON=126
ASM_COMMA=127
ASM_PAR_BEGIN=128
ASM_PAR_END=129
ASM_BRACKET_BEGIN=130
ASM_BRACKET_END=131
ASM_DOT=132
ASM_SHIFT_LEFT=133
ASM_SHIFT_RIGHT=134
ASM_PLUS=135
ASM_MINUS=136
ASM_LESS_THAN=137
ASM_GREATER_THAN=138
ASM_MULTIPLY=139
ASM_DIVIDE=140
ASM_CURLY_BEGIN=141
ASM_CURLY_END=142
ASM_NUMBER=143
ASM_NUMFLOAT=144
ASM_BINFLOAT=145
ASM_DECFLOAT=146
ASM_HEXFLOAT=147
ASM_NUMINT=148
ASM_BININTEGER=149
ASM_DECINTEGER=150
ASM_HEXINTEGER=151
ASM_CHAR=152
ASM_MULTI_REL=153
ASM_MULTI_NAME=154
ASM_NAME=155
ASM_WS=156
ASM_COMMENT_LINE=157
ASM_COMMENT_BLOCK=158
IMPORT_SYSTEMFILE=159
IMPORT_LOCALFILE=160
IMPORT_WS=161
IMPORT_COMMENT_LINE=162
IMPORT_COMMENT_BLOCK=163
';'=8
'..'=11
'...'=12
@ -184,62 +185,63 @@ IMPORT_COMMENT_BLOCK=162
'pc'=41
'target'=42
'link'=43
'emulator'=44
'cpu'=45
'code_seg'=46
'data_seg'=47
'encoding'=48
'const'=49
'extern'=50
'export'=51
'align'=52
'inline'=53
'volatile'=54
'static'=55
'interrupt'=56
'register'=57
'__address'=58
'__zp'=59
'__mem'=60
'__ssa'=61
'__ma'=62
'__intrinsic'=63
'calling'=64
'var_model'=66
'if'=67
'else'=68
'while'=69
'do'=70
'for'=71
'switch'=72
'return'=73
'break'=74
'continue'=75
'asm'=76
'default'=77
'case'=78
'struct'=79
'enum'=80
'sizeof'=81
'typeid'=82
'defined'=83
'kickasm'=84
'resource'=85
'uses'=86
'clobbers'=87
'bytes'=88
'cycles'=89
'!'=90
'#import'=95
'#include'=96
'#pragma'=97
'#define'=98
'#undef'=100
'#ifdef'=101
'#ifndef'=102
'#if'=103
'#elif'=104
'#else'=105
'#endif'=106
'.byte'=122
'#'=124
'extension'=44
'emulator'=45
'cpu'=46
'code_seg'=47
'data_seg'=48
'encoding'=49
'const'=50
'extern'=51
'export'=52
'align'=53
'inline'=54
'volatile'=55
'static'=56
'interrupt'=57
'register'=58
'__address'=59
'__zp'=60
'__mem'=61
'__ssa'=62
'__ma'=63
'__intrinsic'=64
'calling'=65
'var_model'=67
'if'=68
'else'=69
'while'=70
'do'=71
'for'=72
'switch'=73
'return'=74
'break'=75
'continue'=76
'asm'=77
'default'=78
'case'=79
'struct'=80
'enum'=81
'sizeof'=82
'typeid'=83
'defined'=84
'kickasm'=85
'resource'=86
'uses'=87
'clobbers'=88
'bytes'=89
'cycles'=90
'!'=91
'#import'=96
'#include'=97
'#pragma'=98
'#define'=99
'#undef'=101
'#ifdef'=102
'#ifndef'=103
'#if'=104
'#elif'=105
'#else'=106
'#endif'=107
'.byte'=123
'#'=125

View File

@ -517,30 +517,6 @@ public class KickCParserBaseListener implements KickCParserListener {
* <p>The default implementation does nothing.</p>
*/
@Override public void exitParameterDeclList(KickCParser.ParameterDeclListContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx) { }
/**
* {@inheritDoc}
*
@ -577,6 +553,18 @@ public class KickCParserBaseListener implements KickCParserListener {
* <p>The default implementation does nothing.</p>
*/
@Override public void exitGlobalDirectiveLinkScript(KickCParser.GlobalDirectiveLinkScriptContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterGlobalDirectiveExtension(KickCParser.GlobalDirectiveExtensionContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitGlobalDirectiveExtension(KickCParser.GlobalDirectiveExtensionContext ctx) { }
/**
* {@inheritDoc}
*
@ -589,6 +577,30 @@ public class KickCParserBaseListener implements KickCParserListener {
* <p>The default implementation does nothing.</p>
*/
@Override public void exitGlobalDirectiveEmulator(KickCParser.GlobalDirectiveEmulatorContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx) { }
/**
* {@inheritDoc}
*

View File

@ -307,20 +307,6 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitParameterDeclList(KickCParser.ParameterDeclListContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
@ -342,6 +328,13 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitGlobalDirectiveLinkScript(KickCParser.GlobalDirectiveLinkScriptContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitGlobalDirectiveExtension(KickCParser.GlobalDirectiveExtensionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
@ -349,6 +342,20 @@ public class KickCParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> imple
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitGlobalDirectiveEmulator(KickCParser.GlobalDirectiveEmulatorContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*

View File

@ -471,30 +471,6 @@ public interface KickCParserListener extends ParseTreeListener {
* @param ctx the parse tree
*/
void exitParameterDeclList(KickCParser.ParameterDeclListContext ctx);
/**
* Enter a parse tree produced by the {@code globalDirectiveReserve}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
*/
void enterGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx);
/**
* Exit a parse tree produced by the {@code globalDirectiveReserve}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
*/
void exitGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx);
/**
* Enter a parse tree produced by the {@code globalDirectivePc}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
*/
void enterGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx);
/**
* Exit a parse tree produced by the {@code globalDirectivePc}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
*/
void exitGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx);
/**
* Enter a parse tree produced by the {@code globalDirectivePlatform}
* labeled alternative in {@link KickCParser#globalDirective}.
@ -531,6 +507,18 @@ public interface KickCParserListener extends ParseTreeListener {
* @param ctx the parse tree
*/
void exitGlobalDirectiveLinkScript(KickCParser.GlobalDirectiveLinkScriptContext ctx);
/**
* Enter a parse tree produced by the {@code globalDirectiveExtension}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
*/
void enterGlobalDirectiveExtension(KickCParser.GlobalDirectiveExtensionContext ctx);
/**
* Exit a parse tree produced by the {@code globalDirectiveExtension}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
*/
void exitGlobalDirectiveExtension(KickCParser.GlobalDirectiveExtensionContext ctx);
/**
* Enter a parse tree produced by the {@code globalDirectiveEmulator}
* labeled alternative in {@link KickCParser#globalDirective}.
@ -543,6 +531,30 @@ public interface KickCParserListener extends ParseTreeListener {
* @param ctx the parse tree
*/
void exitGlobalDirectiveEmulator(KickCParser.GlobalDirectiveEmulatorContext ctx);
/**
* Enter a parse tree produced by the {@code globalDirectiveReserve}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
*/
void enterGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx);
/**
* Exit a parse tree produced by the {@code globalDirectiveReserve}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
*/
void exitGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx);
/**
* Enter a parse tree produced by the {@code globalDirectivePc}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
*/
void enterGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx);
/**
* Exit a parse tree produced by the {@code globalDirectivePc}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
*/
void exitGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx);
/**
* Enter a parse tree produced by the {@code globalDirectiveCodeSeg}
* labeled alternative in {@link KickCParser#globalDirective}.

View File

@ -285,20 +285,6 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
* @return the visitor result
*/
T visitParameterDeclList(KickCParser.ParameterDeclListContext ctx);
/**
* Visit a parse tree produced by the {@code globalDirectiveReserve}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx);
/**
* Visit a parse tree produced by the {@code globalDirectivePc}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx);
/**
* Visit a parse tree produced by the {@code globalDirectivePlatform}
* labeled alternative in {@link KickCParser#globalDirective}.
@ -320,6 +306,13 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
* @return the visitor result
*/
T visitGlobalDirectiveLinkScript(KickCParser.GlobalDirectiveLinkScriptContext ctx);
/**
* Visit a parse tree produced by the {@code globalDirectiveExtension}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitGlobalDirectiveExtension(KickCParser.GlobalDirectiveExtensionContext ctx);
/**
* Visit a parse tree produced by the {@code globalDirectiveEmulator}
* labeled alternative in {@link KickCParser#globalDirective}.
@ -327,6 +320,20 @@ public interface KickCParserVisitor<T> extends ParseTreeVisitor<T> {
* @return the visitor result
*/
T visitGlobalDirectiveEmulator(KickCParser.GlobalDirectiveEmulatorContext ctx);
/**
* Visit a parse tree produced by the {@code globalDirectiveReserve}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitGlobalDirectiveReserve(KickCParser.GlobalDirectiveReserveContext ctx);
/**
* Visit a parse tree produced by the {@code globalDirectivePc}
* labeled alternative in {@link KickCParser#globalDirective}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitGlobalDirectivePc(KickCParser.GlobalDirectivePcContext ctx);
/**
* Visit a parse tree produced by the {@code globalDirectiveCodeSeg}
* labeled alternative in {@link KickCParser#globalDirective}.

View File

@ -137,6 +137,14 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return null;
}
@Override
public Object visitGlobalDirectiveExtension(KickCParser.GlobalDirectiveExtensionContext ctx) {
String extension = ctx.STRING().getText();
extension = extension.substring(1, extension.length() - 1);
program.getTargetPlatform().setOutFileExtension(extension);
return null;
}
@Override
public Object visitGlobalDirectiveEmulator(KickCParser.GlobalDirectiveEmulatorContext ctx) {
String emuName = ctx.STRING().getText();

View File

@ -16,8 +16,6 @@ import dk.camelot64.kickc.passes.calcs.PassNCalcVariableReferenceInfos;
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
/**
@ -82,16 +80,9 @@ public class Pass4CodeGeneration {
asm.startChunk(currentScope, null, "File Comments");
generateComments(asm, program.getFileComments());
asm.startChunk(currentScope, null, "Upstart");
final File linkScriptFile = program.getTargetPlatform().getLinkScriptFile();
if(linkScriptFile == null)
throw new InternalError("No link script found! Cannot link program.");
String linkScriptBody = null;
try {
linkScriptBody = new String(Files.readAllBytes(linkScriptFile.toPath()));
} catch(IOException e) {
throw new CompileError("Cannot read link script file " + linkScriptFile.getAbsolutePath(), e);
}
String outputFileName = new File(program.getPrimaryFileName()).getName();
final TargetPlatform targetPlatform = program.getTargetPlatform();
String linkScriptBody = targetPlatform.getLinkScriptBody();
String outputFileName = new File(program.getPrimaryFileName()).getName() + "." + program.getTargetPlatform().getOutFileExtension();
linkScriptBody = linkScriptBody.replace("%O", outputFileName);
linkScriptBody = linkScriptBody.replace("%_O", outputFileName.toLowerCase());
linkScriptBody = linkScriptBody.replace("%^O", outputFileName.toUpperCase());

View File

@ -79,13 +79,13 @@ public class Pass5FixLongBranches extends Pass5AsmOptimization {
// Compile using KickAssembler - catch the output in a String
File asmFile = getTmpFile(outputFileName, ".asm");
File asmPrgFile = getTmpFile(outputFileName, ".prg");
File binaryFile = getTmpFile(outputFileName, "."+getProgram().getTargetPlatform().getOutFileExtension());
ByteArrayOutputStream kickAssOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(kickAssOut));
int asmRes = -1;
try {
CharToPetsciiConverter.setCurrentEncoding("screencode_mixed");
asmRes = KickAssembler.main2(new String[]{asmFile.getAbsolutePath(), "-o", asmPrgFile.getAbsolutePath()});
asmRes = KickAssembler.main2(new String[]{asmFile.getAbsolutePath(), "-o", binaryFile.getAbsolutePath()});
} catch(Throwable e) {
if(e instanceof AssertionError && e.getMessage().contains("Invalid number of bytes in memblock!")) {
throw new CompileError("Error! KickAssembler failed due to assertion. Please run java without -ea / -enableassertions.", e);

View File

@ -1,4 +1,5 @@
{
"extension": "prg",
"link": "asm6502.ld",
"cpu": "MOS6502X",
"emulator": "x64sc"

View File

@ -1,5 +1,5 @@
// Atari 2600 VCS 4K ROM
.file [name="%O.prg", type="bin", segments="Code, Vectors"]
.file [name="%O", type="bin", segments="Code, Vectors"]
.segmentdef Code [start=$f800,min=$f800,max=$fff9]
.segmentdef Data [start=$80,max=$ff, virtual]
.segmentdef Vectors [start=$fffa,max=$ffff]

View File

@ -1,4 +1,5 @@
{
"extension": "a26",
"link": "atari2600.ld",
"cpu": "MOS6502X",
"emulator": "stella",

View File

@ -1,4 +1,4 @@
.file [name="%O.prg", type="prg", segments="Program"]
.file [name="%O", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$080d]

View File

@ -1,4 +1,5 @@
{
"extension": "prg",
"link": "c64.ld",
"cpu": "MOS6502X",
"emulator": "x64sc",

View File

@ -1,4 +1,5 @@
{
"extension": "prg",
"link": "c64basic.ld",
"cpu": "MOS6502X",
"emulator": "x64sc",

View File

@ -1,4 +1,4 @@
.file [name="%O.prg", type="prg", segments="Program"]
.file [name="%O", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$1001]
.segmentdef Code [start=$100d]

View File

@ -1,4 +1,5 @@
{
"extension": "prg",
"link": "plus4.ld",
"cpu": "MOS6502X",
"emulator": "xplus4",

View File

@ -1,4 +1,5 @@
{
"extension": "prg",
"link": "plus4basic.ld",
"cpu": "MOS6502X",
"emulator": "xplus4",

View File

@ -1,4 +1,4 @@
.file [name="%O.prg", type="prg", segments="Program"]
.file [name="%O", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$1001]
.segmentdef Code [start=$100e]

View File

@ -1,4 +1,5 @@
{
"extension": "prg",
"link": "vic20.ld",
"cpu": "MOS6502X",
"emulator": "xvic",

View File

@ -1,4 +1,5 @@
{
"extension": "prg",
"link": "vic20basic.ld",
"cpu": "MOS6502X",
"emulator": "xvic",

View File

@ -12,10 +12,9 @@ void main() {
// here we generate the signal that tells the TV to move the beam to the top of
// the screen so we can start the next frame of video.
// The Sync Signal must be on for 3 scanlines.
TIA->WSYNC = 2; // Wait for SYNC (halts CPU until end of scanline)
TIA->VSYNC = 2; // Accumulator D1=1, turns on Vertical Sync signal
TIA->WSYNC = 2; // Wait for Sync - halts CPU until end of 1st scanline of VSYNC
TIA->WSYNC = 2; // wait until end of 2nd scanline of VSYNC
TIA->WSYNC = 0; // Wait for Sync - halts CPU until end of 1st scanline of VSYNC
TIA->WSYNC = 0; // wait until end of 2nd scanline of VSYNC
TIA->WSYNC = 0; // wait until end of 3rd scanline of VSYNC
TIA->VSYNC = 0; // Accumulator D1=0, turns off Vertical Sync signal
@ -40,7 +39,7 @@ void main() {
TIA->WSYNC = 0; // Wait for SYNC (halts CPU until end of scanline)
TIA->VBLANK = 2; // // D1=1 turns image output off
TIA->COLUBK = 0;
for(char i=0;i<07;i++) {
for(char i=0;i<30;i++) {
TIA->WSYNC = 0; // Wait for SYNC (halts CPU until end of scanline)
}

View File

@ -3,6 +3,7 @@
// The functions are placed in the SYSCALLS table surrounded by JMP and NOP
#pragma link("ataritempest.ld")
#pragma extension("bin")
char* const BG_COLOR = 0xc01a;

View File

@ -1,4 +1,4 @@
.file [name="%O.bin", type="bin", segments="AtariTempest"]
.file [name="%O", type="bin", segments="AtariTempest"]
.segmentdef AtariTempest [segments="Code, RomData, Vectors"]
.segmentdef Code [start=$9000, min=$9000, max=$Fff9]
.segmentdef RomData [startAfter="Code", min=$9000, max=$Fff9]

View File

@ -5,6 +5,7 @@
#include <string.h>
#pragma link("xmega65.ld")
#pragma extension("bin")
char* const RASTER = 0xd012;

View File

@ -1,4 +1,4 @@
.file [name="%O.bin", type="bin", segments="XMega65Bin"]
.file [name="%O", type="bin", segments="XMega65Bin"]
.segmentdef XMega65Bin [segments="Syscall, Code, Data, Stack, Zeropage"]
.segmentdef Syscall [start=$8000, max=$81ff]
.segmentdef Code [start=$8200, min=$8200, max=$bdff]

View File

@ -2,6 +2,7 @@
// The kernalload.ld link file creates a D64 disk image containing the executable and the sprite.
// To execute the program succesfully you must mount the D64 disk image and execute the kernalload.PRG program
#pragma link("kernalload.ld")
#pragma extension("d64")
#include <string.h>
#include <c64.h>

View File

@ -1,6 +1,5 @@
// Create a D64 disk containing the program and a sprite file
.file [name="%O.prg", type="prg", segments="Program"]
.disk [filename="%O.d64", name="DISK", id=1] {
.disk [filename="%O", name="DISK", id=1] {
[name="%^O", type="prg", segments="Program"],
[name="SPRITE", type="prg", segments="Sprite"]
}

View File

@ -1,4 +1,4 @@
.file [name="%O.prg", type="prg", segments="Program"]
.file [name="%O", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data, CodeHigh, DataHigh"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$0810]

View File

@ -1,4 +1,4 @@
.file [name="%O.prg", type="prg", segments="Program"]
.file [name="%O", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$0810]

View File

@ -1,7 +1,7 @@
// Minimal Atari 2600 VCS Program
// Source: https://atariage.com/forums/blogs/entry/11109-step-1-generate-a-stable-display/
// Atari 2600 VCS 4K ROM
.file [name="atari2600-min.prg", type="bin", segments="Code, Vectors"]
.file [name="atari2600-min.a26", type="bin", segments="Code, Vectors"]
.segmentdef Code [start=$f800,min=$f800,max=$fff9]
.segmentdef Data [start=$80,max=$ff, virtual]
.segmentdef Vectors [start=$fffa,max=$ffff]
@ -21,24 +21,20 @@ main: {
lda #0
sta col
__b2:
// TIA->WSYNC = 2
// TIA->VSYNC = 2
// Vertical Sync
// here we generate the signal that tells the TV to move the beam to the top of
// the screen so we can start the next frame of video.
// The Sync Signal must be on for 3 scanlines.
lda #2
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// TIA->VSYNC = 2
// Wait for SYNC (halts CPU until end of scanline)
sta TIA
// TIA->WSYNC = 2
// TIA->WSYNC = 0
// Accumulator D1=1, turns on Vertical Sync signal
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// Wait for Sync - halts CPU until end of 1st scanline of VSYNC
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// TIA->WSYNC = 0
// wait until end of 2nd scanline of VSYNC
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// TIA->VSYNC = 0
// wait until end of 3rd scanline of VSYNC
@ -80,15 +76,15 @@ main: {
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK
tax
__b9:
// for(char i=0;i<07;i++)
cpx #7
// for(char i=0;i<30;i++)
cpx #$1e
bcc __b10
jmp __b2
__b10:
// TIA->WSYNC = 0
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// for(char i=0;i<07;i++)
// for(char i=0;i<30;i++)
inx
jmp __b9
__b7:

View File

@ -16,47 +16,46 @@ main::@1: scope:[main] from main main::@9
[5] (byte) col#12 ← phi( main/(byte) 0 main::@9/(byte) col#1 )
to:main::@2
main::@2: scope:[main] from main::@1
[6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2
[7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2
[8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2
[9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2
[10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[11] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0
[6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2
[7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0
to:main::@3
main::@3: scope:[main] from main::@2 main::@4
[12] (byte) main::i#2 ← phi( main::@2/(byte) 0 main::@4/(byte) main::i#1 )
[13] if((byte) main::i#2<(byte) $25) goto main::@4
[11] (byte) main::i#2 ← phi( main::@2/(byte) 0 main::@4/(byte) main::i#1 )
[12] if((byte) main::i#2<(byte) $25) goto main::@4
to:main::@5
main::@5: scope:[main] from main::@3
[14] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0
[15] (byte) main::c#0 ← (byte) col#12
[16] (byte) col#1 ← ++ (byte) col#12
[13] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0
[14] (byte) main::c#0 ← (byte) col#12
[15] (byte) col#1 ← ++ (byte) col#12
to:main::@6
main::@6: scope:[main] from main::@5 main::@7
[17] (byte) main::c#2 ← phi( main::@5/(byte) main::c#0 main::@7/(byte) main::c#1 )
[17] (byte) main::i1#2 ← phi( main::@5/(byte) 0 main::@7/(byte) main::i1#1 )
[18] if((byte) main::i1#2<(byte) $c0) goto main::@7
[16] (byte) main::c#2 ← phi( main::@5/(byte) main::c#0 main::@7/(byte) main::c#1 )
[16] (byte) main::i1#2 ← phi( main::@5/(byte) 0 main::@7/(byte) main::i1#1 )
[17] if((byte) main::i1#2<(byte) $c0) goto main::@7
to:main::@8
main::@8: scope:[main] from main::@6
[19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2
[21] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0
[18] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2
[20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0
to:main::@9
main::@9: scope:[main] from main::@10 main::@8
[22] (byte) main::i2#2 ← phi( main::@10/(byte) main::i2#1 main::@8/(byte) 0 )
[23] if((byte) main::i2#2<(byte) 7) goto main::@10
[21] (byte) main::i2#2 ← phi( main::@10/(byte) main::i2#1 main::@8/(byte) 0 )
[22] if((byte) main::i2#2<(byte) $1e) goto main::@10
to:main::@1
main::@10: scope:[main] from main::@9
[24] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[25] (byte) main::i2#1 ← ++ (byte) main::i2#2
[23] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[24] (byte) main::i2#1 ← ++ (byte) main::i2#2
to:main::@9
main::@7: scope:[main] from main::@6
[26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[27] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) main::c#2
[28] (byte) main::c#1 ← ++ (byte) main::c#2
[29] (byte) main::i1#1 ← ++ (byte) main::i1#2
[25] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) main::c#2
[27] (byte) main::c#1 ← ++ (byte) main::c#2
[28] (byte) main::i1#1 ← ++ (byte) main::i1#2
to:main::@6
main::@4: scope:[main] from main::@3
[30] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[31] (byte) main::i#1 ← ++ (byte) main::i#2
[29] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[30] (byte) main::i#1 ← ++ (byte) main::i#2
to:main::@3

View File

@ -18,10 +18,9 @@ main::@1: scope:[main] from main main::@9
to:main::@return
main::@2: scope:[main] from main::@1
(byte) col#12 ← phi( main::@1/(byte) col#8 )
*((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 2
*((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VSYNC) ← (number) 2
*((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 2
*((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 2
*((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 0
*((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 0
*((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 0
*((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VSYNC) ← (number) 0
(byte) main::i#0 ← (byte) 0
@ -71,7 +70,7 @@ main::@8: scope:[main] from main::@6
main::@9: scope:[main] from main::@10 main::@8
(byte) col#11 ← phi( main::@10/(byte) col#14 main::@8/(byte) col#15 )
(byte) main::i2#2 ← phi( main::@10/(byte) main::i2#1 main::@8/(byte) main::i2#0 )
(bool~) main::$2 ← (byte) main::i2#2 < (number) 7
(bool~) main::$2 ← (byte) main::i2#2 < (number) $1e
if((bool~) main::$2) goto main::@10
to:main::@1
main::@10: scope:[main] from main::@9
@ -230,10 +229,9 @@ SYMBOL TABLE SSA
(byte) main::i2#2
(byte) main::i2#3
Adding number conversion cast (unumber) 2 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 2
Adding number conversion cast (unumber) 2 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VSYNC) ← (number) 2
Adding number conversion cast (unumber) 2 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 2
Adding number conversion cast (unumber) 2 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 2
Adding number conversion cast (unumber) 0 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 0
Adding number conversion cast (unumber) 0 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 0
Adding number conversion cast (unumber) 0 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 0
Adding number conversion cast (unumber) 0 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VSYNC) ← (number) 0
Adding number conversion cast (unumber) $25 in (bool~) main::$0 ← (byte) main::i#2 < (number) $25
@ -244,13 +242,12 @@ Adding number conversion cast (unumber) 0 in *((byte*)(const nomodify struct ATA
Adding number conversion cast (unumber) 0 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 0
Adding number conversion cast (unumber) 2 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (number) 2
Adding number conversion cast (unumber) 0 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (number) 0
Adding number conversion cast (unumber) 7 in (bool~) main::$2 ← (byte) main::i2#2 < (number) 7
Adding number conversion cast (unumber) $1e in (bool~) main::$2 ← (byte) main::i2#2 < (number) $1e
Adding number conversion cast (unumber) 0 in *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (number) 0
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (unumber)(number) 2
Inlining cast *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VSYNC) ← (unumber)(number) 2
Inlining cast *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (unumber)(number) 2
Inlining cast *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (unumber)(number) 2
Inlining cast *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (unumber)(number) 0
Inlining cast *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (unumber)(number) 0
Inlining cast *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (unumber)(number) 0
Inlining cast *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VSYNC) ← (unumber)(number) 0
Inlining cast *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (unumber)(number) 0
@ -263,9 +260,8 @@ Inlining cast *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte)
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (struct ATARI_TIA_WRITE*) 0
Simplifying constant integer cast 2
Simplifying constant integer cast 2
Simplifying constant integer cast 2
Simplifying constant integer cast 2
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast $25
@ -276,13 +272,12 @@ Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast 2
Simplifying constant integer cast 0
Simplifying constant integer cast 7
Simplifying constant integer cast $1e
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) $25
@ -293,7 +288,7 @@ Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 2
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 7
Finalized unsigned number type (byte) $1e
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias col#12 = col#8 col#5 col#2
@ -314,9 +309,9 @@ Identical Phi Values (byte) col#11 (byte) col#15
Identical Phi Values (byte) col#3 (byte) col#12
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) main::$3 [4] if((number) 0!=(number) 1) goto main::@2
Simple Condition (bool~) main::$0 [14] if((byte) main::i#2<(byte) $25) goto main::@4
Simple Condition (bool~) main::$1 [23] if((byte) main::i1#2<(byte) $c0) goto main::@7
Simple Condition (bool~) main::$2 [34] if((byte) main::i2#2<(byte) 7) goto main::@10
Simple Condition (bool~) main::$0 [13] if((byte) main::i#2<(byte) $25) goto main::@4
Simple Condition (bool~) main::$1 [22] if((byte) main::i1#2<(byte) $c0) goto main::@7
Simple Condition (bool~) main::$2 [33] if((byte) main::i2#2<(byte) $1e) goto main::@10
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte) col#0 = 0
Constant (const byte) main::i#0 = 0
@ -325,8 +320,8 @@ Constant (const byte) main::i2#0 = 0
Successful SSA optimization Pass2ConstantIdentification
if() condition always true - replacing block destination [4] if((number) 0!=(number) 1) goto main::@2
Successful SSA optimization Pass2ConstantIfs
Simplifying expression containing zero (byte*)TIA in [6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VSYNC) ← (byte) 2
Simplifying expression containing zero (byte*)TIA in [10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VSYNC) ← (byte) 0
Simplifying expression containing zero (byte*)TIA in [5] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VSYNC) ← (byte) 2
Simplifying expression containing zero (byte*)TIA in [9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VSYNC) ← (byte) 0
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant (const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VSYNC
Successful SSA optimization PassNEliminateUnusedVars
@ -351,12 +346,12 @@ CALL GRAPH
Calls in [] to main:2
Created 5 initial phi equivalence classes
Coalesced [18] main::c#4 ← main::c#0
Coalesced [26] col#18 ← col#1
Coalesced [29] main::i2#4 ← main::i2#1
Coalesced [34] main::i1#4 ← main::i1#1
Coalesced [35] main::c#5 ← main::c#1
Coalesced [38] main::i#4 ← main::i#1
Coalesced [17] main::c#4 ← main::c#0
Coalesced [25] col#18 ← col#1
Coalesced [28] main::i2#4 ← main::i2#1
Coalesced [33] main::i1#4 ← main::i1#1
Coalesced [34] main::c#5 ← main::c#1
Coalesced [37] main::i#4 ← main::i#1
Coalesced down to 5 phi equivalence classes
Culled Empty Block (label) @2
Culled Empty Block (label) main::@11
@ -384,49 +379,48 @@ main::@1: scope:[main] from main main::@9
[5] (byte) col#12 ← phi( main/(byte) 0 main::@9/(byte) col#1 )
to:main::@2
main::@2: scope:[main] from main::@1
[6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2
[7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2
[8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2
[9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2
[10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[11] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0
[6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2
[7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0
to:main::@3
main::@3: scope:[main] from main::@2 main::@4
[12] (byte) main::i#2 ← phi( main::@2/(byte) 0 main::@4/(byte) main::i#1 )
[13] if((byte) main::i#2<(byte) $25) goto main::@4
[11] (byte) main::i#2 ← phi( main::@2/(byte) 0 main::@4/(byte) main::i#1 )
[12] if((byte) main::i#2<(byte) $25) goto main::@4
to:main::@5
main::@5: scope:[main] from main::@3
[14] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0
[15] (byte) main::c#0 ← (byte) col#12
[16] (byte) col#1 ← ++ (byte) col#12
[13] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0
[14] (byte) main::c#0 ← (byte) col#12
[15] (byte) col#1 ← ++ (byte) col#12
to:main::@6
main::@6: scope:[main] from main::@5 main::@7
[17] (byte) main::c#2 ← phi( main::@5/(byte) main::c#0 main::@7/(byte) main::c#1 )
[17] (byte) main::i1#2 ← phi( main::@5/(byte) 0 main::@7/(byte) main::i1#1 )
[18] if((byte) main::i1#2<(byte) $c0) goto main::@7
[16] (byte) main::c#2 ← phi( main::@5/(byte) main::c#0 main::@7/(byte) main::c#1 )
[16] (byte) main::i1#2 ← phi( main::@5/(byte) 0 main::@7/(byte) main::i1#1 )
[17] if((byte) main::i1#2<(byte) $c0) goto main::@7
to:main::@8
main::@8: scope:[main] from main::@6
[19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2
[21] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0
[18] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2
[20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0
to:main::@9
main::@9: scope:[main] from main::@10 main::@8
[22] (byte) main::i2#2 ← phi( main::@10/(byte) main::i2#1 main::@8/(byte) 0 )
[23] if((byte) main::i2#2<(byte) 7) goto main::@10
[21] (byte) main::i2#2 ← phi( main::@10/(byte) main::i2#1 main::@8/(byte) 0 )
[22] if((byte) main::i2#2<(byte) $1e) goto main::@10
to:main::@1
main::@10: scope:[main] from main::@9
[24] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[25] (byte) main::i2#1 ← ++ (byte) main::i2#2
[23] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[24] (byte) main::i2#1 ← ++ (byte) main::i2#2
to:main::@9
main::@7: scope:[main] from main::@6
[26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[27] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) main::c#2
[28] (byte) main::c#1 ← ++ (byte) main::c#2
[29] (byte) main::i1#1 ← ++ (byte) main::i1#2
[25] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) main::c#2
[27] (byte) main::c#1 ← ++ (byte) main::c#2
[28] (byte) main::i1#1 ← ++ (byte) main::i1#2
to:main::@6
main::@4: scope:[main] from main::@3
[30] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[31] (byte) main::i#1 ← ++ (byte) main::i#2
[29] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0
[30] (byte) main::i#1 ← ++ (byte) main::i#2
to:main::@3
@ -501,7 +495,7 @@ VARIABLE REGISTER WEIGHTS
(byte) MOS6532_RIOT::TIM8T
(byte) col
(byte) col#1 78.71428571428571
(byte) col#12 92.53846153846155
(byte) col#12 100.25000000000001
(void()) main()
(byte) main::c
(byte) main::c#0 101.0
@ -542,7 +536,7 @@ Target platform is atari2600 / MOS6502X
// Source: https://atariage.com/forums/blogs/entry/11109-step-1-generate-a-stable-display/
// Upstart
// Atari 2600 VCS 4K ROM
.file [name="atari2600-min.prg", type="bin", segments="Code, Vectors"]
.file [name="atari2600-min.a26", type="bin", segments="Code, Vectors"]
.segmentdef Code [start=$f800,min=$f800,max=$fff9]
.segmentdef Data [start=$80,max=$ff, virtual]
.segmentdef Vectors [start=$fffa,max=$ffff]
@ -592,36 +586,32 @@ main: {
jmp __b2
// main::@2
__b2:
// [6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 -- _deref_pbuc1=vbuc2
// [6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2 -- _deref_pbuc1=vbuc2
// Vertical Sync
// here we generate the signal that tells the TV to move the beam to the top of
// the screen so we can start the next frame of video.
// The Sync Signal must be on for 3 scanlines.
lda #2
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2 -- _deref_pbuc1=vbuc2
// Wait for SYNC (halts CPU until end of scanline)
lda #2
sta TIA
// [8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 -- _deref_pbuc1=vbuc2
// [7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Accumulator D1=1, turns on Vertical Sync signal
lda #2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 -- _deref_pbuc1=vbuc2
// [8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Wait for Sync - halts CPU until end of 1st scanline of VSYNC
lda #2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// wait until end of 2nd scanline of VSYNC
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [11] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0 -- _deref_pbuc1=vbuc2
// wait until end of 3rd scanline of VSYNC
lda #0
sta TIA
// [12] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
// [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
__b3_from___b2:
// [12] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuz1=vbuc1
// [11] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuz1=vbuc1
lda #0
sta.z i
jmp __b3
@ -629,65 +619,65 @@ main: {
// Since we don't have any yet, just delay
// main::@3
__b3:
// [13] if((byte) main::i#2<(byte) $25) goto main::@4 -- vbuz1_lt_vbuc1_then_la1
// [12] if((byte) main::i#2<(byte) $25) goto main::@4 -- vbuz1_lt_vbuc1_then_la1
lda.z i
cmp #$25
bcc __b4
jmp __b5
// main::@5
__b5:
// [14] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [13] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Screen - display logic
// Update the registers in TIA (the video chip) in order to generate what the player sees.
// For now we're just going to output 192 colored scanlines lines so we have something to see.
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK
// [15] (byte) main::c#0 ← (byte) col#12 -- vbuz1=vbum2
// [14] (byte) main::c#0 ← (byte) col#12 -- vbuz1=vbum2
// D1=1, turns off Vertical Blank signal (image output on)
lda col
sta.z c
// [16] (byte) col#1 ← ++ (byte) col#12 -- vbum1=_inc_vbum1
// [15] (byte) col#1 ← ++ (byte) col#12 -- vbum1=_inc_vbum1
inc col
// [17] phi from main::@5 to main::@6 [phi:main::@5->main::@6]
// [16] phi from main::@5 to main::@6 [phi:main::@5->main::@6]
__b6_from___b5:
// [17] phi (byte) main::c#2 = (byte) main::c#0 [phi:main::@5->main::@6#0] -- register_copy
// [17] phi (byte) main::i1#2 = (byte) 0 [phi:main::@5->main::@6#1] -- vbuz1=vbuc1
// [16] phi (byte) main::c#2 = (byte) main::c#0 [phi:main::@5->main::@6#0] -- register_copy
// [16] phi (byte) main::i1#2 = (byte) 0 [phi:main::@5->main::@6#1] -- vbuz1=vbuc1
lda #0
sta.z i1
jmp __b6
// main::@6
__b6:
// [18] if((byte) main::i1#2<(byte) $c0) goto main::@7 -- vbuz1_lt_vbuc1_then_la1
// [17] if((byte) main::i1#2<(byte) $c0) goto main::@7 -- vbuz1_lt_vbuc1_then_la1
lda.z i1
cmp #$c0
bcc __b7
jmp __b8
// main::@8
__b8:
// [19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [18] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Overscan - game logic
// Since we don't have any yet, just delay
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2 -- _deref_pbuc1=vbuc2
// [19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2 -- _deref_pbuc1=vbuc2
// Wait for SYNC (halts CPU until end of scanline)
lda #2
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK
// [21] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// // D1=1 turns image output off
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK
// [22] phi from main::@8 to main::@9 [phi:main::@8->main::@9]
// [21] phi from main::@8 to main::@9 [phi:main::@8->main::@9]
__b9_from___b8:
// [22] phi (byte) main::i2#2 = (byte) 0 [phi:main::@8->main::@9#0] -- vbuz1=vbuc1
// [21] phi (byte) main::i2#2 = (byte) 0 [phi:main::@8->main::@9#0] -- vbuz1=vbuc1
lda #0
sta.z i2
jmp __b9
// main::@9
__b9:
// [23] if((byte) main::i2#2<(byte) 7) goto main::@10 -- vbuz1_lt_vbuc1_then_la1
// [22] if((byte) main::i2#2<(byte) $1e) goto main::@10 -- vbuz1_lt_vbuc1_then_la1
lda.z i2
cmp #7
cmp #$1e
bcc __b10
// [5] phi from main::@9 to main::@1 [phi:main::@9->main::@1]
__b1_from___b9:
@ -695,43 +685,43 @@ main: {
jmp __b1
// main::@10
__b10:
// [24] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [23] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [25] (byte) main::i2#1 ← ++ (byte) main::i2#2 -- vbuz1=_inc_vbuz1
// [24] (byte) main::i2#1 ← ++ (byte) main::i2#2 -- vbuz1=_inc_vbuz1
inc.z i2
// [22] phi from main::@10 to main::@9 [phi:main::@10->main::@9]
// [21] phi from main::@10 to main::@9 [phi:main::@10->main::@9]
__b9_from___b10:
// [22] phi (byte) main::i2#2 = (byte) main::i2#1 [phi:main::@10->main::@9#0] -- register_copy
// [21] phi (byte) main::i2#2 = (byte) main::i2#1 [phi:main::@10->main::@9#0] -- register_copy
jmp __b9
// main::@7
__b7:
// [26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [25] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [27] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) main::c#2 -- _deref_pbuc1=vbuz1
// [26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) main::c#2 -- _deref_pbuc1=vbuz1
// Wait for SYNC (halts CPU until end of scanline)
lda.z c
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK
// [28] (byte) main::c#1 ← ++ (byte) main::c#2 -- vbuz1=_inc_vbuz1
// [27] (byte) main::c#1 ← ++ (byte) main::c#2 -- vbuz1=_inc_vbuz1
inc.z c
// [29] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuz1=_inc_vbuz1
// [28] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuz1=_inc_vbuz1
inc.z i1
// [17] phi from main::@7 to main::@6 [phi:main::@7->main::@6]
// [16] phi from main::@7 to main::@6 [phi:main::@7->main::@6]
__b6_from___b7:
// [17] phi (byte) main::c#2 = (byte) main::c#1 [phi:main::@7->main::@6#0] -- register_copy
// [17] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@7->main::@6#1] -- register_copy
// [16] phi (byte) main::c#2 = (byte) main::c#1 [phi:main::@7->main::@6#0] -- register_copy
// [16] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@7->main::@6#1] -- register_copy
jmp __b6
// main::@4
__b4:
// [30] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [29] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [31] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
// [30] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [12] phi from main::@4 to main::@3 [phi:main::@4->main::@3]
// [11] phi from main::@4 to main::@3 [phi:main::@4->main::@3]
__b3_from___b4:
// [12] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy
// [11] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy
jmp __b3
}
// File Data
@ -739,37 +729,35 @@ main: {
col: .byte 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for mem[1] [ col#12 col#1 ]
Statement [7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [11] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [14] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [21] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [24] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 main::i2#2 ] ( main:2 [ col#1 main::i2#2 ] { } ) always clobbers reg byte a
Statement [7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [13] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [18] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [23] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 main::i2#2 ] ( main:2 [ col#1 main::i2#2 ] { } ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:5 [ main::i2#2 main::i2#1 ]
Statement [26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 main::i1#2 main::c#2 ] ( main:2 [ col#1 main::i1#2 main::c#2 ] { } ) always clobbers reg byte a
Statement [25] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 main::i1#2 main::c#2 ] ( main:2 [ col#1 main::i1#2 main::c#2 ] { } ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::i1#2 main::i1#1 ]
Removing always clobbered register reg byte a as potential for zp[1]:4 [ main::c#2 main::c#0 main::c#1 ]
Statement [30] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 main::i#2 ] ( main:2 [ col#12 main::i#2 ] { } ) always clobbers reg byte a
Statement [29] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 main::i#2 ] ( main:2 [ col#12 main::i#2 ] { } ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Statement [6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [11] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [14] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [21] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [24] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 main::i2#2 ] ( main:2 [ col#1 main::i2#2 ] { } ) always clobbers reg byte a
Statement [26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 main::i1#2 main::c#2 ] ( main:2 [ col#1 main::i1#2 main::c#2 ] { } ) always clobbers reg byte a
Statement [30] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 main::i#2 ] ( main:2 [ col#12 main::i#2 ] { } ) always clobbers reg byte a
Statement [6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [13] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0 [ col#12 ] ( main:2 [ col#12 ] { } ) always clobbers reg byte a
Statement [18] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0 [ col#1 ] ( main:2 [ col#1 ] { } ) always clobbers reg byte a
Statement [23] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 main::i2#2 ] ( main:2 [ col#1 main::i2#2 ] { } ) always clobbers reg byte a
Statement [25] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#1 main::i1#2 main::c#2 ] ( main:2 [ col#1 main::i1#2 main::c#2 ] { } ) always clobbers reg byte a
Statement [29] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 [ col#12 main::i#2 ] ( main:2 [ col#12 main::i#2 ] { } ) always clobbers reg byte a
Potential registers mem[1] [ col#12 col#1 ] : mem[1] , reg byte x , reg byte y ,
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y ,
Potential registers zp[1]:3 [ main::i1#2 main::i1#1 ] : zp[1]:3 , reg byte x , reg byte y ,
@ -778,18 +766,18 @@ Potential registers zp[1]:5 [ main::i2#2 main::i2#1 ] : zp[1]:5 , reg byte x , r
REGISTER UPLIFT SCOPES
Uplift Scope [main] 3,003: zp[1]:2 [ main::i#2 main::i#1 ] 3,003: zp[1]:5 [ main::i2#2 main::i2#1 ] 2,602.6: zp[1]:3 [ main::i1#2 main::i1#1 ] 1,878: zp[1]:4 [ main::c#2 main::c#0 main::c#1 ]
Uplift Scope [] 171.25: mem[1] [ col#12 col#1 ]
Uplift Scope [] 178.96: mem[1] [ col#12 col#1 ]
Uplift Scope [ATARI_TIA_WRITE]
Uplift Scope [ATARI_TIA_READ]
Uplift Scope [MOS6532_RIOT]
Uplifting [main] best 8212 combination reg byte x [ main::i#2 main::i#1 ] reg byte x [ main::i2#2 main::i2#1 ] reg byte y [ main::i1#2 main::i1#1 ] reg byte x [ main::c#2 main::c#0 main::c#1 ]
Uplifting [] best 8212 combination mem[1] [ col#12 col#1 ]
Uplifting [ATARI_TIA_WRITE] best 8212 combination
Uplifting [ATARI_TIA_READ] best 8212 combination
Uplifting [MOS6532_RIOT] best 8212 combination
Uplifting [main] best 8152 combination reg byte x [ main::i#2 main::i#1 ] reg byte x [ main::i2#2 main::i2#1 ] reg byte y [ main::i1#2 main::i1#1 ] reg byte x [ main::c#2 main::c#0 main::c#1 ]
Uplifting [] best 8152 combination mem[1] [ col#12 col#1 ]
Uplifting [ATARI_TIA_WRITE] best 8152 combination
Uplifting [ATARI_TIA_READ] best 8152 combination
Uplifting [MOS6532_RIOT] best 8152 combination
Attempting to uplift remaining variables inmem[1] [ col#12 col#1 ]
Uplifting [] best 8212 combination mem[1] [ col#12 col#1 ]
Uplifting [] best 8152 combination mem[1] [ col#12 col#1 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
@ -797,7 +785,7 @@ ASSEMBLER BEFORE OPTIMIZATION
// Source: https://atariage.com/forums/blogs/entry/11109-step-1-generate-a-stable-display/
// Upstart
// Atari 2600 VCS 4K ROM
.file [name="atari2600-min.prg", type="bin", segments="Code, Vectors"]
.file [name="atari2600-min.a26", type="bin", segments="Code, Vectors"]
.segmentdef Code [start=$f800,min=$f800,max=$fff9]
.segmentdef Data [start=$80,max=$ff, virtual]
.segmentdef Vectors [start=$fffa,max=$ffff]
@ -843,95 +831,91 @@ main: {
jmp __b2
// main::@2
__b2:
// [6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 -- _deref_pbuc1=vbuc2
// [6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2 -- _deref_pbuc1=vbuc2
// Vertical Sync
// here we generate the signal that tells the TV to move the beam to the top of
// the screen so we can start the next frame of video.
// The Sync Signal must be on for 3 scanlines.
lda #2
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2 -- _deref_pbuc1=vbuc2
// Wait for SYNC (halts CPU until end of scanline)
lda #2
sta TIA
// [8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 -- _deref_pbuc1=vbuc2
// [7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Accumulator D1=1, turns on Vertical Sync signal
lda #2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 -- _deref_pbuc1=vbuc2
// [8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Wait for Sync - halts CPU until end of 1st scanline of VSYNC
lda #2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// wait until end of 2nd scanline of VSYNC
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [11] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0 -- _deref_pbuc1=vbuc2
// wait until end of 3rd scanline of VSYNC
lda #0
sta TIA
// [12] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
// [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
__b3_from___b2:
// [12] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuxx=vbuc1
// [11] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuxx=vbuc1
ldx #0
jmp __b3
// Vertical Blank - game logic
// Since we don't have any yet, just delay
// main::@3
__b3:
// [13] if((byte) main::i#2<(byte) $25) goto main::@4 -- vbuxx_lt_vbuc1_then_la1
// [12] if((byte) main::i#2<(byte) $25) goto main::@4 -- vbuxx_lt_vbuc1_then_la1
cpx #$25
bcc __b4
jmp __b5
// main::@5
__b5:
// [14] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [13] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Screen - display logic
// Update the registers in TIA (the video chip) in order to generate what the player sees.
// For now we're just going to output 192 colored scanlines lines so we have something to see.
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK
// [15] (byte) main::c#0 ← (byte) col#12 -- vbuxx=vbum1
// [14] (byte) main::c#0 ← (byte) col#12 -- vbuxx=vbum1
// D1=1, turns off Vertical Blank signal (image output on)
ldx col
// [16] (byte) col#1 ← ++ (byte) col#12 -- vbum1=_inc_vbum1
// [15] (byte) col#1 ← ++ (byte) col#12 -- vbum1=_inc_vbum1
inc col
// [17] phi from main::@5 to main::@6 [phi:main::@5->main::@6]
// [16] phi from main::@5 to main::@6 [phi:main::@5->main::@6]
__b6_from___b5:
// [17] phi (byte) main::c#2 = (byte) main::c#0 [phi:main::@5->main::@6#0] -- register_copy
// [17] phi (byte) main::i1#2 = (byte) 0 [phi:main::@5->main::@6#1] -- vbuyy=vbuc1
// [16] phi (byte) main::c#2 = (byte) main::c#0 [phi:main::@5->main::@6#0] -- register_copy
// [16] phi (byte) main::i1#2 = (byte) 0 [phi:main::@5->main::@6#1] -- vbuyy=vbuc1
ldy #0
jmp __b6
// main::@6
__b6:
// [18] if((byte) main::i1#2<(byte) $c0) goto main::@7 -- vbuyy_lt_vbuc1_then_la1
// [17] if((byte) main::i1#2<(byte) $c0) goto main::@7 -- vbuyy_lt_vbuc1_then_la1
cpy #$c0
bcc __b7
jmp __b8
// main::@8
__b8:
// [19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [18] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Overscan - game logic
// Since we don't have any yet, just delay
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2 -- _deref_pbuc1=vbuc2
// [19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2 -- _deref_pbuc1=vbuc2
// Wait for SYNC (halts CPU until end of scanline)
lda #2
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK
// [21] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// // D1=1 turns image output off
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK
// [22] phi from main::@8 to main::@9 [phi:main::@8->main::@9]
// [21] phi from main::@8 to main::@9 [phi:main::@8->main::@9]
__b9_from___b8:
// [22] phi (byte) main::i2#2 = (byte) 0 [phi:main::@8->main::@9#0] -- vbuxx=vbuc1
// [21] phi (byte) main::i2#2 = (byte) 0 [phi:main::@8->main::@9#0] -- vbuxx=vbuc1
ldx #0
jmp __b9
// main::@9
__b9:
// [23] if((byte) main::i2#2<(byte) 7) goto main::@10 -- vbuxx_lt_vbuc1_then_la1
cpx #7
// [22] if((byte) main::i2#2<(byte) $1e) goto main::@10 -- vbuxx_lt_vbuc1_then_la1
cpx #$1e
bcc __b10
// [5] phi from main::@9 to main::@1 [phi:main::@9->main::@1]
__b1_from___b9:
@ -939,42 +923,42 @@ main: {
jmp __b1
// main::@10
__b10:
// [24] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [23] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [25] (byte) main::i2#1 ← ++ (byte) main::i2#2 -- vbuxx=_inc_vbuxx
// [24] (byte) main::i2#1 ← ++ (byte) main::i2#2 -- vbuxx=_inc_vbuxx
inx
// [22] phi from main::@10 to main::@9 [phi:main::@10->main::@9]
// [21] phi from main::@10 to main::@9 [phi:main::@10->main::@9]
__b9_from___b10:
// [22] phi (byte) main::i2#2 = (byte) main::i2#1 [phi:main::@10->main::@9#0] -- register_copy
// [21] phi (byte) main::i2#2 = (byte) main::i2#1 [phi:main::@10->main::@9#0] -- register_copy
jmp __b9
// main::@7
__b7:
// [26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [25] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [27] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) main::c#2 -- _deref_pbuc1=vbuxx
// [26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) main::c#2 -- _deref_pbuc1=vbuxx
// Wait for SYNC (halts CPU until end of scanline)
stx TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK
// [28] (byte) main::c#1 ← ++ (byte) main::c#2 -- vbuxx=_inc_vbuxx
// [27] (byte) main::c#1 ← ++ (byte) main::c#2 -- vbuxx=_inc_vbuxx
inx
// [29] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuyy=_inc_vbuyy
// [28] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuyy=_inc_vbuyy
iny
// [17] phi from main::@7 to main::@6 [phi:main::@7->main::@6]
// [16] phi from main::@7 to main::@6 [phi:main::@7->main::@6]
__b6_from___b7:
// [17] phi (byte) main::c#2 = (byte) main::c#1 [phi:main::@7->main::@6#0] -- register_copy
// [17] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@7->main::@6#1] -- register_copy
// [16] phi (byte) main::c#2 = (byte) main::c#1 [phi:main::@7->main::@6#0] -- register_copy
// [16] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@7->main::@6#1] -- register_copy
jmp __b6
// main::@4
__b4:
// [30] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [29] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [31] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
// [30] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
// [12] phi from main::@4 to main::@3 [phi:main::@4->main::@3]
// [11] phi from main::@4 to main::@3 [phi:main::@4->main::@3]
__b3_from___b4:
// [12] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy
// [11] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy
jmp __b3
}
// File Data
@ -992,9 +976,8 @@ Removing instruction jmp __b6
Removing instruction jmp __b8
Removing instruction jmp __b9
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #2
Removing instruction lda #2
Removing instruction lda #2
Removing instruction lda #0
Removing instruction lda #0
Removing instruction lda #0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __b1 with __b2
@ -1102,7 +1085,7 @@ FINAL SYMBOL TABLE
(const nomodify struct ATARI_TIA_WRITE*) TIA = (struct ATARI_TIA_WRITE*) 0
(byte) col
(byte) col#1 col mem[1] 78.71428571428571
(byte) col#12 col mem[1] 92.53846153846155
(byte) col#12 col mem[1] 100.25000000000001
(void()) main()
(label) main::@1
(label) main::@10
@ -1136,14 +1119,14 @@ reg byte x [ main::i2#2 main::i2#1 ]
FINAL ASSEMBLER
Score: 6560
Score: 6520
// File Comments
// Minimal Atari 2600 VCS Program
// Source: https://atariage.com/forums/blogs/entry/11109-step-1-generate-a-stable-display/
// Upstart
// Atari 2600 VCS 4K ROM
.file [name="atari2600-min.prg", type="bin", segments="Code, Vectors"]
.file [name="atari2600-min.a26", type="bin", segments="Code, Vectors"]
.segmentdef Code [start=$f800,min=$f800,max=$fff9]
.segmentdef Data [start=$80,max=$ff, virtual]
.segmentdef Vectors [start=$fffa,max=$ffff]
@ -1176,94 +1159,89 @@ main: {
// main::@1
// main::@2
__b2:
// TIA->WSYNC = 2
// [6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 -- _deref_pbuc1=vbuc2
// TIA->VSYNC = 2
// [6] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2 -- _deref_pbuc1=vbuc2
// Vertical Sync
// here we generate the signal that tells the TV to move the beam to the top of
// the screen so we can start the next frame of video.
// The Sync Signal must be on for 3 scanlines.
lda #2
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// TIA->VSYNC = 2
// [7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 2 -- _deref_pbuc1=vbuc2
// Wait for SYNC (halts CPU until end of scanline)
sta TIA
// TIA->WSYNC = 2
// [8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 -- _deref_pbuc1=vbuc2
// Accumulator D1=1, turns on Vertical Sync signal
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 2 -- _deref_pbuc1=vbuc2
// Wait for Sync - halts CPU until end of 1st scanline of VSYNC
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// TIA->WSYNC = 0
// [10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// wait until end of 2nd scanline of VSYNC
// [7] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Accumulator D1=1, turns on Vertical Sync signal
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [8] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Wait for Sync - halts CPU until end of 1st scanline of VSYNC
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// [9] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// wait until end of 2nd scanline of VSYNC
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// TIA->VSYNC = 0
// [11] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [10] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA) ← (byte) 0 -- _deref_pbuc1=vbuc2
// wait until end of 3rd scanline of VSYNC
sta TIA
// [12] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
// [12] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuxx=vbuc1
// [11] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
// [11] phi (byte) main::i#2 = (byte) 0 [phi:main::@2->main::@3#0] -- vbuxx=vbuc1
tax
// Vertical Blank - game logic
// Since we don't have any yet, just delay
// main::@3
__b3:
// for(char i=0;i<37;i++)
// [13] if((byte) main::i#2<(byte) $25) goto main::@4 -- vbuxx_lt_vbuc1_then_la1
// [12] if((byte) main::i#2<(byte) $25) goto main::@4 -- vbuxx_lt_vbuc1_then_la1
cpx #$25
bcc __b4
// main::@5
// TIA->VBLANK = 0
// [14] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [13] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Screen - display logic
// Update the registers in TIA (the video chip) in order to generate what the player sees.
// For now we're just going to output 192 colored scanlines lines so we have something to see.
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK
// c = col++
// [15] (byte) main::c#0 ← (byte) col#12 -- vbuxx=vbum1
// [14] (byte) main::c#0 ← (byte) col#12 -- vbuxx=vbum1
// D1=1, turns off Vertical Blank signal (image output on)
ldx col
// [16] (byte) col#1 ← ++ (byte) col#12 -- vbum1=_inc_vbum1
// [15] (byte) col#1 ← ++ (byte) col#12 -- vbum1=_inc_vbum1
inc col
// [17] phi from main::@5 to main::@6 [phi:main::@5->main::@6]
// [17] phi (byte) main::c#2 = (byte) main::c#0 [phi:main::@5->main::@6#0] -- register_copy
// [17] phi (byte) main::i1#2 = (byte) 0 [phi:main::@5->main::@6#1] -- vbuyy=vbuc1
// [16] phi from main::@5 to main::@6 [phi:main::@5->main::@6]
// [16] phi (byte) main::c#2 = (byte) main::c#0 [phi:main::@5->main::@6#0] -- register_copy
// [16] phi (byte) main::i1#2 = (byte) 0 [phi:main::@5->main::@6#1] -- vbuyy=vbuc1
tay
// main::@6
__b6:
// for(char i=0;i<192;i++)
// [18] if((byte) main::i1#2<(byte) $c0) goto main::@7 -- vbuyy_lt_vbuc1_then_la1
// [17] if((byte) main::i1#2<(byte) $c0) goto main::@7 -- vbuyy_lt_vbuc1_then_la1
cpy #$c0
bcc __b7
// main::@8
// TIA->WSYNC = 0
// [19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [18] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// Overscan - game logic
// Since we don't have any yet, just delay
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// TIA->VBLANK = 2
// [20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2 -- _deref_pbuc1=vbuc2
// [19] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK) ← (byte) 2 -- _deref_pbuc1=vbuc2
// Wait for SYNC (halts CPU until end of scanline)
lda #2
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_VBLANK
// TIA->COLUBK = 0
// [21] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [20] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) 0 -- _deref_pbuc1=vbuc2
// // D1=1 turns image output off
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK
// [22] phi from main::@8 to main::@9 [phi:main::@8->main::@9]
// [22] phi (byte) main::i2#2 = (byte) 0 [phi:main::@8->main::@9#0] -- vbuxx=vbuc1
// [21] phi from main::@8 to main::@9 [phi:main::@8->main::@9]
// [21] phi (byte) main::i2#2 = (byte) 0 [phi:main::@8->main::@9#0] -- vbuxx=vbuc1
tax
// main::@9
__b9:
// for(char i=0;i<07;i++)
// [23] if((byte) main::i2#2<(byte) 7) goto main::@10 -- vbuxx_lt_vbuc1_then_la1
cpx #7
// for(char i=0;i<30;i++)
// [22] if((byte) main::i2#2<(byte) $1e) goto main::@10 -- vbuxx_lt_vbuc1_then_la1
cpx #$1e
bcc __b10
// [5] phi from main::@9 to main::@1 [phi:main::@9->main::@1]
// [5] phi (byte) col#12 = (byte) col#1 [phi:main::@9->main::@1#0] -- register_copy
@ -1271,46 +1249,46 @@ main: {
// main::@10
__b10:
// TIA->WSYNC = 0
// [24] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [23] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// for(char i=0;i<07;i++)
// [25] (byte) main::i2#1 ← ++ (byte) main::i2#2 -- vbuxx=_inc_vbuxx
// for(char i=0;i<30;i++)
// [24] (byte) main::i2#1 ← ++ (byte) main::i2#2 -- vbuxx=_inc_vbuxx
inx
// [22] phi from main::@10 to main::@9 [phi:main::@10->main::@9]
// [22] phi (byte) main::i2#2 = (byte) main::i2#1 [phi:main::@10->main::@9#0] -- register_copy
// [21] phi from main::@10 to main::@9 [phi:main::@10->main::@9]
// [21] phi (byte) main::i2#2 = (byte) main::i2#1 [phi:main::@10->main::@9#0] -- register_copy
jmp __b9
// main::@7
__b7:
// TIA->WSYNC = 0
// [26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [25] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// TIA->COLUBK = c++
// [27] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) main::c#2 -- _deref_pbuc1=vbuxx
// [26] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK) ← (byte) main::c#2 -- _deref_pbuc1=vbuxx
// Wait for SYNC (halts CPU until end of scanline)
stx TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_COLUBK
// TIA->COLUBK = c++;
// [28] (byte) main::c#1 ← ++ (byte) main::c#2 -- vbuxx=_inc_vbuxx
// [27] (byte) main::c#1 ← ++ (byte) main::c#2 -- vbuxx=_inc_vbuxx
inx
// for(char i=0;i<192;i++)
// [29] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuyy=_inc_vbuyy
// [28] (byte) main::i1#1 ← ++ (byte) main::i1#2 -- vbuyy=_inc_vbuyy
iny
// [17] phi from main::@7 to main::@6 [phi:main::@7->main::@6]
// [17] phi (byte) main::c#2 = (byte) main::c#1 [phi:main::@7->main::@6#0] -- register_copy
// [17] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@7->main::@6#1] -- register_copy
// [16] phi from main::@7 to main::@6 [phi:main::@7->main::@6]
// [16] phi (byte) main::c#2 = (byte) main::c#1 [phi:main::@7->main::@6#0] -- register_copy
// [16] phi (byte) main::i1#2 = (byte) main::i1#1 [phi:main::@7->main::@6#1] -- register_copy
jmp __b6
// main::@4
__b4:
// TIA->WSYNC = 0
// [30] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
// [29] *((byte*)(const nomodify struct ATARI_TIA_WRITE*) TIA+(const byte) OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC) ← (byte) 0 -- _deref_pbuc1=vbuc2
lda #0
sta TIA+OFFSET_STRUCT_ATARI_TIA_WRITE_WSYNC
// for(char i=0;i<37;i++)
// [31] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
// [30] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
// [12] phi from main::@4 to main::@3 [phi:main::@4->main::@3]
// [12] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy
// [11] phi from main::@4 to main::@3 [phi:main::@4->main::@3]
// [11] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@4->main::@3#0] -- register_copy
jmp __b3
}
// File Data

View File

@ -76,7 +76,7 @@
(const nomodify struct ATARI_TIA_WRITE*) TIA = (struct ATARI_TIA_WRITE*) 0
(byte) col
(byte) col#1 col mem[1] 78.71428571428571
(byte) col#12 col mem[1] 92.53846153846155
(byte) col#12 col mem[1] 100.25000000000001
(void()) main()
(label) main::@1
(label) main::@10