mirror of
https://github.com/irmen/prog8.git
synced 2026-10-22 05:02:58 +00:00
added diskfont.p8
This commit is contained in:
1 parent
25bd60368a
commit
e1f2faabe7
10 files changed
+196
-81
No files matched your search
@@ -94,8 +94,11 @@ registers survive calls. Long operations may clobber `R12-R15`.
|
||||
## Syntax Pitfalls
|
||||
|
||||
- Hex uses `$FF`, binary uses `%1010`, and casts use `expression as type`.
|
||||
- There is no automatic type widening: `byte * byte` remains a byte. Cast
|
||||
explicitly when a wider result is needed.
|
||||
- There is no automatic type widening in expression results: `byte * byte`
|
||||
remains a byte. Cast explicitly when a wider result is needed. Assignments,
|
||||
call arguments, and mixed-type expressions do widen implicitly
|
||||
(`ubyte`/`byte` to `word`/`uword` to `long`); only same-width signedness
|
||||
reinterpretation (`uword` to `word` and back) needs an explicit `as` cast.
|
||||
- `&` is an untyped address and `&&` is a typed pointer. Complex pointer field
|
||||
assignments may require `ptr^^.field`.
|
||||
- `and`, `or`, `xor`, and `not` are logical operators. Use `&`, `|`, `^`, and
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
%import shared_amiga_diskfont
|
||||
|
||||
diskfont {
|
||||
%option no_symbol_prefixing, ignore_unused
|
||||
}
|
||||
@@ -41,6 +41,7 @@ sys {
|
||||
pointer @shared IFFParseBase ; loaded from disk on demand
|
||||
pointer @shared AsyncIOBase ; loaded from disk on demand
|
||||
pointer @shared LowLevelBase ; kickstart 2.0+, loaded from disk on demand
|
||||
pointer @shared DiskfontBase ; loaded from disk on demand
|
||||
pointer @shared TimerBase ; opened on demand
|
||||
pointer @shared AHIBase ; ahi.device base, opened on demand by ahi.open(); for the low-level ahi.* LVO calls
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
%import shared_amiga_diskfont
|
||||
|
||||
diskfont {
|
||||
%option no_symbol_prefixing, ignore_unused
|
||||
}
|
||||
@@ -41,6 +41,7 @@ sys {
|
||||
pointer @shared IFFParseBase ; kickstart 2.0+, loaded from disk on demand
|
||||
pointer @shared AsyncIOBase ; loaded from disk on demand
|
||||
pointer @shared LowLevelBase ; kickstart 2.0+, loaded from disk on demand
|
||||
pointer @shared DiskfontBase ; loaded from disk on demand
|
||||
pointer @shared TimerBase ; opened on demand
|
||||
|
||||
^^ubyte @shared arguments ; CLI argument string (null-terminated), or NULL if Workbench launch
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
;; Hand-maintained diskfont.library interface, trimmed to pre-3.0 content (up to Kickstart 2.0).
|
||||
;; (Outline engine, diskfont control and tagged-font matching need 3.0+ and were removed.)
|
||||
;; Library base: _DiskfontBase in prog8: sys.DiskfontBase
|
||||
;; Bank: 13
|
||||
|
||||
%import exec
|
||||
%import graphics
|
||||
|
||||
diskfont {
|
||||
%option merge, no_symbol_prefixing
|
||||
|
||||
sub openlib() -> bool {
|
||||
; not opened at startup: diskfont.library lives on disk (not in ROM),
|
||||
; so it must be opened on demand and may legitimately fail
|
||||
sys.DiskfontBase = exec.OpenLibrary("diskfont.library", 0)
|
||||
return sys.DiskfontBase!=0
|
||||
}
|
||||
|
||||
sub closelib() {
|
||||
if sys.DiskfontBase!=0 {
|
||||
exec.CloseLibrary(sys.DiskfontBase)
|
||||
sys.DiskfontBase = 0
|
||||
}
|
||||
}
|
||||
|
||||
private graphics.TextAttr[1] openfont_attr ; scratch for openfont()
|
||||
|
||||
sub openfont(str name, uword size, ubyte style) -> ^^graphics.TextFont {
|
||||
; simplified OpenDiskFont with no flags (style e.g. graphics.FS_NORMAL).
|
||||
; Name is like "helvetica.font". Returns 0 when the font cannot be found.
|
||||
^^graphics.TextAttr fa = &openfont_attr[0]
|
||||
fa.Name = name
|
||||
fa.YSize = size
|
||||
fa.Style = style
|
||||
fa.Flags = 0
|
||||
return OpenDiskFont(fa)
|
||||
}
|
||||
|
||||
extsub @bank 13 -30 = OpenDiskFont(^^graphics.TextAttr textAttr @A0) -> ^^graphics.TextFont @D0
|
||||
extsub @bank 13 -36 = AvailFonts(pointer buffer @A0, long bufBytes @D0, long flags @D1) -> long @D0
|
||||
extsub @bank 13 -42 = NewFontContents(pointer fontsLock @A0, str fontName @A1) -> pointer @D0
|
||||
extsub @bank 13 -48 = DisposeFontContents(pointer fontContentsHeader @A1)
|
||||
extsub @bank 13 -54 = NewScaledDiskFont(^^graphics.TextFont sourceFont @A0, ^^graphics.TextAttr destTextAttr @A1) -> pointer @D0
|
||||
|
||||
; ---- constants ----
|
||||
const uword MAXFONTPATH = $0100
|
||||
const uword FCH_ID = $0f00
|
||||
const uword TFCH_ID = $0f02
|
||||
const uword DFH_ID = $0f80
|
||||
const ubyte MAXFONTNAME = $0020
|
||||
const ubyte AFB_MEMORY = 0
|
||||
const ubyte AFF_MEMORY = $0001
|
||||
const ubyte AFB_DISK = 1
|
||||
const ubyte AFF_DISK = $0002
|
||||
const ubyte AFB_SCALED = 2
|
||||
const ubyte AFF_SCALED = $0004
|
||||
const ubyte AFB_BITMAP = 3
|
||||
const ubyte AFF_BITMAP = $0008
|
||||
const ubyte AFB_OTAG = 4
|
||||
const ubyte AFF_OTAG = $0010
|
||||
const ubyte AFB_CHARSET = 5
|
||||
const ubyte AFF_CHARSET = $0020
|
||||
const ubyte AFB_TYPE = 6
|
||||
const ubyte AFF_TYPE = $0040
|
||||
}
|
||||
@@ -3,11 +3,12 @@
|
||||
; Hides NewScreen/NewWindow boilerplate behind a gfx_lores-style API:
|
||||
; per-call pen, client-relative word coordinates, explicit open/close.
|
||||
; Kickstart 1.3 compatible: uses only OpenScreen/OpenWindow (no taglists,
|
||||
; no AllocBitMap, no DisplayID). All rasterization is done by
|
||||
; no AllocBitMap, no DisplayID), except fillto() which needs SetOutlinePen (3.0+).
|
||||
; All rasterization is done by
|
||||
; graphics.library; filled ellipses and flood fills use AreaEllipse/Flood
|
||||
; with a chip-ram TmpRas scratch buffer allocated when the window opens.
|
||||
; No double buffering (use two screens/windows or raw calls for that).
|
||||
; Read rastport for direct graphics.library calls, window to pump IDCMP.
|
||||
; Use rastport for direct graphics.library calls, window to pump IDCMP.
|
||||
|
||||
%import intuition
|
||||
%import graphics
|
||||
@@ -33,13 +34,13 @@ amiga_gfx {
|
||||
private graphics.TmpRas[1] tmpras_store
|
||||
private graphics.AreaInfo[1] area_store
|
||||
private graphics.TextAttr[1] font_store
|
||||
private ubyte[20] area_vectors ; 5 bytes per vector, AreaEllipse needs 2
|
||||
private ubyte[20] area_vectors ; 5 bytes per vector, room for 4
|
||||
private pointer tmpras_buf
|
||||
private long tmpras_size
|
||||
|
||||
sub fullscreen(uword w, uword h, ubyte ndepth, uword viewmodes, str title) -> bool {
|
||||
; fullscreen custom screen + backdrop borderless window.
|
||||
; viewmodes: 0 = lores, graphics.HIRES for 640px, + graphics.INTERLACE for halfbrite-height.
|
||||
; viewmodes: 0 = lores, graphics.HIRES for 640px, + graphics.INTERLACE for interlaced (doubled height).
|
||||
if w == 0 or h == 0
|
||||
return false
|
||||
if rastport != 0
|
||||
@@ -48,13 +49,13 @@ amiga_gfx {
|
||||
if not untitled
|
||||
untitled = title[0] == 0
|
||||
; NOTE: struct literals must be constant, so allocate zeroed and patch fields.
|
||||
^^intuition.NewScreen ns = [0, 0, 0, 0, 0, 0 as ubyte, 0 as ubyte, 0, 0, 0, 0, 0, 0]
|
||||
^^intuition.NewScreen ns = [0, 0, 0, 0, 0, ; edges, size, depth
|
||||
0, 1, 0, intuition.CUSTOMSCREEN, ; pens, modes, type
|
||||
0, 0, 0, 0] ; font, title, gadgets, bitmap
|
||||
ns.Width = w as word
|
||||
ns.Height = h as word
|
||||
ns.Depth = ndepth as word
|
||||
ns.BlockPen = 1
|
||||
ns.Depth = ndepth
|
||||
ns.ViewModes = viewmodes
|
||||
ns.Type = intuition.CUSTOMSCREEN
|
||||
if not untitled
|
||||
ns.DefaultTitle = title
|
||||
; explicit Topaz 8 screen font (ROM-resident, no diskfont needed)
|
||||
@@ -72,25 +73,27 @@ amiga_gfx {
|
||||
; null and "" both count as titleless.
|
||||
word bar = 0
|
||||
if not untitled {
|
||||
bar = screen.WBorTop as word
|
||||
if h as word - bar <= 0 {
|
||||
bar = screen.WBorTop
|
||||
if h - bar <= 0 {
|
||||
void intuition.CloseScreen(screen)
|
||||
screen = 0
|
||||
return false
|
||||
}
|
||||
}
|
||||
const long idcmp = intuition.IDCMP_MOUSEBUTTONS | intuition.IDCMP_RAWKEY | intuition.IDCMP_VANILLAKEY
|
||||
const long flags = intuition.WFLG_BACKDROP | intuition.WFLG_BORDERLESS | intuition.WFLG_ACTIVATE | intuition.WFLG_RMBTRAP | intuition.WFLG_NOCAREREFRESH
|
||||
^^intuition.NewWindow nw = [0, 0, 0, 0, 0 as ubyte, 0 as ubyte, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
^^intuition.NewWindow nw = [0, 0, 0, 0, ; edges, size
|
||||
0, 1, ; pens
|
||||
; RAWKEY only, never add VANILLAKEY here: with both flags set Intuition
|
||||
; diverts mappable keys to the vanilla channel and starves the raw one,
|
||||
; so cursor keys (and on Kickstart 1.3, all keys) stop arriving as rawkey.
|
||||
; Map raw codes yourself instead; ESC is $45, cursor keys are $4c-$4f.
|
||||
intuition.IDCMP_MOUSEBUTTONS | intuition.IDCMP_RAWKEY,
|
||||
intuition.WFLG_BACKDROP | intuition.WFLG_BORDERLESS | intuition.WFLG_ACTIVATE | intuition.WFLG_RMBTRAP | intuition.WFLG_NOCAREREFRESH,
|
||||
0, 0, 0, 0, ; no gadgets, default checkmark, title, screen
|
||||
0, 0, 0, 0, 0, intuition.CUSTOMSCREEN] ; bitmap, limits, type
|
||||
nw.TopEdge = bar
|
||||
nw.Width = w as word
|
||||
nw.Height = h as word - bar
|
||||
nw.BlockPen = 1
|
||||
nw.IDCMPFlags = idcmp
|
||||
nw.Flags = flags
|
||||
nw.Title = 0 ; backdrop window itself stays titleless and undecorated
|
||||
nw.Height = h - bar
|
||||
nw.Screen = screen
|
||||
nw.Type = intuition.CUSTOMSCREEN
|
||||
window = intuition.OpenWindow(nw)
|
||||
if window == 0 {
|
||||
void intuition.CloseScreen(screen)
|
||||
@@ -98,9 +101,10 @@ amiga_gfx {
|
||||
return false
|
||||
}
|
||||
depth = ndepth
|
||||
intuition.ActivateWindow(window)
|
||||
finish_open(true, bar)
|
||||
width = w
|
||||
height = (h as word - bar) as uword
|
||||
height = (h - bar) as uword
|
||||
graphics.SetDrMd(rastport, graphics.RP_JAM1)
|
||||
if untitled {
|
||||
; ShowTitle(FALSE) renders the bar behind all windows; do it with
|
||||
@@ -111,31 +115,31 @@ amiga_gfx {
|
||||
return true
|
||||
}
|
||||
|
||||
sub windowed(uword w, uword h, str title) -> bool {
|
||||
; fixed-size window on the Workbench screen. Works everywhere,
|
||||
sub windowed(uword x, uword y, uword w, uword h, str title) -> bool {
|
||||
; fixed-size window on the Workbench screen at position (x,y). Works everywhere,
|
||||
; but depth/palette are the Workbench's: use palette() sparingly.
|
||||
if w == 0 or h == 0
|
||||
return false
|
||||
if rastport != 0
|
||||
close()
|
||||
screen = 0
|
||||
const long idcmp = intuition.IDCMP_CLOSEWINDOW | intuition.IDCMP_REFRESHWINDOW | intuition.IDCMP_VANILLAKEY | intuition.IDCMP_MOUSEBUTTONS
|
||||
const long flags = intuition.WFLG_CLOSEGADGET | intuition.WFLG_DRAGBAR | intuition.WFLG_DEPTHGADGET | intuition.WFLG_ACTIVATE
|
||||
^^intuition.NewWindow nw = [0, 0, 0, 0, 0 as ubyte, 0 as ubyte, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
nw.LeftEdge = 10
|
||||
nw.TopEdge = 20
|
||||
^^intuition.NewWindow nw = [0, 0, 0, 0, ; edges, size
|
||||
255, 255, ; pens
|
||||
; RAWKEY only, see fullscreen() for why.
|
||||
intuition.IDCMP_CLOSEWINDOW | intuition.IDCMP_REFRESHWINDOW | intuition.IDCMP_MOUSEBUTTONS | intuition.IDCMP_RAWKEY,
|
||||
intuition.WFLG_CLOSEGADGET | intuition.WFLG_DRAGBAR | intuition.WFLG_DEPTHGADGET | intuition.WFLG_ACTIVATE,
|
||||
0, 0, 0, 0, ; no gadgets, default checkmark, title, screen
|
||||
0, 0, 0, 0, 0, intuition.WBENCHSCREEN] ; bitmap, limits, type
|
||||
nw.LeftEdge = x as word
|
||||
nw.TopEdge = y as word
|
||||
nw.Width = w as word
|
||||
nw.Height = h as word
|
||||
nw.DetailPen = 255
|
||||
nw.BlockPen = 255
|
||||
nw.IDCMPFlags = idcmp
|
||||
nw.Flags = flags
|
||||
nw.Title = title
|
||||
nw.Type = intuition.WBENCHSCREEN
|
||||
window = intuition.OpenWindow(nw)
|
||||
if window == 0
|
||||
return false
|
||||
depth = 0
|
||||
intuition.ActivateWindow(window)
|
||||
finish_open(false, 0)
|
||||
graphics.SetDrMd(rastport, graphics.RP_JAM1)
|
||||
return true
|
||||
@@ -168,7 +172,7 @@ amiga_gfx {
|
||||
if width == 0 or height == 0
|
||||
return
|
||||
graphics.SetAPen(rastport, pen)
|
||||
graphics.RectFill(rastport, origin_x, origin_y, (origin_x + width) as word - 1, (origin_y + height) as word - 1)
|
||||
graphics.RectFill(rastport, origin_x, origin_y, (origin_x + width) - 1, (origin_y + height) - 1)
|
||||
}
|
||||
|
||||
sub plot(word x, word y, ubyte pen) {
|
||||
@@ -231,7 +235,7 @@ amiga_gfx {
|
||||
if radius < 0
|
||||
return
|
||||
graphics.SetAPen(rastport, pen)
|
||||
void do_area_ellipse(cx, cy, aspect_rx(radius), radius)
|
||||
do_area_ellipse(cx, cy, aspect_rx(radius), radius)
|
||||
}
|
||||
|
||||
sub filled_oval(word cx, word cy, word rx, word ry, ubyte pen) {
|
||||
@@ -239,7 +243,7 @@ amiga_gfx {
|
||||
if rx <= 0 or ry <= 0
|
||||
return
|
||||
graphics.SetAPen(rastport, pen)
|
||||
void do_area_ellipse(cx, cy, aspect_rx(rx), ry)
|
||||
do_area_ellipse(cx, cy, aspect_rx(rx), ry)
|
||||
}
|
||||
|
||||
sub text(word x, word y, str s, ubyte pen) {
|
||||
@@ -265,16 +269,15 @@ amiga_gfx {
|
||||
; tweak a single colormap pen (4-bit nibbles)
|
||||
pointer vp = viewport()
|
||||
if vp != 0
|
||||
graphics.SetRGB4(vp, index as word, red, green, blue)
|
||||
graphics.SetRGB4(vp, index, red, green, blue)
|
||||
}
|
||||
|
||||
sub scroll(word dx, word dy) {
|
||||
; shift the client area; the exposed strip is cleared
|
||||
word xa = origin_x
|
||||
word ya = origin_y
|
||||
word x2 = (origin_x + width) as word - 1
|
||||
word y2 = (origin_y + height) as word - 1
|
||||
graphics.ScrollRaster(rastport, dx, dy, xa, ya, x2, y2)
|
||||
sub scrollrect(word dx, word dy, word x, word y, word w, word h) {
|
||||
; scroll a client-relative rectangle
|
||||
; the rectangle should lie inside the client area.
|
||||
if w <= 0 or h <= 0
|
||||
return
|
||||
graphics.ScrollRaster(rastport, dx, dy, origin_x+x, origin_y+y, origin_x+x+w-1, origin_y+y+h-1)
|
||||
}
|
||||
|
||||
inline sub readpixel(word x, word y) -> long {
|
||||
@@ -294,15 +297,28 @@ amiga_gfx {
|
||||
return msg.MouseX - origin_x, msg.MouseY - origin_y
|
||||
}
|
||||
|
||||
sub imsg_wait() -> ^^intuition.IntuiMessage {
|
||||
; block until the next IDCMP message arrives on our window
|
||||
void exec.WaitPort(window.UserPort)
|
||||
return exec.GetMsg(window.UserPort) as ^^intuition.IntuiMessage
|
||||
}
|
||||
|
||||
sub imsg_reply(^^intuition.IntuiMessage msg) -> ^^intuition.IntuiMessage {
|
||||
; reply the message and fetch the next one (0 when drained)
|
||||
exec.ReplyMsg(msg as ^^exec.Message)
|
||||
return exec.GetMsg(window.UserPort) as ^^intuition.IntuiMessage
|
||||
}
|
||||
|
||||
|
||||
sub fill(word x, word y, ubyte pen) {
|
||||
; bucket fill: recolor the connected region holding (x,y)
|
||||
void do_flood(x, y, pen, 1)
|
||||
do_flood(x, y, pen, 1)
|
||||
}
|
||||
|
||||
sub fillto(word x, word y, ubyte pen, ubyte outline) {
|
||||
; boundary fill: fill until the outline-colored border
|
||||
void graphics.SetOutlinePen(rastport, outline as long)
|
||||
void do_flood(x, y, pen, 0)
|
||||
void graphics.SetOutlinePen(rastport, outline)
|
||||
do_flood(x, y, pen, 0)
|
||||
}
|
||||
|
||||
private sub aspect_rx(word rx) -> word {
|
||||
@@ -324,40 +340,37 @@ amiga_gfx {
|
||||
return intuition.GetScreenViewPort(s)
|
||||
}
|
||||
|
||||
private sub do_flood(word x, word y, ubyte pen, long mode) -> bool {
|
||||
private sub do_flood(word x, word y, ubyte pen, long mode) {
|
||||
if rastport == 0 or tmpras_buf == 0
|
||||
return false
|
||||
return
|
||||
graphics.SetAPen(rastport, pen)
|
||||
^^graphics.TmpRas saved = rastport.TmpRas
|
||||
^^graphics.TmpRas tp = &tmpras_store[0]
|
||||
void graphics.InitTmpRas(tp, tmpras_buf, tmpras_size)
|
||||
rastport.TmpRas = tp
|
||||
bool ok = graphics.Flood(rastport, mode, origin_x+x, origin_y+y)
|
||||
void graphics.Flood(rastport, mode, origin_x+x, origin_y+y)
|
||||
rastport.TmpRas = saved
|
||||
return ok
|
||||
}
|
||||
|
||||
private sub finish_open(bool custom, word bar) {
|
||||
rastport = window.RPort
|
||||
origin_x = window.BorderLeft as word
|
||||
origin_y = window.BorderTop as word
|
||||
word right = window.BorderRight as word
|
||||
word bottom = window.BorderBottom as word
|
||||
width = (window.Width - origin_x - right) as uword
|
||||
height = (window.Height - origin_y - bottom) as uword
|
||||
origin_x = window.BorderLeft
|
||||
origin_y = window.BorderTop
|
||||
width = (window.Width - origin_x - window.BorderRight) as uword
|
||||
height = (window.Height - origin_y - window.BorderBottom) as uword
|
||||
; pixel shape from the screen's ViewPort.Modes (big-endian word at offset 32)
|
||||
aspect = 1
|
||||
pointer vp = viewport()
|
||||
if vp != 0 {
|
||||
uword modes = (@(vp+32) as uword) << 8 | (@(vp+33) as uword)
|
||||
if (modes & (graphics.SUPERHIRES as uword)) != 0 {
|
||||
uword modes = (@(vp+32) as uword) << 8 | @(vp+33)
|
||||
if (modes & graphics.SUPERHIRES) != 0 {
|
||||
aspect = 4
|
||||
if (modes & (graphics.INTERLACE as uword)) != 0
|
||||
if (modes & graphics.INTERLACE) != 0
|
||||
aspect = 2
|
||||
} else {
|
||||
if (modes & graphics.V_HIRES) != 0 and (modes & (graphics.INTERLACE as uword)) == 0
|
||||
if (modes & graphics.V_HIRES) != 0 and (modes & graphics.INTERLACE) == 0
|
||||
aspect = 2
|
||||
if (modes & (graphics.INTERLACE as uword)) != 0 and (modes & graphics.V_HIRES) == 0
|
||||
if (modes & graphics.INTERLACE) != 0 and (modes & graphics.V_HIRES) == 0
|
||||
aspect = 0
|
||||
}
|
||||
}
|
||||
@@ -370,14 +383,14 @@ amiga_gfx {
|
||||
; one-plane Flood scratch sized to the rastport's bitmap
|
||||
; (Flood requires the TmpRas to cover the whole bitmap, not just the client area)
|
||||
if rastport.BitMap != 0 {
|
||||
tmpras_size = rastport.BitMap.BytesPerRow as long * rastport.BitMap.Rows as long
|
||||
tmpras_size = rastport.BitMap.BytesPerRow * rastport.BitMap.Rows
|
||||
tmpras_buf = exec.AllocMem(tmpras_size, exec.MEMF_CHIP)
|
||||
}
|
||||
}
|
||||
|
||||
private sub do_area_ellipse(word cx, word cy, word rx, word ry) -> bool {
|
||||
private sub do_area_ellipse(word cx, word cy, word rx, word ry) {
|
||||
if rastport == 0 or tmpras_buf == 0
|
||||
return false
|
||||
return
|
||||
^^graphics.TmpRas saved_tr = rastport.TmpRas
|
||||
^^graphics.AreaInfo saved_ai = rastport.AreaInfo
|
||||
^^graphics.TmpRas tp = &tmpras_store[0]
|
||||
@@ -386,11 +399,9 @@ amiga_gfx {
|
||||
rastport.TmpRas = tp
|
||||
graphics.InitArea(ai, area_vectors, 4)
|
||||
rastport.AreaInfo = ai
|
||||
long err = graphics.AreaEllipse(rastport, origin_x+cx, origin_y+cy, rx, ry)
|
||||
if err == 0
|
||||
err = graphics.AreaEnd(rastport)
|
||||
if graphics.AreaEllipse(rastport, origin_x+cx, origin_y+cy, rx, ry) == 0
|
||||
void graphics.AreaEnd(rastport)
|
||||
rastport.TmpRas = saved_tr
|
||||
rastport.AreaInfo = saved_ai
|
||||
return err == 0
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ graphics {
|
||||
const uword LORES = 0
|
||||
const ubyte LACE = $0004
|
||||
const ubyte SUPERHIRES = $20
|
||||
|
||||
extsub @bank 3 -30 = BltBitMap(^^BitMap srcBitMap @A0, word xSrc @D0, word ySrc @D1, ^^BitMap destBitMap @A1, word xDest @D2, word yDest @D3, word xSize @D4, word ySize @D5, ubyte minterm @D6, ubyte mask @D7, pointer tempA @A2) -> long @D0
|
||||
extsub @bank 3 -36 = BltTemplate(long source @A0, word xSrc @D0, word srcMod @D1, ^^RastPort destRP @A1, word xDest @D2, word yDest @D3, word xSize @D4, word ySize @D5)
|
||||
extsub @bank 3 -42 = ClearEOL(^^RastPort rp @A1)
|
||||
|
||||
+31
-11
@@ -5,7 +5,6 @@
|
||||
%import amiga_gfx
|
||||
%import graphics
|
||||
%import intuition
|
||||
%import exec
|
||||
|
||||
main {
|
||||
uword[8] palette = [$0112, $0f00, $00f0, $000f, $0ff0, $0f0f, $00ff, $0fff]
|
||||
@@ -31,24 +30,23 @@ main {
|
||||
amiga_gfx.oval(240, 200, 50, 20, 6)
|
||||
amiga_gfx.filled_oval(40, 60, 30, 12, 5)
|
||||
amiga_gfx.plot(160, 128, 7)
|
||||
amiga_gfx.text(160, 30, "amiga_gfx demo", 7)
|
||||
word tw = amiga_gfx.textwidth("click to draw stuff, ESC=quit")
|
||||
amiga_gfx.text(160 - tw/2, 60, "click to draw stuff, ESC=quit", 7)
|
||||
amiga_gfx.text(160, 30, "amiga_gfx demo", 5)
|
||||
word tw = amiga_gfx.textwidth("click to draw, arrows scroll")
|
||||
amiga_gfx.text(160 - tw/2, 60, "click to draw, arrows scroll", 6)
|
||||
tw = amiga_gfx.textwidth("ESC=quit")
|
||||
amiga_gfx.text(160 - tw/2, 70, "ESC=quit", 7)
|
||||
amiga_gfx.setcolor(7, $f, $f, $f)
|
||||
; direct library escape hatch via the exposed RastPort:
|
||||
^^graphics.RastPort rp = amiga_gfx.rastport
|
||||
graphics.SetAPen(rp, 3)
|
||||
graphics.Move(rp, 10, 240)
|
||||
graphics.Draw(rp, 310, 240)
|
||||
|
||||
; TODO make amiga_gfx.scroll() work
|
||||
}
|
||||
|
||||
sub interact() {
|
||||
bool done = false
|
||||
while not done {
|
||||
void exec.WaitPort(amiga_gfx.window.UserPort)
|
||||
^^intuition.IntuiMessage msg = exec.GetMsg(amiga_gfx.window.UserPort) as ^^intuition.IntuiMessage
|
||||
^^intuition.IntuiMessage msg = amiga_gfx.imsg_wait()
|
||||
while msg != 0 {
|
||||
when msg.Class {
|
||||
intuition.IDCMP_CLOSEWINDOW -> done = true
|
||||
@@ -59,10 +57,32 @@ main {
|
||||
if msg.Code == intuition.MENUDOWN
|
||||
amiga_gfx.fillrect(mx-10, my-6, 20, 12, 2)
|
||||
}
|
||||
intuition.IDCMP_VANILLAKEY -> if msg.Code == 27 { done = true } ; ESC pressed?
|
||||
intuition.IDCMP_RAWKEY -> {
|
||||
; keyboard arrives as rawkey only: cursor keys scroll (key repeat
|
||||
; scrolls smoothly), ESC quits. Key-up events (bit 7) are ignored.
|
||||
; raw keycodes are positional (same on all national keymaps):
|
||||
; $00 ` $01-$0A 1..0 $0B - $0C = $0D \ $0F numpad-0
|
||||
; $10-$19 Q..P $1A [ $1B ] $1D-$1F numpad-1..3
|
||||
; $20-$28 A..L $29 ; $2A ' $2D-$2F numpad-4..6
|
||||
; $31-$37 Z..M $38 , $39 . $3A / $3C numpad-. $3D-$3F numpad-7..9
|
||||
; $40 space $41 backspace $42 tab $43 numpad-enter $44 return
|
||||
; $45 ESC $46 del $4A numpad-- $4C-$4F cursor up/down/right/left
|
||||
; $50-$59 F1-F10 $5A-$5E numpad ( ) / * + $5F help
|
||||
; $60/$61 shift l/r $62 caps $63 ctrl $64/$65 alt l/r $66/$67 amiga l/r
|
||||
; source: https://wiki.amigaos.net/wiki/Keymap_Library
|
||||
if (msg.Code & $80) == 0 {
|
||||
when (msg.Code & $7f) {
|
||||
; note: ScrollRaster moves bits towards (0,0), so the signs are flipped
|
||||
$45 -> done = true ; ESC
|
||||
$4c -> amiga_gfx.scrollrect(0, 8, 80, 88, 160, 120) ; up
|
||||
$4d -> amiga_gfx.scrollrect(0, -8, 80, 88, 160, 120) ; down
|
||||
$4e -> amiga_gfx.scrollrect(-8, 0, 80, 88, 160, 120) ; right
|
||||
$4f -> amiga_gfx.scrollrect(8, 0, 80, 88, 160, 120) ; left
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exec.ReplyMsg(msg as ^^exec.Message)
|
||||
msg = exec.GetMsg(amiga_gfx.window.UserPort) as ^^intuition.IntuiMessage
|
||||
msg = amiga_gfx.imsg_reply(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1049,6 +1049,9 @@ LIBRARY_BANK_MAP = {
|
||||
# 0. CONFIG - Amiga libraries to generate
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# NOTE: diskfont is intentionally NOT auto-generated: shared_amiga_diskfont.p8 is
|
||||
# hand-maintained, trimmed to pre-2.0 content (the SFD contains post-2.0
|
||||
# outline-engine, diskfont-control and tagged-font APIs).
|
||||
AMIGA_LIBS = ["exec", "dos", "graphics", "intuition", "utility", "iffparse", "arexx", "icon", "lowlevel"]
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user