mirror of
https://github.com/michaelcmartin/Ophis.git
synced 2024-06-08 19:29:28 +00:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
99f074da27 | ||
|
41bf01d035 | ||
|
971fafd918 | ||
|
f6990095c1 | ||
|
778fbf7e2c |
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from os.path import realpath, dirname, join
|
||||
from sys import argv, exit, path
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
"Hi Stella" is a simple "Hello World" program for the "Stella" chip,
|
||||
more famously known as the Atari 2600. Simply running
|
||||
|
||||
ophis hi_stella.oph
|
||||
|
||||
should produce hi_stella.bin, a 256-byte file that prints "HI" on
|
||||
the screen with some rolling color bars.
|
13
examples/stella/README.txt
Normal file
13
examples/stella/README.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
"Hi Stella" is a simple "Hello World" program for the "Stella" chip,
|
||||
more famously known as the Atari 2600. Simply running
|
||||
|
||||
ophis hi_stella.oph
|
||||
|
||||
should produce hi_stella.bin, a 256-byte file that prints "HI" on
|
||||
the screen with some rolling color bars.
|
||||
|
||||
A more sophisticated program is colortest, which lets the user
|
||||
explore the 128 colors provided by the system. Use up and down
|
||||
to move the color value by 2, and left and right to move it
|
||||
by 16. (The lowest bit in the color value byte is ignored, for
|
||||
a total of 128 colors available.)
|
391
examples/stella/colortest.oph
Normal file
391
examples/stella/colortest.oph
Normal file
|
@ -0,0 +1,391 @@
|
|||
;;; ---------- COLOR TEST ----------
|
||||
;;; Michael Martin, 2014
|
||||
;;;
|
||||
;;; This is a sample program for the Atari 2600 VCS that lets you
|
||||
;;; explore the 128-color palette the system provides. This is
|
||||
;;; presented mainly as a more sophisticated example program to
|
||||
;;; supplement "hi_stella".
|
||||
;;;
|
||||
;;; It makes use of every graphical element but the Ball, and also
|
||||
;;; makes use of multicolor asymmetric playfields.
|
||||
|
||||
.require "../../platform/stella.oph"
|
||||
.outfile "colortest.bin"
|
||||
|
||||
.data
|
||||
.org $0080
|
||||
.space startcol 1 ; Starting color for the striped playfield
|
||||
.space subrow 1 ; Counting lines per "tall pixel"
|
||||
.space curcol 1 ; The color number we are focusing on at the moment
|
||||
.space high_nybble 2 ; Pointer to graphic data for 16s hexit
|
||||
.space low_nybble 2 ; Pointer to graphic data for ones hexit
|
||||
.space input_allowed 1 ; Flag for whether or not to ignore input.
|
||||
|
||||
.text
|
||||
;; Start at $f800 - 2KB ROMs are the smallest size available.
|
||||
.org $f800
|
||||
|
||||
reset: `clean'start
|
||||
|
||||
;; We offer 1c as the initial color. It's a nice yellow shade.
|
||||
lda #$1c
|
||||
sta curcol
|
||||
|
||||
|
||||
frame: `vertical'sync ; Beginning of the frame. Set up the timer
|
||||
lda #43 ; to count out the length of VBLANK while
|
||||
sta TIM64T ; we do the processing for the display.
|
||||
|
||||
;; Place the player and missile graphics appropriately. We
|
||||
;; count cycles and write the missile and player reset registers
|
||||
;; at the closest times we can manage. Due to the way the TIA
|
||||
;; timing works, the formula for the pixel they will show up at
|
||||
;; is N*3-55+P, where N is the number of cycles from the end of
|
||||
;; the latest STA WSYNC and the end of the STA RES* instruction,
|
||||
;; and P is 1 for player sprites and 0 for missiles and the ball.
|
||||
;;
|
||||
;; The line after that we can strobe HMOVE to adjust them the
|
||||
;; rest of the way into place.
|
||||
;;
|
||||
;; We will be using the missiles to draw the left and right
|
||||
;; sides of a largish square and the player sprites to display a
|
||||
;; byte value (the current color) as two hex digits (one per
|
||||
;; player). All the rest of our graphics will be done via the
|
||||
;; playfield registers.
|
||||
;;
|
||||
;; The missile graphics are being targeted to pixels 40 and 116
|
||||
;; and will be 4 pixels wide each. The player graphics will be
|
||||
;; 8 pixels wide and are targeting pixels 72 and 80.
|
||||
sta WSYNC
|
||||
sta WSYNC ; = 0
|
||||
ldy #$06 ; +2 = 2
|
||||
* dey ; +2 = 4- 9-14-19-24-29
|
||||
bne - ; +3 = 7-12-17-22-27-31
|
||||
sta RESM0 ; +3 = 34 (31*3-55 = 38. Needs to move 2 pixels right.)
|
||||
lda #$E0 ; +2 = 36
|
||||
sta HMCLR ; +3 = 39 - reset the fine-move registers
|
||||
sta HMM0 ; +3 = 42 - set M0 to move 2 right
|
||||
sta RESP0 ; +3 = 45 (42*3-54 = 72. Placed perfectly.)
|
||||
sta RESP1 ; +3 = 48 (45*3-54 = 81. Needs to move 1 pixel left.)
|
||||
lda #$10 ; +2 = 50
|
||||
sta HMP1 ; +3 = 53 - and set P1 to move 1 left.
|
||||
nop ; +2 = 55
|
||||
nop ; +2 = 57
|
||||
sta RESM1 ; +3 = 60 (57*3-55 = 116. Placed perfectly.)
|
||||
sta WSYNC
|
||||
sta HMOVE ; Next scanline, execute the fine moves.
|
||||
|
||||
lda #$20
|
||||
sta NUSIZ0 ; Quad-size missiles, single copy of single player
|
||||
sta NUSIZ1 ; M1 and P1 are the same
|
||||
|
||||
;; Read the input
|
||||
lda #$00
|
||||
sta SWACNT
|
||||
lda SWCHA
|
||||
bit input_allowed
|
||||
bmi true_input_read
|
||||
;; Wait for neutral stick so we can re-enable input.
|
||||
and #$f0
|
||||
cmp #$f0
|
||||
bne input_done
|
||||
;; Bits are set if the direction isn't active, so we only get
|
||||
;; here if the stick was neutral. this also means the accumulator
|
||||
;; has #$f0 in it now, which means we can store it directly and
|
||||
;; the BIT/BMI above will start succeeding next frame.
|
||||
sta input_allowed
|
||||
beq input_done
|
||||
true_input_read:
|
||||
;; Now we rotate it through the carry bit to see what
|
||||
;; direction was pushed. We advance the color 2 or 16 at a time,
|
||||
;; depending. (The least significant bit in the color register is
|
||||
;; the one ignored, so we are not missing anything here.)
|
||||
ror ; Skip P2 input
|
||||
ror
|
||||
ror
|
||||
ror
|
||||
ror ; Carry clear if up
|
||||
bcs +
|
||||
inc curcol ; If up, increase color by 2
|
||||
inc curcol
|
||||
jmp input_found
|
||||
* ror ; Carry clear if down
|
||||
bcs +
|
||||
dec curcol ; If down, decrease color by 2
|
||||
dec curcol
|
||||
jmp input_found
|
||||
* ror ; Carry clear if left
|
||||
bcs +
|
||||
lda curcol
|
||||
sec
|
||||
sbc #$10 ; Left decreases color by 16
|
||||
sta curcol
|
||||
jmp input_found
|
||||
* ror ; Carry clear if right
|
||||
bcs input_done
|
||||
lda curcol
|
||||
adc #$10 ; Right increases color by 16
|
||||
sta curcol
|
||||
input_found:
|
||||
lda #$00
|
||||
sta input_allowed
|
||||
|
||||
input_done:
|
||||
;; Clear the playfield while we wait, and make it asymmetric
|
||||
lda #$00
|
||||
sta PF0
|
||||
sta PF1
|
||||
sta PF2
|
||||
sta CTRLPF
|
||||
|
||||
;; alter playfield color so we get a rotating effect
|
||||
dec startcol
|
||||
|
||||
;; prepare numeric sprite values
|
||||
lda curcol
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
lsr
|
||||
tay
|
||||
lda digits_low, y
|
||||
sta high_nybble
|
||||
lda curcol
|
||||
and #$0f
|
||||
tay
|
||||
lda digits_low, y
|
||||
sta low_nybble
|
||||
lda #$ff
|
||||
sta low_nybble+1
|
||||
sta high_nybble+1
|
||||
|
||||
;; Wait for VBLANK to finish, then turn off the VBLANK signal.
|
||||
* lda INTIM
|
||||
bne -
|
||||
sta WSYNC
|
||||
sta VBLANK
|
||||
|
||||
;; Display kernel.
|
||||
;; Top blank: 4 lines
|
||||
ldx #4
|
||||
stx subrow
|
||||
* sta WSYNC
|
||||
dex
|
||||
bne -
|
||||
|
||||
;; Header graphics: 20 lines
|
||||
ldy #5
|
||||
ldx startcol
|
||||
header_loop:
|
||||
sta WSYNC
|
||||
stx COLUPF ; +3 = 3
|
||||
lda pf0_left-1,y ; +4 = 7
|
||||
sta PF0 ; +3 = 10
|
||||
lda pf1_left-1,y ; +4 = 14
|
||||
sta PF1 ; +3 = 17
|
||||
lda pf2_left-1,y ; +4 = 21
|
||||
sta PF2 ; +3 = 24
|
||||
cmp $80 ; +3 = 27 (3-cycle no-op)
|
||||
lda pf0_right-1,y ; +4 = 31
|
||||
sta PF0 ; +3 = 34
|
||||
lda pf1_right-1,y ; +4 = 38
|
||||
sta PF1 ; +3 = 41
|
||||
lda pf2_right-1,y ; +4 = 45
|
||||
sta PF2 ; +3 = 48 ** MUST STORE PF2 2ND TIME ON EXACTLY CYCLE 48 **
|
||||
inx ; +2 = 50
|
||||
inx ; +2 = 52
|
||||
dec subrow ; +5 = 57
|
||||
bne header_loop ; +2 = 59
|
||||
dey ; +2 = 61
|
||||
beq header_done ; +2 = 63
|
||||
lda #4 ; +2 = 65
|
||||
sta subrow ; +3 = 68
|
||||
bne header_loop ; +3 = 71
|
||||
;; We've cut it very fine here! We only have 76 cycles per
|
||||
;; scanline and we use nearly all of them.
|
||||
header_done:
|
||||
;; Ruled split between title and data (8 lines)
|
||||
ldy #$00 ; Clear playfield now that we're done (+2 = 72)
|
||||
ldx #$0c ; Default status color is light grey (+2 = 74)
|
||||
sta WSYNC ; Rest of previous line
|
||||
sty PF0
|
||||
sty PF1
|
||||
sty PF2
|
||||
stx COLUPF
|
||||
stx COLUP0
|
||||
stx COLUP1
|
||||
dey
|
||||
ldx #$f0
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
stx PF0 ; Fill playfield completely
|
||||
sty PF1
|
||||
sty PF2
|
||||
|
||||
ldy #$01
|
||||
sty CTRLPF ; Symmetric PF
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
dey
|
||||
sty PF0 ; Clear playfield again
|
||||
sty PF1
|
||||
sty PF2
|
||||
|
||||
ldy #$08 ; 32 lines (for letters; 8, 16, 8)
|
||||
* sta WSYNC
|
||||
dey
|
||||
bne -
|
||||
ldy #$05
|
||||
* lda (high_nybble), y
|
||||
sta GRP0
|
||||
lda (low_nybble), y
|
||||
sta GRP1
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
dey
|
||||
bpl -
|
||||
iny
|
||||
sty GRP0
|
||||
sty GRP1
|
||||
ldy #$0A
|
||||
* sta WSYNC
|
||||
dey
|
||||
bne -
|
||||
|
||||
;; Top border (12 lines)
|
||||
lda #$03
|
||||
sta PF1
|
||||
lda #$ff
|
||||
sta PF2
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
ldx #$00
|
||||
stx PF1
|
||||
stx PF2
|
||||
ldx #$02 ; Turn on walls (the missiles)
|
||||
stx ENAM0
|
||||
stx ENAM1
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta PF2
|
||||
lda curcol
|
||||
sta COLUPF
|
||||
|
||||
;; Color blob (96 lines)
|
||||
ldx #96
|
||||
* sta WSYNC
|
||||
dex
|
||||
bne -
|
||||
|
||||
;; Bottom border (12 lines)
|
||||
stx PF2
|
||||
lda #$0c
|
||||
sta COLUPF
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
stx ENAM0 ; Turn off walls (the missles)
|
||||
stx ENAM1
|
||||
lda #$03
|
||||
sta PF1
|
||||
lda #$ff
|
||||
sta PF2
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
sta WSYNC
|
||||
stx PF1
|
||||
stx PF2
|
||||
ldx #$0a
|
||||
* sta WSYNC
|
||||
dex
|
||||
bne -
|
||||
|
||||
; Turn on VBLANK, do 30 lines of Overscan
|
||||
lda #$02
|
||||
sta VBLANK
|
||||
ldy #30
|
||||
* sta WSYNC
|
||||
dey
|
||||
bne -
|
||||
jmp frame ; And the frame is done, back to VSYNC.
|
||||
|
||||
;;; Graphical data. Notice that we have to start not on a page
|
||||
;;; boundary, but with all graphics in each group on one page.
|
||||
.advance $FF01
|
||||
pf0_left:
|
||||
.byte $e0,$20,$20,$20,$e0
|
||||
|
||||
pf1_left:
|
||||
.byte $77,$54,$54,$54,$74
|
||||
|
||||
pf2_left:
|
||||
.byte $ae,$6a,$ea,$aa,$ee
|
||||
|
||||
pf0_right:
|
||||
.byte $00,$00,$00,$00,$00
|
||||
|
||||
pf1_right:
|
||||
.byte $4e,$48,$4c,$48,$ee
|
||||
|
||||
pf2_right:
|
||||
.byte $27,$24,$27,$21,$77
|
||||
|
||||
;; We don't need a digits_high. It's always $FF!
|
||||
digits_low:
|
||||
.byte <digit_0, <digit_1, <digit_2, <digit_3
|
||||
.byte <digit_4, <digit_5, <digit_6, <digit_7
|
||||
.byte <digit_8, <digit_9, <digit_a, <digit_b
|
||||
.byte <digit_c, <digit_d, <digit_e, <digit_f
|
||||
|
||||
digit_0:
|
||||
.byte $3c,$66,$76,$6e,$66,$3c
|
||||
digit_1:
|
||||
.byte $7e,$18,$18,$18,$38,$18
|
||||
digit_2:
|
||||
.byte $7e,$30,$18,$0c,$66,$3c
|
||||
digit_3:
|
||||
.byte $3c,$66,$0c,$18,$0c,$7e
|
||||
digit_4:
|
||||
.byte $0c,$7e,$6c,$3c,$1c,$0c
|
||||
digit_5:
|
||||
.byte $3c,$66,$06,$7c,$60,$7e
|
||||
digit_6:
|
||||
.byte $3c,$66,$66,$7c,$60,$3c
|
||||
digit_7:
|
||||
.byte $30,$30,$18,$0c,$06,$7e
|
||||
digit_8:
|
||||
.byte $3c,$66,$66,$3c,$66,$3c
|
||||
digit_9:
|
||||
.byte $38,$0c,$06,$3e,$66,$3c
|
||||
digit_a:
|
||||
.byte $66,$7e,$66,$66,$3c,$18
|
||||
digit_b:
|
||||
.byte $7c,$66,$66,$7c,$66,$7c
|
||||
digit_c:
|
||||
.byte $3c,$66,$60,$60,$66,$3c
|
||||
digit_d:
|
||||
.byte $78,$6c,$66,$66,$6c,$78
|
||||
digit_e:
|
||||
.byte $7e,$60,$60,$7c,$60,$7e
|
||||
digit_f:
|
||||
.byte $60,$60,$60,$7c,$60,$7e
|
||||
;;; Interrupt vectors.
|
||||
.advance $FFFA
|
||||
.word reset, reset, reset
|
|
@ -9,37 +9,42 @@
|
|||
.space counter 1
|
||||
|
||||
.text
|
||||
.org $FF00
|
||||
.org $F800
|
||||
|
||||
reset: `clean'start
|
||||
|
||||
; Initialize the player sprites.
|
||||
|
||||
; We're going to use quad-sized players for our
|
||||
; letters. With 160 color clocks, and letters
|
||||
; twenty clocks wide, and a 68 color clock HBLANK,
|
||||
; we want to place the two letters at color clock
|
||||
; 68+80-20-2 = 126 and 68+80+2 = 150. Those
|
||||
; translate to cycle counts 42 and 50.
|
||||
; letters, and each one is 5 notional pixels wide.
|
||||
; When we write RESP*, the start cycle after WSYNC
|
||||
; determines the pixel it appears at with the
|
||||
; formula 3N - 54 (minimum 1). Cycles 36 and 44
|
||||
; get us close. We end up 4 pixels too far left.
|
||||
|
||||
; While we wait, we set up our sprites to be
|
||||
; quad-sized and initialize the independent
|
||||
; color-counters for each sprite.
|
||||
|
||||
sta WSYNC ; 3
|
||||
lda #$07 ; 5
|
||||
sta NUSIZ0 ; 7
|
||||
sta NUSIZ1 ; 10
|
||||
lda #$20 ; 13
|
||||
ldy #5 ; 15
|
||||
sta WSYNC
|
||||
lda #$07 ; +2= 2
|
||||
sta NUSIZ0 ; +3= 5
|
||||
sta NUSIZ1 ; +3= 8
|
||||
lda #$20 ; +2=10
|
||||
ldy #5 ; +2=12
|
||||
* dey
|
||||
bne - ; 20-25-30-35-39
|
||||
sta RESP0 ; 42 - color clock 126
|
||||
sta col'0 ; 45
|
||||
eor #$80 ; 47
|
||||
sta RESP1 ; 50 - color clock 150
|
||||
bne - ; 17-22-27-32-36
|
||||
sta RESP0 ; +3=39 (P0 at pixel 54)
|
||||
sta col'0 ; +3=42
|
||||
eor #$80 ; +2=44
|
||||
sta RESP1 ; (P1 at pixel 78)
|
||||
sta col'1
|
||||
sta temp
|
||||
lda #$C0 ; HMOVE us 4 right
|
||||
sta HMP0
|
||||
sta HMP1
|
||||
sta WSYNC
|
||||
sta HMOVE
|
||||
|
||||
frame: `vertical'sync
|
||||
lda #43
|
||||
|
@ -117,7 +122,7 @@ frame: `vertical'sync
|
|||
dey ; loop.
|
||||
bne -
|
||||
|
||||
; Clear out the player graphics,,,
|
||||
; Clear out the player graphics...
|
||||
lda #$00
|
||||
sta GRP0
|
||||
sta GRP1
|
|
@ -10,7 +10,8 @@ import Ophis.CmdLine
|
|||
import Ophis.IR as IR
|
||||
import Ophis.Frontend as FE
|
||||
import Ophis.Errors as Err
|
||||
import math, os.path
|
||||
import math
|
||||
import os.path
|
||||
|
||||
basecharmap = "".join([chr(x) for x in range(256)])
|
||||
currentcharmap = basecharmap
|
||||
|
@ -68,7 +69,7 @@ def pragmaIncbin(ppt, line, result):
|
|||
line.expect("EOL")
|
||||
if type(filename) == str:
|
||||
try:
|
||||
f = file(os.path.join(FE.context_directory, filename), "rb")
|
||||
f = open(os.path.join(FE.context_directory, filename), "rb")
|
||||
if offset.hardcoded and (size is None or size.hardcoded):
|
||||
# We know how big it will be, we can just use the values.
|
||||
# First check to make sure they're sane
|
||||
|
@ -94,7 +95,7 @@ def pragmaIncbin(ppt, line, result):
|
|||
size = IR.ConstantExpr(-1)
|
||||
f.seek(offset.value())
|
||||
bytes = f.read(size.value())
|
||||
bytes = [IR.ConstantExpr(ord(x)) for x in bytes]
|
||||
bytes = [IR.ConstantExpr(x) for x in bytes]
|
||||
result.append(IR.Node(ppt, "Byte", *bytes))
|
||||
else:
|
||||
# offset or length could change based on label placement.
|
||||
|
@ -103,7 +104,7 @@ def pragmaIncbin(ppt, line, result):
|
|||
# alias. Don't use symbolic aliases when extracting tiny
|
||||
# pieces out of humongous files, I guess.
|
||||
bytes = f.read()
|
||||
bytes = [IR.ConstantExpr(ord(x)) for x in bytes]
|
||||
bytes = [IR.ConstantExpr(x) for x in bytes]
|
||||
if size is None:
|
||||
size = IR.SequenceExpr([IR.ConstantExpr(len(bytes)),
|
||||
"-",
|
||||
|
@ -141,7 +142,7 @@ def pragmaCharmapbin(ppt, line, result):
|
|||
line.expect("EOL")
|
||||
if type(filename) == str:
|
||||
try:
|
||||
f = file(os.path.join(FE.context_directory, filename), "rb")
|
||||
f = open(os.path.join(FE.context_directory, filename), "rb")
|
||||
bytes = f.read()
|
||||
f.close()
|
||||
except IOError:
|
||||
|
|
|
@ -18,14 +18,14 @@ def log(err):
|
|||
the global error count."""
|
||||
global count
|
||||
count = count + 1
|
||||
print>>sys.stderr, currentpoint + ": " + err
|
||||
print(currentpoint + ": " + err, file=sys.stderr)
|
||||
|
||||
|
||||
def report():
|
||||
"Print out the number of errors."
|
||||
if count == 0:
|
||||
print>>sys.stderr, "No errors"
|
||||
print("No errors", file=sys.stderr)
|
||||
elif count == 1:
|
||||
print>>sys.stderr, "1 error"
|
||||
print("1 error", file=sys.stderr)
|
||||
else:
|
||||
print>>sys.stderr, str(count) + " errors"
|
||||
print(str(count) + " errors", file=sys.stderr)
|
||||
|
|
|
@ -70,7 +70,7 @@ def lex(point, line):
|
|||
return
|
||||
elif firstchar in bases:
|
||||
try:
|
||||
result.append(Lexeme("NUM", long(rest, bases[firstchar][1])))
|
||||
result.append(Lexeme("NUM", int(rest, bases[firstchar][1])))
|
||||
return
|
||||
except ValueError:
|
||||
Err.log('Invalid ' + bases[firstchar][0] + ' constant: ' +
|
||||
|
@ -79,7 +79,7 @@ def lex(point, line):
|
|||
return
|
||||
elif firstchar.isdigit():
|
||||
try:
|
||||
result.append(Lexeme("NUM", long(token)))
|
||||
result.append(Lexeme("NUM", int(token)))
|
||||
except ValueError:
|
||||
Err.log('Identifiers may not begin with a number')
|
||||
result.append(Lexeme("LABEL", "ERROR"))
|
||||
|
@ -403,19 +403,19 @@ def parse_file(ppt, filename, load_once=False):
|
|||
filename))
|
||||
if load_once and filename in loadedfiles:
|
||||
if Cmd.print_loaded_files:
|
||||
print>>sys.stderr, "Skipping " + filename
|
||||
print("Skipping " + filename, file=sys.stderr)
|
||||
return IR.NullNode
|
||||
loadedfiles[filename] = True
|
||||
if Cmd.print_loaded_files:
|
||||
if filename != '-':
|
||||
print>>sys.stderr, "Loading " + filename
|
||||
print("Loading " + filename, file=sys.stderr)
|
||||
else:
|
||||
print>>sys.stderr, "Loading from standard input"
|
||||
print("Loading from standard input", file=sys.stderr)
|
||||
try:
|
||||
if filename != '-':
|
||||
if context_directory is not None:
|
||||
filename = os.path.join(context_directory, filename)
|
||||
f = file(filename)
|
||||
f = open(filename, "rt")
|
||||
linelist = f.readlines()
|
||||
f.close()
|
||||
context_directory = os.path.abspath(os.path.dirname(filename))
|
||||
|
@ -423,8 +423,8 @@ def parse_file(ppt, filename, load_once=False):
|
|||
context_directory = os.getcwd()
|
||||
linelist = sys.stdin.readlines()
|
||||
pptlist = ["%s:%d" % (filename, i + 1) for i in range(len(linelist))]
|
||||
lexlist = map(lex, pptlist, linelist)
|
||||
IRlist = map(parse_line, pptlist, lexlist)
|
||||
lexlist = list(map(lex, pptlist, linelist))
|
||||
IRlist = list(map(parse_line, pptlist, lexlist))
|
||||
IRlist = [node for node in IRlist if node is not IR.NullNode]
|
||||
context_directory = old_context
|
||||
return IR.SequenceNode(ppt, IRlist)
|
||||
|
|
|
@ -179,7 +179,7 @@ class SequenceExpr(Expr):
|
|||
return True
|
||||
|
||||
def value(self, env=None):
|
||||
subs = map((lambda x: x.value(env)), self.operands)
|
||||
subs = list(map((lambda x: x.value(env)), self.operands))
|
||||
result = subs[0]
|
||||
index = 1
|
||||
for op in self.operators:
|
||||
|
|
|
@ -40,10 +40,10 @@ class Listing(object):
|
|||
if self.filename == "-":
|
||||
out = sys.stdout
|
||||
else:
|
||||
out = file(self.filename, "w")
|
||||
out = open(self.filename, "wt")
|
||||
for x in self.listing:
|
||||
if type(x) is str:
|
||||
print>>out, x
|
||||
print(x, file=out)
|
||||
elif type(x) is tuple:
|
||||
i = 0
|
||||
pc = x[0]
|
||||
|
@ -59,7 +59,7 @@ class Listing(object):
|
|||
charline += "."
|
||||
else:
|
||||
charline += chr(c)
|
||||
print>>out, "%-54s |%-16s|" % (dataline, charline)
|
||||
print("%-54s |%-16s|" % (dataline, charline), file=out)
|
||||
i += 16
|
||||
if self.filename != "-":
|
||||
out.close()
|
||||
|
@ -118,7 +118,7 @@ class LabelMapper(object):
|
|||
if self.filename == "-":
|
||||
out = sys.stdout
|
||||
else:
|
||||
out = file(self.filename, "w")
|
||||
out = open(self.filename, "wt")
|
||||
maxlabellen = 0
|
||||
self.labeldata.sort()
|
||||
for (loc, label, srcloc) in self.labeldata:
|
||||
|
|
|
@ -55,7 +55,7 @@ def expandMacro(ppt, name, arglist):
|
|||
Err.log("Undefined macro '%s'" % name)
|
||||
return IR.NullNode
|
||||
argexprs = [IR.Node(ppt, "Label", "_*%d" % i, arg)
|
||||
for (i, arg) in zip(xrange(1, sys.maxint), arglist)]
|
||||
for (i, arg) in zip(range(1, sys.maxsize), arglist)]
|
||||
bindexprs = [IR.Node(ppt, "Label", "_%d" % i, IR.LabelExpr("_*%d" % i))
|
||||
for i in range(1, len(arglist) + 1)]
|
||||
body = [IR.Node("%s->%s" % (ppt, node.ppt), node.nodetype, *node.data)
|
||||
|
@ -70,7 +70,7 @@ def dump():
|
|||
global macros
|
||||
for mac in macros:
|
||||
body = macros[mac]
|
||||
print>>sys.stderr, "Macro: " + mac
|
||||
print("Macro: " + mac, file=sys.stderr)
|
||||
for node in body:
|
||||
print>>sys.stderr, node
|
||||
print>>sys.stderr, ""
|
||||
print(node, file=sys.stderr)
|
||||
print("", file=sys.stderr)
|
||||
|
|
|
@ -72,7 +72,7 @@ def run_all():
|
|||
try:
|
||||
outfile = Ophis.CmdLine.outfile
|
||||
if outfile == '-':
|
||||
output = sys.stdout
|
||||
output = sys.stdout.buffer
|
||||
if sys.platform == "win32":
|
||||
# We can't dump our binary in text mode; that would be
|
||||
# disastrous. So, we'll do some platform-specific
|
||||
|
@ -80,16 +80,16 @@ def run_all():
|
|||
import msvcrt
|
||||
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
|
||||
elif outfile is None:
|
||||
output = file('ophis.bin', 'wb')
|
||||
output = open('ophis.bin', 'wb')
|
||||
else:
|
||||
output = file(outfile, 'wb')
|
||||
output.write("".join(map(chr, a.output)))
|
||||
output = open(outfile, 'wb')
|
||||
output.write(bytes(a.output))
|
||||
output.flush()
|
||||
if outfile != '-':
|
||||
output.close()
|
||||
return 0
|
||||
except IOError:
|
||||
print>>sys.stderr, "Could not write to " + outfile
|
||||
print("Could not write to " + outfile, file=sys.stderr)
|
||||
return 1
|
||||
else:
|
||||
Err.report()
|
||||
|
|
|
@ -67,18 +67,18 @@ class Pass(object):
|
|||
printing debugging information."""
|
||||
if Err.count == 0:
|
||||
if Cmd.print_pass:
|
||||
print>>sys.stderr, "Running: " + self.name
|
||||
print("Running: " + self.name, file=sys.stderr)
|
||||
env.reset()
|
||||
self.prePass()
|
||||
node.accept(self, env)
|
||||
self.postPass()
|
||||
env.reset()
|
||||
if Cmd.print_labels:
|
||||
print>>sys.stderr, "Current labels:"
|
||||
print>>sys.stderr, env
|
||||
print("Current labels:", file=sys.stderr)
|
||||
print(env, file=sys.stderr)
|
||||
if Cmd.print_ir:
|
||||
print>>sys.stderr, "Current IR:"
|
||||
print>>sys.stderr, node
|
||||
print("Current IR:", file=sys.stderr)
|
||||
print(node, file=sys.stderr)
|
||||
|
||||
|
||||
class FixPoint(object):
|
||||
|
@ -92,7 +92,7 @@ class FixPoint(object):
|
|||
def go(self, node, env):
|
||||
"""Runs this FixPoint's passes, in order, until the fixpoint
|
||||
is true. Always runs the passes at least once."""
|
||||
for i in xrange(100):
|
||||
for i in range(100):
|
||||
if Err.count != 0:
|
||||
break
|
||||
for p in self.passes:
|
||||
|
@ -102,7 +102,7 @@ class FixPoint(object):
|
|||
if self.fixpoint():
|
||||
break
|
||||
if Cmd.print_pass:
|
||||
print>>sys.stderr, "Fixpoint failed, looping back"
|
||||
print("Fixpoint failed, looping back", file=sys.stderr)
|
||||
else:
|
||||
Err.log("Can't make %s converge! Maybe there's a recursive "
|
||||
"dependency somewhere?" % self.name)
|
||||
|
@ -120,7 +120,7 @@ class DefineMacros(Pass):
|
|||
if self.inDef:
|
||||
Err.log("Unmatched .macro")
|
||||
elif Cmd.print_ir:
|
||||
print>>sys.stderr, "Macro definitions:"
|
||||
print("Macro definitions:", file=sys.stderr)
|
||||
Macro.dump()
|
||||
|
||||
def visitMacroBegin(self, node, env):
|
||||
|
@ -197,11 +197,11 @@ class InitLabels(Pass):
|
|||
env[label] = 0
|
||||
self.changed = True
|
||||
if label in ['a', 'x', 'y'] and self.runcount == 1:
|
||||
print>>sys.stderr, str(node.ppt) + ": WARNING: " \
|
||||
"using register name as label"
|
||||
print(str(node.ppt) + ": WARNING: " \
|
||||
"using register name as label", file=sys.stderr)
|
||||
if label in Ops.opcodes and self.runcount == 1:
|
||||
print>>sys.stderr, str(node.ppt) + ": WARNING: " \
|
||||
"using opcode name as label"
|
||||
print(str(node.ppt) + ": WARNING: " \
|
||||
"using opcode name as label", file=sys.stderr)
|
||||
|
||||
def visitUnknown(self, node, env):
|
||||
pass
|
||||
|
@ -636,16 +636,16 @@ class ExtendBranches(PCTracker):
|
|||
if Cmd.enable_4502_exts:
|
||||
node.nodetype = "RelativeLong"
|
||||
if Cmd.warn_on_branch_extend:
|
||||
print>>sys.stderr, str(node.ppt) + ": WARNING: " \
|
||||
"branch out of range, replacing with 16-bit relative branch"
|
||||
print(str(node.ppt) + ": WARNING: " \
|
||||
"branch out of range, replacing with 16-bit relative branch", file=sys.stderr)
|
||||
else:
|
||||
if opcode == 'bra':
|
||||
# If BRA - BRanch Always - is out of range, it's a JMP.
|
||||
node.data = ('jmp', expr, None)
|
||||
node.nodetype = "Absolute"
|
||||
if Cmd.warn_on_branch_extend:
|
||||
print>>sys.stderr, str(node.ppt) + ": WARNING: " \
|
||||
"bra out of range, replacing with jmp"
|
||||
print(str(node.ppt) + ": WARNING: " \
|
||||
"bra out of range, replacing with jmp", file=sys.stderr)
|
||||
else:
|
||||
# Otherwise, we replace it with a 'macro' of sorts by hand:
|
||||
# $branch LOC -> $reversed_branch ^+5; JMP LOC
|
||||
|
@ -661,11 +661,11 @@ class ExtendBranches(PCTracker):
|
|||
node.nodetype = 'SEQUENCE'
|
||||
node.data = expansion
|
||||
if Cmd.warn_on_branch_extend:
|
||||
print>>sys.stderr, str(node.ppt) + ": WARNING: " + \
|
||||
print(str(node.ppt) + ": WARNING: " + \
|
||||
opcode + " out of range, " \
|
||||
"replacing with " + \
|
||||
ExtendBranches.reversed[opcode] + \
|
||||
"/jmp combo"
|
||||
"/jmp combo", file=sys.stderr)
|
||||
self.changed = True
|
||||
node.accept(self, env)
|
||||
else:
|
||||
|
@ -690,11 +690,11 @@ class ExtendBranches(PCTracker):
|
|||
node.nodetype = 'SEQUENCE'
|
||||
node.data = expansion
|
||||
if Cmd.warn_on_branch_extend:
|
||||
print>>sys.stderr, str(node.ppt) + ": WARNING: " + \
|
||||
print(str(node.ppt) + ": WARNING: " + \
|
||||
opcode + " out of range, " \
|
||||
"replacing with " + \
|
||||
ExtendBranches.reversed[opcode] + \
|
||||
"/jmp combo"
|
||||
"/jmp combo", file=sys.stderr)
|
||||
self.changed = True
|
||||
node.accept(self, env)
|
||||
else:
|
||||
|
@ -763,10 +763,10 @@ class Assembler(Pass):
|
|||
self.listing.dump()
|
||||
self.mapper.dump()
|
||||
if Cmd.print_summary and Err.count == 0:
|
||||
print>>sys.stderr, "Assembly complete: %s bytes output " \
|
||||
print("Assembly complete: %s bytes output " \
|
||||
"(%s code, %s data, %s filler)" \
|
||||
% (len(self.output),
|
||||
self.code, self.data, self.filler)
|
||||
self.code, self.data, self.filler), file=sys.stderr)
|
||||
|
||||
def outputbyte(self, expr, env, tee=None):
|
||||
'Outputs a byte, with range checking'
|
||||
|
@ -799,7 +799,7 @@ class Assembler(Pass):
|
|||
'Outputs a little-endian dword, with range checking'
|
||||
if self.writeOK:
|
||||
val = expr.value(env)
|
||||
if val < 0x00000000 or val > 0xFFFFFFFFL:
|
||||
if val < 0x00000000 or val > 0xFFFFFFFF:
|
||||
Err.log("DWord constant " + str(expr) + " out of range")
|
||||
val = 0
|
||||
self.output.append(int(val & 0xFF))
|
||||
|
@ -829,7 +829,7 @@ class Assembler(Pass):
|
|||
'Outputs a big-endian dword, with range checking'
|
||||
if self.writeOK:
|
||||
val = expr.value(env)
|
||||
if val < 0x00000000 or val > 0xFFFFFFFFL:
|
||||
if val < 0x00000000 or val > 0xFFFFFFFF:
|
||||
Err.log("DWord constant " + str(expr) + " out of range")
|
||||
val = 0
|
||||
self.output.append(int((val >> 24) & 0xFF))
|
||||
|
@ -1083,7 +1083,7 @@ class Assembler(Pass):
|
|||
(pc, target))
|
||||
else:
|
||||
created = []
|
||||
for i in xrange(target - pc):
|
||||
for i in range(target - pc):
|
||||
self.outputbyte(node.data[1], env, created)
|
||||
self.filler += target - pc
|
||||
self.registerData(created, env.getPC())
|
||||
|
|
|
@ -86,9 +86,14 @@ Section "Ophis" SEC01
|
|||
File "..\..\examples\structuredemo.oph"
|
||||
File "..\..\examples\fibonacci.oph"
|
||||
File "..\..\examples\kinematics.oph"
|
||||
SetOutPath "$INSTDIR\examples\hi_stella"
|
||||
File "..\..\examples\hi_stella\hi_stella.oph"
|
||||
File "..\..\examples\hi_stella\README.txt"
|
||||
# Remove the older copies of hi_stella if needed
|
||||
Delete "$INSTDIR\examples\hi_stella\hi_stella.oph"
|
||||
Delete "$INSTDIR\examples\hi_stella\README.txt"
|
||||
RMDir "$INSTDIR\examples\hi_stella"
|
||||
SetOutPath "$INSTDIR\examples\stella"
|
||||
File "..\..\examples\stella\hi_stella.oph"
|
||||
File "..\..\examples\stella\colortest.oph"
|
||||
File "..\..\examples\stella\README.txt"
|
||||
SetOutPath "$INSTDIR\examples\hello_nes"
|
||||
File "..\..\examples\hello_nes\hello_prg.oph"
|
||||
File "..\..\examples\hello_nes\hello_chr.oph"
|
||||
|
@ -159,8 +164,9 @@ Section Uninstall
|
|||
Delete "$INSTDIR\ophis.exe"
|
||||
Delete "$INSTDIR\ophismanual.pdf"
|
||||
Delete "$INSTDIR\README.txt"
|
||||
Delete "$INSTDIR\examples\hi_stella\hi_stella.oph"
|
||||
Delete "$INSTDIR\examples\hi_stella\README.txt"
|
||||
Delete "$INSTDIR\examples\stella\hi_stella.oph"
|
||||
Delete "$INSTDIR\examples\stella\colortest.oph"
|
||||
Delete "$INSTDIR\examples\stella\README.txt"
|
||||
Delete "$INSTDIR\examples\hello_nes\hello_prg.oph"
|
||||
Delete "$INSTDIR\examples\hello_nes\hello_chr.oph"
|
||||
Delete "$INSTDIR\examples\hello_nes\hello_ines.oph"
|
||||
|
@ -180,7 +186,7 @@ Section Uninstall
|
|||
Delete "$STARTMENU\Manual.lnk"
|
||||
|
||||
RMDir "$SMPROGRAMS\$ICONS_GROUP"
|
||||
RMDir "$INSTDIR\examples\hi_stella"
|
||||
RMDir "$INSTDIR\examples\stella"
|
||||
RMDir "$INSTDIR\examples\hello_nes"
|
||||
RMDir "$INSTDIR\examples"
|
||||
RMDir "$INSTDIR\platform"
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
import struct
|
||||
|
||||
x = ''.join([chr(x) for x in range(256)])
|
||||
x = bytes(list(range(256)))
|
||||
bits = struct.unpack("32s32s32s32s32s32s32s32s", x)
|
||||
norm = [4, 5, 6, 7, 0, 1, 2, 3]
|
||||
ivrs = [4, 1, 0, 7, 6, 5, 2, 3]
|
||||
blnk = [4, 3, 2, 7, 0, 1, 6, 5]
|
||||
normmap = ''.join([bits[x] for x in norm])
|
||||
ivrsmap = ''.join([bits[x] for x in ivrs])
|
||||
blnkmap = ''.join([bits[x] for x in blnk])
|
||||
normmap = b''.join([bits[x] for x in norm])
|
||||
ivrsmap = b''.join([bits[x] for x in ivrs])
|
||||
blnkmap = b''.join([bits[x] for x in blnk])
|
||||
|
||||
|
||||
def dumpfile(n, m):
|
||||
f = file(n, 'wb')
|
||||
f = open(n, 'wb')
|
||||
f.write(m)
|
||||
f.close()
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
|
||||
verbose = 0
|
||||
|
@ -80,7 +80,7 @@ def decomment(l):
|
|||
|
||||
|
||||
def decomment_readlines(fname):
|
||||
result = [decomment(x) for x in file(fname).readlines()]
|
||||
result = [decomment(x) for x in open(fname, "rt").readlines()]
|
||||
return [x for x in result if len(x) > 0]
|
||||
|
||||
|
||||
|
@ -103,22 +103,22 @@ def parse_chipset_file(fname):
|
|||
result[op] = []
|
||||
result[op].append((mnem, flatmodes.index(mode)))
|
||||
else:
|
||||
print "Unknown mode '%s'" % s_p[1]
|
||||
print("Unknown mode '%s'" % s_p[1])
|
||||
except ValueError:
|
||||
print "Illegal opcode '%s'" % l[0]
|
||||
print("Illegal opcode '%s'" % l[0])
|
||||
return result
|
||||
|
||||
|
||||
def collate_chipset_map(cs_list, base):
|
||||
result = {}
|
||||
for (opcode, insts) in zip(range(256), cs_list):
|
||||
for (opcode, insts) in zip(list(range(256)), cs_list):
|
||||
if insts is not None:
|
||||
for inst in insts:
|
||||
(mnem, mode) = inst
|
||||
if mnem not in result:
|
||||
result[mnem] = [None] * len(modes)
|
||||
if result[mnem][mode] is not None:
|
||||
print "Warning: Reassigning %s - %s" % (mnem, modes[mode])
|
||||
print("Warning: Reassigning %s - %s" % (mnem, modes[mode]))
|
||||
result[mnem][mode] = opcode
|
||||
if base is not None:
|
||||
todel = []
|
||||
|
@ -127,9 +127,9 @@ def collate_chipset_map(cs_list, base):
|
|||
if result[x] == base[x]:
|
||||
todel.append(x)
|
||||
elif verbose != 0:
|
||||
print "# Opcode %s changed" % x
|
||||
print("# Opcode %s changed" % x)
|
||||
elif verbose != 0:
|
||||
print "# Opcode %s added" % x
|
||||
print("# Opcode %s added" % x)
|
||||
for x in todel:
|
||||
del result[x]
|
||||
return result
|
||||
|
@ -143,14 +143,14 @@ def mapval(x):
|
|||
|
||||
|
||||
def dump_map(m, prologue=''):
|
||||
mnems = m.keys()
|
||||
mnems = list(m.keys())
|
||||
mnems.sort()
|
||||
for mnem in mnems:
|
||||
codes = [mapval(x) for x in m[mnem]]
|
||||
print "%s'%s': [%s,\n%s %s]," % (prologue, mnem,
|
||||
print("%s'%s': [%s,\n%s %s]," % (prologue, mnem,
|
||||
', '.join(codes[:8]),
|
||||
prologue + " " * len(mnem),
|
||||
', '.join(codes[8:]))
|
||||
', '.join(codes[8:])))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -165,18 +165,18 @@ if __name__ == '__main__':
|
|||
for y in [z.split(':', 1) for z in decomment_readlines(x)]]
|
||||
for l in ls:
|
||||
if len(l) != 2:
|
||||
print "Could not parse the chipset line '%s'" % ":".join(l)
|
||||
print("Could not parse the chipset line '%s'" % ":".join(l))
|
||||
else:
|
||||
archs.append((l[0], l[1]))
|
||||
except IOError:
|
||||
print "Could not read file %s" % x
|
||||
print prologue
|
||||
print("Could not read file %s" % x)
|
||||
print(prologue)
|
||||
baseset = None
|
||||
for (field, fname) in archs:
|
||||
chipset_list = parse_chipset_file(fname)
|
||||
instruction_map = collate_chipset_map(chipset_list, baseset)
|
||||
if baseset is None:
|
||||
baseset = instruction_map
|
||||
print "%s = {" % field
|
||||
print("%s = {" % field)
|
||||
dump_map(instruction_map, ' ' * (len(field) + 4))
|
||||
print "%s}" % (' ' * (len(field) + 3))
|
||||
print("%s}" % (' ' * (len(field) + 3)))
|
||||
|
|
|
@ -193,7 +193,7 @@
|
|||
C0: CPY - Immediate
|
||||
C1: CMP - (Zero Page, X)
|
||||
C2: CPZ - Immediate
|
||||
C3: DEW - Absolute
|
||||
C3: DEW - Zero Page
|
||||
C4: CPY - Zero Page
|
||||
C5: CMP - Zero Page
|
||||
C6: DEC - Zero Page
|
||||
|
@ -225,7 +225,7 @@
|
|||
E0: CPX - Immediate
|
||||
E1: SBC - (Zero Page, X)
|
||||
E2: LDA - (Zero Page, SP), Y
|
||||
E3: INW - Absolute
|
||||
E3: INW - Zero Page
|
||||
E4: CPX - Zero Page
|
||||
E5: SBC - Zero Page
|
||||
E6: INC - Zero Page
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
|
@ -20,14 +20,14 @@ failed = 0
|
|||
|
||||
|
||||
def assembled(raw):
|
||||
return ' '.join(["%02X" % ord(c) for c in raw])
|
||||
return ' '.join(["%02X" % c for c in raw])
|
||||
|
||||
|
||||
def assemble_raw(asm="", options=[]):
|
||||
p = subprocess.Popen([pythonpath, ophispath] + options,
|
||||
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
return p.communicate(asm)
|
||||
return p.communicate(asm.encode("UTF-8"))
|
||||
|
||||
|
||||
def assemble_string(asm, options=[]):
|
||||
|
@ -37,15 +37,15 @@ def assemble_string(asm, options=[]):
|
|||
def test_string(test_name, asm, expected, options=[]):
|
||||
(out, err) = assemble_string(asm, options)
|
||||
if out == expected:
|
||||
print "%s: SUCCESS" % test_name
|
||||
print("%s: SUCCESS" % test_name)
|
||||
else:
|
||||
global failed
|
||||
failed += 1
|
||||
print "%s: FAILED" % test_name
|
||||
print "Assembled code: ", assembled(out)
|
||||
print "Expected code: ", assembled(expected)
|
||||
print("%s: FAILED" % test_name)
|
||||
print("Assembled code: ", assembled(out))
|
||||
print("Expected code: ", assembled(expected))
|
||||
if err != '':
|
||||
print "Error output:\n%s" % err
|
||||
print("Error output:\n%s" % err.decode(sys.stderr.encoding))
|
||||
|
||||
|
||||
def test_file(test_name, fname, ename, options=[]):
|
||||
|
@ -57,7 +57,7 @@ def test_file(test_name, fname, ename, options=[]):
|
|||
expected = f.read()
|
||||
f.close()
|
||||
else: # a test where we expect failure
|
||||
expected = ''
|
||||
expected = b''
|
||||
test_string(test_name, asm, expected, options)
|
||||
|
||||
|
||||
|
@ -66,16 +66,16 @@ def test_file(test_name, fname, ename, options=[]):
|
|||
# on, then we start running through the features.
|
||||
|
||||
def test_basic():
|
||||
print
|
||||
print "==== BASIC OPERATION ===="
|
||||
print()
|
||||
print("==== BASIC OPERATION ====")
|
||||
test_string('Basic Ophis operation', '.byte "Hello, world!"',
|
||||
'Hello, world!')
|
||||
b'Hello, world!')
|
||||
test_string('Newline/EOF passthrough', '.byte 10,26,13,4,0,"Hi",13,10',
|
||||
'\n\x1a\r\x04\x00Hi\r\n')
|
||||
b'\n\x1a\r\x04\x00Hi\r\n')
|
||||
# Normally these would go in Expressions but we need them to run the
|
||||
# tests for relative instructions.
|
||||
test_string('Program counter recognition', '.org $41\nlda #^\n', '\xa9A')
|
||||
test_string('Program counter math', '.org $41\nlda #^+3\n', '\xa9D')
|
||||
test_string('Program counter recognition', '.org $41\nlda #^\n', b'\xa9A')
|
||||
test_string('Program counter math', '.org $41\nlda #^+3\n', b'\xa9D')
|
||||
if failed == 0:
|
||||
test_file('Basic instructions', 'testbase.oph', 'testbase.bin')
|
||||
test_file('Basic data pragmas', 'testdata.oph', 'testdata.bin')
|
||||
|
@ -100,13 +100,13 @@ def test_basic():
|
|||
|
||||
def test_outfile():
|
||||
global failed
|
||||
print "\n==== INPUT AND OUTPUT ===="
|
||||
print("\n==== INPUT AND OUTPUT ====")
|
||||
if os.path.exists("ophis.bin"):
|
||||
print "TEST SUITE FAILED: unclean test environment (ophis.bin exists)"
|
||||
print("TEST SUITE FAILED: unclean test environment (ophis.bin exists)")
|
||||
failed += 1
|
||||
return
|
||||
elif os.path.exists("custom.bin"):
|
||||
print "TEST SUITE FAILED: unclean test environment (custom.bin exists)"
|
||||
print("TEST SUITE FAILED: unclean test environment (custom.bin exists)")
|
||||
failed += 1
|
||||
return
|
||||
|
||||
|
@ -114,45 +114,46 @@ def test_outfile():
|
|||
try:
|
||||
assemble_raw('.byte "Hello, world!", 10', ['-'])
|
||||
f = open('ophis.bin', 'rb')
|
||||
if f.read() != 'Hello, world!\n':
|
||||
print "Default output filename: FAILED (bad output)"
|
||||
if f.read() != b'Hello, world!\n':
|
||||
print("Default output filename: FAILED (bad output)")
|
||||
failed += 1
|
||||
else:
|
||||
print "Default output filename: SUCCESS"
|
||||
print("Default output filename: SUCCESS")
|
||||
f.close()
|
||||
os.unlink('ophis.bin')
|
||||
except:
|
||||
print "Default output filename: FAILED (exception)"
|
||||
print("Default output filename: FAILED (exception)")
|
||||
failed += 1
|
||||
raise
|
||||
|
||||
# Test 2: Command line override
|
||||
try:
|
||||
assemble_raw('.byte "Hello, world!", 10', ['-', '-o', 'custom.bin'])
|
||||
f = open('custom.bin', 'rb')
|
||||
if f.read() != 'Hello, world!\n':
|
||||
print "Commandline output filename: FAILED (bad output)"
|
||||
if f.read() != b'Hello, world!\n':
|
||||
print("Commandline output filename: FAILED (bad output)")
|
||||
failed += 1
|
||||
else:
|
||||
print "Commandline output filename: SUCCESS"
|
||||
print("Commandline output filename: SUCCESS")
|
||||
f.close()
|
||||
os.unlink('custom.bin')
|
||||
except:
|
||||
print "Commandline output filename: FAILED (exception)"
|
||||
print("Commandline output filename: FAILED (exception)")
|
||||
failed += 1
|
||||
|
||||
# Test 3: Pragma override
|
||||
try:
|
||||
assemble_raw('.outfile "custom.bin"\n.byte "Hello, world!", 10', ['-'])
|
||||
f = open('custom.bin', 'rb')
|
||||
if f.read() != 'Hello, world!\n':
|
||||
print "Commandline output filename: FAILED (bad output)"
|
||||
if f.read() != b'Hello, world!\n':
|
||||
print("Commandline output filename: FAILED (bad output)")
|
||||
failed += 1
|
||||
else:
|
||||
print "Commandline output filename: SUCCESS"
|
||||
print("Commandline output filename: SUCCESS")
|
||||
f.close()
|
||||
os.unlink('custom.bin')
|
||||
except:
|
||||
print "Commandline output filename: FAILED (exception)"
|
||||
print("Commandline output filename: FAILED (exception)")
|
||||
failed += 1
|
||||
|
||||
# Test 4: Command line override of .outfile
|
||||
|
@ -160,15 +161,15 @@ def test_outfile():
|
|||
assemble_raw('.outfile "custom2.bin"\n'
|
||||
'.byte "Hello, world!", 10', ['-', '-o', 'custom.bin'])
|
||||
f = open('custom.bin', 'rb')
|
||||
if f.read() != 'Hello, world!\n':
|
||||
print "Commandline override of pragma: FAILED (bad output)"
|
||||
if f.read() != b'Hello, world!\n':
|
||||
print("Commandline override of pragma: FAILED (bad output)")
|
||||
failed += 1
|
||||
else:
|
||||
print "Commandline override of pragma: SUCCESS"
|
||||
print("Commandline override of pragma: SUCCESS")
|
||||
f.close()
|
||||
os.unlink('custom.bin')
|
||||
except:
|
||||
print "Commandline override of pragma: FAILED (exception)"
|
||||
print("Commandline override of pragma: FAILED (exception)")
|
||||
failed += 1
|
||||
|
||||
# Test 5: Pragma repetition priority
|
||||
|
@ -177,15 +178,15 @@ def test_outfile():
|
|||
'.outfile "custom2.bin"\n'
|
||||
'.byte "Hello, world!", 10', ['-'])
|
||||
f = open('custom.bin', 'rb')
|
||||
if f.read() != 'Hello, world!\n':
|
||||
print "Pragma repetition: FAILED (bad output)"
|
||||
if f.read() != b'Hello, world!\n':
|
||||
print("Pragma repetition: FAILED (bad output)")
|
||||
failed += 1
|
||||
else:
|
||||
print "Pragma repetition: SUCCESS"
|
||||
print("Pragma repetition: SUCCESS")
|
||||
f.close()
|
||||
os.unlink('custom.bin')
|
||||
except:
|
||||
print "Pragma repetition: FAILED (exception)"
|
||||
print("Pragma repetition: FAILED (exception)")
|
||||
failed += 1
|
||||
|
||||
# Test 6: multiple input files
|
||||
|
@ -200,73 +201,73 @@ def test_outfile():
|
|||
s += f.read()
|
||||
f.close()
|
||||
if out != s:
|
||||
print "Multiple input files: FAILED (bad output)"
|
||||
print("Multiple input files: FAILED (bad output)")
|
||||
failed += 1
|
||||
else:
|
||||
print "Multiple input files: SUCCESS"
|
||||
print("Multiple input files: SUCCESS")
|
||||
except:
|
||||
print "Multiple input files: FAILED (exception)"
|
||||
print("Multiple input files: FAILED (exception)")
|
||||
failed += 1
|
||||
|
||||
|
||||
def test_transforms():
|
||||
print "\n==== BINARY TRANSFORM PASSES ===="
|
||||
print "Simple zero page selection: SUCCESS (covered in basic tests)"
|
||||
print("\n==== BINARY TRANSFORM PASSES ====")
|
||||
print("Simple zero page selection: SUCCESS (covered in basic tests)")
|
||||
test_string('Chained collapse', '.org $fa \n lda + \n lda ^ \n * rts \n',
|
||||
'\xa5\xfe\xa5\xfc\x60')
|
||||
b'\xa5\xfe\xa5\xfc\x60')
|
||||
test_string('Reversible collapse', '.org $fb \n bne ^+200 \n lda ^ \n',
|
||||
'\xf0\x03\x4c\xc5\x01\xad\x00\x01')
|
||||
b'\xf0\x03\x4c\xc5\x01\xad\x00\x01')
|
||||
|
||||
|
||||
def test_expressions():
|
||||
print "\n==== EXPRESSIONS AND LABELS ===="
|
||||
test_string('Basic addition', '.byte 3+2', '\x05')
|
||||
test_string('Basic subtraction', '.byte 3-2', '\x01')
|
||||
test_string('Basic multiplication', '.byte 3*2', '\x06')
|
||||
test_string('Basic division', '.byte 6/2', '\x03')
|
||||
test_string('Basic bit-union', '.byte 5|9', '\x0d')
|
||||
test_string('Basic bit-intersection', '.byte 5&9', '\x01')
|
||||
test_string('Basic bit-toggle', '.byte 5^9', '\x0c')
|
||||
test_string('Division truncation', '.byte 5/2', '\x02')
|
||||
test_string('Overflow', '.byte $FF*$10', '')
|
||||
test_string('Multibyte overflow', '.word $FF*$10', '\xf0\x0f')
|
||||
test_string('Masked overflow', '.byte $FF*$10&$FF', '\xf0')
|
||||
test_string('Underflow', '.byte 2-3', '')
|
||||
test_string('Masked underflow', '.byte 2-3&$FF', '\xff')
|
||||
test_string('Arithmetic precedence', '.byte 2+3*4-6/2', '\x0b')
|
||||
test_string('Parentheses', '.byte [2+3]*[4-6/2]', '\x05')
|
||||
print("\n==== EXPRESSIONS AND LABELS ====")
|
||||
test_string('Basic addition', '.byte 3+2', b'\x05')
|
||||
test_string('Basic subtraction', '.byte 3-2', b'\x01')
|
||||
test_string('Basic multiplication', '.byte 3*2', b'\x06')
|
||||
test_string('Basic division', '.byte 6/2', b'\x03')
|
||||
test_string('Basic bit-union', '.byte 5|9', b'\x0d')
|
||||
test_string('Basic bit-intersection', '.byte 5&9', b'\x01')
|
||||
test_string('Basic bit-toggle', '.byte 5^9', b'\x0c')
|
||||
test_string('Division truncation', '.byte 5/2', b'\x02')
|
||||
test_string('Overflow', '.byte $FF*$10', b'')
|
||||
test_string('Multibyte overflow', '.word $FF*$10', b'\xf0\x0f')
|
||||
test_string('Masked overflow', '.byte $FF*$10&$FF', b'\xf0')
|
||||
test_string('Underflow', '.byte 2-3', b'')
|
||||
test_string('Masked underflow', '.byte 2-3&$FF', b'\xff')
|
||||
test_string('Arithmetic precedence', '.byte 2+3*4-6/2', b'\x0b')
|
||||
test_string('Parentheses', '.byte [2+3]*[4-6/2]', b'\x05')
|
||||
test_string('String escapes',
|
||||
'.byte "The man said, \\"The \\\\ is Windowsy.\\""',
|
||||
'The man said, "The \\ is Windowsy."')
|
||||
b'The man said, "The \\ is Windowsy."')
|
||||
test_string('Byte selector precedence',
|
||||
'.byte >$d000+32,>[$d000+32],<[$D000-275]',
|
||||
'\xf0\xd0\xed')
|
||||
test_string('Named labels', '.org $6948\nl: .word l', 'Hi')
|
||||
test_string('.alias directive (basic)', '.alias hi $6948\n.word hi', 'Hi')
|
||||
b'\xf0\xd0\xed')
|
||||
test_string('Named labels', '.org $6948\nl: .word l', b'Hi')
|
||||
test_string('.alias directive (basic)', '.alias hi $6948\n.word hi', b'Hi')
|
||||
test_string('.alias directive (derived)',
|
||||
'.alias hi $6948\n.alias ho hi+$600\n.word hi,ho', 'HiHo')
|
||||
'.alias hi $6948\n.alias ho hi+$600\n.word hi,ho', b'HiHo')
|
||||
test_string('.alias directive (circular)',
|
||||
'.alias a c+1\n.alias b a+3\n.alias c b-4\n.word a, b, c',
|
||||
'')
|
||||
b'')
|
||||
test_string('.advance directive (basic)',
|
||||
'lda #$05\n.advance $05\n.byte ^',
|
||||
'\xa9\x05\x00\x00\x00\x05')
|
||||
b'\xa9\x05\x00\x00\x00\x05')
|
||||
test_string('.advance directive (filler)',
|
||||
'lda #$05\nf: .advance $05,f+3\n.byte ^',
|
||||
'\xa9\x05\x05\x05\x05\x05')
|
||||
b'\xa9\x05\x05\x05\x05\x05')
|
||||
test_string('.advance no-op', 'lda #$05\n.advance $02\n.byte ^',
|
||||
'\xa9\x05\x02')
|
||||
test_string('.advance failure', 'lda #$05\n.advance $01\n.byte ^', '')
|
||||
test_string('.checkpc, space > 0', 'lda #$05\n.checkpc $10', '\xa9\x05')
|
||||
test_string('.checkpc, space = 0', 'lda #$05\n.checkpc 2', '\xa9\x05')
|
||||
test_string('.checkpc, space < 0', 'lda $05\n.checkpc 1', '')
|
||||
b'\xa9\x05\x02')
|
||||
test_string('.advance failure', 'lda #$05\n.advance $01\n.byte ^', b'')
|
||||
test_string('.checkpc, space > 0', 'lda #$05\n.checkpc $10', b'\xa9\x05')
|
||||
test_string('.checkpc, space = 0', 'lda #$05\n.checkpc 2', b'\xa9\x05')
|
||||
test_string('.checkpc, space < 0', 'lda $05\n.checkpc 1', b'')
|
||||
test_string('A X Y usable as labels',
|
||||
'.alias a 1\n.alias x 2\n.alias y 3\n'
|
||||
'lda (a+x+y),y\nlda (x+y,x)',
|
||||
'\xb1\x06\xa1\x05')
|
||||
b'\xb1\x06\xa1\x05')
|
||||
test_string('Opcodes usable as labels',
|
||||
'ldy #$00\n dey: dey\n bne dey',
|
||||
'\xa0\x00\x88\xd0\xfd')
|
||||
b'\xa0\x00\x88\xd0\xfd')
|
||||
|
||||
|
||||
def test_segments():
|
||||
|
@ -277,18 +278,18 @@ def test_segments():
|
|||
'.org $61\n'
|
||||
'd:\n'
|
||||
'.text\n'
|
||||
'l: .byte l, d', 'Aa')
|
||||
test_string('Data cleanliness', '.byte 65\n.data\n.byte 65', '')
|
||||
'l: .byte l, d', b'Aa')
|
||||
test_string('Data cleanliness', '.byte 65\n.data\n.byte 65', b'')
|
||||
test_string('.space directive',
|
||||
'.data\n.org $41\n.space a 2\n.space b 1\n.space c 1\n'
|
||||
'.text\n.byte a, b, c\n', 'ACD')
|
||||
'.text\n.byte a, b, c\n', b'ACD')
|
||||
test_string('Multiple named segments',
|
||||
'.data\n.org $41\n.data a\n.org $61\n.data b\n.org $4a\n'
|
||||
'.data\n.space q 1\n.data a\n.space r 1\n.data b\n.space s 1\n'
|
||||
'.text\n.org $10\n.text a\n.org $20\n'
|
||||
'.text\n.byte ^,q,r,s\n'
|
||||
'.text a\n.byte ^,q,r,s\n',
|
||||
'\x10AaJ\x20AaJ')
|
||||
b'\x10AaJ\x20AaJ')
|
||||
|
||||
|
||||
def test_scopes():
|
||||
|
@ -300,13 +301,13 @@ def test_scopes():
|
|||
'.scend\n'
|
||||
'.scope\n'
|
||||
'_l: .byte _l\n'
|
||||
'.scend\n', 'AB')
|
||||
'.scend\n', b'AB')
|
||||
test_string('Data hiding outside of scope',
|
||||
'.org $41\n'
|
||||
'.scope\n'
|
||||
'_l: .byte _l\n'
|
||||
'.scend\n'
|
||||
' .byte _l\n', '')
|
||||
' .byte _l\n', b'')
|
||||
test_string('Repeated labels, nested scopes',
|
||||
'.org $41\n'
|
||||
'.scope\n'
|
||||
|
@ -315,17 +316,17 @@ def test_scopes():
|
|||
'_l: .byte _l\n'
|
||||
'.scend\n'
|
||||
' .byte _l\n'
|
||||
'.scend\n', 'ABA')
|
||||
'.scend\n', b'ABA')
|
||||
test_string('Anonymous labels (basic)',
|
||||
'.org $41\n'
|
||||
'* .byte -, +\n'
|
||||
'* .byte -, --\n', 'ACCA')
|
||||
'* .byte -, --\n', b'ACCA')
|
||||
test_string('Anonymous labels (across scopes)',
|
||||
'.org $41\n'
|
||||
'* .byte -, +\n'
|
||||
'.scope\n'
|
||||
'* .byte -, --\n'
|
||||
'.scend\n', 'ACCA')
|
||||
'.scend\n', b'ACCA')
|
||||
|
||||
|
||||
def test_macros():
|
||||
|
@ -334,12 +335,12 @@ def test_macros():
|
|||
'.macro greet\n'
|
||||
' .byte "hi"\n'
|
||||
'.macend\n'
|
||||
'`greet\n.invoke greet', "hihi")
|
||||
'`greet\n.invoke greet', b"hihi")
|
||||
test_string('Macros with arguments',
|
||||
'.macro greet\n'
|
||||
' .byte "hi",_1\n'
|
||||
'.macend\n'
|
||||
"`greet 'A\n.invoke greet 'B", "hiAhiB")
|
||||
"`greet 'A\n.invoke greet 'B", b"hiAhiB")
|
||||
test_string('Macros invoking macros',
|
||||
'.macro inner\n'
|
||||
' .byte " there"\n'
|
||||
|
@ -348,7 +349,7 @@ def test_macros():
|
|||
' .byte "hi"\n'
|
||||
' `inner\n'
|
||||
'.macend\n'
|
||||
"`greet", "hi there")
|
||||
"`greet", b"hi there")
|
||||
test_string('Macros defining macros (illegal)',
|
||||
'.macro greet\n'
|
||||
'.macro inner\n'
|
||||
|
@ -357,7 +358,7 @@ def test_macros():
|
|||
' .byte "hi"\n'
|
||||
' `inner\n'
|
||||
'.macend\n'
|
||||
"`greet", "")
|
||||
"`greet", b"")
|
||||
test_string('Fail on infinite recursion',
|
||||
'.macro inner\n'
|
||||
' .byte " there"\n'
|
||||
|
@ -367,75 +368,75 @@ def test_macros():
|
|||
' .byte "hi"\n'
|
||||
' `inner\n'
|
||||
'.macend\n'
|
||||
"`greet", "")
|
||||
"`greet", b"")
|
||||
|
||||
|
||||
def test_subfiles():
|
||||
print("\n==== COMPILATION UNITS ====")
|
||||
test_string(".include pragma", '.include "baseinc.oph"', 'BASIC\n')
|
||||
test_string(".include pragma", '.include "baseinc.oph"', b'BASIC\n')
|
||||
test_string(".include repeated",
|
||||
'.include "baseinc.oph"\n.include "baseinc.oph"',
|
||||
'BASIC\nBASIC\n')
|
||||
test_string(".require pragma", '.require "baseinc.oph"', 'BASIC\n')
|
||||
b'BASIC\nBASIC\n')
|
||||
test_string(".require pragma", '.require "baseinc.oph"', b'BASIC\n')
|
||||
test_string(".include before .require",
|
||||
'.include "baseinc.oph"\n.require "baseinc.oph"',
|
||||
'BASIC\n')
|
||||
b'BASIC\n')
|
||||
test_string(".require before .include",
|
||||
'.require "baseinc.oph"\n.include "baseinc.oph"',
|
||||
'BASIC\nBASIC\n')
|
||||
b'BASIC\nBASIC\n')
|
||||
test_string(".require same file twice with different paths",
|
||||
'.include "baseinc.oph"\n.include "sub/baseinc.oph"',
|
||||
'BASIC\nSUB 1 START\nSUB 1 END\n')
|
||||
b'BASIC\nSUB 1 START\nSUB 1 END\n')
|
||||
test_string(".require different files with identical paths",
|
||||
'.include "sub/sub/sub.oph"',
|
||||
'SUB 2 START\nSUB 1 START\nBASIC\nSUB 1 END\nSUB 2 END\n')
|
||||
b'SUB 2 START\nSUB 1 START\nBASIC\nSUB 1 END\nSUB 2 END\n')
|
||||
test_string(".charmap (basic)",
|
||||
'.charmap \'A, "abcdefghijklmnopqrstuvwxyz"\n'
|
||||
'.charmap \'a, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\n'
|
||||
'.byte "hELLO, wORLD!"', "Hello, World!")
|
||||
'.byte "hELLO, wORLD!"', b"Hello, World!")
|
||||
test_string(".charmap (reset)",
|
||||
'.charmap \'A, "abcdefghijklmnopqrstuvwxyz"\n'
|
||||
'.charmap \'a, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\n'
|
||||
'.byte "hELLO, wORLD!",10\n'
|
||||
'.charmap\n'
|
||||
'.byte "hELLO, wORLD!",10\n',
|
||||
"Hello, World!\nhELLO, wORLD!\n")
|
||||
b"Hello, World!\nhELLO, wORLD!\n")
|
||||
test_string(".charmap (out of range)",
|
||||
'.charmap 250, "ABCDEFGHIJKLM"\n.byte 250,251',
|
||||
'')
|
||||
b'')
|
||||
test_string(".charmapbin (basic)",
|
||||
'.charmapbin "../examples/petscii.map"\n.byte "hELLO, wORLD!"',
|
||||
"Hello, World!")
|
||||
b"Hello, World!")
|
||||
test_string(".charmapbin (illegal)",
|
||||
'.charmapbin "baseinc.bin"\n.byte "hELLO, wORLD!"', '')
|
||||
test_string(".incbin (basic)", '.incbin "baseinc.bin"', "BASIC\n")
|
||||
'.charmapbin "baseinc.bin"\n.byte "hELLO, wORLD!"', b'')
|
||||
test_string(".incbin (basic)", '.incbin "baseinc.bin"', b"BASIC\n")
|
||||
test_string(".incbin (hardcoded offset)",
|
||||
'.incbin "baseinc.bin",3', "IC\n")
|
||||
'.incbin "baseinc.bin",3', b"IC\n")
|
||||
test_string(".incbin (hardcoded offset and length)",
|
||||
'.incbin "baseinc.bin",3,2', "IC")
|
||||
'.incbin "baseinc.bin",3,2', b"IC")
|
||||
test_string(".incbin (softcoded offset and length)",
|
||||
'.alias off len+1\n.alias len 2\n'
|
||||
'.incbin "baseinc.bin",off,len', "IC")
|
||||
'.incbin "baseinc.bin",off,len', b"IC")
|
||||
test_string(".incbin (length too long)",
|
||||
'.byte 65\n.incbin "baseinc.bin",3,4', "")
|
||||
'.byte 65\n.incbin "baseinc.bin",3,4', b"")
|
||||
test_string(".incbin (negative offset)",
|
||||
'.byte 65\n.incbin "baseinc.bin",1-5,4', "")
|
||||
'.byte 65\n.incbin "baseinc.bin",1-5,4', b"")
|
||||
test_string(".incbin (offset = size)",
|
||||
'.byte 65\n.incbin "baseinc.bin",6', "A")
|
||||
'.byte 65\n.incbin "baseinc.bin",6', b"A")
|
||||
test_string(".incbin (offset > size)",
|
||||
'.byte 65\n.incbin "baseinc.bin",7', "")
|
||||
'.byte 65\n.incbin "baseinc.bin",7', b"")
|
||||
test_string(".incbin (softcoded length too long)",
|
||||
'.alias off len\n.alias len 4\n'
|
||||
'.byte 65\n.incbin "baseinc.bin",off,len', "")
|
||||
'.byte 65\n.incbin "baseinc.bin",off,len', b"")
|
||||
test_string(".incbin (softcoded negative offset)",
|
||||
'.alias off 1-5\n'
|
||||
'.byte 65\n.incbin "baseinc.bin",off,4', "")
|
||||
'.byte 65\n.incbin "baseinc.bin",off,4', b"")
|
||||
test_string(".incbin (softcoded offset = size)",
|
||||
'.alias off 6\n'
|
||||
'.byte 65\n.incbin "baseinc.bin",off', "A")
|
||||
'.byte 65\n.incbin "baseinc.bin",off', b"A")
|
||||
test_string(".incbin (softcoded offset > size)",
|
||||
'.alias off 7\n'
|
||||
'.byte 65\n.incbin "baseinc.bin",off', "")
|
||||
'.byte 65\n.incbin "baseinc.bin",off', b"")
|
||||
|
||||
|
||||
def test_systematic():
|
||||
|
@ -449,18 +450,18 @@ def test_systematic():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "Using Python interpreter:", pythonpath
|
||||
print("Using Python interpreter:", pythonpath)
|
||||
|
||||
test_basic()
|
||||
os.chdir(os.path.dirname(os.path.realpath(sys.argv[0])))
|
||||
if failed == 0:
|
||||
test_systematic()
|
||||
else:
|
||||
print "\nBasic test cases failed, aborting test."
|
||||
print("\nBasic test cases failed, aborting test.")
|
||||
|
||||
if failed > 0:
|
||||
print "\nTotal test case failures: %d" % failed
|
||||
print("\nTotal test case failures: %d" % failed)
|
||||
sys.exit(1)
|
||||
else:
|
||||
print "\nAll test cases succeeded"
|
||||
print("\nAll test cases succeeded")
|
||||
sys.exit(0)
|
||||
|
|
Loading…
Reference in New Issue
Block a user