The Goal: Draw a Picture at coordinates, with an independent Width/Height, using XMin/XMax and YMin/YMax as the screen.
The idea, a DrawPicture Macro/Procedure that can draw a picture in any screen mode(or even on a flat surface).
I wrote it in QBasic for ease, now just need to convert it to assembly!
Lets look at the Inner Loop :)
FOR Y = 0 TO YLen
FOR X = 0 TO XLen
POKE ViewStart, C(DataStart)
ViewStart = ViewStart + 1
DataStart = DataStart + 1
NEXT X
ViewStart = ViewStart + ViewChange
DataStart = DataStart + DataChange
NEXT Y
Hmm, the For Loops will be the hardest, considering everything else is either a Inc/Mov/Add
The next hard part will be using Signed Numbers(I don't use them very often).
Ohh well, back to the labratory.
Still Needs:
Bits Per Pixel Calculations, right now its "flat 256", so it can only use 8-bit color modes.
Scaling/Rotating would be nice.
DECLARE SUB DrawPicture (XStart%, YStart%, XLen%, YLen%, XMin%, YMin%, XMax%, YMax%)
DEFINT A-Z
' 8x8 Picture
'DIM SHARED C(0 TO 63) AS INTEGER
'DATA 1,1,1,1,1,1,1,1
'DATA 1,2,2,0,0,2,2,1
'DATA 1,2,2,0,0,2,2,1
'DATA 1,0,0,4,4,0,0,1
'DATA 1,0,0,4,4,0,0,1
'DATA 1,2,2,0,0,2,2,1
'DATA 1,2,2,0,0,2,2,1
'DATA 1,1,1,1,1,1,1,1
'FOR Temp = 0 TO 63: READ C(Temp): NEXT Temp
' 320x2 Picture
DIM SHARED C(0 TO 639)
FOR Temp = 0 TO 639: C(Temp) = 4: NEXT Temp
C(0) = 15
C(319) = 15
C(320) = 14
C(639) = 14
' Set Screen/Set Segment/Draw Picture
SCREEN 13
DEF SEG = 40960
' 8x8 Picture
'DrawPicture -1, -1, 7, 7, 0, 0, 319, 199
'DrawPicture 313, -1, 7, 7, 0, 0, 319, 199
'DrawPicture -1, 193, 7, 7, 0, 0, 319, 199
'DrawPicture 313, 193, 7, 7, 0, 0, 319, 199
' 321x1 Picture
DrawPicture 319, -1, 319, 1, 0, 0, 319, 199
DO: LOOP WHILE INKEY$ <> CHR$(27)
SUB DrawPicture (XStart, YStart, W, H, XMin, YMin, XMax, YMax)
' Right Now, all Longs
DIM DataStart AS LONG
DIM DataChange AS LONG
DIM ViewStart AS LONG
DIM ViewChange AS LONG
IF XStart + W < XMin OR XStart > XMax OR YStart + H < YMin OR YStart > YMax THEN EXIT SUB
DataStart = 0
DataChange = 0
ViewChange = 0
IF XStart < XMin THEN
XLen = W - ABS(XStart)
DataStart = ABS(XStart)
DataChange = ABS(XStart)
ViewStart = XMin
ViewChange = XMax - W + ABS(XStart)
ELSE
ViewStart = XStart
IF XStart + W > XMax THEN
XLen = XMax - XStart
DataChange = W - XLen
ViewChange = XStart
ELSE
XLen = W
END IF
END IF
IF YStart < YMin THEN
YLen = H - ABS(YStart)
DataStart = DataStart + ((W + 1) * ABS(YStart))
ELSE
ViewStart = ViewStart + (ABS(YStart) * (XMax + 1&))
IF YStart + H > YMax THEN
YLen = YMax - YStart
ELSE
YLen = H
END IF
END IF
FOR Y = 0 TO YLen
FOR X = 0 TO XLen
POKE ViewStart, C(DataStart)
ViewStart = ViewStart + 1
DataStart = DataStart + 1
NEXT X
ViewStart = ViewStart + ViewChange
DataStart = DataStart + DataChange
NEXT Y
END SUB
I just counted them btw, 8 separate values in the Loop:
Y(Ax), YLen(Cx), X(Bx), XLen(Dx), ViewStart(Es:Di), DataStart(Ds:Si), ViewChange, DataChange
Need 2 more...
Ohh well, tell me what you guys think! :D
It's not great, but it somewhat works. :'(
Ohh, and NO, it's not Masm32 compatible. The code is pretty self-explanitory though.
VideoDrawPicture Macro Picture, XStart, YStart, W, H, XMin, YMin, XMax, YMax
;Local L_LeftChange, L_RightChange, L_NoXChange, L_FinishXChange, L_BottomChange, L_TopChange, L_FinishYChange, L_NoYChange, LoopY, LoopX, L_Exit
; Ds:Si = Picture/DataStart, Es:Di = Screen/ViewStart
MoveSegOff Picture,Ds,Si,Ax
MoveSR Es,Ax,0A000h
; XStart > XMax, XStart + W < XMin, YStart > YMax, YStart + H < YMin
Move Ax, XStart
CompareAndJumpIfGreater Ax, XMax, L_Exit
Addition Ax, W
CompareAndJumpIfLess Ax, XMin, L_Exit
Move Ax, YStart
CompareAndJumpIfGreater Ax, YMax, L_Exit
Addition Ax, H
CompareAndJumpIfLess Ax, YMin, L_Exit
; If XStart < XMin Then Goto L_LeftChange
Move Ax, XStart
CompareAndJumpIfLess Ax, XMin, L_LeftChange
; Else
; ViewStart = XStart
Move Di, XStart
; If XStart + W > XMax Then Goto L_RightChange Else Goto L_NoXChange
Addition Ax, W
CompareAndJumpIfGreaterElseJump Ax, XMax, L_RightChange, L_NoXChange
L_LeftChange:
; DataStart = ABS(XStart)
Move Ax, XStart
TestAndJumpIfZero Ax, 1000000000000000b, L_NoLeftChange
Not Ax
Increase Ax
L_NoLeftChange:
Move Si, Ax
; DataChange = ABS(XStart)
PushWord Ax
; ViewChange = XMax - W + ABS(XStart)
Addition Ax, W
Move Dx, XMax
Subtraction Dx, Ax
PushWord Dx
; XLen = W - ABS(XStart)
Move Cx, W
Subtraction Cx, Ax
PushWord Cx
; ViewStart = XMin
Move Di, XMin
Jump L_FinishXChange
L_RightChange:
; XLen = XMax - XStart
Move Cx, XMax
Subtraction Cx, XStart
; DataChange = W - XLen
Move Bx, W
Subtraction Bx, Cx
PushWord Bx
; ViewChange = XStart
Move Ax, XStart
PushWord Ax, Cx
Jump L_FinishXChange
L_NoXChange:
; XLen = W
MoveZero Ax
Move Bx,W, Cx, XMax-W
PushWord Ax, Cx, Bx
L_FinishXChange:
; If YStart < YMin Then L_TopChange
Move Ax, YStart
CompareAndJumpIfLess Ax, YMin, L_TopChange
; ViewStart = ViewStart + (ABS(YStart) * (XMax + 1&))
Move Ax, YStart
TestAndJumpIfZero Ax, 1000000000000000b, L_NoRegYChange
Not Ax
Increase Ax
L_NoRegYChange:
Move Dx, XMax
Increase Dx
IMul Dx
Addition Di, Ax
; If YStart + H > YMax Then Goto L_BottomChange
Move Ax, YStart
Addition Ax, H
CompareAndJumpIfGreater Ax, YMax, L_BottomChange
; Else
; YLen = H
Move Ax, H
PushWord Ax
Jump L_FinishYChange
L_BottomChange:
; YLen = YMax - YStart
Move Ax, YMax
Subtraction Ax, YStart
PushWord Ax
Jump L_FinishYChange
L_TopChange:
; YLen = H - ABS(YStart)
Move Ax, YStart
TestAndJumpIfZero Ax, 1000000000000000b, L_NoTopChange
Not Ax
Increase Ax
L_NoTopChange:
Move Dx, Ax
Subtraction Ax, H
PushWord Ax
; DataStart = DataStart + ((W + 1) * ABS(YStart))
Move Ax, W
Increase Ax
IMul Dx
Addition Si, Ax
L_FinishYChange:
; The Stack
; DataChange
; ViewChange
; XLen
; YLen
; Data
; Si, Di
PopWord Dx, Cx
Increase Dx, Cx
MoveZero Bx, Ax
LoopY:
LoopX:
PushWord Ax
Move Al,Ds:[Si], Es:[Di],Al
PopWord Ax
Increase Di, Si, Ax
CompareAndJumpIfNotEqual Ax, Cx, LoopX
PopWord Ax, Bp
Addition Di,Ax, Si,Bp
PushWord Bp, Ax
MoveZero Ax
Increase Bx
CompareAndJumpIfNotEqual Bx, Dx, LoopY
L_Exit:
EndM